Merge branch 'master' into r5/sw-renderer-set-geometry

This commit is contained in:
rz5 2019-11-15 01:13:47 +00:00 committed by GitHub
commit 3dd62f96bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 290 additions and 175 deletions

View File

@ -1550,6 +1550,7 @@ static void InitCommon(std::vector<CDIF *> *_CDInterfaces, const bool EmulateMem
PSX_CPU = new PS_CPU();
PSX_SPU = new PS_SPU();
/* check_variables() has been previously called, we can now use psx_gpu_upscale_shift */
GPU_Init(content_is_pal, sls, sle, psx_gpu_upscale_shift);
PSX_CDC = new PS_CDC();
@ -1571,7 +1572,7 @@ static void InitCommon(std::vector<CDIF *> *_CDInterfaces, const bool EmulateMem
switch (psx_gpu_dither_mode)
{
case DITHER_NATIVE:
GPU_set_dither_upscale_shift(psx_gpu_upscale_shift);
GPU_set_dither_upscale_shift(GPU_get_upscale_shift());
break;
case DITHER_UPSCALED:
GPU_set_dither_upscale_shift(0);
@ -2651,13 +2652,11 @@ static bool old_cdimagecache = true;
static bool old_cdimagecache = false;
#endif
static bool boot = true;
// shared memory cards support
static bool shared_memorycards = false;
static bool shared_memorycards_toggle = false;
static void check_variables(bool startup)
static void check_variables(void)
{
struct retro_variable var = {0};
@ -2719,21 +2718,21 @@ static void check_variables(bool startup)
var.key = BEETLE_OPT(gpu_overclock);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
unsigned val = atoi(var.value);
// Upscale must be a power of two
assert((val & (val - 1)) == 0);
// Crappy "ffs" implementation since the standard function is not
// widely supported by libc in the wild
uint8_t n;
for (n = 0; (val & 1) == 0; ++n)
{
unsigned val = atoi(var.value);
// Upscale must be a power of two
assert((val & (val - 1)) == 0);
// Crappy "ffs" implementation since the standard function is not
// widely supported by libc in the wild
uint8_t n;
for (n = 0; (val & 1) == 0; ++n)
{
val >>= 1;
}
psx_gpu_overclock_shift = n;
val >>= 1;
}
psx_gpu_overclock_shift = n;
}
else
psx_gpu_overclock_shift = 0;
@ -2789,74 +2788,7 @@ static void check_variables(bool startup)
else
input_enable_calibration( false );
if (startup)
{
var.key = BEETLE_OPT(renderer);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (!strcmp(var.value, "software"))
{
var.key = BEETLE_OPT(internal_resolution);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
uint8_t new_upscale_shift;
uint8_t val = atoi(var.value);
// Upscale must be a power of two
assert((val & (val - 1)) == 0);
// Crappy "ffs" implementation since the standard function is not
// widely supported by libc in the wild
for (new_upscale_shift = 0; (val & 1) == 0; ++new_upscale_shift)
val >>= 1;
psx_gpu_upscale_shift = new_upscale_shift;
}
else
psx_gpu_upscale_shift = 0;
}
else
psx_gpu_upscale_shift = 0;
}
else
/* If 'BEETLE_OPT(renderer)' option is not found, then
* we are running in software mode */
psx_gpu_upscale_shift = 0;
}
else
{
rsx_intf_refresh_variables();
switch (rsx_intf_is_type())
{
case RSX_SOFTWARE:
var.key = BEETLE_OPT(internal_resolution);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
uint8_t new_upscale_shift;
uint8_t val = atoi(var.value);
// Upscale must be a power of two
assert((val & (val - 1)) == 0);
// Crappy "ffs" implementation since the standard function is not
// widely supported by libc in the wild
for (new_upscale_shift = 0; (val & 1) == 0; ++new_upscale_shift)
val >>= 1;
psx_gpu_upscale_shift = new_upscale_shift;
}
else
psx_gpu_upscale_shift = 0;
break;
case RSX_OPENGL:
case RSX_VULKAN:
psx_gpu_upscale_shift = 0;
break;
}
}
rsx_intf_refresh_variables();
var.key = BEETLE_OPT(dither_mode);
@ -3081,46 +3013,6 @@ static void check_variables(bool startup)
else
input_set_player_count( 2 );
var.key = BEETLE_OPT(use_mednafen_memcard0_method);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (strcmp(var.value, "libretro") == 0)
use_mednafen_memcard0_method = false;
else if (strcmp(var.value, "mednafen") == 0)
use_mednafen_memcard0_method = true;
}
//this option depends on beetle_psx_use_mednafen_memcard0_method being disabled so it should be evaluated that
var.key = BEETLE_OPT(shared_memory_cards);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (strcmp(var.value, "enabled") == 0)
{
if(boot)
{
if(use_mednafen_memcard0_method)
shared_memorycards_toggle = true;
}
else
{
if(use_mednafen_memcard0_method)
shared_memorycards_toggle = true;
}
}
else if (strcmp(var.value, "disabled") == 0)
{
if(boot)
shared_memorycards_toggle = false;
else
{
shared_memorycards = false;
}
}
}
var.key = BEETLE_OPT(frame_duping);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
@ -3464,6 +3356,7 @@ bool retro_load_game(const struct retro_game_info *info)
{
char tocbasepath[4096];
bool ret = false;
is_startup = true;
if (failed_init)
return false;
@ -3484,10 +3377,26 @@ bool retro_load_game(const struct retro_game_info *info)
else
snprintf(retro_cd_path, sizeof(retro_cd_path), "%s", info->path);
check_variables(true);
/* make sure shared memory cards and save states are enabled only at startup */
struct retro_variable var = {0};
var.key = BEETLE_OPT(use_mednafen_memcard0_method);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (strcmp(var.value, "libretro") == 0)
use_mednafen_memcard0_method = false;
else if (strcmp(var.value, "mednafen") == 0)
use_mednafen_memcard0_method = true;
}
//make sure shared memory cards and save states are enabled only at startup
shared_memorycards = shared_memorycards_toggle;
/* this option depends on use_mednafen_memcard0_method being **enabled** */
var.key = BEETLE_OPT(shared_memory_cards);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (strcmp(var.value, "enabled") == 0 && use_mednafen_memcard0_method)
shared_memorycards = true;
else if (strcmp(var.value, "disabled") == 0)
shared_memorycards = false;
}
if (!MDFNI_LoadGame(retro_cd_path))
{
@ -3498,16 +3407,7 @@ bool retro_load_game(const struct retro_game_info *info)
MDFN_LoadGameCheats(NULL);
MDFNMP_InstallReadPatches();
alloc_surface();
#ifdef NEED_DEINTERLACER
PrevInterlaced = false;
deint.ClearState();
#endif
input_init();
boot = false;
input_init();
frame_count = 0;
internal_frame_count = 0;
@ -3524,9 +3424,16 @@ bool retro_load_game(const struct retro_game_info *info)
how to copy the ugui framebuffer to the hardware renderer side with rsx_intf calls,
so we don't have to force this anymore. */
force_software_renderer = true;
}
}
#ifdef NEED_DEINTERLACER
PrevInterlaced = false;
deint.ClearState();
#endif
ret = rsx_intf_open(content_is_pal, force_software_renderer);
check_variables();
alloc_surface();
/* Hide irrelevant core options */
switch (rsx_intf_is_type())
@ -3594,8 +3501,6 @@ bool retro_load_game(const struct retro_game_info *info)
option_display.key = BEETLE_OPT(display_vram);
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
option_display.key = BEETLE_OPT(crop_overscan);
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
option_display.key = BEETLE_OPT(image_offset);
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
option_display.key = BEETLE_OPT(image_crop);
@ -3667,34 +3572,24 @@ void retro_run(void)
rsx_intf_prepare_frame();
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
if (is_startup || environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
{
check_variables(false);
struct retro_system_av_info new_av_info;
/* Startup ends here */
is_startup = false;
check_variables();
/* Max width/height changed, need to call SET_SYSTEM_AV_INFO */
if (GPU_get_upscale_shift() != psx_gpu_upscale_shift)
/* Software renderer changed its upscale, the static MDFN_Surface needs to be recreated */
if (need_new_surface)
{
retro_get_system_av_info(&new_av_info);
if (environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &new_av_info))
{
// We successfully changed the frontend's resolution, we can
// apply the change immediately
GPU_Rescale(psx_gpu_upscale_shift);
alloc_surface();
has_new_geometry = false; /* New AV info also updates geometry */
}
else
{
/* Failed, we have to postpone the upscaling change */
psx_gpu_upscale_shift = GPU_get_upscale_shift();
}
alloc_surface();
need_new_surface = false;
}
struct retro_system_av_info new_av_info;
switch (psx_gpu_dither_mode)
{
case DITHER_NATIVE:
GPU_set_dither_upscale_shift(psx_gpu_upscale_shift);
GPU_set_dither_upscale_shift(GPU_get_upscale_shift());
break;
case DITHER_UPSCALED:
GPU_set_dither_upscale_shift(0);

View File

@ -5,7 +5,7 @@ bool content_is_pal = false;
retro_video_refresh_t video_cb;
retro_environment_t environ_cb;
uint8_t widescreen_hack;
uint8_t psx_gpu_upscale_shift;
uint8_t psx_gpu_upscale_shift; /* Used to keep track of the SW renderer upscale */
int lineRenderMode;
int filter_mode;
bool opaque_check;
@ -21,3 +21,5 @@ int initial_scanline = 0;
int initial_scanline_pal = 0;
int last_scanline = 239;
int last_scanline_pal = 287;
bool need_new_surface = false;
bool is_startup = true;

View File

@ -27,6 +27,13 @@ extern int initial_scanline;
extern int initial_scanline_pal;
extern int last_scanline;
extern int last_scanline_pal;
/* Warns the libretro implementation that it needs to update its static MDFN_Surface object */
extern bool need_new_surface;
/* Whether or not the libretro core is starting up i.e. not in retro_run()
* Prevents HW renderers from calling SET_SYSTEM_AV_INFO */
extern bool is_startup;
#ifdef __cplusplus
}

View File

@ -580,7 +580,7 @@ struct retro_core_option_definition option_defs_us[] = {
#endif
{
BEETLE_OPT(use_mednafen_memcard0_method),
"Memory Card 0 Method",
"Memory Card 0 Method (Restart)",
"Choose the save data format used for memory card 0. 'Libretro' is recommended. 'Mednafen' may be used for compatibility with the stand-alone version of Mednafen.",
{
{ "libretro", "Libretro" },

View File

@ -631,7 +631,7 @@ static uint16_t *VRAM_Alloc(uint8 upscale_shift)
void GPU_Init(bool pal_clock_and_tv,
int sls, int sle, uint8 upscale_shift)
{
GPU_set_upscale_shift(upscale_shift);
GPU.vram = VRAM_Alloc(upscale_shift);
int x, y, v;
@ -724,7 +724,8 @@ void GPU_Rescale(uint8 ushift)
}
/* Cleanup the old VRAM */
delete [] GPU.vram;
if (GPU.vram)
delete [] GPU.vram;
}
GPU.vram = NULL;
@ -2092,4 +2093,4 @@ void GPU_SetVisibleLines(int sls, int sle)
{
GPU.LineVisFirst = sls;
GPU.LineVisLast = sle;
}
}

View File

@ -443,8 +443,12 @@ static bool read_command(const CLIArguments &args, FILE *file, Device &device, R
auto w = read_u32(file);
auto h = read_u32(file);
auto depth_24bpp = read_u32(file);
auto is_pal = readu32(file);
auto is_480i = readu32(file);
auto width_mode = readu32(file);
renderer.set_display_mode({ x, y, w, h }, depth_24bpp != 0);
renderer.set_display_mode({ x, y, w, h }, depth_24bpp != 0, is_pal != 0, is_480i != 0,
static_cast<Renderer::WidthMode>(width_mode));
break;
}

View File

@ -675,6 +675,49 @@ void Renderer::mipmap_framebuffer()
}
}
Renderer::DisplayRect Renderer::compute_display_rect()
{
unsigned display_width;
unsigned display_height = (render_state.is_pal ? 288 : 240) * (render_state.is_480i ? 2 : 1);
int left_offset = 0;
unsigned clock_div = 10;
switch (render_state.width_mode)
{
case WidthMode::WIDTH_MODE_256:
clock_div = 10;
break;
case WidthMode::WIDTH_MODE_320:
clock_div = 8;
break;
case WidthMode::WIDTH_MODE_512:
clock_div = 5;
break;
case WidthMode::WIDTH_MODE_640:
clock_div = 4;
break;
case WidthMode::WIDTH_MODE_368:
clock_div = 7;
break;
}
if (render_state.crop_overscan)
{
// Horizontal crop amount is currently hardcoded. Future improvement could allow adjusting this.
display_width = 2560/clock_div;
left_offset = (render_state.horiz_start - 608) / (int) clock_div;
}
else
{
display_width = 2800/clock_div;
left_offset = (render_state.horiz_start - 488) / (int) clock_div;
}
int upper_offset = (render_state.vert_start - (render_state.is_pal ? 20 : 16)) * (render_state.is_480i ? 2 : 1);
return DisplayRect(left_offset, upper_offset, display_width, display_height);
}
ImageHandle Renderer::scanout_to_texture()
{
atlas.flush_render_pass();
@ -758,9 +801,13 @@ ImageHandle Renderer::scanout_to_texture()
bool scaled = !bpp24 && !ssaa;
unsigned render_scale = scaled ? scaling : 1;
auto display_rect = compute_display_rect();
auto info = ImageCreateInfo::render_target(
rect.width * (scaled ? scaling : 1),
rect.height * (scaled ? scaling : 1),
display_rect.width * render_scale,
display_rect.height * render_scale,
render_state.scanout_mode == ScanoutMode::ABGR1555_Dither ? VK_FORMAT_A1R5G5B5_UNORM_PACK16 : VK_FORMAT_R8G8B8A8_UNORM);
if (!reuseable_scanout ||
@ -779,6 +826,10 @@ ImageHandle Renderer::scanout_to_texture()
rp.num_color_attachments = 1;
rp.store_attachments = 1;
rp.clear_color[0] = {0, 0, 0, 0};
//rp.clear_color[0] = {60.0f/256.0f, 230.0f/256.0f, 60.0f/256.0f, 0};
rp.clear_attachments = 1;
cmd->image_barrier(*reuseable_scanout, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
@ -786,6 +837,16 @@ ImageHandle Renderer::scanout_to_texture()
cmd->begin_render_pass(rp);
cmd->set_quad_state();
auto old_vp = cmd->get_viewport();
VkViewport new_vp = {display_rect.x * (float) render_scale,
display_rect.y * (float) render_scale,
rect.width * (float) render_scale,
rect.height * (float) render_scale,
old_vp.minDepth,
old_vp.maxDepth};
cmd->set_viewport(new_vp);
bool dither = render_state.scanout_mode == ScanoutMode::ABGR1555_Dither;
if (bpp24)

View File

@ -60,6 +60,33 @@ public:
MDEC_YUV
};
enum class WidthMode
{
WIDTH_MODE_256 = 0,
WIDTH_MODE_320 = 1,
WIDTH_MODE_512 = 2,
WIDTH_MODE_640 = 3,
WIDTH_MODE_368 = 4
};
struct DisplayRect
{
// Unlike Rect, the x-y coordinates for a DisplayRect can be negative
int x = 0;
int y = 0;
unsigned width = 0;
unsigned height = 0;
DisplayRect() = default;
DisplayRect(int x, int y, unsigned width, unsigned height)
: x(x)
, y(y)
, width(width)
, height(height)
{
}
};
struct RenderState
{
Rect display_mode;
@ -73,6 +100,16 @@ public:
unsigned texture_offset_x = 0;
unsigned texture_offset_y = 0;
int vert_start = 0x10;
int vert_end = 0x100;
int horiz_start = 0x200;
int horiz_end = 0xC00;
bool is_pal = false;
bool is_480i = false;
WidthMode width_mode = WidthMode::WIDTH_MODE_320;
bool crop_overscan = false;
TextureMode texture_mode = TextureMode::None;
SemiTransparentMode semi_transparent = SemiTransparentMode::None;
ScanoutMode scanout_mode = ScanoutMode::ABGR1555_555;
@ -135,13 +172,35 @@ public:
void end_copy(Vulkan::BufferHandle handle);
void blit_vram(const Rect &dst, const Rect &src);
void set_display_mode(const Rect &rect, ScanoutMode mode)
void set_horizontal_display_range(int x1, int x2)
{
render_state.horiz_start = x1;
render_state.horiz_end = x2;
}
void set_vertical_display_range(int y1, int y2)
{
render_state.vert_start = y1;
render_state.vert_end = y2;
}
void set_display_mode(const Rect &rect, ScanoutMode mode, bool is_pal, bool is_480i, WidthMode width_mode)
{
if (rect != render_state.display_mode || render_state.scanout_mode != mode)
last_scanout.reset();
render_state.display_mode = rect;
render_state.scanout_mode = mode;
render_state.is_pal = is_pal;
render_state.is_480i = is_480i;
render_state.width_mode = width_mode;
}
void set_horizontal_overscan_cropping(bool crop_overscan)
{
render_state.crop_overscan = crop_overscan;
}
void set_display_filter(ScanoutFilter filter)
@ -444,6 +503,7 @@ private:
Vulkan::ImageHandle last_scanout;
Vulkan::ImageHandle reuseable_scanout;
DisplayRect compute_display_rect();
void mipmap_framebuffer();
Vulkan::BufferHandle quad;

View File

@ -2289,6 +2289,9 @@ static void rsx_gl_refresh_variables(void)
return;
}
if (is_startup)
return;
if (retro_refresh_variables(renderer))
{
/* The resolution has changed, we must tell the frontend
@ -3002,6 +3005,7 @@ static unsigned msaa = 1;
static bool mdec_yuv;
static vector<function<void ()>> defer;
static dither_mode dither_mode = DITHER_NATIVE;
static bool crop_overscan;
static retro_video_refresh_t video_refresh_cb;
@ -3201,6 +3205,15 @@ static void rsx_vulkan_refresh_variables(void)
dither_mode = DITHER_OFF;
}
var.key = BEETLE_OPT(crop_overscan);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (!strcmp(var.value, "enabled"))
crop_overscan = true;
else
crop_overscan = false;
}
var.key = BEETLE_OPT(widescreen_hack);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
@ -3210,6 +3223,10 @@ static void rsx_vulkan_refresh_variables(void)
widescreen_hack = false;
}
if (is_startup)
return;
// Changing crop_overscan will likely need to be included here in future geometry fixes
if ((old_scaling != scaling || old_super_sampling != super_sampling || old_msaa != msaa) && renderer)
{
retro_system_av_info info;
@ -3228,6 +3245,7 @@ static void rsx_vulkan_finalize_frame(const void *fb, unsigned width,
{
renderer->set_adaptive_smoothing(adaptive_smoothing);
renderer->set_dither_native_resolution(dither_mode == DITHER_NATIVE);
renderer->set_horizontal_overscan_cropping(crop_overscan);
if (renderer->get_scanout_mode() == Renderer::ScanoutMode::BGR24)
renderer->set_display_filter(mdec_yuv ? Renderer::ScanoutFilter::MDEC_YUV : Renderer::ScanoutFilter::None);
@ -3772,7 +3790,54 @@ void rsx_intf_refresh_variables(void)
switch (rsx_type)
{
case RSX_SOFTWARE:
{
struct retro_variable var = {0};
var.key = BEETLE_OPT(internal_resolution);
uint8_t old_psx_gpu_upscale_shift = GPU_get_upscale_shift();
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
uint8_t new_upscale_shift;
uint8_t val = atoi(var.value);
// Upscale must be a power of two
assert((val & (val - 1)) == 0);
// Crappy "ffs" implementation since the standard function is not
// widely supported by libc in the wild
for (new_upscale_shift = 0; (val & 1) == 0; ++new_upscale_shift)
val >>= 1;
psx_gpu_upscale_shift = new_upscale_shift;
}
else
psx_gpu_upscale_shift = 0;
/* According to the libretro spec, can't call set_av_info when not in retro_run() */
if (is_startup)
GPU_Rescale(psx_gpu_upscale_shift);
/* Max width/height changed, need to call SET_SYSTEM_AV_INFO */
else if (old_psx_gpu_upscale_shift != psx_gpu_upscale_shift)
{
retro_system_av_info info;
rsx_intf_get_system_av_info(&info);
if (environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &info))
{
/* We successfully changed the frontend's resolution, we can
apply the change immediately */
GPU_Rescale(psx_gpu_upscale_shift);
need_new_surface = true;
}
else
{
/* Failed, we have to postpone the upscaling change */
psx_gpu_upscale_shift = GPU_get_upscale_shift();
}
}
break;
}
case RSX_OPENGL:
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
if (static_renderer.inited)
@ -4034,7 +4099,16 @@ void rsx_intf_set_horizontal_display_range(uint16_t x1, uint16_t x2)
#endif
break;
case RSX_VULKAN:
//implement me for Vulkan and set HAVE_VULKAN define check
#if defined(HAVE_VULKAN)
if (renderer)
renderer->set_horizontal_display_range(x1, x2);
else
{
defer.push_back([=]() {
renderer->set_horizontal_display_range(x1, x2);
});
}
#endif
break;
}
}
@ -4063,7 +4137,16 @@ void rsx_intf_set_vertical_display_range(uint16_t y1, uint16_t y2)
#endif
break;
case RSX_VULKAN:
//implement me for Vulkan and set HAVE_VULKAN define check
#if defined(HAVE_VULKAN)
if (renderer)
renderer->set_vertical_display_range(y1, y2);
else
{
defer.push_back([=]() {
renderer->set_vertical_display_range(y1, y2);
});
}
#endif
break;
}
}
@ -4150,11 +4233,13 @@ void rsx_intf_set_display_mode(uint16_t x, uint16_t y,
case RSX_VULKAN:
#if defined(HAVE_VULKAN)
if (renderer)
renderer->set_display_mode({ x, y, w, h }, get_scanout_mode(depth_24bpp));
renderer->set_display_mode({ x, y, w, h }, get_scanout_mode(depth_24bpp), is_pal,
is_480i, static_cast<Renderer::WidthMode>(width_mode));
else
{
defer.push_back([=]() {
renderer->set_display_mode({ x, y, w, h }, get_scanout_mode(depth_24bpp));
renderer->set_display_mode({ x, y, w, h }, get_scanout_mode(depth_24bpp), is_pal,
is_480i, static_cast<Renderer::WidthMode>(width_mode));
});
}
#endif