diff --git a/Makefile.common b/Makefile.common
index 34576dd4b0..5394c2c1a9 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -668,7 +668,7 @@ else ifeq ($(HAVE_BUILTINMBEDTLS), 1)
DEFINES += -DMBEDTLS_SSL_DEBUG_ALL
endif
- # MinGW requires this for some reason,
+ # MinGW requires this for some reason,
# even though the include paths are relative to the source
INCLUDE_DIRS += -Ideps/mbedtls
@@ -1576,8 +1576,14 @@ else ifeq ($(HAVE_SDL), 1)
else ifeq ($(HAVE_SDL_DINGUX), 1)
HAVE_SDL_COMMON = 1
DEF_FLAGS += -DHAVE_SDL -DHAVE_SDL_DINGUX
- OBJ += gfx/drivers/sdl_dingux_gfx.o \
- input/drivers/sdl_dingux_input.o \
+
+ ifeq ($(RS90), 1)
+ OBJ += gfx/drivers/sdl_rs90_gfx.o
+ else
+ OBJ += gfx/drivers/sdl_dingux_gfx.o
+ endif
+
+ OBJ += input/drivers/sdl_dingux_input.o \
input/drivers_joypad/sdl_dingux_joypad.o
DEF_FLAGS += $(SDL_DINGUX_CFLAGS)
LIBS += $(SDL_DINGUX_LIBS)
@@ -2296,9 +2302,9 @@ ifeq ($(HAVE_CRTSWITCHRES), 1)
$(DEPS_DIR)/switchres/resync_windows.o
endif
ifneq ($(findstring Linux,$(OS)),)
- OBJ += $(DEPS_DIR)/switchres/display_linux.o
+ OBJ += $(DEPS_DIR)/switchres/display_linux.o
ifeq ($(HAVE_X11)$(HAVE_XRANDR), 11)
- OBJ += $(DEPS_DIR)/switchres/custom_video_xrandr.o
+ OBJ += $(DEPS_DIR)/switchres/custom_video_xrandr.o
DEFINES += -DSR_WITH_XRANDR
endif
endif
@@ -2325,9 +2331,9 @@ ifeq ($(HAVE_COCOA_COMMON),1)
OBJ += input/drivers/cocoa_input.o \
ui/drivers/ui_cocoa.o \
ui/drivers/cocoa/cocoa_common.o
-
+
ifeq ($(HAVE_OPENGL), 1)
- DEFINES += -DGL_SILENCE_DEPRECATION
+ DEFINES += -DGL_SILENCE_DEPRECATION
OBJ += gfx/drivers_context/cocoa_gl_ctx.o
endif
ifeq ($(HAVE_VULKAN), 1)
@@ -2482,4 +2488,3 @@ ifeq ($(HAVE_ODROIDGO2), 1)
endif
##################################
-
diff --git a/Makefile.rs90 b/Makefile.rs90
new file mode 100644
index 0000000000..cfb26c41d1
--- /dev/null
+++ b/Makefile.rs90
@@ -0,0 +1,236 @@
+#########################
+## Toolchain variables ##
+#########################
+
+# Alpha toolchain
+TOOLCHAIN_DIR=/opt/rs90-toolchain
+
+# All toolchain-related variables may be
+# overridden via the command line
+ifdef GCW0_CC
+CC = $(GCW0_CC)
+else
+CC = $(TOOLCHAIN_DIR)/usr/bin/mipsel-rs90-linux-musl-gcc
+endif
+
+ifdef GCW0_CXX
+CXX = $(GCW0_CXX)
+else
+CXX = $(TOOLCHAIN_DIR)/usr/bin/mipsel-rs90-linux-musl-g++
+endif
+
+ifdef GCW0_STRIP
+STRIP = $(GCW0_STRIP)
+else
+STRIP = $(TOOLCHAIN_DIR)/usr/bin/mipsel-rs90-linux-musl-strip
+endif
+
+GCW0_SDL_CONFIG ?= $(TOOLCHAIN_DIR)/usr/mipsel-rs90-linux-musl/sysroot/usr/bin/sdl-config
+GCW0_FREETYPE_CONFIG ?= $(TOOLCHAIN_DIR)/usr/mipsel-rs90-linux-musl/sysroot/usr/bin/freetype-config
+GCW0_MK_SQUASH_FS ?= $(TOOLCHAIN_DIR)/usr/bin/mksquashfs
+
+GCW0_INC_DIR ?= $(TOOLCHAIN_DIR)/usr/mipsel-rs90-linux-musl/sysroot/usr/include
+GCW0_LIB_DIR ?= $(TOOLCHAIN_DIR)/usr/mipsel-rs90-linux-musl/sysroot/usr/lib
+
+#########################
+#########################
+
+PACKAGE_NAME = retroarch
+
+DEBUG ?= 0
+
+RS90 = 1
+DINGUX = 1
+DINGUX_BETA = 1
+HAVE_SCREENSHOTS = 0
+HAVE_REWIND = 1
+HAVE_7ZIP = 1
+HAVE_AL = 0
+# ALSA freezes when switching back from menu
+HAVE_ALSA = 1
+HAVE_DSP_FILTER = 1
+HAVE_VIDEO_FILTER = 1
+HAVE_STATIC_VIDEO_FILTERS = 1
+HAVE_STATIC_AUDIO_FILTERS = 1
+HAVE_FILTERS_BUILTIN = 1
+HAVE_BUILTINMBEDTLS = 0
+HAVE_BUILTINZLIB = 1
+HAVE_C99 = 1
+HAVE_CC = 1
+HAVE_CC_RESAMPLER = 1
+
+HAVE_CHD = 1
+HAVE_COMMAND = 0
+HAVE_CXX = 1
+HAVE_DR_MP3 = 1
+HAVE_DYNAMIC = 1
+HAVE_EGL = 0
+HAVE_FREETYPE = 0
+HAVE_GDI = 1
+HAVE_GETADDRINFO = 0
+HAVE_GETOPT_LONG = 1
+HAVE_GLSL = 0
+HAVE_HID = 1
+HAVE_IBXM = 1
+HAVE_IMAGEVIEWER = 1
+HAVE_LANGEXTRA = 0
+HAVE_LIBRETRODB = 1
+HAVE_MENU = 1
+HAVE_MENU_COMMON = 1
+HAVE_GFX_WIDGETS = 0
+HAVE_MMAP = 1
+HAVE_OPENDINGUX_FBDEV = 0
+HAVE_OPENGL = 0
+HAVE_OPENGL1 = 0
+HAVE_OPENGLES = 0
+HAVE_OPENGLES3 = 0
+HAVE_OPENGL_CORE = 0
+HAVE_OPENSSL = 1
+HAVE_OVERLAY = 0
+HAVE_RBMP = 1
+HAVE_RJPEG = 1
+HAVE_RPILED = 0
+HAVE_RPNG = 1
+HAVE_RUNAHEAD = 1
+HAVE_SDL_DINGUX = 1
+HAVE_SHADERPIPELINE = 0
+HAVE_STB_FONT = 0
+HAVE_STB_IMAGE = 1
+HAVE_STB_VORBIS = 1
+HAVE_STDIN_CMD = 0
+HAVE_STRCASESTR = 1
+HAVE_THREADS = 1
+HAVE_UDEV = 1
+HAVE_RGUI = 1
+HAVE_MATERIALUI = 0
+HAVE_XMB = 0
+HAVE_OZONE = 0
+HAVE_ZLIB = 1
+HAVE_CONFIGFILE = 1
+HAVE_PATCH = 1
+HAVE_CHEATS = 1
+HAVE_CHEEVOS = 0
+HAVE_LIBSHAKE = 0
+HAVE_TINYALSA = 1
+HAVE_NEAREST_RESAMPLER = 1
+
+OS = Linux
+TARGET = retroarch
+OPK_NAME = retroarch_rs90_odbeta.opk
+
+OBJ :=
+LINK := $(CXX)
+DEF_FLAGS := -mplt -mno-shared
+DEF_FLAGS += -ffunction-sections -fdata-sections
+DEF_FLAGS += -I. -Ideps -Ideps/stb -DRS90=1 -DDINGUX=1 -DDINGUX_BETA=1 -MMD
+DEF_FLAGS += -Wall -Wno-unused-variable
+DEF_FLAGS += -std=gnu99 -D_GNU_SOURopendinguxCE -flto -lasound
+LIBS := -ldl -lz -lrt -ludev -pthread
+CFLAGS :=
+CXXFLAGS := -fno-exceptions -fno-rtti -std=c++11 -D__STDC_CONSTANT_MACROS
+ASFLAGS :=
+LDFLAGS := -Wl,--gc-sections
+INCLUDE_DIRS = -I$(GCW0_INC_DIR)
+LIBRARY_DIRS = -L$(GCW0_LIB_DIR)
+DEFINES := -DRARCH_INTERNAL -D_FILE_OFFSET_BITS=64 -UHAVE_STATIC_DUMMY
+DEFINES += -DHAVE_C99=1 -DHAVE_CXX=1
+DEFINES += -DHAVE_GETOPT_LONG=1 -DHAVE_STRCASESTR=1 -DHAVE_DYNAMIC=1
+DEFINES += -DHAVE_FILTERS_BUILTIN
+DEFINES += -DHAVE_UDEV=1
+DEFINES += -DHAVE_ALSA
+DEFINES += -DCC_RESAMPLER_PRECISION=0
+
+SDL_DINGUX_CFLAGS := $(shell $(GCW0_SDL_CONFIG) --cflags)
+SDL_DINGUX_LIBS := $(shell $(GCW0_SDL_CONFIG) --libs)
+FREETYPE_CFLAGS := $(shell $(GCW0_FREETYPE_CONFIG) --cflags)
+FREETYPE_LIBS := $(shell $(GCW0_FREETYPE_CONFIG) --libs)
+# AL_LIBS := -lopenal
+MMAP_LIBS = -lc
+
+OBJDIR_BASE := obj-unix
+
+ifeq ($(DEBUG), 1)
+ OBJDIR := $(OBJDIR_BASE)/debug
+ DEF_FLAGS += -O0 -g -DDEBUG -D_DEBUG
+else
+ OBJDIR := $(OBJDIR_BASE)/release
+ DEF_FLAGS += -Ofast -DNDEBUG
+endif
+
+include Makefile.common
+
+DEF_FLAGS += $(INCLUDE_DIRS)
+LDFLAGS += $(CFLAGS) $(CXXFLAGS) $(DEF_FLAGS)
+CFLAGS += $(DEF_FLAGS)
+CXXFLAGS += $(DEF_FLAGS)
+
+HEADERS = $(wildcard */*/*.h) $(wildcard */*.h) $(wildcard *.h)
+
+Q := @
+
+RARCH_OBJ := $(addprefix $(OBJDIR)/,$(OBJ))
+
+define DESKTOP_ENTRY
+[Desktop Entry]
+Name=RetroArch
+Comment=Frontend for emulators, game engines
+Exec=retroarch
+Terminal=false
+Type=Application
+StartupNotify=true
+Icon=retroarch
+Categories=emulators;
+X-OD-NeedsDownscaling=true
+endef
+export DESKTOP_ENTRY
+
+all: $(TARGET) opk
+
+-include $(RARCH_OBJ:.o=.d)
+
+SYMBOL_MAP := -Wl,-Map=output.map
+
+$(TARGET): $(RARCH_OBJ)
+ @$(if $(Q), $(shell echo echo LD $@),)
+ $(Q)$(LINK) -o $@ $(RARCH_OBJ) $(LIBS) $(LDFLAGS) $(LIBRARY_DIRS)
+
+$(OBJDIR)/%.o: %.c
+ @mkdir -p $(dir $@)
+ @$(if $(Q), $(shell echo echo CC $<),)
+ $(Q)$(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c -o $@ $<
+
+$(OBJDIR)/%.o: %.cpp
+ @mkdir -p $(dir $@)
+ @$(if $(Q), $(shell echo echo CXX $<),)
+ $(Q)$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES) -MMD -c -o $@ $<
+
+$(OBJDIR)/%.o: %.m
+ @mkdir -p $(dir $@)
+ @$(if $(Q), $(shell echo echo OBJC $<),)
+ $(Q)$(CXX) $(OBJCFLAGS) $(DEFINES) -MMD -c -o $@ $<
+
+$(OBJDIR)/%.o: %.S $(HEADERS)
+ @mkdir -p $(dir $@)
+ @$(if $(Q), $(shell echo echo AS $<),)
+ $(Q)$(CC) $(CFLAGS) $(ASFLAGS) $(DEFINES) -c -o $@ $<
+
+clean:
+ rm -rf $(OBJDIR_BASE)
+ rm -f $(TARGET)
+ rm -f *.d
+ rm -rf $(OPK_NAME)
+
+opk: $(TARGET)
+ echo "$$DESKTOP_ENTRY" > default.rs90.desktop
+ rm -f $(OPK_NAME)
+ cp media/ico_src/icon32.png retroarch.png
+ifeq ($STRIP_BIN, 1)
+ $(STRIP) --strip-unneeded retroarch
+endif
+ $(GCW0_MK_SQUASH_FS) retroarch default.rs90.desktop retroarch.png $(OPK_NAME) -all-root -no-xattrs -noappend -no-exports
+ rm -f default.rs90.desktop retroarch.png
+
+.PHONY: all clean opk
+
+print-%:
+ @echo '$*=$($*)'
diff --git a/config.def.h b/config.def.h
index 0d6d7a8983..45c99427d1 100644
--- a/config.def.h
+++ b/config.def.h
@@ -739,7 +739,9 @@ static const bool default_savefiles_in_content_dir = false;
static const bool default_systemfiles_in_content_dir = false;
static const bool default_screenshots_in_content_dir = false;
-#if defined(_XBOX1) || defined(__PS3__) || defined(_XBOX360) || defined(DINGUX)
+#if defined(RS90)
+#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_START_SELECT
+#elif defined(_XBOX1) || defined(__PS3__) || defined(_XBOX360) || defined(DINGUX)
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_L3_R3
#elif defined(PS2) || defined(PSP)
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_HOLD_START
diff --git a/configuration.c b/configuration.c
index de23095dbc..f7f99b7b9f 100644
--- a/configuration.c
+++ b/configuration.c
@@ -70,6 +70,7 @@ enum video_driver_enum
VIDEO_SDL,
VIDEO_SDL2,
VIDEO_SDL_DINGUX,
+ VIDEO_SDL_RS90,
VIDEO_EXT,
VIDEO_WII,
VIDEO_WIIU,
@@ -311,7 +312,11 @@ static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL;
#elif defined(HAVE_SDL2)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL2;
#elif defined(HAVE_SDL_DINGUX)
+#if defined(RS90)
+static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL_RS90;
+#else
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL_DINGUX;
+#endif
#elif defined(_WIN32) && !defined(_XBOX)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GDI;
#elif defined(DJGPP)
@@ -388,7 +393,9 @@ static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_EXT;
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_NULL;
#endif
-#if defined(PSP) || defined(EMSCRIPTEN)
+#if defined(RS90)
+static const enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_NEAREST;
+#elif defined(PSP) || defined(EMSCRIPTEN)
static const enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_CC;
#else
static const enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_SINC;
@@ -852,6 +859,8 @@ const char *config_get_default_video(void)
return "xvideo";
case VIDEO_SDL_DINGUX:
return "sdl_dingux";
+ case VIDEO_SDL_RS90:
+ return "sdl_rs90";
case VIDEO_SDL:
return "sdl";
case VIDEO_SDL2:
diff --git a/gfx/drivers/sdl_dingux_gfx.c b/gfx/drivers/sdl_dingux_gfx.c
index 865c16f478..ae49b0d347 100644
--- a/gfx/drivers/sdl_dingux_gfx.c
+++ b/gfx/drivers/sdl_dingux_gfx.c
@@ -2,6 +2,7 @@
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2011-2017 - Higor Euripedes
+ * Copyright (C) 2019-2021 - James Leaver
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
diff --git a/gfx/drivers/sdl_rs90_gfx.c b/gfx/drivers/sdl_rs90_gfx.c
new file mode 100644
index 0000000000..77246a7e5f
--- /dev/null
+++ b/gfx/drivers/sdl_rs90_gfx.c
@@ -0,0 +1,1187 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2017 - Daniel De Matteis
+ * Copyright (C) 2011-2017 - Higor Euripedes
+ * Copyright (C) 2019-2021 - James Leaver
+ * Copyright (C) 2021 - John Parton
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef HAVE_CONFIG_H
+#include "../../config.h"
+#endif
+
+#ifdef HAVE_MENU
+#include "../../menu/menu_driver.h"
+#endif
+
+#include "../../dingux/dingux_utils.h"
+
+#include "../../verbosity.h"
+#include "../../gfx/drivers_font_renderer/bitmap.h"
+#include "../../configuration.h"
+#include "../../retroarch.h"
+#if defined(DINGUX_BETA)
+#include "../../driver.h"
+#endif
+
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
+#define SDL_RS90_WIDTH 240
+#define SDL_RS90_HEIGHT 160
+
+#define SDL_RS90_NUM_FONT_GLYPHS 256
+
+typedef struct sdl_rs90_video
+{
+ retro_time_t last_frame_time;
+ retro_time_t ff_frame_time_min;
+ SDL_Surface *screen;
+ bitmapfont_lut_t *osd_font;
+ /* Scaling/padding/cropping parameters */
+ unsigned content_width;
+ unsigned content_height;
+ unsigned frame_width;
+ unsigned frame_height;
+ unsigned frame_padding_x;
+ unsigned frame_padding_y;
+ unsigned frame_crop_x;
+ unsigned frame_crop_y;
+#if defined(DINGUX_BETA)
+ enum dingux_refresh_rate refresh_rate;
+#endif
+ uint32_t font_colour32;
+ uint16_t font_colour16;
+ uint16_t menu_texture[SDL_RS90_WIDTH * SDL_RS90_HEIGHT];
+ bool rgb32;
+ bool vsync;
+ bool keep_aspect;
+ bool scale_integer;
+ bool menu_active;
+ bool was_in_menu;
+ bool quitting;
+ bool mode_valid;
+} sdl_rs90_video_t;
+
+static void sdl_rs90_init_font_color(sdl_rs90_video_t *vid)
+{
+ settings_t *settings = config_get_ptr();
+ uint32_t red = 0xFF;
+ uint32_t green = 0xFF;
+ uint32_t blue = 0xFF;
+
+ if (settings)
+ {
+ red = (uint32_t)((settings->floats.video_msg_color_r * 255.0f) + 0.5f) & 0xFF;
+ green = (uint32_t)((settings->floats.video_msg_color_g * 255.0f) + 0.5f) & 0xFF;
+ blue = (uint32_t)((settings->floats.video_msg_color_b * 255.0f) + 0.5f) & 0xFF;
+ }
+
+ /* Convert to XRGB8888 */
+ vid->font_colour32 = (red << 16) | (green << 8) | blue;
+
+ /* Convert to RGB565 */
+ red = red >> 3;
+ green = green >> 3;
+ blue = blue >> 3;
+
+ vid->font_colour16 = (red << 11) | (green << 6) | blue;
+}
+
+static void sdl_rs90_blit_text16(
+ sdl_rs90_video_t *vid,
+ unsigned x, unsigned y,
+ const char *str)
+{
+ /* Note: Cannot draw text in padding region
+ * (padding region is never cleared, so
+ * any text pixels would remain as garbage) */
+ uint16_t *screen_buf = (uint16_t*)vid->screen->pixels;
+ bool **font_lut = vid->osd_font->lut;
+ /* 16 bit - divide pitch by 2 */
+ uint16_t screen_stride = (uint16_t)(vid->screen->pitch >> 1);
+ uint16_t screen_width = vid->frame_width;
+ uint16_t screen_height = vid->frame_height;
+ unsigned x_pos = x + vid->frame_padding_x;
+ unsigned y_pos = (y > (screen_height >> 1)) ?
+ (y - vid->frame_padding_y) : (y + vid->frame_padding_y);
+ uint16_t shadow_color_buf[2] = {0};
+ uint16_t color_buf[2];
+
+ color_buf[0] = vid->font_colour16;
+ color_buf[1] = 0;
+
+ /* Check for out of bounds y coordinates */
+ if (y_pos + FONT_HEIGHT + 1 >=
+ screen_height - vid->frame_padding_y)
+ return;
+
+ while (!string_is_empty(str))
+ {
+ /* Check for out of bounds x coordinates */
+ if (x_pos + FONT_WIDTH_STRIDE + 1 >=
+ screen_width - vid->frame_padding_x)
+ return;
+
+ /* Deal with spaces first, for efficiency */
+ if (*str == ' ')
+ str++;
+ else
+ {
+ uint16_t i, j;
+ bool *symbol_lut;
+ uint32_t symbol = utf8_walk(&str);
+
+ /* Stupid hack: 'oe' ligatures are not really
+ * standard extended ASCII, so we have to waste
+ * CPU cycles performing a conversion from the
+ * unicode values... */
+ if (symbol == 339) /* Latin small ligature oe */
+ symbol = 156;
+ if (symbol == 338) /* Latin capital ligature oe */
+ symbol = 140;
+
+ if (symbol >= SDL_RS90_NUM_FONT_GLYPHS)
+ continue;
+
+ symbol_lut = font_lut[symbol];
+
+ for (j = 0; j < FONT_HEIGHT; j++)
+ {
+ uint32_t buff_offset = ((y_pos + j) * screen_stride) + x_pos;
+
+ for (i = 0; i < FONT_WIDTH; i++)
+ {
+ if (*(symbol_lut + i + (j * FONT_WIDTH)))
+ {
+ uint16_t *screen_buf_ptr = screen_buf + buff_offset + i;
+
+ /* Text pixel + right shadow */
+ memcpy(screen_buf_ptr, color_buf, sizeof(uint16_t));
+
+ /* Bottom shadow */
+ screen_buf_ptr += screen_stride;
+ memcpy(screen_buf_ptr, shadow_color_buf, sizeof(uint16_t));
+ }
+ }
+ }
+ }
+
+ x_pos += FONT_WIDTH_STRIDE;
+ }
+}
+
+static void sdl_rs90_blit_text32(
+ sdl_rs90_video_t *vid,
+ unsigned x, unsigned y,
+ const char *str)
+{
+ /* Note: Cannot draw text in padding region
+ * (padding region is never cleared, so
+ * any text pixels would remain as garbage) */
+ uint32_t *screen_buf = (uint32_t*)vid->screen->pixels;
+ bool **font_lut = vid->osd_font->lut;
+ /* 32 bit - divide pitch by 4 */
+ uint32_t screen_stride = (uint32_t)(vid->screen->pitch >> 2);
+ uint32_t screen_width = vid->screen->w;
+ uint32_t screen_height = vid->screen->h;
+ unsigned x_pos = x + vid->frame_padding_x;
+ unsigned y_pos = (y > (screen_height >> 1)) ?
+ (y - vid->frame_padding_y) : (y + vid->frame_padding_y);
+ uint32_t shadow_color_buf[2] = {0};
+ uint32_t color_buf[2];
+
+ color_buf[0] = vid->font_colour32;
+ color_buf[1] = 0;
+
+ /* Check for out of bounds y coordinates */
+ if (y_pos + FONT_HEIGHT + 1 >=
+ screen_height - vid->frame_padding_y)
+ return;
+
+ while (!string_is_empty(str))
+ {
+ /* Check for out of bounds x coordinates */
+ if (x_pos + FONT_WIDTH_STRIDE + 1 >=
+ screen_width - vid->frame_padding_x)
+ return;
+
+ /* Deal with spaces first, for efficiency */
+ if (*str == ' ')
+ str++;
+ else
+ {
+ uint32_t i, j;
+ bool *symbol_lut;
+ uint32_t symbol = utf8_walk(&str);
+
+ /* Stupid hack: 'oe' ligatures are not really
+ * standard extended ASCII, so we have to waste
+ * CPU cycles performing a conversion from the
+ * unicode values... */
+ if (symbol == 339) /* Latin small ligature oe */
+ symbol = 156;
+ if (symbol == 338) /* Latin capital ligature oe */
+ symbol = 140;
+
+ if (symbol >= SDL_RS90_NUM_FONT_GLYPHS)
+ continue;
+
+ symbol_lut = font_lut[symbol];
+
+ for (j = 0; j < FONT_HEIGHT; j++)
+ {
+ uint32_t buff_offset = ((y_pos + j) * screen_stride) + x_pos;
+
+ for (i = 0; i < FONT_WIDTH; i++)
+ {
+ if (*(symbol_lut + i + (j * FONT_WIDTH)))
+ {
+ uint32_t *screen_buf_ptr = screen_buf + buff_offset + i;
+
+ /* Text pixel + right shadow */
+ memcpy(screen_buf_ptr, color_buf, sizeof(uint32_t));
+
+ /* Bottom shadow */
+ screen_buf_ptr += screen_stride;
+ memcpy(screen_buf_ptr, shadow_color_buf, sizeof(uint32_t));
+ }
+ }
+ }
+ }
+
+ x_pos += FONT_WIDTH_STRIDE;
+ }
+}
+
+static void sdl_rs90_blit_video_mode_error_msg(sdl_rs90_video_t *vid)
+{
+ const char *error_msg = msg_hash_to_str(MSG_UNSUPPORTED_VIDEO_MODE);
+ char display_mode[64];
+
+ display_mode[0] = '\0';
+
+ /* Zero out pixel buffer */
+ memset(vid->screen->pixels, 0,
+ vid->screen->pitch * vid->screen->h);
+
+ /* Generate display mode string */
+ snprintf(display_mode, sizeof(display_mode), "> %ux%u, %s",
+ vid->frame_width, vid->frame_height,
+ vid->rgb32 ? "XRGB8888" : "RGB565");
+
+ /* Print error message */
+ if (vid->rgb32)
+ {
+ sdl_rs90_blit_text32(vid,
+ FONT_WIDTH_STRIDE, FONT_WIDTH_STRIDE,
+ error_msg);
+
+ sdl_rs90_blit_text32(vid,
+ FONT_WIDTH_STRIDE, FONT_WIDTH_STRIDE + FONT_HEIGHT_STRIDE,
+ display_mode);
+ }
+ else
+ {
+ sdl_rs90_blit_text16(vid,
+ FONT_WIDTH_STRIDE, FONT_WIDTH_STRIDE,
+ error_msg);
+
+ sdl_rs90_blit_text16(vid,
+ FONT_WIDTH_STRIDE, FONT_WIDTH_STRIDE + FONT_HEIGHT_STRIDE,
+ display_mode);
+ }
+}
+
+static void sdl_rs90_gfx_free(void *data)
+{
+ sdl_rs90_video_t *vid = (sdl_rs90_video_t*)data;
+
+ if (!vid)
+ return;
+
+ if (vid->osd_font)
+ bitmapfont_free_lut(vid->osd_font);
+
+ free(vid);
+}
+
+static void sdl_rs90_input_driver_init(
+ const char *input_driver_name, const char *joypad_driver_name,
+ input_driver_t **input, void **input_data)
+{
+ /* Sanity check */
+ if (!input || !input_data)
+ return;
+
+ *input = NULL;
+ *input_data = NULL;
+
+ /* If input driver name is empty, cannot
+ * initialise anything... */
+ if (string_is_empty(input_driver_name))
+ return;
+
+ if (string_is_equal(input_driver_name, "sdl_dingux"))
+ {
+ *input_data = input_driver_init_wrap(&input_sdl_dingux,
+ joypad_driver_name);
+
+ if (*input_data)
+ *input = &input_sdl_dingux;
+
+ return;
+ }
+
+#if defined(HAVE_SDL) || defined(HAVE_SDL2)
+ if (string_is_equal(input_driver_name, "sdl"))
+ {
+ *input_data = input_driver_init_wrap(&input_sdl,
+ joypad_driver_name);
+
+ if (*input_data)
+ *input = &input_sdl;
+
+ return;
+ }
+#endif
+
+#if defined(HAVE_UDEV)
+ if (string_is_equal(input_driver_name, "udev"))
+ {
+ *input_data = input_driver_init_wrap(&input_udev,
+ joypad_driver_name);
+
+ if (*input_data)
+ *input = &input_udev;
+
+ return;
+ }
+#endif
+
+#if defined(__linux__)
+ if (string_is_equal(input_driver_name, "linuxraw"))
+ {
+ *input_data = input_driver_init_wrap(&input_linuxraw,
+ joypad_driver_name);
+
+ if (*input_data)
+ *input = &input_linuxraw;
+
+ return;
+ }
+#endif
+}
+
+static void *sdl_rs90_gfx_init(const video_info_t *video,
+ input_driver_t **input, void **input_data)
+{
+ sdl_rs90_video_t *vid = NULL;
+ uint32_t sdl_subsystem_flags = SDL_WasInit(0);
+ settings_t *settings = config_get_ptr();
+#if defined(DINGUX_BETA)
+ enum dingux_refresh_rate current_refresh_rate = DINGUX_REFRESH_RATE_60HZ;
+ enum dingux_refresh_rate target_refresh_rate = (enum dingux_refresh_rate)
+ settings->uints.video_dingux_refresh_rate;
+ bool refresh_rate_valid = false;
+ float hw_refresh_rate = 0.0f;
+#endif
+ const char *input_driver_name = settings->arrays.input_driver;
+ const char *joypad_driver_name = settings->arrays.input_joypad_driver;
+ uint32_t surface_flags = (video->vsync) ?
+ (SDL_HWSURFACE | SDL_TRIPLEBUF | SDL_FULLSCREEN) :
+ (SDL_HWSURFACE | SDL_FULLSCREEN);
+
+ /* Initialise graphics subsystem, if required */
+ if (sdl_subsystem_flags == 0)
+ {
+ if (SDL_Init(SDL_INIT_VIDEO) < 0)
+ return NULL;
+ }
+ else if ((sdl_subsystem_flags & SDL_INIT_VIDEO) == 0)
+ {
+ if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
+ return NULL;
+ }
+
+ vid = (sdl_rs90_video_t*)calloc(1, sizeof(*vid));
+ if (!vid)
+ return NULL;
+
+#if defined(DINGUX_BETA)
+ /* Get current refresh rate */
+ refresh_rate_valid = dingux_get_video_refresh_rate(¤t_refresh_rate);
+
+ /* Check if refresh rate needs to be updated */
+ if (!refresh_rate_valid ||
+ (current_refresh_rate != target_refresh_rate))
+ hw_refresh_rate = dingux_set_video_refresh_rate(target_refresh_rate);
+ else
+ {
+ /* Correct refresh rate is already set,
+ * just convert to float */
+ switch (current_refresh_rate)
+ {
+ case DINGUX_REFRESH_RATE_50HZ:
+ hw_refresh_rate = 50.0f;
+ break;
+ default:
+ hw_refresh_rate = 60.0f;
+ break;
+ }
+ }
+
+ if (hw_refresh_rate == 0.0f)
+ {
+ RARCH_ERR("[SDL1]: Failed to set video refresh rate\n");
+ goto error;
+ }
+
+ vid->refresh_rate = target_refresh_rate;
+ switch (target_refresh_rate)
+ {
+ case DINGUX_REFRESH_RATE_50HZ:
+ vid->ff_frame_time_min = 20000;
+ break;
+ default:
+ vid->ff_frame_time_min = 16667;
+ break;
+ }
+
+ driver_ctl(RARCH_DRIVER_CTL_SET_REFRESH_RATE, &hw_refresh_rate);
+#else
+ vid->ff_frame_time_min = 16667;
+#endif
+
+ vid->screen = SDL_SetVideoMode(
+ SDL_RS90_WIDTH, SDL_RS90_HEIGHT,
+ video->rgb32 ? 32 : 16,
+ surface_flags);
+
+ if (!vid->screen)
+ {
+ RARCH_ERR("[SDL1]: Failed to init SDL surface: %s\n", SDL_GetError());
+ goto error;
+ }
+
+ vid->content_width = SDL_RS90_WIDTH;
+ vid->content_height = SDL_RS90_HEIGHT;
+ vid->frame_width = SDL_RS90_WIDTH;
+ vid->frame_height = SDL_RS90_HEIGHT;
+ vid->rgb32 = video->rgb32;
+ vid->vsync = video->vsync;
+ vid->keep_aspect = settings->bools.video_dingux_ipu_keep_aspect;
+ vid->scale_integer = settings->bools.video_scale_integer;
+ vid->menu_active = false;
+ vid->was_in_menu = false;
+ vid->quitting = false;
+ vid->mode_valid = true;
+ vid->last_frame_time = 0;
+
+ SDL_ShowCursor(SDL_DISABLE);
+
+ sdl_rs90_input_driver_init(input_driver_name,
+ joypad_driver_name, input, input_data);
+
+ /* Initialise OSD font */
+ sdl_rs90_init_font_color(vid);
+
+ vid->osd_font = bitmapfont_get_lut();
+
+ if (!vid->osd_font ||
+ vid->osd_font->glyph_max <
+ (SDL_RS90_NUM_FONT_GLYPHS - 1))
+ {
+ RARCH_ERR("[SDL1]: Failed to init OSD font\n");
+ goto error;
+ }
+
+ return vid;
+
+error:
+ sdl_rs90_gfx_free(vid);
+ return NULL;
+}
+
+static void sdl_rs90_set_output(
+ sdl_rs90_video_t* vid,
+ unsigned width, unsigned height, bool rgb32)
+{
+ uint32_t surface_flags = (vid->vsync) ?
+ (SDL_HWSURFACE | SDL_TRIPLEBUF | SDL_FULLSCREEN) :
+ (SDL_HWSURFACE | SDL_FULLSCREEN);
+
+ vid->content_width = width;
+ vid->content_height = height;
+
+ /* Technically, "scale_integer" here just means "do not scale"
+ * If the content is larger, we crop, otherwise we just centre
+ * it in the frame.
+ * If we want to support a core with an absolutely tiny screen
+ * (i.e. less than 120x80), we should do actual integer scaling
+ * (PokeMini @ 96x64 and VeMUlator @ 48x32 are probably the
+ * only cores where this is an issue, but PokeMini at least
+ * offers internal upscaling...) */
+ if (vid->scale_integer)
+ {
+ if (width > SDL_RS90_WIDTH)
+ {
+ vid->frame_width = SDL_RS90_WIDTH;
+ vid->frame_crop_x = (width - SDL_RS90_WIDTH) >> 1;
+ vid->frame_padding_x = 0;
+ }
+ else
+ {
+ vid->frame_width = width;
+ vid->frame_crop_x = 0;
+ vid->frame_padding_x = (SDL_RS90_WIDTH - width) >> 1;
+ }
+
+ if (height > SDL_RS90_HEIGHT)
+ {
+ vid->frame_height = SDL_RS90_HEIGHT;
+ vid->frame_crop_y = (height - SDL_RS90_HEIGHT) >> 1;
+ vid->frame_padding_y = 0;
+ }
+ else
+ {
+ vid->frame_height = height;
+ vid->frame_crop_y = 0;
+ vid->frame_padding_y = (SDL_RS90_HEIGHT - height) >> 1;
+ }
+ }
+ else
+ {
+ /* Normal scaling */
+ if (vid->keep_aspect)
+ {
+ if (height * SDL_RS90_WIDTH > width * SDL_RS90_HEIGHT)
+ {
+ /* Integer math is fine */
+ vid->frame_width = (width * SDL_RS90_HEIGHT) / height;
+ vid->frame_height = SDL_RS90_HEIGHT;
+ }
+ else
+ {
+ /* Integer math is fine */
+ vid->frame_width = SDL_RS90_WIDTH;
+ vid->frame_height = (height * SDL_RS90_WIDTH) / width;
+ }
+ }
+ else
+ {
+ vid->frame_width = SDL_RS90_WIDTH;
+ vid->frame_height = SDL_RS90_HEIGHT;
+ }
+
+ vid->frame_crop_x = 0;
+ vid->frame_padding_x = (SDL_RS90_WIDTH - vid->frame_width) >> 1;
+ vid->frame_crop_y = 0;
+ vid->frame_padding_y = (SDL_RS90_HEIGHT - vid->frame_height) >> 1;
+ }
+
+ /* Attempt to change video mode */
+ vid->screen = SDL_SetVideoMode(
+ SDL_RS90_WIDTH, SDL_RS90_HEIGHT,
+ rgb32 ? 32 : 16,
+ surface_flags);
+
+ /* Check whether selected display mode is valid */
+ if (unlikely(!vid->screen))
+ {
+ RARCH_ERR("[SDL1]: Failed to init SDL surface: %s\n", SDL_GetError());
+ vid->mode_valid = false;
+ }
+ else
+ {
+ /* Determine whether frame padding is required */
+ if ((vid->frame_padding_x > 0) ||
+ (vid->frame_padding_y > 0))
+ {
+ /* To prevent garbage pixels in the padding
+ * region, must zero out pixel buffer */
+ if (SDL_MUSTLOCK(vid->screen))
+ SDL_LockSurface(vid->screen);
+
+ memset(vid->screen->pixels, 0,
+ vid->screen->pitch * vid->screen->h);
+
+ if (SDL_MUSTLOCK(vid->screen))
+ SDL_UnlockSurface(vid->screen);
+ }
+
+ vid->mode_valid = true;
+ }
+}
+
+/* Approximate nearest-neighbour scaling using
+ * bitshifts and integer math */
+static void sdl_rs90_blit_frame16_scale(sdl_rs90_video_t *vid,
+ uint16_t* src, unsigned width, unsigned height,
+ unsigned src_pitch)
+{
+ uint32_t x_step = (((uint32_t)(width) << 16) + 1) / vid->frame_width;
+ uint32_t y_step = (((uint32_t)(height) << 16) + 1) / vid->frame_height;
+
+ /* 16 bit - divide pitch by 2 */
+ size_t in_stride = (size_t)(src_pitch >> 1);
+ size_t out_stride = (size_t)(vid->screen->pitch >> 1);
+
+ /* Apply x/y padding offset */
+ uint16_t *top_corner = (uint16_t*)(vid->screen->pixels) + vid->frame_padding_x +
+ out_stride * vid->frame_padding_y;
+
+ /* Temporary pointers */
+ uint16_t *in_ptr = NULL;
+ uint16_t *out_ptr = NULL;
+
+ uint32_t y = 0;
+ size_t row;
+
+ /* TODO/FIXME: Optimize these loops further.
+ * Consider saving these computations in an array
+ * and indexing over them.
+ * Would likely be slower due to cache (non-)locality,
+ * but it's worth a shot.
+ * Tons of -> operations. */
+ for (row = 0; row < vid->frame_height; row++)
+ {
+ size_t col = vid->frame_width;
+ uint32_t x = 0;
+
+ out_ptr = top_corner + out_stride * row;
+ in_ptr = src + (y >> 16) * in_stride;
+
+ do
+ {
+ *out_ptr = in_ptr[x >> 16];
+ x += x_step;
+ out_ptr++;
+ }
+ while (--col);
+
+ y += y_step;
+ }
+}
+
+static void sdl_rs90_blit_frame16_no_scale(sdl_rs90_video_t *vid,
+ uint16_t* src, unsigned width, unsigned height,
+ unsigned src_pitch)
+{
+ /* 16 bit - divide pitch by 2 */
+ size_t in_stride = (size_t)(src_pitch >> 1);
+ size_t out_stride = (size_t)(vid->screen->pitch >> 1);
+
+ /* Manipulate offsets so that padding/crop
+ * are applied correctly */
+ uint16_t *in_ptr = src + vid->frame_crop_x + vid->frame_crop_y * in_stride;
+ uint16_t *out_ptr = (uint16_t*)(vid->screen->pixels) + vid->frame_padding_x +
+ out_stride * vid->frame_padding_y;
+
+ size_t y = vid->frame_height;
+
+ /* TODO/FIXME: Optimize this loop */
+ do
+ {
+ memcpy(out_ptr, in_ptr, vid->frame_width * sizeof(uint16_t));
+ in_ptr += in_stride;
+ out_ptr += out_stride;
+ }
+ while (--y);
+}
+
+static void sdl_rs90_blit_frame16(sdl_rs90_video_t *vid,
+ uint16_t* src, unsigned width, unsigned height,
+ unsigned src_pitch)
+{
+ /* If source and destination buffers have the
+ * same pitch, perform fast copy of raw pixel data */
+ /* TODO/FIXME: Make sure this code path is used for
+ * GBA content */
+ if (src_pitch == vid->screen->pitch &&
+ height == SDL_RS90_HEIGHT)
+ memcpy(vid->screen->pixels, src, src_pitch * SDL_RS90_HEIGHT);
+ else
+ {
+ if (vid->scale_integer)
+ sdl_rs90_blit_frame16_no_scale(
+ vid, src, width, height, src_pitch);
+ else
+ sdl_rs90_blit_frame16_scale(
+ vid, src, width, height, src_pitch);
+ }
+}
+
+static void sdl_rs90_blit_frame32_scale(sdl_rs90_video_t *vid,
+ uint32_t* src, unsigned width, unsigned height,
+ unsigned src_pitch)
+{
+ uint32_t x_step = (((uint32_t)(width) << 16) + 1) / vid->frame_width;
+ uint32_t y_step = (((uint32_t)(height) << 16) + 1) / vid->frame_height;
+
+ /* 32 bit - divide pitch by 4 */
+ size_t in_stride = (size_t)(src_pitch >> 2);
+ size_t out_stride = (size_t)(vid->screen->pitch >> 2);
+
+ /* Apply x/y padding offset */
+ uint32_t *top_corner = (uint32_t*)(vid->screen->pixels) + vid->frame_padding_x +
+ out_stride * vid->frame_padding_y;
+
+ /* Temporary pointers */
+ uint32_t *in_ptr = NULL;
+ uint32_t *out_ptr = NULL;
+
+ uint32_t y = 0;
+ size_t row;
+
+ /* TODO/FIXME: Optimize these loops further.
+ * Consider saving these computations in an array
+ * and indexing over them.
+ * Would likely be slower due to cache (non-)locality,
+ * but it's worth a shot.
+ * Tons of -> operations. */
+ for (row = 0; row < vid->frame_height; row++)
+ {
+ size_t col = vid->frame_width;
+ uint32_t x = 0;
+
+ out_ptr = top_corner + out_stride * row;
+ in_ptr = src + (y >> 16) * in_stride;
+
+ do
+ {
+ *out_ptr = in_ptr[x >> 16];
+ x += x_step;
+ out_ptr++;
+ }
+ while (--col);
+
+ y += y_step;
+ }
+}
+
+static void sdl_rs90_blit_frame32_no_scale(sdl_rs90_video_t *vid,
+ uint32_t* src, unsigned width, unsigned height,
+ unsigned src_pitch)
+{
+ /* 32 bit - divide pitch by 4 */
+ size_t in_stride = (size_t)(src_pitch >> 2);
+ size_t out_stride = (size_t)(vid->screen->pitch >> 2);
+
+ /* Manipulate offsets so that padding/crop
+ * are applied correctly */
+ uint32_t *in_ptr = src + vid->frame_crop_x + vid->frame_crop_y * in_stride;
+ uint32_t *out_ptr = (uint32_t*)(vid->screen->pixels) + vid->frame_padding_x +
+ out_stride * vid->frame_padding_y;
+
+ size_t y = vid->frame_height;
+
+ /* TODO/FIXME: Optimize this loop */
+ do
+ {
+ memcpy(out_ptr, in_ptr, vid->frame_width * sizeof(uint32_t));
+ in_ptr += in_stride;
+ out_ptr += out_stride;
+ }
+ while (--y);
+}
+
+static void sdl_rs90_blit_frame32(sdl_rs90_video_t *vid,
+ uint32_t* src, unsigned width, unsigned height,
+ unsigned src_pitch)
+{
+ /* If source and destination buffers have the
+ * same pitch, perform fast copy of raw pixel data */
+ /* TODO/FIXME: Make sure this code path is used for
+ * GBA content */
+ if ((src_pitch == vid->screen->pitch) &&
+ (height == SDL_RS90_HEIGHT))
+ memcpy(vid->screen->pixels, src, src_pitch * SDL_RS90_HEIGHT);
+ else
+ {
+ if (vid->scale_integer)
+ sdl_rs90_blit_frame32_no_scale(
+ vid, src, width, height, src_pitch);
+ else
+ sdl_rs90_blit_frame32_scale(
+ vid, src, width, height, src_pitch);
+ }
+}
+
+static bool sdl_rs90_gfx_frame(void *data, const void *frame,
+ unsigned width, unsigned height, uint64_t frame_count,
+ unsigned pitch, const char *msg, video_frame_info_t *video_info)
+{
+ sdl_rs90_video_t* vid = (sdl_rs90_video_t*)data;
+
+ /* Return early if:
+ * - Input sdl_rs90_video_t struct is NULL
+ * (cannot realistically happen)
+ * - Menu is inactive and input 'content' frame
+ * data is NULL (may happen when e.g. a running
+ * core skips a frame) */
+ if (unlikely(!vid || (!frame && !vid->menu_active)))
+ return true;
+
+ /* If fast forward is currently active, we may
+ * push frames at an 'unlimited' rate. Since the
+ * display has a fixed refresh rate of 60 Hz (or
+ * potentially 50 Hz on OpenDingux Beta), this
+ * represents wasted effort. We therefore drop any
+ * 'excess' frames in this case.
+ * (Note that we *only* do this when fast forwarding.
+ * Attempting this trick while running content normally
+ * will cause bad frame pacing) */
+ if (unlikely(video_info->input_driver_nonblock_state))
+ {
+ retro_time_t current_time = cpu_features_get_time_usec();
+
+ if ((current_time - vid->last_frame_time) <
+ vid->ff_frame_time_min)
+ return true;
+
+ vid->last_frame_time = current_time;
+ }
+
+#ifdef HAVE_MENU
+ menu_driver_frame(video_info->menu_is_alive, video_info);
+#endif
+
+ if (likely(!vid->menu_active))
+ {
+ /* Update video mode if we were in the menu on
+ * the previous frame, or width/height have changed */
+ if (unlikely(
+ vid->was_in_menu ||
+ (vid->content_width != width) ||
+ (vid->content_height != height)))
+ sdl_rs90_set_output(vid, width, height, vid->rgb32);
+
+ /* Must always lock SDL surface before
+ * manipulating raw pixel buffer */
+ if (SDL_MUSTLOCK(vid->screen))
+ SDL_LockSurface(vid->screen);
+
+ if (likely(vid->mode_valid))
+ {
+ /* Blit frame to SDL surface */
+ if (vid->rgb32)
+ sdl_rs90_blit_frame32(vid, (uint32_t*)frame,
+ width, height, pitch);
+ else
+ sdl_rs90_blit_frame16(vid, (uint16_t*)frame,
+ width, height, pitch);
+ }
+ /* If current display mode is invalid,
+ * just display an error message */
+ else
+ sdl_rs90_blit_video_mode_error_msg(vid);
+
+ vid->was_in_menu = false;
+ }
+ else
+ {
+ /* If this is the first frame that the menu
+ * is active, update video mode */
+ if (!vid->was_in_menu)
+ {
+ sdl_rs90_set_output(vid,
+ SDL_RS90_WIDTH, SDL_RS90_HEIGHT, false);
+
+ vid->was_in_menu = true;
+ }
+
+ if (SDL_MUSTLOCK(vid->screen))
+ SDL_LockSurface(vid->screen);
+
+ /* Blit menu texture to SDL surface */
+ sdl_rs90_blit_frame16(vid, vid->menu_texture,
+ SDL_RS90_WIDTH, SDL_RS90_HEIGHT,
+ SDL_RS90_WIDTH * sizeof(uint16_t));
+ }
+
+ /* Print OSD text, if required */
+ if (msg)
+ {
+ /* If menu is active, colour depth is overridden
+ * to 16 bit */
+ if (vid->rgb32 && !vid->menu_active)
+ sdl_rs90_blit_text32(vid, FONT_WIDTH_STRIDE,
+ vid->screen->h - (FONT_HEIGHT + FONT_WIDTH_STRIDE), msg);
+ else
+ sdl_rs90_blit_text16(vid, FONT_WIDTH_STRIDE,
+ vid->screen->h - (FONT_HEIGHT + FONT_WIDTH_STRIDE), msg);
+ }
+
+ /* Pixel manipulation complete - unlock
+ * SDL surface */
+ if (SDL_MUSTLOCK(vid->screen))
+ SDL_UnlockSurface(vid->screen);
+
+ SDL_Flip(vid->screen);
+
+ return true;
+}
+
+static void sdl_rs90_set_texture_enable(void *data, bool state, bool full_screen)
+{
+ sdl_rs90_video_t *vid = (sdl_rs90_video_t*)data;
+
+ if (unlikely(!vid))
+ return;
+
+ vid->menu_active = state;
+}
+
+static void sdl_rs90_set_texture_frame(void *data, const void *frame, bool rgb32,
+ unsigned width, unsigned height, float alpha)
+{
+ sdl_rs90_video_t *vid = (sdl_rs90_video_t*)data;
+
+ if (unlikely(
+ !vid ||
+ rgb32 ||
+ (width > SDL_RS90_WIDTH) ||
+ (height > SDL_RS90_HEIGHT)))
+ return;
+
+ memcpy(vid->menu_texture, frame, width * height * sizeof(uint16_t));
+}
+
+static void sdl_rs90_gfx_set_nonblock_state(void *data, bool toggle,
+ bool adaptive_vsync_enabled, unsigned swap_interval)
+{
+ sdl_rs90_video_t *vid = (sdl_rs90_video_t*)data;
+ bool vsync = !toggle;
+
+ if (unlikely(!vid))
+ return;
+
+ /* Check whether vsync status has changed */
+ if (vid->vsync != vsync)
+ {
+ unsigned current_width = vid->content_width;
+ unsigned current_height = vid->content_height;
+ vid->vsync = vsync;
+
+ /* Update video mode */
+
+ /* TODO/FIXME: The following workaround is required
+ * on GCW0 devices; check whether it is required on
+ * the RS-90, and remove if not */
+
+ /* Note that a tedious workaround is required...
+ * - Calling SDL_SetVideoMode() with the currently
+ * set width, height and pixel format can randomly
+ * become a noop even if the surface flags change.
+ * - Since all we are doing here is changing the VSYNC
+ * parameter (which just modifies surface flags), this
+ * means the VSYNC toggle may not be registered...
+ * - This is a huge problem when enabling fast forward,
+ * because VSYNC ON effectively limits maximum frame
+ * rate - if we push frames too rapidly, the OS chokes
+ * and the display freezes.
+ * We have to ensure that the VSYNC state change is
+ * applied in all cases. We can only do this by forcing
+ * a 'real' video mode update, which means adjusting the
+ * video resolution. We therefore end up calling
+ * sdl_rs90_set_output() *twice*, setting the dimensions
+ * to an arbitrary value before restoring the actual
+ * desired width/height */
+ sdl_rs90_set_output(vid,
+ current_width,
+ (current_height > 4) ? (current_height - 2) : 16,
+ vid->rgb32);
+
+ sdl_rs90_set_output(vid,
+ current_width, current_height, vid->rgb32);
+ }
+}
+
+static void sdl_rs90_gfx_check_window(sdl_rs90_video_t *vid)
+{
+ SDL_Event event;
+
+ SDL_PumpEvents();
+ while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_QUITMASK))
+ {
+ if (event.type != SDL_QUIT)
+ continue;
+
+ vid->quitting = true;
+ break;
+ }
+}
+
+static bool sdl_rs90_gfx_alive(void *data)
+{
+ sdl_rs90_video_t *vid = (sdl_rs90_video_t*)data;
+
+ if (unlikely(!vid))
+ return false;
+
+ sdl_rs90_gfx_check_window(vid);
+ return !vid->quitting;
+}
+
+static bool sdl_rs90_gfx_focus(void *data)
+{
+ return true;
+}
+
+static bool sdl_rs90_gfx_suppress_screensaver(void *data, bool enable)
+{
+ return false;
+}
+
+static bool sdl_rs90_gfx_has_windowed(void *data)
+{
+ return false;
+}
+
+static void sdl_rs90_gfx_viewport_info(void *data, struct video_viewport *vp)
+{
+ sdl_rs90_video_t *vid = (sdl_rs90_video_t*)data;
+
+ if (unlikely(!vid))
+ return;
+
+ vp->x = 0;
+ vp->y = 0;
+ vp->width = vp->full_width = vid->frame_width;
+ vp->height = vp->full_height = vid->frame_height;
+}
+
+static float sdl_rs90_get_refresh_rate(void *data)
+{
+#if defined(DINGUX_BETA)
+ sdl_rs90_video_t *vid = (sdl_rs90_video_t*)data;
+
+ if (!vid)
+ return 0.0f;
+
+ switch (vid->refresh_rate)
+ {
+ case DINGUX_REFRESH_RATE_50HZ:
+ return 50.0f;
+ default:
+ break;
+ }
+#endif
+
+ return 60.0f;
+}
+
+static void sdl_rs90_apply_state_changes(void *data)
+{
+ sdl_rs90_video_t *vid = (sdl_rs90_video_t*)data;
+ settings_t *settings = config_get_ptr();
+ bool keep_aspect = (settings) ? settings->bools.video_dingux_ipu_keep_aspect : true;
+ bool integer_scaling = (settings) ? settings->bools.video_scale_integer : false;
+
+ if (!vid || !settings)
+ return;
+
+ if ((vid->keep_aspect != keep_aspect) ||
+ (vid->scale_integer != integer_scaling))
+ {
+ vid->keep_aspect = keep_aspect;
+ vid->scale_integer = integer_scaling;
+
+ /* Aspect/scaling changes require all frame
+ * dimension/padding/cropping parameters to
+ * be recalculated. Easiest method is to just
+ * (re-)set the current output video mode */
+ sdl_rs90_set_output(vid, vid->content_width,
+ vid->content_height, vid->rgb32);
+ }
+}
+
+static uint32_t sdl_rs90_get_flags(void *data)
+{
+ return 0;
+}
+
+static const video_poke_interface_t sdl_rs90_poke_interface = {
+ sdl_rs90_get_flags,
+ NULL,
+ NULL,
+ NULL,
+ sdl_rs90_get_refresh_rate,
+ NULL, /* set_filtering */
+ NULL, /* get_video_output_size */
+ NULL, /* get_video_output_prev */
+ NULL, /* get_video_output_next */
+ NULL, /* get_current_framebuffer */
+ NULL, /* get_proc_address */
+ NULL,
+ sdl_rs90_apply_state_changes,
+ sdl_rs90_set_texture_frame,
+ sdl_rs90_set_texture_enable,
+ NULL,
+ NULL, /* sdl_show_mouse */
+ NULL, /* sdl_grab_mouse_toggle */
+ NULL, /* get_current_shader */
+ NULL, /* get_current_software_framebuffer */
+ NULL /* get_hw_render_interface */
+};
+
+static void sdl_rs90_get_poke_interface(void *data, const video_poke_interface_t **iface)
+{
+ *iface = &sdl_rs90_poke_interface;
+}
+
+static bool sdl_rs90_gfx_set_shader(void *data,
+ enum rarch_shader_type type, const char *path)
+{
+ return false;
+}
+
+video_driver_t video_sdl_rs90 = {
+ sdl_rs90_gfx_init,
+ sdl_rs90_gfx_frame,
+ sdl_rs90_gfx_set_nonblock_state,
+ sdl_rs90_gfx_alive,
+ sdl_rs90_gfx_focus,
+ sdl_rs90_gfx_suppress_screensaver,
+ sdl_rs90_gfx_has_windowed,
+ sdl_rs90_gfx_set_shader,
+ sdl_rs90_gfx_free,
+ "sdl_rs90",
+ NULL,
+ NULL, /* set_rotation */
+ sdl_rs90_gfx_viewport_info,
+ NULL, /* read_viewport */
+ NULL, /* read_frame_raw */
+#ifdef HAVE_OVERLAY
+ NULL,
+#endif
+#ifdef HAVE_VIDEO_LAYOUT
+ NULL,
+#endif
+ sdl_rs90_get_poke_interface
+};
diff --git a/griffin/griffin.c b/griffin/griffin.c
index e60461a0ca..a187296e3b 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -467,6 +467,14 @@ VIDEO DRIVER
#include "../gfx/common/sdl2_common.c"
#endif
+#if defined(DINGUX) && defined(HAVE_SDL_DINGUX)
+#if defined(RS90)
+#include "../gfx/drivers/sdl_rs90_gfx.c"
+#else
+#include "../gfx/drivers/sdl_dingux_gfx.c"
+#endif
+#endif
+
#ifdef HAVE_VG
#include "../gfx/drivers/vg.c"
#endif
diff --git a/input/drivers_joypad/sdl_dingux_joypad.c b/input/drivers_joypad/sdl_dingux_joypad.c
index 4b74166a40..8406390660 100644
--- a/input/drivers_joypad/sdl_dingux_joypad.c
+++ b/input/drivers_joypad/sdl_dingux_joypad.c
@@ -31,6 +31,11 @@
#include "../../configuration.h"
#endif
+#if !defined(RS90)
+#define SDL_DINGUX_HAS_ANALOG 1
+#define SDL_DINGUX_HAS_MENU_TOGGLE 1
+#endif
+
/* Simple joypad driver designed to rationalise
* the bizarre keyboard/gamepad hybrid setup
* of OpenDingux devices */
@@ -66,7 +71,9 @@ typedef struct
typedef struct
{
+#if defined(SDL_DINGUX_HAS_ANALOG)
SDL_Joystick *device;
+#endif
#if defined(HAVE_LIBSHAKE)
dingux_joypad_rumble_t rumble;
#endif
@@ -74,11 +81,15 @@ typedef struct
uint16_t pad_state;
int16_t analog_state[2][2];
bool connected;
+#if defined(SDL_DINGUX_HAS_MENU_TOGGLE)
bool menu_toggle;
+#endif
} dingux_joypad_t;
+#if defined(SDL_DINGUX_HAS_MENU_TOGGLE)
/* TODO/FIXME - global referenced outside */
extern uint64_t lifecycle_state;
+#endif
static dingux_joypad_t dingux_joypad;
@@ -259,6 +270,7 @@ static void sdl_dingux_joypad_connect(void)
{
dingux_joypad_t *joypad = (dingux_joypad_t*)&dingux_joypad;
+#if defined(SDL_DINGUX_HAS_ANALOG)
/* Open joypad device */
if (SDL_NumJoysticks() > 0)
joypad->device = SDL_JoystickOpen(0);
@@ -266,6 +278,7 @@ static void sdl_dingux_joypad_connect(void)
/* If joypad exists, get number of axes */
if (joypad->device)
joypad->num_axes = SDL_JoystickNumAxes(joypad->device);
+#endif
#if defined(HAVE_LIBSHAKE)
/* Configure rumble interface */
@@ -289,8 +302,10 @@ static void sdl_dingux_joypad_disconnect(void)
{
dingux_joypad_t *joypad = (dingux_joypad_t*)&dingux_joypad;
+#if defined(SDL_DINGUX_HAS_ANALOG)
if (joypad->device)
SDL_JoystickClose(joypad->device);
+#endif
if (joypad->connected)
input_autoconfigure_disconnect(0, sdl_dingux_joypad.ident);
@@ -329,7 +344,9 @@ static void sdl_dingux_joypad_destroy(void)
Shake_Quit();
#endif
+#if defined(SDL_DINGUX_HAS_MENU_TOGGLE)
BIT64_CLEAR(lifecycle_state, RARCH_MENU_TOGGLE);
+#endif
}
static void *sdl_dingux_joypad_init(void *data)
@@ -338,8 +355,11 @@ static void *sdl_dingux_joypad_init(void *data)
uint32_t sdl_subsystem_flags = SDL_WasInit(0);
memset(joypad, 0, sizeof(dingux_joypad_t));
+#if defined(SDL_DINGUX_HAS_MENU_TOGGLE)
BIT64_CLEAR(lifecycle_state, RARCH_MENU_TOGGLE);
+#endif
+#if defined(SDL_DINGUX_HAS_ANALOG)
/* Initialise joystick subsystem, if required */
if (sdl_subsystem_flags == 0)
{
@@ -351,6 +371,7 @@ static void *sdl_dingux_joypad_init(void *data)
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
return NULL;
}
+#endif
#if defined(HAVE_LIBSHAKE)
/* Initialise rumble interface */
@@ -397,6 +418,7 @@ static void sdl_dingux_joypad_get_buttons(unsigned port, input_bits_t *state)
static int16_t sdl_dingux_joypad_axis_state(unsigned port, uint32_t joyaxis)
{
+#if defined(SDL_DINGUX_HAS_ANALOG)
dingux_joypad_t *joypad = (dingux_joypad_t*)&dingux_joypad;
int val = 0;
int axis = -1;
@@ -437,6 +459,9 @@ static int16_t sdl_dingux_joypad_axis_state(unsigned port, uint32_t joyaxis)
return 0;
return val;
+#else
+ return 0;
+#endif
}
static int16_t sdl_dingux_joypad_axis(unsigned port, uint32_t joyaxis)
@@ -465,16 +490,20 @@ static int16_t sdl_dingux_joypad_state(
/* Auto-binds are per joypad, not per user. */
const uint64_t joykey = (binds[i].joykey != NO_BTN)
? binds[i].joykey : joypad_info->auto_binds[i].joykey;
+#if defined(SDL_DINGUX_HAS_ANALOG)
const uint32_t joyaxis = (binds[i].joyaxis != AXIS_NONE)
? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis;
-
- if ((uint16_t)joykey != NO_BTN &&
+#endif
+
+ if ((uint16_t)joykey != NO_BTN &&
(joypad->pad_state & (1 << (uint16_t)joykey)))
ret |= (1 << i);
+#if defined(SDL_DINGUX_HAS_ANALOG)
else if (joyaxis != AXIS_NONE &&
- ((float)abs(sdl_dingux_joypad_axis_state(port_idx, joyaxis))
+ ((float)abs(sdl_dingux_joypad_axis_state(port_idx, joyaxis))
/ 0x8000) > joypad_info->axis_threshold)
ret |= (1 << i);
+#endif
}
return ret;
@@ -485,6 +514,7 @@ static void sdl_dingux_joypad_poll(void)
dingux_joypad_t *joypad = (dingux_joypad_t*)&dingux_joypad;
SDL_Event event;
+#if defined(SDL_DINGUX_HAS_MENU_TOGGLE)
/* Note: The menu toggle key is an awkward special
* case - the press/release events happen almost
* instantaneously, and since we only sample once
@@ -496,6 +526,7 @@ static void sdl_dingux_joypad_poll(void)
BIT64_CLEAR(lifecycle_state, RARCH_MENU_TOGGLE);
joypad->menu_toggle = false;
}
+#endif
/* All digital inputs map to keyboard keys
* - X: SDLK_SPACE
@@ -571,10 +602,12 @@ static void sdl_dingux_joypad_poll(void)
case SDLK_LEFT:
BIT16_SET(joypad->pad_state, RETRO_DEVICE_ID_JOYPAD_LEFT);
break;
+#if defined(SDL_DINGUX_HAS_MENU_TOGGLE)
case SDLK_HOME:
BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE);
joypad->menu_toggle = true;
break;
+#endif
default:
break;
}
@@ -639,6 +672,7 @@ static void sdl_dingux_joypad_poll(void)
}
}
+#if defined(SDL_DINGUX_HAS_ANALOG)
/* Analog inputs come from the joypad device,
* if connected */
if (joypad->device)
@@ -676,6 +710,7 @@ static void sdl_dingux_joypad_poll(void)
(axis_value < -0x7FFF) ? -0x7FFF : axis_value;
}
}
+#endif
}
input_device_driver_t sdl_dingux_joypad = {
diff --git a/libretro-common/rthreads/rthreads.c b/libretro-common/rthreads/rthreads.c
index bb5b38b037..3942651532 100644
--- a/libretro-common/rthreads/rthreads.c
+++ b/libretro-common/rthreads/rthreads.c
@@ -872,7 +872,7 @@ bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us)
int tickms = ps2_clock();
now.tv_sec = tickms/1000;
now.tv_nsec = tickms * 1000;
-#elif defined(__mips__) || defined(VITA) || defined(_3DS)
+#elif !defined(DINGUX_BETA) && (defined(__mips__) || defined(VITA) || defined(_3DS))
struct timeval tm;
gettimeofday(&tm, NULL);
diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c
index ff8631edeb..522c03b778 100644
--- a/menu/drivers/rgui.c
+++ b/menu/drivers/rgui.c
@@ -80,6 +80,22 @@
#define RGUI_MIN_FB_WIDTH 256
#define RGUI_MAX_FB_WIDTH 426
+#if defined(DINGUX)
+#if defined(RS90)
+/* The RS-90 uses a fixed framebuffer size
+ * of 240x160 */
+#define RGUI_DINGUX_ASPECT_RATIO RGUI_ASPECT_RATIO_3_2
+#define RGUI_DINGUX_FB_WIDTH 240
+#define RGUI_DINGUX_FB_HEIGHT 160
+#else
+/* Other Dingux devices (RG350 etc.) use a
+ * fixed framebuffer size of 320x240 */
+#define RGUI_DINGUX_ASPECT_RATIO RGUI_ASPECT_RATIO_4_3
+#define RGUI_DINGUX_FB_WIDTH 320
+#define RGUI_DINGUX_FB_HEIGHT 240
+#endif
+#endif
+
/* Maximum entry value length in characters
* when using fixed with layouts
* (i.e. Maximum possible 'spacing' as
@@ -1502,20 +1518,21 @@ static bool rgui_set_pixel_format_function(void)
return transparency_supported;
}
- if ( string_is_equal(driver_ident, "ps2")) /* PS2 */
+ if ( string_is_equal(driver_ident, "ps2")) /* PS2 */
{
argb32_to_pixel_platform_format = argb32_to_abgr1555;
transparency_supported = false;
}
- else if (string_is_equal(driver_ident, "gx")) /* GEKKO */
+ else if (string_is_equal(driver_ident, "gx")) /* GEKKO */
argb32_to_pixel_platform_format = argb32_to_rgb5a3;
- else if (string_is_equal(driver_ident, "psp1")) /* PSP */
+ else if (string_is_equal(driver_ident, "psp1")) /* PSP */
argb32_to_pixel_platform_format = argb32_to_abgr4444;
- else if (string_is_equal(driver_ident, "d3d10") || /* D3D10/11/12 */
+ else if (string_is_equal(driver_ident, "d3d10") || /* D3D10/11/12 */
string_is_equal(driver_ident, "d3d11") ||
string_is_equal(driver_ident, "d3d12"))
argb32_to_pixel_platform_format = argb32_to_bgra4444;
- else if (string_is_equal(driver_ident, "sdl_dingux")) /* DINGUX SDL */
+ else if (string_is_equal(driver_ident, "sdl_dingux") || /* DINGUX SDL */
+ string_is_equal(driver_ident, "sdl_rs90"))
{
argb32_to_pixel_platform_format = argb32_to_rgb565;
transparency_supported = false;
@@ -3006,7 +3023,7 @@ static void load_custom_theme(rgui_t *rgui, rgui_theme_t *theme_colors, const ch
const char *wallpaper_key = NULL;
bool success = false;
#if defined(DINGUX)
- unsigned aspect_ratio = RGUI_ASPECT_RATIO_4_3;
+ unsigned aspect_ratio = RGUI_DINGUX_ASPECT_RATIO;
#else
settings_t *settings = config_get_ptr();
unsigned aspect_ratio = settings->uints.menu_rgui_aspect_ratio;
@@ -5435,15 +5452,14 @@ static bool rgui_set_aspect_ratio(rgui_t *rgui,
* width value must be zero... */
unsigned max_frame_buf_width = 424;
#elif defined(DINGUX)
- /* Dingux devices use a fixed framebuffer size
- * of 320x240 */
- unsigned max_frame_buf_width = 320;
+ /* Dingux devices use a fixed framebuffer size */
+ unsigned max_frame_buf_width = RGUI_DINGUX_FB_WIDTH;
#else
struct video_viewport vp;
unsigned max_frame_buf_width = RGUI_MAX_FB_WIDTH;
#endif
#if defined(DINGUX)
- unsigned aspect_ratio = RGUI_ASPECT_RATIO_4_3;
+ unsigned aspect_ratio = RGUI_DINGUX_ASPECT_RATIO;
unsigned aspect_ratio_lock = RGUI_ASPECT_RATIO_LOCK_NONE;
#else
settings_t *settings = config_get_ptr();
@@ -5469,9 +5485,8 @@ static bool rgui_set_aspect_ratio(rgui_t *rgui,
* values */
rgui->frame_buf.height = p_disp->framebuf_height;
#elif defined(DINGUX)
- /* Dingux devices use a fixed framebuffer size
- * of 320x240 */
- rgui->frame_buf.height = 240;
+ /* Dingux devices use a fixed framebuffer size */
+ rgui->frame_buf.height = RGUI_DINGUX_FB_HEIGHT;
#else
/* If window height is less than RGUI default
* height of 240, allow the frame buffer to
@@ -6587,7 +6602,7 @@ static void rgui_frame(void *data, video_frame_info_t *video_info)
bool bg_filler_thickness_enable = settings->bools.menu_rgui_background_filler_thickness_enable;
bool border_filler_thickness_enable = settings->bools.menu_rgui_border_filler_thickness_enable;
#if defined(DINGUX)
- unsigned aspect_ratio = RGUI_ASPECT_RATIO_4_3;
+ unsigned aspect_ratio = RGUI_DINGUX_ASPECT_RATIO;
unsigned aspect_ratio_lock = RGUI_ASPECT_RATIO_LOCK_NONE;
#else
unsigned aspect_ratio = settings->uints.menu_rgui_aspect_ratio;
@@ -6714,7 +6729,7 @@ static void rgui_frame(void *data, video_frame_info_t *video_info)
if ((rgui->window_width != video_width) ||
(rgui->window_height != video_height))
{
-#if !defined(GEKKO)
+#if !defined(GEKKO) && !defined(DINGUX)
/* If window width or height are less than the
* RGUI default size of (320-426)x240, must enable
* dynamic menu 'downscaling'.
@@ -6744,7 +6759,6 @@ static void rgui_frame(void *data, video_frame_info_t *video_info)
case RGUI_ASPECT_RATIO_5_3_CENTRE:
default_fb_width = 400;
break;
-
default:
/* 4:3 */
default_fb_width = 320;
diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c
index 00805b4f5c..c972e8696b 100644
--- a/menu/menu_displaylist.c
+++ b/menu/menu_displaylist.c
@@ -7768,7 +7768,8 @@ unsigned menu_displaylist_build_list(
case DISPLAYLIST_VIDEO_SCALING_SETTINGS_LIST:
{
#if defined(DINGUX)
- if (string_is_equal(settings->arrays.video_driver, "sdl_dingux"))
+ if (string_is_equal(settings->arrays.video_driver, "sdl_dingux") ||
+ string_is_equal(settings->arrays.video_driver, "sdl_rs90"))
{
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER,
diff --git a/menu/menu_setting.c b/menu/menu_setting.c
index 19631ad7a3..ca7aad473e 100644
--- a/menu/menu_setting.c
+++ b/menu/menu_setting.c
@@ -10954,7 +10954,8 @@ static bool setting_append_list(
}
#if defined(DINGUX) && defined(DINGUX_BETA)
- if (string_is_equal(settings->arrays.video_driver, "sdl_dingux"))
+ if (string_is_equal(settings->arrays.video_driver, "sdl_dingux") ||
+ string_is_equal(settings->arrays.video_driver, "sdl_rs90"))
{
CONFIG_UINT(
list, list_info,
@@ -11209,7 +11210,8 @@ static bool setting_append_list(
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_LAKKA_ADVANCED);
#if defined(DINGUX)
- if (string_is_equal(settings->arrays.video_driver, "sdl_dingux"))
+ if (string_is_equal(settings->arrays.video_driver, "sdl_dingux") ||
+ string_is_equal(settings->arrays.video_driver, "sdl_rs90"))
{
CONFIG_BOOL(
list, list_info,
@@ -14935,10 +14937,11 @@ static bool setting_append_list(
general_read_handler);
MENU_SETTINGS_LIST_CURRENT_ADD_VALUES(list, list_info, "cfg");
- /* ps2 and sdl_dingux gfx drivers do not support
- * menu framebuffer transparency */
+ /* ps2 and sdl_dingux/sdl_rs90 gfx drivers do
+ * not support menu framebuffer transparency */
if (!string_is_equal(settings->arrays.video_driver, "ps2") &&
- !string_is_equal(settings->arrays.video_driver, "sdl_dingux"))
+ !string_is_equal(settings->arrays.video_driver, "sdl_dingux") &&
+ !string_is_equal(settings->arrays.video_driver, "sdl_rs90"))
{
CONFIG_BOOL(
list, list_info,
diff --git a/retroarch.h b/retroarch.h
index 8dde537f69..d49dca46cd 100644
--- a/retroarch.h
+++ b/retroarch.h
@@ -1874,6 +1874,7 @@ extern video_driver_t video_xvideo;
extern video_driver_t video_sdl;
extern video_driver_t video_sdl2;
extern video_driver_t video_sdl_dingux;
+extern video_driver_t video_sdl_rs90;
extern video_driver_t video_vg;
extern video_driver_t video_omap;
extern video_driver_t video_exynos;
diff --git a/retroarch_data.h b/retroarch_data.h
index 22d74a3406..b48ace713d 100644
--- a/retroarch_data.h
+++ b/retroarch_data.h
@@ -645,8 +645,12 @@ static const video_driver_t *video_drivers[] = {
&video_sdl2,
#endif
#ifdef HAVE_SDL_DINGUX
+#if defined(RS90)
+ &video_sdl_rs90,
+#else
&video_sdl_dingux,
#endif
+#endif
#ifdef HAVE_XVIDEO
&video_xvideo,
#endif
@@ -995,7 +999,7 @@ static input_device_driver_t *joypad_drivers[] = {
};
#ifdef HAVE_HID
-static bool null_hid_joypad_query(void *data, unsigned pad) {
+static bool null_hid_joypad_query(void *data, unsigned pad) {
return pad < MAX_USERS; }
static const char *null_hid_joypad_name(
void *data, unsigned pad) { return NULL; }
@@ -1665,7 +1669,7 @@ typedef struct discord_state discord_state_t;
#endif
struct runloop
-{
+{
retro_usec_t frame_time_last; /* int64_t alignment */
msg_queue_t msg_queue; /* ptr alignment */
@@ -1733,7 +1737,7 @@ struct rarch_state
menu_input_t menu_input_state; /* retro_time_t alignment */
#endif
-
+
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
rarch_timer_t shader_delay_timer; /* int64_t alignment */
@@ -1911,7 +1915,7 @@ struct rarch_state
struct retro_subsystem_rom_info
subsystem_data_roms[SUBSYSTEM_MAX_SUBSYSTEMS]
[SUBSYSTEM_MAX_SUBSYSTEM_ROMS]; /* ptr alignment */
-
+
gfx_ctx_driver_t current_video_context; /* ptr alignment */
content_state_t content_st; /* ptr alignment */
midi_event_t midi_drv_input_event; /* ptr alignment */
@@ -1989,7 +1993,7 @@ struct rarch_state
size_t runahead_save_state_size;
#endif
- jmp_buf error_sjlj_context; /* 4-byte alignment,
+ jmp_buf error_sjlj_context; /* 4-byte alignment,
put it right before long */
turbo_buttons_t input_driver_turbo_btns; /* int32_t alignment */
@@ -2017,7 +2021,7 @@ struct rarch_state
int reannounce;
#endif
- input_device_info_t input_device_info[MAX_INPUT_DEVICES];
+ input_device_info_t input_device_info[MAX_INPUT_DEVICES];
/* unsigned alignment */
#ifdef HAVE_MENU
menu_dialog_t dialog_st; /* unsigned alignment */
@@ -2093,7 +2097,7 @@ struct rarch_state
#endif
#ifdef HAVE_MENU
- menu_input_pointer_hw_state_t menu_input_pointer_hw_state;
+ menu_input_pointer_hw_state_t menu_input_pointer_hw_state;
/* int16_t alignment */
#endif