From c4bfa6b0d2cd0a7ba8a925dc9e79d99e64d8fe73 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Sat, 21 Jan 2017 17:41:20 -0500 Subject: [PATCH] DOS: initial VGA int13 graphics driver --- Makefile.common | 8 + config.def.h | 3 + configuration.c | 2 + gfx/drivers/caca_gfx.c | 16 +- gfx/drivers/vga_gfx.c | 360 ++++++++++++++++++++++++ gfx/drivers_font/vga_font.c | 147 ++++++++++ gfx/font_driver.c | 34 +++ gfx/font_driver.h | 4 +- gfx/video_driver.c | 3 + gfx/video_driver.h | 1 + griffin/griffin.c | 8 + menu/drivers_display/menu_display_vga.c | 101 +++++++ menu/menu_display.c | 7 + menu/menu_display.h | 4 +- 14 files changed, 688 insertions(+), 10 deletions(-) create mode 100644 gfx/drivers/vga_gfx.c create mode 100644 gfx/drivers_font/vga_font.c create mode 100644 menu/drivers_display/menu_display_vga.c diff --git a/Makefile.common b/Makefile.common index ab3538335f..58aa2c0240 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1268,3 +1268,11 @@ ifeq ($(HAVE_COCOA),1) ui/drivers/cocoa/cocoa_common.o \ gfx/drivers_context/cocoa_gl_ctx.o endif + +ifneq ($(findstring DOS,$(OS)),) + OBJ += gfx/drivers/vga_gfx.o gfx/drivers_font/vga_font.o + + ifeq ($(HAVE_MENU_COMMON), 1) + OBJ += menu/drivers_display/menu_display_vga.o + endif +endif diff --git a/config.def.h b/config.def.h index 28ed46adef..8483c0b356 100644 --- a/config.def.h +++ b/config.def.h @@ -53,6 +53,7 @@ enum video_driver_enum VIDEO_DISPMANX, VIDEO_CACA, VIDEO_GDI, + VIDEO_VGA, VIDEO_NULL }; @@ -213,6 +214,8 @@ enum record_driver_enum #define VIDEO_DEFAULT_DRIVER VIDEO_SDL2 #elif defined(_WIN32) && !defined(_XBOX) #define VIDEO_DEFAULT_DRIVER VIDEO_GDI +#elif defined(DJGPP) +#define VIDEO_DEFAULT_DRIVER VIDEO_VGA #elif defined(HAVE_DYLIB) && !defined(ANDROID) #define VIDEO_DEFAULT_DRIVER VIDEO_EXT #else diff --git a/configuration.c b/configuration.c index 76d2271c77..ed64f08c65 100644 --- a/configuration.c +++ b/configuration.c @@ -314,6 +314,8 @@ const char *config_get_default_video(void) return "caca"; case VIDEO_GDI: return "gdi"; + case VIDEO_VGA: + return "vga"; case VIDEO_NULL: break; } diff --git a/gfx/drivers/caca_gfx.c b/gfx/drivers/caca_gfx.c index ea0ba6bbf0..b18b187dae 100644 --- a/gfx/drivers/caca_gfx.c +++ b/gfx/drivers/caca_gfx.c @@ -40,7 +40,7 @@ static unsigned caca_menu_pitch = 0; static unsigned caca_video_width = 0; static unsigned caca_video_height = 0; static unsigned caca_video_pitch = 0; -static bool caca_rgb32 = 0; +static bool caca_rgb32 = false; static void caca_gfx_free(void *data); @@ -120,7 +120,7 @@ static bool caca_gfx_frame(void *data, const void *frame, if (!frame || !frame_width || !frame_height) return true; - if ( caca_video_width != frame_width || + if ( caca_video_width != frame_width || caca_video_height != frame_height || caca_video_pitch != pitch) { @@ -143,9 +143,9 @@ static bool caca_gfx_frame(void *data, const void *frame, width = caca_get_canvas_width(caca_cv); height = caca_get_canvas_height(caca_cv); - if ( frame_to_copy == frame && - frame_width == 4 && - frame_height == 4 && + if ( frame_to_copy == frame && + frame_width == 4 && + frame_height == 4 && (frame_width < width && frame_height < height)) draw = false; @@ -284,9 +284,9 @@ static void caca_set_texture_frame(void *data, caca_menu_frame = NULL; } - if ( !caca_menu_frame || - caca_menu_width != width || - caca_menu_height != height || + if ( !caca_menu_frame || + caca_menu_width != width || + caca_menu_height != height || caca_menu_pitch != pitch) if (pitch && height) caca_menu_frame = (unsigned char*)malloc(pitch * height); diff --git a/gfx/drivers/vga_gfx.c b/gfx/drivers/vga_gfx.c new file mode 100644 index 0000000000..67b1b4ae59 --- /dev/null +++ b/gfx/drivers/vga_gfx.c @@ -0,0 +1,360 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2016 - Daniel De Matteis + * Copyright (C) 2016 - Brad Parker + * + * 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 + +#ifdef HAVE_MENU +#include "../../menu/menu_driver.h" +#endif + +#include "../common/vga_common.h" + +#include "../font_driver.h" + +#include "../../driver.h" +#include "../../verbosity.h" + +static unsigned char *vga_menu_frame = NULL; +static unsigned vga_menu_width = 0; +static unsigned vga_menu_height = 0; +static unsigned vga_menu_pitch = 0; +static unsigned vga_menu_bits = 0; +static unsigned vga_video_width = 0; +static unsigned vga_video_height = 0; +static unsigned vga_video_pitch = 0; +static unsigned vga_video_bits = 0; +static bool vga_rgb32 = false; + +static void set_mode_13h() +{ + __dpmi_regs r; + + r.x.ax = 0x13; + __dpmi_int(0x10, &r); +} + +static void return_to_text_mode() +{ + __dpmi_regs r; + + r.x.ax = 3; + __dpmi_int(0x10, &r); +} + +static void vga_vsync() +{ + /* wait until any previous retrace has ended */ + do + { + } + while (inportb(0x3DA) & 8); + + /* wait until a new retrace has just begun */ + do + { + } + while (!(inportb(0x3DA) & 8)); +} + +static void vga_gfx_create(void) +{ + set_mode_13h(); +} + +static void *vga_gfx_init(const video_info_t *video, + const input_driver_t **input, void **input_data) +{ + vga_t *vga = (vga_t*)calloc(1, sizeof(*vga)); + + *input = NULL; + *input_data = NULL; + + vga_video_width = video->width; + vga_video_height = video->height; + vga_rgb32 = video->rgb32; + + if (video->rgb32) + vga_video_pitch = video->width * 4; + else + vga_video_pitch = video->width * 2; + + vga_gfx_create(); + + if (video->font_enable) + font_driver_init_osd(NULL, false, FONT_DRIVER_RENDER_VGA); + + return vga; +} + +static bool vga_gfx_frame(void *data, const void *frame, + unsigned frame_width, unsigned frame_height, uint64_t frame_count, + unsigned pitch, const char *msg, video_frame_info_t *video_info) +{ + size_t len = 0; + void *buffer = NULL; + unsigned width, height, bits; + const void *frame_to_copy = frame; + bool draw = true; + + (void)data; + (void)frame; + (void)frame_width; + (void)frame_height; + (void)pitch; + (void)msg; + + if (!frame || !frame_width || !frame_height) + return true; + +#ifdef HAVE_MENU + menu_driver_frame(video_info); +#endif + + if ( vga_video_width != frame_width || + vga_video_height != frame_height || + vga_video_pitch != pitch) + { + if (frame_width > 4 && frame_height > 4) + { + vga_video_width = frame_width; + vga_video_height = frame_height; + vga_video_pitch = pitch; + } + } + + if (vga_menu_frame && menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) + { + frame_to_copy = vga_menu_frame; + width = vga_menu_width; + height = vga_menu_height; + pitch = vga_menu_pitch; + bits = vga_menu_bits; + } + else + { + width = vga_video_width; + height = vga_video_height; + pitch = vga_video_pitch; + + if (frame_width == 4 && frame_height == 4 && (frame_width < width && frame_height < height)) + draw = false; + + if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) + draw = false; + } + + if (draw) + { + vga_vsync(); + dosmemput(frame_to_copy, MIN(320,width)*MIN(200,height), 0xA0000); + } + + if (msg) + font_driver_render_msg(video_info, NULL, msg, NULL); + + video_context_driver_update_window_title(video_info); + + return true; +} + +static void vga_gfx_set_nonblock_state(void *data, bool toggle) +{ + (void)data; + (void)toggle; +} + +static bool vga_gfx_alive(void *data) +{ + (void)data; + video_driver_set_size(&vga_video_width, &vga_video_height); + return true; +} + +static bool vga_gfx_focus(void *data) +{ + (void)data; + return true; +} + +static bool vga_gfx_suppress_screensaver(void *data, bool enable) +{ + (void)data; + (void)enable; + return false; +} + +static bool vga_gfx_has_windowed(void *data) +{ + (void)data; + return true; +} + +static void vga_gfx_free(void *data) +{ + (void)data; + + if (vga_menu_frame) + { + free(vga_menu_frame); + vga_menu_frame = NULL; + } + + return_to_text_mode(); +} + +static bool vga_gfx_set_shader(void *data, + enum rarch_shader_type type, const char *path) +{ + (void)data; + (void)type; + (void)path; + + return false; +} + +static void vga_gfx_set_rotation(void *data, + unsigned rotation) +{ + (void)data; + (void)rotation; +} + +static void vga_gfx_viewport_info(void *data, + struct video_viewport *vp) +{ + (void)data; + (void)vp; +} + +static bool vga_gfx_read_viewport(void *data, uint8_t *buffer) +{ + (void)data; + (void)buffer; + + return true; +} + +static void vga_set_texture_frame(void *data, + const void *frame, bool rgb32, unsigned width, unsigned height, + float alpha) +{ + unsigned pitch = width * 2; + + if (rgb32) + pitch = width * 4; + + if (vga_menu_frame) + { + free(vga_menu_frame); + vga_menu_frame = NULL; + } + + if ( !vga_menu_frame || + vga_menu_width != width || + vga_menu_height != height || + vga_menu_pitch != pitch) + if (pitch && height) + vga_menu_frame = (unsigned char*)malloc(pitch * height); + + if (vga_menu_frame && frame && pitch && height) + { + memcpy(vga_menu_frame, frame, pitch * height); + vga_menu_width = width; + vga_menu_height = height; + vga_menu_pitch = pitch; + vga_menu_bits = rgb32 ? 32 : 16; + } +} + +static void vga_set_osd_msg(void *data, const char *msg, + const void *params, void *font) +{ + video_frame_info_t video_info; + video_driver_build_info(&video_info); + font_driver_render_msg(&video_info, font, msg, params); +} + +static const video_poke_interface_t vga_poke_interface = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +#ifdef HAVE_FBO + NULL, +#else + NULL, +#endif + NULL, + NULL, + NULL, +#if defined(HAVE_MENU) + vga_set_texture_frame, + NULL, + vga_set_osd_msg, + NULL, +#else + NULL, + NULL, + NULL, + NULL, +#endif + + NULL, +#ifdef HAVE_MENU + NULL, +#endif +}; + +static void vga_gfx_get_poke_interface(void *data, + const video_poke_interface_t **iface) +{ + (void)data; + *iface = &vga_poke_interface; +} + +void vga_gfx_set_viewport(void *data, unsigned viewport_width, + unsigned viewport_height, bool force_full, bool allow_rotate) +{ +} + +video_driver_t video_vga = { + vga_gfx_init, + vga_gfx_frame, + vga_gfx_set_nonblock_state, + vga_gfx_alive, + vga_gfx_focus, + vga_gfx_suppress_screensaver, + vga_gfx_has_windowed, + vga_gfx_set_shader, + vga_gfx_free, + "vga", + vga_gfx_set_viewport, + vga_gfx_set_rotation, + vga_gfx_viewport_info, + vga_gfx_read_viewport, + NULL, /* read_frame_raw */ + +#ifdef HAVE_OVERLAY + NULL, /* overlay_interface */ +#endif + vga_gfx_get_poke_interface, +}; diff --git a/gfx/drivers_font/vga_font.c b/gfx/drivers_font/vga_font.c new file mode 100644 index 0000000000..601934cc63 --- /dev/null +++ b/gfx/drivers_font/vga_font.c @@ -0,0 +1,147 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2016 - Daniel De Matteis + * Copyright (C) 2016 - Brad Parker + * + * 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 + +#ifdef HAVE_CONFIG_H +#include "../../config.h" +#endif + +#include "../font_driver.h" +#include "../../verbosity.h" +#include "../common/vga_common.h" + +typedef struct +{ + const font_renderer_driver_t *vga_font_driver; + void *vga_font_data; + vga_t *vga; +} vga_raster_t; + +static void *vga_init_font(void *data, + const char *font_path, float font_size) +{ + vga_raster_t *font = (vga_raster_t*)calloc(1, sizeof(*font)); + + if (!font) + return NULL; + + font->vga = (vga_t*)data; + + font_size = 1; + + if (!font_renderer_create_default((const void**)&font->vga_font_driver, + &font->vga_font_data, font_path, font_size)) + { + RARCH_WARN("Couldn't initialize font renderer.\n"); + return NULL; + } + + return font; +} + +static void vga_render_free_font(void *data) +{ + +} + +static int vga_get_message_width(void *data, const char *msg, + unsigned msg_len, float scale) +{ + return 0; +} + +static const struct font_glyph *vga_font_get_glyph( + void *data, uint32_t code) +{ + return NULL; +} + +static void vga_render_msg(video_frame_info_t *video_info, + void *data, const char *msg, + const void *userdata) +{ + float x, y, scale; + unsigned width, height; + unsigned newX, newY; + unsigned align; + vga_raster_t *font = (vga_raster_t*)data; + const struct font_params *params = (const struct font_params*)userdata; + + if (!font || string_is_empty(msg)) + return; + + if (params) + { + x = params->x; + y = params->y; + scale = params->scale; + align = params->text_align; + } + else + { + x = video_info->font_msg_pos_x; + y = video_info->font_msg_pos_y; + scale = 1.0f; + align = TEXT_ALIGN_LEFT; + } + + if (!font->vga) + return; + + width = VGA_WIDTH; + height = VGA_HEIGHT; + newY = height - (y * height * scale); + + switch (align) + { + case TEXT_ALIGN_LEFT: + newX = x * width * scale; + break; + case TEXT_ALIGN_RIGHT: + newX = (x * width * scale) - strlen(msg); + break; + case TEXT_ALIGN_CENTER: + newX = (x * width * scale) - (strlen(msg) / 2); + break; + default: + break; + } +} + +static void vga_font_flush_block(unsigned width, unsigned height, + void* data) +{ + (void)data; +} + +static void vga_font_bind_block(void* data, void* userdata) +{ + (void)data; +} + +font_renderer_t vga_font = { + vga_init_font, + vga_render_free_font, + vga_render_msg, + "vga font", + vga_font_get_glyph, /* get_glyph */ + vga_font_bind_block, /* bind_block */ + vga_font_flush_block, /* flush */ + vga_get_message_width /* get_message_width */ +}; diff --git a/gfx/font_driver.c b/gfx/font_driver.c index 5ab340b731..a6342a7a7f 100644 --- a/gfx/font_driver.c +++ b/gfx/font_driver.c @@ -178,6 +178,35 @@ static bool caca_font_init_first( } #endif +#ifdef DJGPP +static const font_renderer_t *vga_font_backends[] = { + &vga_font, + NULL, +}; + +static bool vga_font_init_first( + const void **font_driver, void **font_handle, + void *video_data, const char *font_path, float font_size) +{ + unsigned i; + + for (i = 0; vga_font_backends[i]; i++) + { + void *data = vga_font_backends[i]->init( + video_data, font_path, font_size); + + if (!data) + continue; + + *font_driver = vga_font_backends[i]; + *font_handle = data; + return true; + } + + return false; +} +#endif + #if defined(_WIN32) && !defined(_XBOX) static const font_renderer_t *gdi_font_backends[] = { &gdi_font, @@ -335,6 +364,11 @@ static bool font_init_first( case FONT_DRIVER_RENDER_GDI: return gdi_font_init_first(font_driver, font_handle, video_data, font_path, font_size); +#endif +#ifdef DJGPP + case FONT_DRIVER_RENDER_VGA: + return vga_font_init_first(font_driver, font_handle, + video_data, font_path, font_size); #endif case FONT_DRIVER_RENDER_DONT_CARE: /* TODO/FIXME - lookup graphics driver's 'API' */ diff --git a/gfx/font_driver.h b/gfx/font_driver.h index 9e276f34b4..86c6365176 100644 --- a/gfx/font_driver.h +++ b/gfx/font_driver.h @@ -35,7 +35,8 @@ enum font_driver_render_api FONT_DRIVER_RENDER_CTR, FONT_DRIVER_RENDER_VULKAN_API, FONT_DRIVER_RENDER_CACA, - FONT_DRIVER_RENDER_GDI + FONT_DRIVER_RENDER_GDI, + FONT_DRIVER_RENDER_VGA }; enum text_alignment @@ -171,6 +172,7 @@ extern font_renderer_t ctr_font; extern font_renderer_t vulkan_raster_font; extern font_renderer_t caca_font; extern font_renderer_t gdi_font; +extern font_renderer_t vga_font; extern font_renderer_driver_t stb_font_renderer; extern font_renderer_driver_t stb_unicode_font_renderer; diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 46b3b6922c..d097f4639b 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -275,6 +275,9 @@ static const video_driver_t *video_drivers[] = { #endif #ifdef HAVE_CACA &video_caca, +#endif +#ifdef DJGPP + &video_vga, #endif &video_null, NULL, diff --git a/gfx/video_driver.h b/gfx/video_driver.h index 71fecbc2a9..054f7ff822 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -578,6 +578,7 @@ extern video_driver_t video_drm; extern video_driver_t video_xshm; extern video_driver_t video_caca; extern video_driver_t video_gdi; +extern video_driver_t video_vga; extern video_driver_t video_null; extern const void *frame_cache_data; diff --git a/griffin/griffin.c b/griffin/griffin.c index c2b5eb0e0f..570b6eba30 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -405,6 +405,10 @@ FONTS #include "../gfx/drivers_font/caca_font.c" #endif +#if defined(DJGPP) +#include "../gfx/drivers_font/vga_font.c" +#endif + #if defined(_WIN32) && !defined(_XBOX) #include "../gfx/drivers_font/gdi_font.c" #endif @@ -1000,6 +1004,10 @@ MENU #include "../menu/drivers_display/menu_display_caca.c" #endif +#ifdef DJGPP +#include "../menu/drivers_display/menu_display_vga.c" +#endif + #if defined(_WIN32) && !defined(_XBOX) #include "../menu/drivers_display/menu_display_gdi.c" #endif diff --git a/menu/drivers_display/menu_display_vga.c b/menu/drivers_display/menu_display_vga.c new file mode 100644 index 0000000000..cf99b8d3b4 --- /dev/null +++ b/menu/drivers_display/menu_display_vga.c @@ -0,0 +1,101 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2016 - Daniel De Matteis + * Copyright (C) 2016 - Brad Parker + * + * 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 "../../config.def.h" +#include "../../gfx/font_driver.h" +#include "../../gfx/video_context_driver.h" + +#include "../menu_display.h" + +static void *menu_display_vga_get_default_mvp(void) +{ + return NULL; +} + +static void menu_display_vga_blend_begin(void) +{ +} + +static void menu_display_vga_blend_end(void) +{ +} + +static void menu_display_vga_draw(void *data) +{ + (void)data; +} + +static void menu_display_vga_draw_pipeline(void *data) +{ + (void)data; +} + +static void menu_display_vga_viewport(void *data) +{ + (void)data; +} + +static void menu_display_vga_restore_clear_color(void) +{ +} + +static void menu_display_vga_clear_color(menu_display_ctx_clearcolor_t *clearcolor) +{ + (void)clearcolor; +} + +static bool menu_display_vga_font_init_first( + void **font_handle, void *video_data, + const char *font_path, float font_size) +{ + font_data_t **handle = (font_data_t**)font_handle; + *handle = font_driver_init_first(video_data, + font_path, font_size, true, FONT_DRIVER_RENDER_VGA); + return *handle; +} + +static const float *menu_display_vga_get_default_vertices(void) +{ + static float dummy[16] = {0.0f}; + return &dummy[0]; +} + +static const float *menu_display_vga_get_default_tex_coords(void) +{ + static float dummy[16] = {0.0f}; + return &dummy[0]; +} + +menu_display_ctx_driver_t menu_display_ctx_vga = { + menu_display_vga_draw, + menu_display_vga_draw_pipeline, + menu_display_vga_viewport, + menu_display_vga_blend_begin, + menu_display_vga_blend_end, + menu_display_vga_restore_clear_color, + menu_display_vga_clear_color, + menu_display_vga_get_default_mvp, + menu_display_vga_get_default_vertices, + menu_display_vga_get_default_tex_coords, + menu_display_vga_font_init_first, + MENU_VIDEO_DRIVER_VGA, + "menu_display_vga", +}; diff --git a/menu/menu_display.c b/menu/menu_display.c index d4549c7a42..89a675466e 100644 --- a/menu/menu_display.c +++ b/menu/menu_display.c @@ -85,6 +85,9 @@ static menu_display_ctx_driver_t *menu_display_ctx_drivers[] = { #endif #if defined(_WIN32) && !defined(_XBOX) &menu_display_ctx_gdi, +#endif +#ifdef DJGPP + &menu_display_ctx_vga, #endif &menu_display_ctx_null, NULL, @@ -147,6 +150,10 @@ static bool menu_display_check_compatibility( if (string_is_equal(video_driver, "gdi")) return true; break; + case MENU_VIDEO_DRIVER_VGA: + if (string_is_equal(video_driver, "vga")) + return true; + break; } return false; diff --git a/menu/menu_display.h b/menu/menu_display.h index ea32acf50d..e2d43afde5 100644 --- a/menu/menu_display.h +++ b/menu/menu_display.h @@ -97,7 +97,8 @@ enum menu_display_driver_type MENU_VIDEO_DRIVER_VITA2D, MENU_VIDEO_DRIVER_CTR, MENU_VIDEO_DRIVER_CACA, - MENU_VIDEO_DRIVER_GDI + MENU_VIDEO_DRIVER_GDI, + MENU_VIDEO_DRIVER_VGA }; typedef struct menu_display_ctx_clearcolor @@ -302,6 +303,7 @@ extern menu_display_ctx_driver_t menu_display_ctx_vita2d; extern menu_display_ctx_driver_t menu_display_ctx_ctr; extern menu_display_ctx_driver_t menu_display_ctx_caca; extern menu_display_ctx_driver_t menu_display_ctx_gdi; +extern menu_display_ctx_driver_t menu_display_ctx_vga; extern menu_display_ctx_driver_t menu_display_ctx_null; RETRO_END_DECLS