diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 65953ebfe1..54e784c61d 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -167,6 +167,23 @@ "cStandard": "c11", "cppStandard": "c++11", "intelliSenseMode": "gcc-x64" + }, + { + "name": "ps2sdk-ee", + "includePath": [ + "${env:PS2DEV}/ps2sdk/common/include", + "${env:PS2DEV}/ps2sdk/ee/include", + "${env:PS2DEV}/gsKit/include", + "${workspaceFolder}/**" + ], + "defines": [ + "PS2", + "_EE" + ], + "compilerPath": "${env:PS2DEV}/ee/bin/mips64r5900el-ps2-elf-gcc", + "cStandard": "c11", + "cppStandard": "c++11", + "intelliSenseMode": "gcc-x64" } ], "version": 4 diff --git a/Makefile.ps2 b/Makefile.ps2 index 5dd46d0099..6e8f9af8ff 100644 --- a/Makefile.ps2 +++ b/Makefile.ps2 @@ -30,7 +30,7 @@ ASFLAGS = $(CFLAGS) RARCH_DEFINES += -DPS2 -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DHAVE_SCREENSHOTS -DHAVE_REWIND -DRARCH_CONSOLE -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_CHEATS RARCH_DEFINES += -DHAVE_ZLIB -DHAVE_NO_BUILTINZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_FILTERS_BUILTIN -DHAVE_7ZIP -D_7ZIP_ST -DHAVE_CC_RESAMPLER -DHAVE_AUDIOMIXER -RARCH_DEFINES += -DHAVE_VIDEO_FILTER -DHAVE_RGUI +RARCH_DEFINES += -DHAVE_WINDOW_OFFSET -DHAVE_VIDEO_FILTER -DHAVE_RGUI RARCH_DEFINES += -DHAVE_DSP_FILTER LDFLAGS += -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ports/lib -L. @@ -58,7 +58,7 @@ EE_OBJS += $(IRX_DIR)/mcman_irx.o $(IRX_DIR)/mcserv_irx.o EE_OBJS += $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/bdm_irx.o $(IRX_DIR)/bdmfs_vfat_irx.o $(IRX_DIR)/usbmass_bd_irx.o EE_OBJS += $(IRX_DIR)/libsd_irx.o $(IRX_DIR)/audsrv_irx.o EE_OBJS += $(IRX_DIR)/cdfs_irx.o -EE_OBJS += $(IRX_DIR)/ps2dev9_irx.o $(IRX_DIR)/ps2atad_irx.o $(IRX_DIR)/ps2hdd_irx.o $(IRX_DIR)/ps2fs_irx.o $(IRX_DIR)/poweroff_irx.o +EE_OBJS += $(IRX_DIR)/ps2dev9_irx.o $(IRX_DIR)/ps2atad_irx.o $(IRX_DIR)/ps2hdd_irx.o $(IRX_DIR)/ps2fs_irx.o $(IRX_DIR)/poweroff_irx.o EE_OBJS += $(IRX_DIR)/mtapman_irx.o $(IRX_DIR)/padman_irx.o # Missing objecst on the PS2SDK diff --git a/config.def.h b/config.def.h index fec65fdee6..514b486ef9 100644 --- a/config.def.h +++ b/config.def.h @@ -280,6 +280,12 @@ #define DEFAULT_FULLSCREEN_Y 0 #endif +#if defined(HAVE_WINDOW_OFFSET) +/* Screen offsets to center content in CTRs */ +#define DEFAULT_WINDOW_OFFSET_X 0 +#define DEFAULT_WINDOW_OFFSET_Y 0 +#endif + /* Number of threads to use for video recording */ #define DEFAULT_VIDEO_RECORD_THREADS 2 diff --git a/configuration.c b/configuration.c index a791b3c2e4..c3fadc4136 100644 --- a/configuration.c +++ b/configuration.c @@ -2327,6 +2327,10 @@ static struct config_int_setting *populate_settings_int( #endif #ifdef HAVE_D3D12 SETTING_INT("d3d12_gpu_index", &settings->ints.d3d12_gpu_index, true, DEFAULT_D3D12_GPU_INDEX, false); +#endif +#ifdef HAVE_WINDOW_OFFSET + SETTING_INT("video_window_offset_x", &settings->ints.video_window_offset_x, true, DEFAULT_WINDOW_OFFSET_X, false); + SETTING_INT("video_window_offset_y", &settings->ints.video_window_offset_y, true, DEFAULT_WINDOW_OFFSET_Y, false); #endif SETTING_INT("content_favorites_size", &settings->ints.content_favorites_size, true, default_content_favorites_size, false); diff --git a/configuration.h b/configuration.h index 37a2c7ae70..002318b724 100644 --- a/configuration.h +++ b/configuration.h @@ -140,6 +140,10 @@ typedef struct settings #endif #ifdef HAVE_D3D12 int d3d12_gpu_index; +#endif +#ifdef HAVE_WINDOW_OFFSET + int video_window_offset_x; + int video_window_offset_y; #endif int content_favorites_size; } ints; diff --git a/gfx/common/win32_common.c b/gfx/common/win32_common.c index f4bd98a052..c2f5b574df 100644 --- a/gfx/common/win32_common.c +++ b/gfx/common/win32_common.c @@ -2527,7 +2527,7 @@ bool win32_get_video_output(DEVMODE *dm, int mode, size_t len) return true; } -void win32_get_video_output_size(unsigned *width, unsigned *height) +void win32_get_video_output_size(unsigned *width, unsigned *height, char *desc, size_t desc_len) { DEVMODE dm; diff --git a/gfx/common/win32_common.h b/gfx/common/win32_common.h index 9ad09c6509..8b9ec39eb3 100644 --- a/gfx/common/win32_common.h +++ b/gfx/common/win32_common.h @@ -113,7 +113,7 @@ void win32_set_window(unsigned *width, unsigned *height, bool fullscreen, bool windowed_full, void *rect_data); void win32_get_video_output_size( - unsigned *width, unsigned *height); + unsigned *width, unsigned *height, char *desc, size_t desc_len); void win32_get_video_output_prev( unsigned *width, unsigned *height); diff --git a/gfx/drivers/d3d10.c b/gfx/drivers/d3d10.c index 4968f7e3ee..9e0409c6db 100644 --- a/gfx/drivers/d3d10.c +++ b/gfx/drivers/d3d10.c @@ -1750,9 +1750,9 @@ static uint32_t d3d10_get_flags(void *data) #ifndef __WINRT__ static void d3d10_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { - win32_get_video_output_size(width, height); + win32_get_video_output_size(width, height, desc, desc_len); } static void d3d10_get_video_output_prev(void *data) diff --git a/gfx/drivers/d3d11.c b/gfx/drivers/d3d11.c index 928d36430c..914662205e 100644 --- a/gfx/drivers/d3d11.c +++ b/gfx/drivers/d3d11.c @@ -2325,9 +2325,9 @@ static bool d3d11_get_hw_render_interface( #ifndef __WINRT__ static void d3d11_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { - win32_get_video_output_size(width, height); + win32_get_video_output_size(width, height, desc, desc_len); } static void d3d11_get_video_output_prev(void *data) diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c index 0d2e7c688e..83eba32d17 100644 --- a/gfx/drivers/d3d12.c +++ b/gfx/drivers/d3d12.c @@ -2208,9 +2208,9 @@ static uint32_t d3d12_get_flags(void *data) #ifndef __WINRT__ static void d3d12_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { - win32_get_video_output_size(width, height); + win32_get_video_output_size(width, height, desc, desc_len); } static void d3d12_get_video_output_prev(void *data) diff --git a/gfx/drivers/fpga_gfx.c b/gfx/drivers/fpga_gfx.c index 5578912913..3566315b13 100644 --- a/gfx/drivers/fpga_gfx.c +++ b/gfx/drivers/fpga_gfx.c @@ -349,7 +349,7 @@ static void fpga_set_osd_msg(void *data, } static void fpga_get_video_output_size(void *data, - unsigned *width, unsigned *height) { } + unsigned *width, unsigned *height, char *desc, size_t desc_len) { } static void fpga_get_video_output_prev(void *data) { } static void fpga_get_video_output_next(void *data) { } diff --git a/gfx/drivers/gdi_gfx.c b/gfx/drivers/gdi_gfx.c index 2e6a8b1a02..953a7606cb 100644 --- a/gfx/drivers/gdi_gfx.c +++ b/gfx/drivers/gdi_gfx.c @@ -684,9 +684,9 @@ static void gdi_unload_texture(void *data, static uint32_t gdi_get_flags(void *data) { return 0; } static void gdi_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { - win32_get_video_output_size(width, height); + win32_get_video_output_size(width, height, desc, desc_len); } static void gdi_get_video_output_prev(void *data) diff --git a/gfx/drivers/gl1.c b/gfx/drivers/gl1.c index b4af249385..7a6e994ca8 100644 --- a/gfx/drivers/gl1.c +++ b/gfx/drivers/gl1.c @@ -1214,14 +1214,14 @@ static void gl1_set_texture_frame(void *data, } static void gl1_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { gl1_t *gl = (gl1_t*)data; if (!gl || !gl->ctx_driver || !gl->ctx_driver->get_video_output_size) return; gl->ctx_driver->get_video_output_size( gl->ctx_data, - width, height); + width, height, desc, desc_len); } static void gl1_get_video_output_prev(void *data) diff --git a/gfx/drivers/gl2.c b/gfx/drivers/gl2.c index d9083e7ae9..f499749a18 100644 --- a/gfx/drivers/gl2.c +++ b/gfx/drivers/gl2.c @@ -4417,14 +4417,14 @@ static void gl2_apply_state_changes(void *data) } static void gl2_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { gl2_t *gl = (gl2_t*)data; if (!gl || !gl->ctx_driver || !gl->ctx_driver->get_video_output_size) return; gl->ctx_driver->get_video_output_size( gl->ctx_data, - width, height); + width, height, desc, desc_len); } static void gl2_get_video_output_prev(void *data) diff --git a/gfx/drivers/gl3.c b/gfx/drivers/gl3.c index c62631fdf3..fe2a150ecf 100644 --- a/gfx/drivers/gl3.c +++ b/gfx/drivers/gl3.c @@ -2221,14 +2221,14 @@ static void gl_core_set_texture_enable(void *data, bool state, bool full_screen) } static void gl_core_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { gl_core_t *gl = (gl_core_t*)data; if (!gl || !gl->ctx_driver || !gl->ctx_driver->get_video_output_size) return; gl->ctx_driver->get_video_output_size( gl->ctx_data, - width, height); + width, height, desc, desc_len); } static void gl_core_get_video_output_prev(void *data) diff --git a/gfx/drivers/gx_gfx.c b/gfx/drivers/gx_gfx.c index 0f7aedfc1f..21c43a9247 100644 --- a/gfx/drivers/gx_gfx.c +++ b/gfx/drivers/gx_gfx.c @@ -600,7 +600,7 @@ static void gx_set_aspect_ratio(void *data, unsigned aspect_ratio_idx) } static void gx_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { global_t *global = global_get_ptr(); if (!global) @@ -621,6 +621,7 @@ static void gx_get_video_output_size(void *data, static void setup_video_mode(gx_video_t *gx) { unsigned width, height; + char desc[64] = {0}; if (!gx->framebuf[0]) { @@ -633,7 +634,7 @@ static void setup_video_mode(gx_video_t *gx) gx->orientation = ORIENTATION_NORMAL; OSInitThreadQueue(&g_video_cond); - gx_get_video_output_size(gx, &width, &height); + gx_get_video_output_size(gx, &width, &height, desc, sizeof(desc)); gx_set_video_mode(gx, width, height, true); } diff --git a/gfx/drivers/network_gfx.c b/gfx/drivers/network_gfx.c index d42bb02169..3243b1e359 100644 --- a/gfx/drivers/network_gfx.c +++ b/gfx/drivers/network_gfx.c @@ -424,7 +424,7 @@ static void network_set_texture_frame(void *data, } static void network_get_video_output_size(void *data, - unsigned *width, unsigned *height) { } + unsigned *width, unsigned *height, char *desc, size_t desc_len) { } static void network_get_video_output_prev(void *data) { } static void network_get_video_output_next(void *data) { } diff --git a/gfx/drivers/ps2_gfx.c b/gfx/drivers/ps2_gfx.c index f4d32b1e50..92936894ef 100644 --- a/gfx/drivers/ps2_gfx.c +++ b/gfx/drivers/ps2_gfx.c @@ -24,12 +24,40 @@ #include "../../libretro-common/include/libretro_gskit_ps2.h" /* Generic tint color */ -#define GS_TEXT GS_SETREG_RGBA(0x80,0x80,0x80,0x80) +#define GS_TEXT GS_SETREG_RGBA(0x80, 0x80, 0x80, 0x80) /* turn black GS Screen */ -#define GS_BLACK GS_SETREG_RGBA(0x00,0x00,0x00,0x80) +#define GS_BLACK GS_SETREG_RGBA(0x00, 0x00, 0x00, 0x80) -#define NTSC_WIDTH 640 -#define NTSC_HEIGHT 448 +#define NUM_RM_VMODES 7 +#define PS2_RESOLUTION_LAST NUM_RM_VMODES - 1 +#define RM_VMODE_AUTO 0 + +/* RM Vmode -> GS Vmode conversion table */ +struct rm_mode +{ + char mode; + short int width; + short int height; + short int VCK; + short int interlace; + short int field; + short int PAR1; /* Pixel Aspect Ratio 1 (For video modes with non-square pixels, like PAL/NTSC) */ + short int PAR2; /* Pixel Aspect Ratio 2 (For video modes with non-square pixels, like PAL/NTSC) */ + char *desc; +}; + +static struct rm_mode rm_mode_table[NUM_RM_VMODES] = { + /* SDTV modes */ + {-1, 704, -1, 4, GS_INTERLACED, GS_FIELD, -1, 11, "AUTO"}, + {GS_MODE_PAL, 704, 576, 4, GS_INTERLACED, GS_FIELD, 12, 11, "PAL@50Hz"}, + {GS_MODE_NTSC, 704, 480, 4, GS_INTERLACED, GS_FIELD, 10, 11, "NTSC@60Hz"}, + /* SDTV special modes */ + {GS_MODE_PAL, 704, 288, 4, GS_NONINTERLACED, GS_FRAME, 12, 22, "PAL@50Hz-288p"}, + {GS_MODE_NTSC, 704, 240, 4, GS_NONINTERLACED, GS_FRAME, 10, 22, "NTSC@60Hz-240p"}, + /* EDTV modes (component cable!) */ + {GS_MODE_DTV_480P, 704, 480, 2, GS_NONINTERLACED, GS_FRAME, 10, 11, "DTV480P@60Hz"}, + {GS_MODE_DTV_576P, 704, 576, 2, GS_NONINTERLACED, GS_FRAME, 12, 11, "DTV576P@50Hz"}, +}; typedef struct ps2_video { @@ -41,9 +69,13 @@ typedef struct ps2_video int vsync_callback_id; bool force_aspect; + int8_t vmode; + int video_window_offset_x; + int video_window_offset_y; + int PSM; + int tex_filter; int menu_filter; - int core_filter; video_viewport_t vp; @@ -53,6 +85,17 @@ typedef struct ps2_video GSGLOBAL *gsGlobal; GSTEXTURE *menuTexture; GSTEXTURE *coreTexture; + + /* Last scaling state, for detecting changes */ + int iTextureWidth; + int iTextureHeight; + float fDAR; + bool bScaleInteger; + struct retro_hw_ps2_insets padding; + + /* Current scaling calculation result */ + int iDisplayWidth; + int iDisplayHeight; } ps2_video_t; static int vsync_sema_id; @@ -66,50 +109,33 @@ static int vsync_handler() return 0; } -static GSGLOBAL *init_GSGlobal(void) +static void rmEnd(ps2_video_t *ps2) { - ee_sema_t sema; - sema.init_count = 0; - sema.max_count = 1; - sema.option = 0; - vsync_sema_id = CreateSema(&sema); + if (!ps2->gsGlobal) + return; - GSGLOBAL *gsGlobal = gsKit_init_global(); - - gsGlobal->Mode = GS_MODE_NTSC; - gsGlobal->Interlace = GS_INTERLACED; - gsGlobal->Field = GS_FIELD; - gsGlobal->Width = NTSC_WIDTH; - gsGlobal->Height = NTSC_HEIGHT; - - gsGlobal->PSM = GS_PSM_CT16; - gsGlobal->PSMZ = GS_PSMZ_16; - gsGlobal->DoubleBuffering = GS_SETTING_OFF; - gsGlobal->ZBuffering = GS_SETTING_OFF; - gsGlobal->PrimAlphaEnable = GS_SETTING_OFF; - - dmaKit_init(D_CTRL_RELE_OFF,D_CTRL_MFD_OFF, D_CTRL_STS_UNSPEC, - D_CTRL_STD_OFF, D_CTRL_RCYC_8, 1 << DMA_CHANNEL_GIF); - - /* Initialize the DMAC */ - dmaKit_chan_init(DMA_CHANNEL_GIF); - - gsKit_init_screen(gsGlobal); - gsKit_mode_switch(gsGlobal, GS_ONESHOT); - - gsKit_set_test(gsGlobal, GS_ZTEST_OFF); - gsKit_set_primalpha(gsGlobal, GS_SETREG_ALPHA(0, 1, 0, 1, 0), 0); - - gsKit_clear(gsGlobal, GS_BLACK); - - return gsGlobal; + gsKit_deinit_global(ps2->gsGlobal); + gsKit_remove_vsync_handler(ps2->vsync_callback_id); } -static void deinit_GSGlobal(GSGLOBAL *gsGlobal) +static void updateOffSetsIfNeeded(ps2_video_t *ps2) { - gsKit_clear(gsGlobal, GS_BLACK); - gsKit_vram_clear(gsGlobal); - gsKit_deinit_global(gsGlobal); + bool shouldUpdate = false; + settings_t *settings = config_get_ptr(); + int video_window_offset_x = settings->ints.video_window_offset_x; + int video_window_offset_y = settings->ints.video_window_offset_y; + + if (video_window_offset_x != ps2->video_window_offset_x || video_window_offset_y != ps2->video_window_offset_y) + shouldUpdate = true; + + if (!shouldUpdate) + return; + + ps2->video_window_offset_x = video_window_offset_x; + ps2->video_window_offset_y = video_window_offset_y; + + gsKit_set_display_offset(ps2->gsGlobal, ps2->video_window_offset_x * rm_mode_table[ps2->vmode].VCK, ps2->video_window_offset_y); + RARCH_LOG("PS2_GFX Change offset: %d, %d\n", ps2->video_window_offset_x, ps2->video_window_offset_y); } /* Copy of gsKit_sync_flip, but without the 'flip' */ @@ -118,7 +144,8 @@ static void gsKit_sync(GSGLOBAL *gsGlobal) if (!gsGlobal->FirstFrame) WaitSema(vsync_sema_id); - while (PollSema(vsync_sema_id) >= 0); + while (PollSema(vsync_sema_id) >= 0) + ; } /* Copy of gsKit_sync_flip, but without the 'sync' */ @@ -128,131 +155,292 @@ static void gsKit_flip(GSGLOBAL *gsGlobal) { if (gsGlobal->DoubleBuffering == GS_SETTING_ON) { - GS_SET_DISPFB2( gsGlobal->ScreenBuffer[ - gsGlobal->ActiveBuffer & 1] / 8192, - gsGlobal->Width / 64, gsGlobal->PSM, 0, 0 ); + GS_SET_DISPFB2(gsGlobal->ScreenBuffer[gsGlobal->ActiveBuffer & 1] / 8192, + gsGlobal->Width / 64, gsGlobal->PSM, 0, 0); gsGlobal->ActiveBuffer ^= 1; } - } gsKit_setactive(gsGlobal); } +static void rmSetMode(ps2_video_t *ps2, int force) +{ + struct rm_mode *mode; + global_t *global = global_get_ptr(); + + /* we don't want to set the vmode without a reason... */ + if (ps2->vmode == global->console.screen.resolutions.current.id && force == 0) + return; + + /* Cleanup previous gsKit instance */ + if (ps2->vmode >= 0) + { + rmEnd(ps2); + /* Set new mode */ + global->console.screen.resolutions.current.id = ps2->vmode; + } + else + /* first driver init */ + ps2->vmode = global->console.screen.resolutions.current.id; + + mode = &rm_mode_table[ps2->vmode]; + + /* Invalidate scaling state */ + ps2->iTextureWidth = 0; + ps2->iTextureHeight = 0; + + ps2->gsGlobal = gsKit_init_global(); + gsKit_TexManager_setmode(ps2->gsGlobal, ETM_DIRECT); + ps2->vsync_callback_id = gsKit_add_vsync_handler(vsync_handler); + ps2->gsGlobal->Mode = mode->mode; + ps2->gsGlobal->Width = mode->width; + ps2->gsGlobal->Height = mode->height; + ps2->gsGlobal->Interlace = mode->interlace; + ps2->gsGlobal->Field = mode->field; + ps2->gsGlobal->PSM = GS_PSM_CT16; + ps2->gsGlobal->PSMZ = GS_PSMZ_16S; + ps2->gsGlobal->DoubleBuffering = GS_SETTING_ON; + ps2->gsGlobal->ZBuffering = GS_SETTING_OFF; + ps2->gsGlobal->PrimAlphaEnable = GS_SETTING_OFF; + + if ((ps2->gsGlobal->Interlace == GS_INTERLACED) && (ps2->gsGlobal->Field == GS_FRAME)) + ps2->gsGlobal->Height /= 2; + + /* Coordinate space ranges from 0 to 4096 pixels + * Center the buffer in the coordinate space */ + ps2->gsGlobal->OffsetX = ((4096 - ps2->gsGlobal->Width) / 2) * 16; + ps2->gsGlobal->OffsetY = ((4096 - ps2->gsGlobal->Height) / 2) * 16; + + gsKit_init_screen(ps2->gsGlobal); + gsKit_mode_switch(ps2->gsGlobal, GS_ONESHOT); + + gsKit_set_test(ps2->gsGlobal, GS_ZTEST_OFF); + gsKit_set_test(ps2->gsGlobal, GS_ATEST_OFF); + + /* reset the contents of the screen to avoid garbage being displayed */ + gsKit_clear(ps2->gsGlobal, GS_BLACK); + gsKit_sync(ps2->gsGlobal); + gsKit_flip(ps2->gsGlobal); + + RARCH_LOG("PS2_GFX New vmode: %d, %d x %d\n", ps2->vmode, ps2->gsGlobal->Width, ps2->gsGlobal->Height); + + updateOffSetsIfNeeded(ps2); +} + +static void rmInit(ps2_video_t *ps2) +{ + ee_sema_t sema; + sema.init_count = 0; + sema.max_count = 1; + sema.option = 0; + vsync_sema_id = CreateSema(&sema); + + short int mode = gsKit_check_rom(); + + rm_mode_table[RM_VMODE_AUTO].mode = mode; + rm_mode_table[RM_VMODE_AUTO].height = (mode == GS_MODE_PAL) ? 576 : 480; + rm_mode_table[RM_VMODE_AUTO].PAR1 = (mode == GS_MODE_PAL) ? 12 : 10; + + dmaKit_init(D_CTRL_RELE_OFF, D_CTRL_MFD_OFF, D_CTRL_STS_UNSPEC, + D_CTRL_STD_OFF, D_CTRL_RCYC_8, 1 << DMA_CHANNEL_GIF); + + /* Initialize the DMAC */ + dmaKit_chan_init(DMA_CHANNEL_GIF); + + rmSetMode(ps2, 1); +} + static GSTEXTURE *prepare_new_texture(void) { - GSTEXTURE *texture = (GSTEXTURE*)calloc(1, sizeof(GSTEXTURE)); + GSTEXTURE *texture = (GSTEXTURE *)calloc(1, sizeof(GSTEXTURE)); return texture; } static void init_ps2_video(ps2_video_t *ps2) { - ps2->gsGlobal = init_GSGlobal(); - gsKit_TexManager_init(ps2->gsGlobal); + ps2->vmode = -1; + rmInit(ps2); - ps2->vp.x = 0; - ps2->vp.y = 0; - ps2->vp.width = ps2->gsGlobal->Width; - ps2->vp.height = ps2->gsGlobal->Height; - ps2->vp.full_width = ps2->gsGlobal->Width; - ps2->vp.full_height = ps2->gsGlobal->Height; + ps2->vp.x = 0; + ps2->vp.y = 0; + ps2->vp.width = ps2->gsGlobal->Width; + ps2->vp.height = ps2->gsGlobal->Height; + ps2->vp.full_width = ps2->gsGlobal->Width; + ps2->vp.full_height = ps2->gsGlobal->Height; - ps2->vsync_callback_id = gsKit_add_vsync_handler(vsync_handler); ps2->menuTexture = prepare_new_texture(); ps2->coreTexture = prepare_new_texture(); + ps2->video_window_offset_x = 0; + ps2->video_window_offset_y = 0; + /* Used for cores that supports palette */ - ps2->iface.interface_type = RETRO_HW_RENDER_INTERFACE_GSKIT_PS2; + ps2->iface.interface_type = RETRO_HW_RENDER_INTERFACE_GSKIT_PS2; ps2->iface.interface_version = RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION; - ps2->iface.coreTexture = ps2->coreTexture; + ps2->iface.coreTexture = ps2->coreTexture; } static void ps2_gfx_deinit_texture(GSTEXTURE *texture) { - texture->Mem = NULL; + texture->Mem = NULL; texture->Clut = NULL; } static void set_texture(GSTEXTURE *texture, const void *frame, - int width, int height, int PSM, int filter) + int width, int height, int PSM, int filter) { - texture->Width = width; + texture->Width = width; texture->Height = height; - texture->PSM = PSM; + texture->PSM = PSM; texture->Filter = filter; - texture->Mem = (void *)frame; + texture->Mem = (void *)frame; } -static void prim_texture(GSGLOBAL *gsGlobal, GSTEXTURE *texture, int zPosition, float aspect_ratio, bool scale_integer, struct retro_hw_ps2_insets padding) +static int ABS(int v) { - float x1, y1, x2, y2; - float visible_width = texture->Width - padding.left - padding.right; - float visible_height = texture->Height - padding.top - padding.bottom; + return (v >= 0) ? v : -v; +} - if (scale_integer) +static void setupScalingMode(ps2_video_t *ps2, int iWidth, int iHeight, float fDAR, bool bScaleInteger) +{ + GSGLOBAL *gsGlobal = ps2->gsGlobal; + struct rm_mode *currMode = &rm_mode_table[ps2->vmode]; + int iBestFBWidth = currMode->width; + int iBestMagH = currMode->VCK - 1; + float fPAR; + + /* Calculate the pixel aspect ratio (PAR) */ + fPAR = (float)currMode->PAR2 / (float)currMode->PAR1; + +#if defined(DEBUG) + printf("Aspect ratio: %.4f x %.4f = %.4f\n", fDAR, fPAR, fDAR * fPAR); +#endif + + if (bScaleInteger == false) { - float width_proportion = (float)gsGlobal->Width / (float)visible_width; - float height_proportion = (float)gsGlobal->Height / (float)visible_height; - int delta = MIN(width_proportion, height_proportion); - float newWidth = visible_width * delta; - float newHeight = visible_height * delta; - - x1 = (gsGlobal->Width - newWidth) / 2.0f; - y1 = (gsGlobal->Height - newHeight) / 2.0f; - x2 = newWidth + x1; - y2 = newHeight + y1; - } - else if (aspect_ratio > 0) - { - float gs_aspect_ratio = (float)gsGlobal->Width / (float)gsGlobal->Height; - float newWidth = (gs_aspect_ratio > aspect_ratio) ? gsGlobal->Height * aspect_ratio : gsGlobal->Width; - float newHeight = (gs_aspect_ratio > aspect_ratio) ? gsGlobal->Height : gsGlobal->Width / aspect_ratio; - - x1 = (gsGlobal->Width - newWidth) / 2.0f; - y1 = (gsGlobal->Height - newHeight) / 2.0f; - x2 = newWidth + x1; - y2 = newHeight + y1; + /* Assume black bars left/right */ + ps2->iDisplayHeight = currMode->height; + ps2->iDisplayWidth = (int)((float)ps2->iDisplayHeight * fDAR * fPAR + 0.5f); + if (ps2->iDisplayWidth > currMode->width) + { + /* Really wide screen, black bars top/bottom */ + ps2->iDisplayWidth = currMode->width; + ps2->iDisplayHeight = (int)((float)ps2->iDisplayWidth / (fDAR * fPAR) + 0.5f); + } } else { - x1 = 0.0f; - y1 = 0.0f; - x2 = gsGlobal->Width; - y2 = gsGlobal->Height; + /* Best match the framebuffer width/height to a multiple of the texture + * Width, rounded down so it always fits */ + int iHeightScale = MAX(1, currMode->height / iHeight); + ps2->iDisplayHeight = iHeight * iHeightScale; + /* Height, rounded */ + int iWidthScale = MAX(1, (int)((float)ps2->iDisplayHeight * fDAR * fPAR + (float)(iWidth / 2)) / iWidth); + ps2->iDisplayWidth = iWidth * iWidthScale; + +#if defined(DEBUG) + printf("Integer scaling:\n"); + printf("- Width = %d x %d = %d\n", iWidth, iWidthScale, ps2->iDisplayWidth); + printf("- Height = %d x %d = %d\n", iHeight, iHeightScale, ps2->iDisplayHeight); +#endif + + if (currMode->VCK > 1 && ps2->iDisplayWidth < currMode->width) + { + /* We try to best match the number of "VCK" units, for the best output + * For 576i/480i: 1 pixel = 4 VCK (4x super-resolution) + * For 576p/480p: 1 pixel = 2 VCK (2x super-resolution) */ + int iTargetVCK = (int)((float)ps2->iDisplayHeight * fDAR * fPAR * (float)currMode->VCK + 0.5f); + int iBestVCK = ps2->iDisplayWidth * currMode->VCK; + /* Try all possible framebuffer widths */ +#if defined(DEBUG) + printf("Find match for %d * SCALE * MagH = %d VCK (current = %d VCK)\n", iWidth, iTargetVCK, iBestVCK); +#endif + int iFBWidth; + for (iFBWidth = 64; iFBWidth <= currMode->width; iFBWidth += 64) + { + /* Ignore too small framebuffers */ + if (iFBWidth < iWidth) + continue; + + iWidthScale = iFBWidth / iWidth; + + /* Try all possible magnifications */ + int iMagH; + for (iMagH = 0; iMagH < 15; iMagH++) + { + int iVCK = iWidth * iWidthScale * (iMagH + 1); + if (ABS(iTargetVCK - iVCK) < ABS(iTargetVCK - iBestVCK)) + { +#if defined(DEBUG) + printf("- found %d * %d * %d = %d\n", iWidth, iWidthScale, iMagH + 1, iVCK); +#endif + + /* Better match */ + iBestVCK = iVCK; + iBestFBWidth = iFBWidth; + iBestMagH = iMagH; + ps2->iDisplayWidth = iWidth * iWidthScale; + } + } + } + } } - gsKit_prim_sprite_texture( gsGlobal, texture, - x1, /* X1 */ - y1, /* Y1 */ - padding.left, /* U1 */ - padding.top, /* V1 */ - x2, /* X2 */ - y2, /* Y2 */ - texture->Width - padding.right, /* U2 */ - texture->Height - padding.bottom, /* V2 */ - zPosition, - GS_TEXT); -} + if ((gsGlobal->Interlace == GS_INTERLACED) && (gsGlobal->Field == GS_FRAME)) + ps2->iDisplayHeight /= 2; -static void refreshScreen(ps2_video_t *ps2) -{ - if (ps2->vsync) - { - gsKit_sync(ps2->gsGlobal); - gsKit_flip(ps2->gsGlobal); - } - gsKit_queue_exec(ps2->gsGlobal); - gsKit_TexManager_nextFrame(ps2->gsGlobal); +#if defined(DEBUG) + printf("Texture resolution:\n"); + printf("- Width = %d x %.2f = %d\n", iWidth, (float)ps2->iDisplayWidth / (float)iWidth, ps2->iDisplayWidth); + printf("- Height = %d x %.2f = %d\n", iHeight, (float)ps2->iDisplayHeight / (float)iHeight, ps2->iDisplayHeight); + printf("Setting custom framebuffer:\n"); + printf("- Width = %d x %d / %d = %d\n", iBestFBWidth, iBestMagH + 1, currMode->VCK, iBestFBWidth * (iBestMagH + 1) / currMode->VCK); + printf("- Height = %d x %d = %d\n", currMode->height, gsGlobal->MagV + 1, currMode->height * (gsGlobal->MagV + 1)); +#endif + + /* Center on screen by adding the difference (in VCK units). */ + gsGlobal->StartX += (gsGlobal->Width * (gsGlobal->MagH + 1) - iBestFBWidth * (iBestMagH + 1)) / 2; + /* Calculate the actual display width and height, again */ + gsGlobal->DW = (iBestMagH + 1) * iBestFBWidth; + /* Override magh */ + gsGlobal->MagH = iBestMagH; + + /* Reset VRAM allocation */ + gsGlobal->CurrentPointer = 0; + /* Allocate new framebuffer(s) */ + gsGlobal->ScreenBuffer[0] = gsKit_vram_alloc(gsGlobal, gsKit_texture_size(iBestFBWidth, currMode->height, gsGlobal->PSM), GSKIT_ALLOC_SYSBUFFER); + if (gsGlobal->DoubleBuffering == GS_SETTING_ON) + gsGlobal->ScreenBuffer[1] = gsKit_vram_alloc(gsGlobal, gsKit_texture_size(iBestFBWidth, currMode->height, gsGlobal->PSM), GSKIT_ALLOC_SYSBUFFER); + /* Set the new framebuffer as display buffer */ + gsGlobal->Width = iBestFBWidth; + gsKit_display_buffer(gsGlobal); + + /* Update DISPLAY1/2 register (code from gsKit) */ + GS_SET_DISPLAY1( + gsGlobal->StartX + gsGlobal->StartXOffset, + gsGlobal->StartY + gsGlobal->StartYOffset, + gsGlobal->MagH, + gsGlobal->MagV, + gsGlobal->DW - 1, + gsGlobal->DH - 1); + GS_SET_DISPLAY2( + gsGlobal->StartX + gsGlobal->StartXOffset, + gsGlobal->StartY + gsGlobal->StartYOffset, + gsGlobal->MagH, + gsGlobal->MagV, + gsGlobal->DW - 1, + gsGlobal->DH - 1); } static void *ps2_gfx_init(const video_info_t *video, - input_driver_t **input, void **input_data) + input_driver_t **input, void **input_data) { - void *ps2input = NULL; - ps2_video_t *ps2 = (ps2_video_t*)calloc(1, sizeof(ps2_video_t)); + void *ps2input = NULL; + ps2_video_t *ps2 = (ps2_video_t *)calloc(1, sizeof(ps2_video_t)); - *input_data = NULL; + *input_data = NULL; if (!ps2) return NULL; @@ -260,37 +448,38 @@ static void *ps2_gfx_init(const video_info_t *video, init_ps2_video(ps2); if (video->font_enable) font_driver_init_osd(ps2, - video, - false, - video->is_threaded, - FONT_DRIVER_RENDER_PS2); + video, + false, + video->is_threaded, + FONT_DRIVER_RENDER_PS2); - ps2->PSM = (video->rgb32 ? GS_PSM_CT32 : GS_PSM_CT16); - ps2->core_filter = video->smooth ? GS_FILTER_LINEAR : GS_FILTER_NEAREST; + ps2->PSM = (video->rgb32 ? GS_PSM_CT32 : GS_PSM_CT16); + ps2->tex_filter = video->smooth ? GS_FILTER_LINEAR : GS_FILTER_NEAREST; ps2->force_aspect = video->force_aspect; - ps2->vsync = video->vsync; + ps2->vsync = video->vsync; if (input && input_data) { settings_t *settings = config_get_ptr(); - ps2input = input_driver_init_wrap(&input_ps2, - settings->arrays.input_joypad_driver); - *input = ps2input ? &input_ps2 : NULL; - *input_data = ps2input; + ps2input = input_driver_init_wrap(&input_ps2, + settings->arrays.input_joypad_driver); + *input = ps2input ? &input_ps2 : NULL; + *input_data = ps2input; } return ps2; } static bool ps2_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) + unsigned width, unsigned height, uint64_t frame_count, + unsigned pitch, const char *msg, video_frame_info_t *video_info) { - ps2_video_t *ps2 = (ps2_video_t*)data; - struct font_params *osd_params = (struct font_params*) - &video_info->osd_stat_params; - bool statistics_show = video_info->statistics_show; - settings_t *settings = config_get_ptr(); + ps2_video_t *ps2 = (ps2_video_t *)data; + GSGLOBAL *gsGlobal = ps2->gsGlobal; + struct font_params *osd_params = (struct font_params *)&video_info->osd_stat_params; + bool statistics_show = video_info->statistics_show; + settings_t *settings = config_get_ptr(); + GSTEXTURE *tex = ps2->coreTexture; if (!width || !height) return false; @@ -300,42 +489,99 @@ static bool ps2_gfx_frame(void *data, const void *frame, printf("ps2_gfx_frame %llu\n", frame_count); #endif + /* Check if user change offset values */ + updateOffSetsIfNeeded(ps2); + if (frame) { - struct retro_hw_ps2_insets padding = empty_ps2_insets; + /* New frame from core, update */ + float fDAR = ps2->force_aspect ? video_driver_get_aspect_ratio() : 0; + bool bScaleInteger = settings->bools.video_scale_integer; + /* Checking if the transfer is done in the core */ if (frame != RETRO_HW_FRAME_BUFFER_VALID) { - /* calculate proper width based in the pitch */ + /* SW rendered texture */ int shifh_per_bytes = (ps2->PSM == GS_PSM_CT32) ? 2 : 1; - int real_width = pitch >> shifh_per_bytes; - set_texture(ps2->coreTexture, frame, real_width, height, ps2->PSM, ps2->core_filter); + int real_width = pitch >> shifh_per_bytes; + set_texture(tex, frame, real_width, height, ps2->PSM, ps2->tex_filter); - padding.right = real_width - width; + /* Padding */ + ps2->padding = empty_ps2_insets; + ps2->padding.right = real_width - width; } else { - padding = ps2->iface.padding; + /* "HW" rendered texture */ + /* Set current filter mode */ + tex->Filter = ps2->tex_filter; + + /* Padding */ + ps2->padding = ps2->iface.padding; } - float aspect_ratio = ps2->force_aspect ? video_driver_get_aspect_ratio() : 0; - bool scale_integer = settings->bools.video_scale_integer; + /* Texture dimensions */ + int iTextureWidth = tex->Width - ps2->padding.left - ps2->padding.right; + int iTextureHeight = tex->Height - ps2->padding.top - ps2->padding.bottom; + if (ps2->iTextureWidth != iTextureWidth || + ps2->iTextureHeight != iTextureHeight || + ps2->fDAR != fDAR || + ps2->bScaleInteger != bScaleInteger) + { + /* Scaling changed, try to find best matching output mode */ + ps2->iTextureWidth = iTextureWidth; + ps2->iTextureHeight = iTextureHeight; + ps2->fDAR = fDAR; + ps2->bScaleInteger = bScaleInteger; + setupScalingMode(ps2, iTextureWidth, iTextureHeight, fDAR, bScaleInteger); + } - /* Disable Alpha for cores */ - ps2->gsGlobal->PrimAlphaEnable = GS_SETTING_OFF; - gsKit_set_test(ps2->gsGlobal, GS_ATEST_OFF); - - gsKit_TexManager_invalidate(ps2->gsGlobal, ps2->coreTexture); - gsKit_TexManager_bind(ps2->gsGlobal, ps2->coreTexture); - prim_texture(ps2->gsGlobal, ps2->coreTexture, 1, aspect_ratio, scale_integer, padding); + gsKit_TexManager_invalidate(ps2->gsGlobal, tex); } + /* Center texture on framebuffer */ + float fDisplayOffsetX = (gsGlobal->Width - ps2->iDisplayWidth + 1) / 2 - 0.5f; + float fDisplayOffsetY = (gsGlobal->Height - ps2->iDisplayHeight + 1) / 2 - 0.5f; + /* Draw */ + gsGlobal->PrimAlphaEnable = GS_SETTING_OFF; + gsKit_TexManager_bind(gsGlobal, tex); + gsKit_prim_sprite_texture(gsGlobal, tex, + fDisplayOffsetX, /* X1 */ + fDisplayOffsetY, /* Y1 */ + ps2->padding.left, /* U1 */ + ps2->padding.top, /* V1 */ + fDisplayOffsetX + ps2->iDisplayWidth, /* X2 */ + fDisplayOffsetY + ps2->iDisplayHeight, /* Y2 */ + ps2->padding.left + ps2->iTextureWidth, /* U2 */ + ps2->padding.top + ps2->iTextureHeight, /* V2 */ + 1, + GS_TEXT); + if (ps2->menuVisible) { bool texture_empty = !ps2->menuTexture->Width || !ps2->menuTexture->Height; if (!texture_empty) { - prim_texture(ps2->gsGlobal, ps2->menuTexture, 2, 0, 0, empty_ps2_insets); +#define A_COLOR_SOURCE 0 +#define A_COLOR_DEST 1 +#define A_COLOR_NULL 2 +#define A_ALPHA_SOURCE 0 +#define A_ALPHA_DEST 1 +#define A_ALPHA_FIX 2 + /* (A - B) * C + D */ + gsKit_set_primalpha(gsGlobal, GS_SETREG_ALPHA(A_COLOR_DEST, A_COLOR_NULL, A_ALPHA_FIX, A_COLOR_SOURCE, 0x20), 0); + gsGlobal->PrimAlphaEnable = GS_SETTING_ON; + gsKit_prim_sprite_texture(gsGlobal, ps2->menuTexture, + -0.5f, /* X1 */ + -0.5f, /* Y1 */ + 0, /* U1 */ + 0, /* V1 */ + -0.5f + (float)gsGlobal->Width, /* X2 */ + -0.5f + (float)gsGlobal->Height, /* Y2 */ + ps2->menuTexture->Width, /* U2 */ + ps2->menuTexture->Height, /* V2 */ + 2, + GS_TEXT); } } else if (statistics_show) @@ -347,15 +593,39 @@ static bool ps2_gfx_frame(void *data, const void *frame, if (!string_is_empty(msg)) font_driver_render_msg(ps2, msg, NULL, NULL); - refreshScreen(ps2); + if (gsGlobal->DoubleBuffering == GS_SETTING_OFF) + { + /* Without double buffering: + * - Wait for VSync + * - Draw to front buffer (during VSync, so it's not visible to the user) */ + if (ps2->vsync) + gsKit_sync(gsGlobal); + gsKit_queue_exec(gsGlobal); + } + else + { + /* With double buffering: + * - Draw to back buffer (invisible to user) + * - Make sure drawing is completed (gsKit_finish) + * - Wait for VSync + * - Flip (back and front) buffers */ + gsKit_queue_exec(gsGlobal); + gsKit_finish(); + if (ps2->vsync) + gsKit_sync(gsGlobal); + gsKit_flip(gsGlobal); + } + + gsKit_TexManager_nextFrame(gsGlobal); + gsKit_clear(gsGlobal, GS_BLACK); return true; } static void ps2_gfx_set_nonblock_state(void *data, bool toggle, - bool adaptive_vsync_enabled, unsigned swap_interval) + bool adaptive_vsync_enabled, unsigned swap_interval) { - ps2_video_t *ps2 = (ps2_video_t*)data; + ps2_video_t *ps2 = (ps2_video_t *)data; if (ps2) ps2->vsync = !toggle; @@ -368,7 +638,7 @@ static bool ps2_gfx_has_windowed(void *data) { return false; } static void ps2_gfx_free(void *data) { - ps2_video_t *ps2 = (ps2_video_t*)data; + ps2_video_t *ps2 = (ps2_video_t *)data; gsKit_clear(ps2->gsGlobal, GS_BLACK); gsKit_vram_clear(ps2->gsGlobal); @@ -381,8 +651,7 @@ static void ps2_gfx_free(void *data) free(ps2->menuTexture); free(ps2->coreTexture); - gsKit_remove_vsync_handler(ps2->vsync_callback_id); - deinit_GSGlobal(ps2->gsGlobal); + rmEnd(ps2); if (vsync_sema_id >= 0) DeleteSema(vsync_sema_id); @@ -391,21 +660,72 @@ static void ps2_gfx_free(void *data) } static bool ps2_gfx_set_shader(void *data, - enum rarch_shader_type type, const char *path) { return false; } + enum rarch_shader_type type, const char *path) { return false; } + +static void ps2_set_video_mode(void *data, unsigned fbWidth, unsigned lines, + bool fullscreen) +{ + ps2_video_t *ps2 = (ps2_video_t *)data; + if (!ps2) + return; + + rmSetMode(ps2, 0); +} static void ps2_set_filtering(void *data, unsigned index, bool smooth, bool ctx_scaling) { - ps2_video_t *ps2 = (ps2_video_t*)data; + ps2_video_t *ps2 = (ps2_video_t *)data; ps2->menu_filter = smooth ? GS_FILTER_LINEAR : GS_FILTER_NEAREST; } -static void ps2_set_texture_frame(void *data, const void *frame, bool rgb32, - unsigned width, unsigned height, float alpha) +static void ps2_get_video_output_size(void *data, + unsigned *width, unsigned *height, char *desc, size_t desc_len) { - ps2_video_t *ps2 = (ps2_video_t*)data; + ps2_video_t *ps2 = (ps2_video_t *)data; + if (!ps2) + return; - int PSM = (rgb32 ? GS_PSM_CT32 : GS_PSM_CT16); + /* If the current index is out of bound default it to zero */ + if (ps2->vmode > PS2_RESOLUTION_LAST || ps2->vmode < 0) + ps2->vmode = 0; + + *width = rm_mode_table[ps2->vmode].width; + *height = rm_mode_table[ps2->vmode].height; + + strlcpy(desc, rm_mode_table[ps2->vmode].desc, desc_len); +} + +static void ps2_get_video_output_prev(void *data) +{ + ps2_video_t *ps2 = (ps2_video_t *)data; + if (!ps2) + return; + + if (ps2->vmode == 0) + ps2->vmode = PS2_RESOLUTION_LAST; + else + ps2->vmode--; +} + +static void ps2_get_video_output_next(void *data) +{ + ps2_video_t *ps2 = (ps2_video_t *)data; + if (!ps2) + return; + + if (ps2->vmode >= PS2_RESOLUTION_LAST) + ps2->vmode = 0; + else + ps2->vmode++; +} + +static void ps2_set_texture_frame(void *data, const void *frame, bool rgb32, + unsigned width, unsigned height, float alpha) +{ + ps2_video_t *ps2 = (ps2_video_t *)data; + + int PSM = (rgb32 ? GS_PSM_CT32 : GS_PSM_CT16); set_texture(ps2->menuTexture, frame, width, height, PSM, ps2->menu_filter); gsKit_TexManager_invalidate(ps2->gsGlobal, ps2->menuTexture); @@ -414,93 +734,88 @@ static void ps2_set_texture_frame(void *data, const void *frame, bool rgb32, static void ps2_set_texture_enable(void *data, bool enable, bool fullscreen) { - ps2_video_t *ps2 = (ps2_video_t*)data; + ps2_video_t *ps2 = (ps2_video_t *)data; - if (ps2->menuVisible != enable) - { - /* If Menu change status, CLEAR SCREEN */ - gsKit_clear(ps2->gsGlobal, GS_BLACK); - } ps2->menuVisible = enable; } static void ps2_set_osd_msg(void *data, - const char *msg, - const void *params, void *font) + const char *msg, + const void *params, void *font) { - ps2_video_t *ps2 = (ps2_video_t*)data; + ps2_video_t *ps2 = (ps2_video_t *)data; if (ps2) font_driver_render_msg(data, msg, params, font); } -static bool ps2_get_hw_render_interface(void* data, - const struct retro_hw_render_interface** iface) +static bool ps2_get_hw_render_interface(void *data, + const struct retro_hw_render_interface **iface) { - ps2_video_t *ps2 = (ps2_video_t*)data; - ps2->iface.padding = empty_ps2_insets; - *iface = - (const struct retro_hw_render_interface*)&ps2->iface; + ps2_video_t *ps2 = (ps2_video_t *)data; + ps2->iface.padding = empty_ps2_insets; + *iface = + (const struct retro_hw_render_interface *)&ps2->iface; return true; } static const video_poke_interface_t ps2_poke_interface = { - NULL, /* get_flags */ - NULL, - NULL, - NULL, - NULL, /* get_refresh_rate */ - ps2_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, /* set_aspect_ratio */ - NULL, /* apply_state_changes */ - ps2_set_texture_frame, - ps2_set_texture_enable, - ps2_set_osd_msg, /* set_osd_msg */ - NULL, /* show_mouse */ - NULL, /* grab_mouse_toggle */ - NULL, /* get_current_shader */ - NULL, /* get_current_software_framebuffer */ - ps2_get_hw_render_interface, /* get_hw_render_interface */ - NULL, /* set_hdr_max_nits */ - NULL, /* set_hdr_paper_white_nits */ - NULL, /* set_hdr_contrast */ - NULL /* set_hdr_expand_gamut */ + NULL, /* get_flags */ + NULL, /* load_texture */ + NULL, /* unload_texture */ + ps2_set_video_mode, + NULL, /* get_refresh_rate */ + ps2_set_filtering, + ps2_get_video_output_size, + ps2_get_video_output_prev, + ps2_get_video_output_next, + NULL, /* get_current_framebuffer */ + NULL, /* get_proc_address */ + NULL, /* set_aspect_ratio */ + NULL, /* apply_state_changes */ + ps2_set_texture_frame, + ps2_set_texture_enable, + ps2_set_osd_msg, + NULL, /* show_mouse */ + NULL, /* grab_mouse_toggle */ + NULL, /* get_current_shader */ + NULL, /* get_current_software_framebuffer */ + ps2_get_hw_render_interface, + NULL, /* set_hdr_max_nits */ + NULL, /* set_hdr_paper_white_nits */ + NULL, /* set_hdr_contrast */ + NULL /* set_hdr_expand_gamut */ }; static void ps2_gfx_get_poke_interface(void *data, - const video_poke_interface_t **iface) + const video_poke_interface_t **iface) { (void)data; *iface = &ps2_poke_interface; } video_driver_t video_ps2 = { - ps2_gfx_init, - ps2_gfx_frame, - ps2_gfx_set_nonblock_state, - ps2_gfx_alive, - ps2_gfx_focus, - ps2_gfx_suppress_screensaver, - ps2_gfx_has_windowed, - ps2_gfx_set_shader, - ps2_gfx_free, - "ps2", - NULL, /* set_viewport */ - NULL, /* set_rotation */ - NULL, /* viewport_info */ - NULL, /* read_viewport */ - NULL, /* read_frame_raw */ + ps2_gfx_init, + ps2_gfx_frame, + ps2_gfx_set_nonblock_state, + ps2_gfx_alive, + ps2_gfx_focus, + ps2_gfx_suppress_screensaver, + ps2_gfx_has_windowed, + ps2_gfx_set_shader, + ps2_gfx_free, + "ps2", + NULL, /* set_viewport */ + NULL, /* set_rotation */ + NULL, /* viewport_info */ + NULL, /* read_viewport */ + NULL, /* read_frame_raw */ #ifdef HAVE_OVERLAY - NULL, /* overlay_interface */ + NULL, /* overlay_interface */ #endif #ifdef HAVE_VIDEO_LAYOUT - NULL, + NULL, #endif - ps2_gfx_get_poke_interface, + ps2_gfx_get_poke_interface, }; diff --git a/gfx/drivers/sixel_gfx.c b/gfx/drivers/sixel_gfx.c index 09b9f79b9b..1fdc80c5d0 100644 --- a/gfx/drivers/sixel_gfx.c +++ b/gfx/drivers/sixel_gfx.c @@ -516,7 +516,7 @@ static void sixel_set_texture_frame(void *data, } static void sixel_get_video_output_size(void *data, - unsigned *width, unsigned *height) { } + unsigned *width, unsigned *height, char *desc, size_t desc_len) { } static void sixel_get_video_output_prev(void *data) { } static void sixel_get_video_output_next(void *data) { } static void sixel_set_video_mode(void *data, unsigned width, unsigned height, diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 928e515065..3082f74d37 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -2590,14 +2590,14 @@ static uint32_t vulkan_get_flags(void *data) } static void vulkan_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { vk_t *vk = (vk_t*)data; if (!vk || !vk->ctx_driver || !vk->ctx_driver->get_video_output_size) return; vk->ctx_driver->get_video_output_size( vk->ctx_data, - width, height); + width, height, desc, desc_len); } static void vulkan_get_video_output_prev(void *data) diff --git a/gfx/drivers_context/ps3_ctx.c b/gfx/drivers_context/ps3_ctx.c index 4a24b0eb18..1be8558b85 100644 --- a/gfx/drivers_context/ps3_ctx.c +++ b/gfx/drivers_context/ps3_ctx.c @@ -312,7 +312,7 @@ static bool gfx_ctx_ps3_bind_api(void *data, } static void gfx_ctx_ps3_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { global_t *global = global_get_ptr(); diff --git a/gfx/drivers_context/psl1ght_ctx.c b/gfx/drivers_context/psl1ght_ctx.c index 9a2d2cceaf..c8a94f27d2 100755 --- a/gfx/drivers_context/psl1ght_ctx.c +++ b/gfx/drivers_context/psl1ght_ctx.c @@ -249,7 +249,7 @@ static bool gfx_ctx_psl1ght_bind_api(void *data, } static void gfx_ctx_psl1ght_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { global_t *global = global_get_ptr(); diff --git a/gfx/drivers_context/w_vk_ctx.c b/gfx/drivers_context/w_vk_ctx.c index fe3923eb20..ecf5efa36b 100644 --- a/gfx/drivers_context/w_vk_ctx.c +++ b/gfx/drivers_context/w_vk_ctx.c @@ -345,9 +345,9 @@ static uint32_t gfx_ctx_w_vk_get_flags(void *data) static void gfx_ctx_w_vk_set_flags(void *data, uint32_t flags) { } static void gfx_ctx_w_vk_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { - win32_get_video_output_size(width, height); + win32_get_video_output_size(width, height, desc, desc_len); } static void gfx_ctx_w_vk_get_video_output_prev(void *data) { } diff --git a/gfx/drivers_context/wgl_ctx.c b/gfx/drivers_context/wgl_ctx.c index a5d1233c46..bcf8f57485 100644 --- a/gfx/drivers_context/wgl_ctx.c +++ b/gfx/drivers_context/wgl_ctx.c @@ -836,9 +836,9 @@ static void gfx_ctx_wgl_set_flags(void *data, uint32_t flags) } static void gfx_ctx_wgl_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { - win32_get_video_output_size(width, height); + win32_get_video_output_size(width, height, desc, desc_len); } static void gfx_ctx_wgl_get_video_output_prev(void *data) { } diff --git a/gfx/drivers_font/ps2_font.c b/gfx/drivers_font/ps2_font.c index a754fce247..7ee91f6269 100644 --- a/gfx/drivers_font/ps2_font.c +++ b/gfx/drivers_font/ps2_font.c @@ -148,6 +148,7 @@ static void ps2_font_render_line( return; /* Enable Alpha for font */ + gsKit_set_primalpha(ps2->gsGlobal, GS_SETREG_ALPHA(0, 1, 0, 1, 0), 0); ps2->gsGlobal->PrimAlphaEnable = GS_SETTING_ON; gsKit_set_test(ps2->gsGlobal, GS_ATEST_ON); diff --git a/gfx/video_driver.h b/gfx/video_driver.h index eb959fb0e8..d2e774b846 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -544,7 +544,7 @@ typedef struct gfx_ctx_driver float (*get_refresh_rate)(void*); - void (*get_video_output_size)(void*, unsigned*, unsigned*); + void (*get_video_output_size)(void*, unsigned*, unsigned*, char *, size_t); void (*get_video_output_prev)(void*); @@ -687,7 +687,7 @@ typedef struct video_poke_interface float (*get_refresh_rate)(void *data); void (*set_filtering)(void *data, unsigned index, bool smooth, bool ctx_scaling); void (*get_video_output_size)(void *data, - unsigned *width, unsigned *height); + unsigned *width, unsigned *height, char *desc, size_t desc_len); /* Move index to previous resolution */ void (*get_video_output_prev)(void *data); @@ -922,7 +922,7 @@ bool video_driver_set_video_mode(unsigned width, unsigned height, bool fullscreen); bool video_driver_get_video_output_size( - unsigned *width, unsigned *height); + unsigned *width, unsigned *height, char *desc, size_t desc_len); void video_driver_set_texture_enable(bool enable, bool full_screen); diff --git a/gfx/video_thread_wrapper.c b/gfx/video_thread_wrapper.c index 8965b734db..dbdbd2303d 100644 --- a/gfx/video_thread_wrapper.c +++ b/gfx/video_thread_wrapper.c @@ -1012,7 +1012,7 @@ static void thread_set_hdr_expand_gamut(void *data, bool expand_gamut) } static void thread_get_video_output_size(void *data, - unsigned *width, unsigned *height) + unsigned *width, unsigned *height, char *desc, size_t desc_len) { thread_video_t *thr = (thread_video_t*)data; @@ -1022,7 +1022,7 @@ static void thread_get_video_output_size(void *data, if (thr->poke && thr->poke->get_video_output_size) thr->poke->get_video_output_size(thr->driver_data, width, - height); + height, desc, desc_len); } static void thread_get_video_output_prev(void *data) diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index fc8e578700..75e35a287b 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -3316,6 +3316,14 @@ MSG_HASH( MENU_ENUM_LABEL_VIDEO_MONITOR_INDEX, "video_monitor_index" ) +MSG_HASH( + MENU_ENUM_LABEL_VIDEO_WINDOW_OFFSET_X, + "video_window_offset_x" + ) +MSG_HASH( + MENU_ENUM_LABEL_VIDEO_WINDOW_OFFSET_Y, + "video_window_offset_y" + ) MSG_HASH( MENU_ENUM_LABEL_VIDEO_POST_FILTER_RECORD, "video_post_filter_record" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index c370df7810..d9025a9569 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -1514,6 +1514,22 @@ MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_GPU_INDEX, "Select which graphics card to use." ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_OFFSET_X, + "Screen Horizontal Offset" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_WINDOW_OFFSET_X, + "Forces a certain offset horizontally to the video. The offset is applied globaly." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_OFFSET_Y, + "Screen Vertical Offset" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_WINDOW_OFFSET_Y, + "Forces a certain offset vertically to the video. The offset is applied globaly." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, "Vertical Refresh Rate" @@ -12267,6 +12283,50 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_SCREEN_RESOLUTION, "Screen Resolution" ) +MSG_HASH( + MSG_SCREEN_RESOLUTION_FORMAT_NO_DESC, + "%ux%u" + ) +MSG_HASH( + MSG_SCREEN_RESOLUTION_FORMAT_DESC, + "%ux%u - %s" + ) +MSG_HASH( + MSG_SCREEN_RESOLUTION_DEFAULT, + "Screen Resolution: Default" + ) +MSG_HASH( + MSG_SCREEN_RESOLUTION_NO_DESC, + "Screen Resolution: %dx%d" + ) +MSG_HASH( + MSG_SCREEN_RESOLUTION_DESC, + "Screen Resolution: %dx%d - %s" + ) +MSG_HASH( + MSG_SCREEN_RESOLUTION_APPLYING_DEFAULT, + "Applying: Default" + ) +MSG_HASH( + MSG_SCREEN_RESOLUTION_APPLYING_NO_DESC, + "Applying: %dx%d\nSTART to reset" + ) +MSG_HASH( + MSG_SCREEN_RESOLUTION_APPLYING_DESC, + "Applying: %dx%d - %s\nSTART to reset" + ) +MSG_HASH( + MSG_SCREEN_RESOLUTION_RESETTING_DEFAULT, + "Resetting to: Default" + ) +MSG_HASH( + MSG_SCREEN_RESOLUTION_RESETTING_NO_DESC, + "Resetting to: %dx%d" + ) +MSG_HASH( + MSG_SCREEN_RESOLUTION_RESETTING_DESC, + "Resetting to: %dx%d - %s" + ) MSG_HASH( MENU_ENUM_SUBLABEL_SCREEN_RESOLUTION, "Select display mode." diff --git a/menu/cbs/menu_cbs_get_value.c b/menu/cbs/menu_cbs_get_value.c index 447d8d63bd..7d63747cce 100644 --- a/menu/cbs/menu_cbs_get_value.c +++ b/menu/cbs/menu_cbs_get_value.c @@ -1036,20 +1036,27 @@ static void menu_action_setting_disp_set_label_menu_video_resolution( char *s2, size_t len2) { unsigned width = 0, height = 0; - + char desc[64] = {0}; *w = 19; *s = '\0'; strlcpy(s2, path, len2); - if (video_driver_get_video_output_size(&width, &height)) + if (video_driver_get_video_output_size(&width, &height, desc, sizeof(desc))) { #ifdef GEKKO if (width == 0 || height == 0) - strcpy_literal(s, "DEFAULT"); + snprintf(s, len, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DONT_CARE)); else #endif - snprintf(s, len, "%ux%u", width, height); + { + if (!string_is_empty(desc)) + snprintf(s, len, msg_hash_to_str(MSG_SCREEN_RESOLUTION_FORMAT_DESC), + width, height, desc); + else + snprintf(s, len, msg_hash_to_str(MSG_SCREEN_RESOLUTION_FORMAT_NO_DESC), + width, height); + } } else strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE), len); diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 2e5cdf5aba..c39aef6dc7 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -6757,11 +6757,12 @@ static int generic_dropdown_box_list(size_t idx, unsigned lbl) static int action_ok_video_resolution(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { -#if defined(GEKKO) || !defined(__PSL1GHT__) && defined(__PS3__) +#if defined(GEKKO) || defined(PS2) || !defined(__PSL1GHT__) && defined(__PS3__) unsigned width = 0; unsigned height = 0; + char desc[64] = {0}; - if (video_driver_get_video_output_size(&width, &height)) + if (video_driver_get_video_output_size(&width, &height, desc, sizeof(desc))) { char msg[PATH_MAX_LENGTH]; @@ -6773,12 +6774,17 @@ static int action_ok_video_resolution(const char *path, video_driver_set_video_mode(width, height, true); #ifdef GEKKO if (width == 0 || height == 0) - strcpy_literal(msg, "Applying: DEFAULT"); + snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_SCREEN_RESOLUTION_APPLYING_DEFAULT)); else #endif - snprintf(msg, sizeof(msg), - "Applying: %dx%d\n START to reset", + { + if (!string_is_empty(desc)) + snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_SCREEN_RESOLUTION_APPLYING_DESC), + width, height, desc); + else + snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_SCREEN_RESOLUTION_APPLYING_NO_DESC), width, height); + } runloop_msg_queue_push(msg, 1, 100, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); } diff --git a/menu/cbs/menu_cbs_start.c b/menu/cbs/menu_cbs_start.c index 29fb73ed4a..789ab5045d 100644 --- a/menu/cbs/menu_cbs_start.c +++ b/menu/cbs/menu_cbs_start.c @@ -486,14 +486,15 @@ static int action_start_video_resolution( const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { -#if defined(GEKKO) || !defined(__PSL1GHT__) && !defined(__PS3__) +#if defined(GEKKO) || defined(PS2) || !defined(__PSL1GHT__) && !defined(__PS3__) unsigned width = 0, height = 0; + char desc[64] = {0}; global_t *global = global_get_ptr(); /* Reset the resolution id to zero */ global->console.screen.resolutions.current.id = 0; - if (video_driver_get_video_output_size(&width, &height)) + if (video_driver_get_video_output_size(&width, &height, desc, sizeof(desc))) { char msg[PATH_MAX_LENGTH]; @@ -508,8 +509,15 @@ static int action_start_video_resolution( strlcpy(msg, "Resetting to: DEFAULT", sizeof(msg)); else #endif - snprintf(msg, sizeof(msg), - "Resetting to: %dx%d", width, height); + { + if (!string_is_empty(desc)) + snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_SCREEN_RESOLUTION_RESETTING_DESC), + width, height, desc); + else + snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_SCREEN_RESOLUTION_RESETTING_NO_DESC), + width, height); + } + runloop_msg_queue_push(msg, 1, 100, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); } #endif diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index fd4e103e6b..de3f8bebcd 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -935,6 +935,11 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_overscan_correction_top, ME DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_overscan_correction_bottom, MENU_ENUM_SUBLABEL_VIDEO_OVERSCAN_CORRECTION_BOTTOM) #endif +#if defined(HAVE_WINDOW_OFFSET) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_window_offset_x, MENU_ENUM_SUBLABEL_VIDEO_WINDOW_OFFSET_X) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_window_offset_y, MENU_ENUM_SUBLABEL_VIDEO_WINDOW_OFFSET_Y) +#endif + DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_playlist_show_sublabels, MENU_ENUM_SUBLABEL_PLAYLIST_SHOW_SUBLABELS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_playlist_show_entry_idx, MENU_ENUM_SUBLABEL_PLAYLIST_SHOW_ENTRY_IDX) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_rgui_border_filler_enable, MENU_ENUM_SUBLABEL_MENU_RGUI_BORDER_FILLER_ENABLE) @@ -3763,6 +3768,14 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_VIDEO_MONITOR_INDEX: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_monitor_index); break; +#if defined(HAVE_WINDOW_OFFSET) + case MENU_ENUM_LABEL_VIDEO_WINDOW_OFFSET_X: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_window_offset_x); + break; + case MENU_ENUM_LABEL_VIDEO_WINDOW_OFFSET_Y: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_window_offset_y); + break; +#endif case MENU_ENUM_LABEL_LOG_VERBOSITY: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_log_verbosity); break; @@ -4241,6 +4254,14 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_VIDEO_OVERSCAN_CORRECTION_BOTTOM: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_overscan_correction_bottom); break; +#endif +#if defined(HAVE_WINDOW_OFFSET) + case MENU_ENUM_SUBLABEL_VIDEO_WINDOW_OFFSET_X: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_window_offset_x); + break; + case MENU_ENUM_SUBLABEL_VIDEO_WINDOW_OFFSET_Y: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_window_offset_y); + break; #endif case MENU_ENUM_LABEL_CHEAT_APPLY_AFTER_LOAD: #ifdef HAVE_CHEATS diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 2452028c13..54b8b7fcbc 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -7893,7 +7893,7 @@ unsigned menu_displaylist_build_list( PARSE_ONLY_UINT, false) == 0) count++; -#if defined(GEKKO) || !defined(__PSL1GHT__) && defined(__PS3__) +#if defined(GEKKO) || defined(PS2) || !defined(__PSL1GHT__) && defined(__PS3__) if (true) #else if (video_display_server_has_resolution_list()) @@ -7904,7 +7904,17 @@ unsigned menu_displaylist_build_list( PARSE_ACTION, false) == 0) count++; } +#if defined(HAVE_WINDOW_OFFSET) + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_VIDEO_WINDOW_OFFSET_X, + PARSE_ONLY_INT, false) == 0) + count++; + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_VIDEO_WINDOW_OFFSET_Y, + PARSE_ONLY_INT, false) == 0) + count++; +#endif if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_PAL60_ENABLE, PARSE_ONLY_BOOL, false) == 0) diff --git a/menu/menu_setting.c b/menu/menu_setting.c index bed125c2b1..e9107c1a67 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -11390,7 +11390,7 @@ static bool setting_append_list( CMD_EVENT_VIDEO_APPLY_STATE_CHANGES); SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_LAKKA_ADVANCED); -#if defined(GEKKO) || !defined(__PSL1GHT__) && defined(__PS3__) +#if defined(GEKKO) || defined(PS2) || !defined(__PSL1GHT__) && defined(__PS3__) if (true) #else if (!string_is_equal(video_display_server_get_ident(), "null")) @@ -11405,6 +11405,34 @@ static bool setting_append_list( parent_group); } +#if defined(HAVE_WINDOW_OFFSET) + CONFIG_INT( + list, list_info, + &settings->ints.video_window_offset_x, + MENU_ENUM_LABEL_VIDEO_WINDOW_OFFSET_X, + MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_OFFSET_X, + DEFAULT_WINDOW_OFFSET_X, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + menu_settings_list_current_add_range(list, list_info, -50, 50, 1, true, true); + + CONFIG_INT( + list, list_info, + &settings->ints.video_window_offset_y, + MENU_ENUM_LABEL_VIDEO_WINDOW_OFFSET_Y, + MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_OFFSET_Y, + DEFAULT_WINDOW_OFFSET_Y, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + menu_settings_list_current_add_range(list, list_info, -50, 50, 1, true, true); +#endif + CONFIG_UINT( list, list_info, &custom_vp->width, diff --git a/msg_hash.h b/msg_hash.h index 8e59f4c935..42893a4ab9 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1088,6 +1088,8 @@ enum msg_hash_enums MENU_LABEL(VIDEO_FULLSCREEN), MENU_LABEL(VIDEO_MONITOR_INDEX), MENU_LABEL(VIDEO_WINDOW_SCALE), + MENU_LABEL(VIDEO_WINDOW_OFFSET_X), + MENU_LABEL(VIDEO_WINDOW_OFFSET_Y), MENU_LABEL(VIDEO_REFRESH_RATE), MENU_LABEL(VIDEO_REFRESH_RATE_AUTO), MENU_LABEL(VIDEO_REFRESH_RATE_POLLED), @@ -1843,6 +1845,19 @@ enum msg_hash_enums MENU_LABEL(CHEAT_COPY_MATCH), MENU_LABEL(CHEAT_DELETE_MATCH), MENU_LABEL(SCREEN_RESOLUTION), + + MSG_SCREEN_RESOLUTION_FORMAT_NO_DESC, + MSG_SCREEN_RESOLUTION_FORMAT_DESC, + MSG_SCREEN_RESOLUTION_DEFAULT, + MSG_SCREEN_RESOLUTION_NO_DESC, + MSG_SCREEN_RESOLUTION_DESC, + MSG_SCREEN_RESOLUTION_APPLYING_DEFAULT, + MSG_SCREEN_RESOLUTION_APPLYING_NO_DESC, + MSG_SCREEN_RESOLUTION_APPLYING_DESC, + MSG_SCREEN_RESOLUTION_RESETTING_DEFAULT, + MSG_SCREEN_RESOLUTION_RESETTING_NO_DESC, + MSG_SCREEN_RESOLUTION_RESETTING_DESC, + MENU_LABEL(SAVESTATE_AUTO_INDEX), MENU_LABEL(SAVESTATE_MAX_KEEP), MENU_LABEL(SAVESTATE_AUTO_SAVE), diff --git a/retroarch.c b/retroarch.c index 9ee3337208..f46ca6add7 100644 --- a/retroarch.c +++ b/retroarch.c @@ -7197,22 +7197,29 @@ bool command_event(enum event_command cmd, void *data) #if defined(GEKKO) { unsigned width = 0, height = 0; + char desc[64] = {0}; command_event(CMD_EVENT_VIDEO_SET_ASPECT_RATIO, NULL); - if (video_driver_get_video_output_size(&width, &height)) + if (video_driver_get_video_output_size(&width, &height, desc, sizeof(desc))) { char msg[128] = {0}; video_driver_set_video_mode(width, height, true); if (width == 0 || height == 0) - snprintf(msg, sizeof(msg), "%s: DEFAULT", - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCREEN_RESOLUTION)); + snprintf(msg, sizeof(msg), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCREEN_RESOLUTION_DEFAULT)); else - snprintf(msg, sizeof(msg),"%s: %dx%d", - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCREEN_RESOLUTION), + { + if (!string_is_empty(desc)) + snprintf(msg, sizeof(msg), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCREEN_RESOLUTION_DESC), + width, height, desc); + else + snprintf(msg, sizeof(msg), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCREEN_RESOLUTION_NO_DESC), width, height); + } + runloop_msg_queue_push(msg, 1, 100, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); } } @@ -18454,13 +18461,13 @@ bool video_driver_set_video_mode(unsigned width, return false; } -bool video_driver_get_video_output_size(unsigned *width, unsigned *height) +bool video_driver_get_video_output_size(unsigned *width, unsigned *height, char *desc, size_t desc_len) { struct rarch_state *p_rarch = &rarch_st; if (!p_rarch->video_driver_poke || !p_rarch->video_driver_poke->get_video_output_size) return false; p_rarch->video_driver_poke->get_video_output_size(p_rarch->video_driver_data, - width, height); + width, height, desc, desc_len); return true; }