From 20a88ae9db9732e9e6b02316cba5b9c45d73764a Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Tue, 15 Apr 2025 13:18:05 +0200 Subject: [PATCH 01/16] cdrom: Align read buffers to 64 bytes Align the address and size of read buffers to 64 bytes, which should be bigger or equal than the size of the cache lines on most systems. This allows hardware CD-ROM implementations to perform reads using DMA, which generally have tight requirements on alignment. Signed-off-by: Paul Cercueil --- libpcsxcore/cdrom-async.c | 8 ++++++-- libpcsxcore/cdrom.c | 3 ++- libpcsxcore/cdrom.h | 4 ++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libpcsxcore/cdrom-async.c b/libpcsxcore/cdrom-async.c index 84395e23..c2b64501 100644 --- a/libpcsxcore/cdrom-async.c +++ b/libpcsxcore/cdrom-async.c @@ -10,6 +10,7 @@ * GNU General Public License for more details. * ***************************************************************************/ +#include #include #include #include "system.h" @@ -104,12 +105,15 @@ static struct { u32 buf_cnt, thread_exit, do_prefetch, prefetch_failed, have_subchannel; u32 total_lba, prefetch_lba; int check_eject_delay; - u8 buf_local[CD_FRAMESIZE_RAW]; // single sector cache, not touched by the thread + + // single sector cache, not touched by the thread + alignas(64) u8 buf_local[CD_FRAMESIZE_RAW_ALIGNED]; } acdrom; static void lbacache_do(u32 lba) { - unsigned char msf[3], buf[CD_FRAMESIZE_RAW], buf_sub[SUB_FRAMESIZE]; + alignas(64) unsigned char buf[CD_FRAMESIZE_RAW_ALIGNED]; + unsigned char msf[3], buf_sub[SUB_FRAMESIZE]; u32 i = lba % acdrom.buf_cnt; int ret; diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index e52f74b8..df958bab 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -21,6 +21,7 @@ * Handles all CD-ROM registers and functions. */ +#include #include #include "cdrom.h" #include "cdrom-async.h" @@ -124,7 +125,7 @@ static struct { u8 AttenuatorLeftToLeftT, AttenuatorLeftToRightT; u8 AttenuatorRightToRightT, AttenuatorRightToLeftT; } cdr; -static s16 read_buf[CD_FRAMESIZE_RAW/2]; +alignas(64) static s16 read_buf[CD_FRAMESIZE_RAW_ALIGNED / 2]; struct SubQ { char res0[12]; diff --git a/libpcsxcore/cdrom.h b/libpcsxcore/cdrom.h index b8682b03..b762738c 100644 --- a/libpcsxcore/cdrom.h +++ b/libpcsxcore/cdrom.h @@ -41,6 +41,10 @@ extern "C" { #define CD_FRAMESIZE_RAW 2352 #define DATA_SIZE (CD_FRAMESIZE_RAW - 12) +/* CD_FRAMESIZE_RAW aligned to a cache line for DMA buffers + * (assuming a cache line of max. 64 bytes) */ +#define CD_FRAMESIZE_RAW_ALIGNED 2368 + #define SUB_FRAMESIZE 96 #define MSF2SECT(m, s, f) (((m) * 60 + (s) - 2) * 75 + (f)) -- 2.39.5 From b21c766fc243f2cc3b413bb8905a4e7ecff3f6c4 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 23 Apr 2025 01:26:42 +0300 Subject: [PATCH 02/16] disable a false-positive warning --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index bc4711f5..7d76d217 100644 --- a/Makefile +++ b/Makefile @@ -463,6 +463,7 @@ endif ifeq "$(USE_FRONTEND)" "1" OBJS += frontend/menu.o OBJS += frontend/libpicofe/input.o +frontend/libpicofe/input.o: CFLAGS += -Wno-array-bounds frontend/menu.o: frontend/libpicofe/menu.c ifeq "$(HAVE_TSLIB)" "1" frontend/%.o: CFLAGS += -DHAVE_TSLIB -- 2.39.5 From 9db64035a4ebea8efdb2297b687756e38d4e9d4c Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 25 Apr 2025 01:13:08 +0300 Subject: [PATCH 03/16] cdrom: fix double free on exit --- libpcsxcore/cdrom-async.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libpcsxcore/cdrom-async.c b/libpcsxcore/cdrom-async.c index c2b64501..9bd14bb8 100644 --- a/libpcsxcore/cdrom-async.c +++ b/libpcsxcore/cdrom-async.c @@ -308,8 +308,10 @@ void cdra_close(void) { acdrom_dbg("%s\n", __func__); cdra_stop_thread(); - if (g_cd_handle) + if (g_cd_handle) { rcdrom_close(g_cd_handle); + g_cd_handle = NULL; + } else ISOclose(); } -- 2.39.5 From 810239393ddf80252d03ff6220e945a684c744e3 Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 11 May 2025 01:21:51 +0300 Subject: [PATCH 04/16] sdandalone: rework sdl output - 2x overlay mode from PicoDrive - somewhat proper fullscreen mode - overlay scaling options - gles mode probably broken (no longer works on more modern distros anyway - it's some very old code) - new bugs --- Makefile | 5 +- frontend/cspace.c | 198 +++++++++++------- frontend/cspace.h | 4 +- frontend/libpicofe | 2 +- frontend/menu.c | 25 ++- frontend/pandora/ui_feat.h | 1 + frontend/plat_sdl.c | 415 +++++++++++++++++++++++++++++-------- frontend/plugin_lib.c | 54 +++-- frontend/plugin_lib.h | 1 + 9 files changed, 510 insertions(+), 195 deletions(-) diff --git a/Makefile b/Makefile index 7d76d217..f56ca1a5 100644 --- a/Makefile +++ b/Makefile @@ -363,9 +363,11 @@ endif ifeq "$(PLATFORM)" "generic" OBJS += frontend/libpicofe/in_sdl.o -OBJS += frontend/libpicofe/plat_sdl.o +#OBJS += frontend/libpicofe/plat_sdl.o OBJS += frontend/libpicofe/plat_dummy.o OBJS += frontend/plat_sdl.o +frontend/plat_sdl.o frontend/libpicofe/plat_sdl.o: CFLAGS += -DSDL_OVERLAY_2X +frontend/menu.o: CFLAGS += -DSDL_OVERLAY_2X -DMENU_SHOW_VARSCALER=1 ifeq "$(HAVE_EVDEV)" "1" OBJS += frontend/libpicofe/linux/in_evdev.o endif @@ -387,6 +389,7 @@ OBJS += frontend/libpicofe/linux/in_evdev.o OBJS += frontend/plat_pandora.o frontend/plat_omap.o frontend/main.o frontend/menu.o: CFLAGS += -include frontend/pandora/ui_feat.h frontend/libpicofe/linux/plat.o: CFLAGS += -DPANDORA +frontend/plugin_lib.o: CFLAGS += -DPANDORA USE_PLUGIN_LIB = 1 USE_FRONTEND = 1 CFLAGS += -gdwarf-3 diff --git a/frontend/cspace.c b/frontend/cspace.c index 3a09792c..8249f80f 100644 --- a/frontend/cspace.c +++ b/frontend/cspace.c @@ -168,36 +168,53 @@ void bgr888_to_xrgb8888(void * __restrict__ dst_, const void * __restrict__ src_ /* YUV stuff */ static int yuv_ry[32], yuv_gy[32], yuv_by[32]; static unsigned char yuv_u[32 * 2], yuv_v[32 * 2]; +static struct uyvy { uint32_t y:8; uint32_t vyu:24; } yuv_uyvy[32768]; void bgr_to_uyvy_init(void) { - int i, v; - - /* init yuv converter: - y0 = (int)((0.299f * r0) + (0.587f * g0) + (0.114f * b0)); - y1 = (int)((0.299f * r1) + (0.587f * g1) + (0.114f * b1)); - u = (int)(8 * 0.565f * (b0 - y0)) + 128; - v = (int)(8 * 0.713f * (r0 - y0)) + 128; - */ - for (i = 0; i < 32; i++) { - yuv_ry[i] = (int)(0.299f * i * 65536.0f + 0.5f); - yuv_gy[i] = (int)(0.587f * i * 65536.0f + 0.5f); - yuv_by[i] = (int)(0.114f * i * 65536.0f + 0.5f); - } - for (i = -32; i < 32; i++) { - v = (int)(8 * 0.565f * i) + 128; - if (v < 0) - v = 0; - if (v > 255) - v = 255; - yuv_u[i + 32] = v; - v = (int)(8 * 0.713f * i) + 128; - if (v < 0) - v = 0; - if (v > 255) - v = 255; - yuv_v[i + 32] = v; - } + unsigned char yuv_y[256]; + int i, v; + + /* init yuv converter: + y0 = (int)((0.299f * r0) + (0.587f * g0) + (0.114f * b0)); + y1 = (int)((0.299f * r1) + (0.587f * g1) + (0.114f * b1)); + u = (int)(8 * 0.565f * (b0 - y0)) + 128; + v = (int)(8 * 0.713f * (r0 - y0)) + 128; + */ + for (i = 0; i < 32; i++) { + yuv_ry[i] = (int)(0.299f * i * 65536.0f + 0.5f); + yuv_gy[i] = (int)(0.587f * i * 65536.0f + 0.5f); + yuv_by[i] = (int)(0.114f * i * 65536.0f + 0.5f); + } + for (i = -32; i < 32; i++) { + v = (int)(8 * 0.565f * i) + 128; + if (v < 0) + v = 0; + if (v > 255) + v = 255; + yuv_u[i + 32] = v; + v = (int)(8 * 0.713f * i) + 128; + if (v < 0) + v = 0; + if (v > 255) + v = 255; + yuv_v[i + 32] = v; + } + // valid Y range seems to be 16..235 + for (i = 0; i < 256; i++) { + yuv_y[i] = 16 + 219 * i / 32; + } + // everything combined into one large array for speed + for (i = 0; i < 32768; i++) { + int r = (i >> 0) & 0x1f, g = (i >> 5) & 0x1f, b = (i >> 10) & 0x1f; + int y = (yuv_ry[r] + yuv_gy[g] + yuv_by[b]) >> 16; + yuv_uyvy[i].y = yuv_y[y]; +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + yuv_uyvy[i].vyu = (yuv_v[b-y + 32] << 16) | (yuv_y[y] << 8) | yuv_u[r-y + 32]; +#else + yuv_uyvy[i].vyu = (yuv_v[r-y + 32] << 16) | (yuv_y[y] << 8) | yuv_u[b-y + 32]; +#endif + } } void rgb565_to_uyvy(void *d, const void *s, int pixels) @@ -229,54 +246,89 @@ void rgb565_to_uyvy(void *d, const void *s, int pixels) } } -void bgr555_to_uyvy(void *d, const void *s, int pixels) +void bgr555_to_uyvy(void *d, const void *s, int pixels, int x2) { - unsigned int *dst = d; - const unsigned short *src = s; - const unsigned char *yu = yuv_u + 32; - const unsigned char *yv = yuv_v + 32; - int r0, g0, b0, r1, g1, b1; - int y0, y1, u, v; - - for (; pixels > 1; src += 2, dst++, pixels -= 2) - { - b0 = (src[0] >> 10) & 0x1f; - g0 = (src[0] >> 5) & 0x1f; - r0 = src[0] & 0x1f; - b1 = (src[1] >> 10) & 0x1f; - g1 = (src[1] >> 5) & 0x1f; - r1 = src[1] & 0x1f; - y0 = (yuv_ry[r0] + yuv_gy[g0] + yuv_by[b0]) >> 16; - y1 = (yuv_ry[r1] + yuv_gy[g1] + yuv_by[b1]) >> 16; - u = yu[b0 - y0]; - v = yv[r0 - y0]; - y0 = 16 + 219 * y0 / 31; - y1 = 16 + 219 * y1 / 31; - - *dst = (y1 << 24) | (v << 16) | (y0 << 8) | u; - } + uint32_t *dst = d; + const uint16_t *src = s; + int i; + + if (x2) { + for (i = pixels; i >= 4; src += 4, dst += 4, i -= 4) + { + const struct uyvy *uyvy0 = yuv_uyvy + (src[0] & 0x7fff); + const struct uyvy *uyvy1 = yuv_uyvy + (src[1] & 0x7fff); + const struct uyvy *uyvy2 = yuv_uyvy + (src[2] & 0x7fff); + const struct uyvy *uyvy3 = yuv_uyvy + (src[3] & 0x7fff); +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + dst[0] = uyvy0->y | (uyvy0->vyu << 8); + dst[1] = uyvy1->y | (uyvy1->vyu << 8); + dst[2] = uyvy2->y | (uyvy2->vyu << 8); + dst[3] = uyvy3->y | (uyvy3->vyu << 8); +#else + dst[0] = (uyvy0->y << 24) | uyvy0->vyu; + dst[1] = (uyvy1->y << 24) | uyvy1->vyu; + dst[2] = (uyvy2->y << 24) | uyvy2->vyu; + dst[3] = (uyvy3->y << 24) | uyvy3->vyu; +#endif + } + } else { + for (i = pixels; i >= 4; src += 4, dst += 2, i -= 4) + { + const struct uyvy *uyvy0 = yuv_uyvy + (src[0] & 0x7fff); + const struct uyvy *uyvy1 = yuv_uyvy + (src[1] & 0x7fff); + const struct uyvy *uyvy2 = yuv_uyvy + (src[2] & 0x7fff); + const struct uyvy *uyvy3 = yuv_uyvy + (src[3] & 0x7fff); +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + dst[0] = uyvy1->y | (uyvy0->vyu << 8); + dst[1] = uyvy3->y | (uyvy2->vyu << 8); +#else + dst[0] = (uyvy1->y << 24) | uyvy0->vyu; + dst[1] = (uyvy3->y << 24) | uyvy2->vyu; +#endif + } + } } -void bgr888_to_uyvy(void *d, const void *s, int pixels) +void bgr888_to_uyvy(void *d, const void *s, int pixels, int x2) { - unsigned int *dst = d; - const unsigned char *src8 = s; - const unsigned char *yu = yuv_u + 32; - const unsigned char *yv = yuv_v + 32; - int r0, g0, b0, r1, g1, b1; - int y0, y1, u, v; - - for (; pixels > 0; src8 += 3*2, dst++, pixels -= 2) - { - r0 = src8[0], g0 = src8[1], b0 = src8[2]; - r1 = src8[3], g1 = src8[4], b1 = src8[5]; - y0 = (r0 * 19595 + g0 * 38470 + b0 * 7471) >> 16; - y1 = (r1 * 19595 + g1 * 38470 + b1 * 7471) >> 16; - u = yu[(b0 - y0) / 8]; - v = yv[(r0 - y0) / 8]; - y0 = 16 + 219 * y0 / 255; - y1 = 16 + 219 * y1 / 255; - - *dst = (y1 << 24) | (v << 16) | (y0 << 8) | u; - } + unsigned int *dst = d; + const unsigned char *src8 = s; + const unsigned char *yu = yuv_u + 32; + const unsigned char *yv = yuv_v + 32; + int r0, g0, b0, r1, g1, b1; + int y0, y1, u0, u1, v0, v1; + + if (x2) { + for (; pixels >= 2; src8 += 3*2, pixels -= 2) + { + r0 = src8[0], g0 = src8[1], b0 = src8[2]; + r1 = src8[3], g1 = src8[4], b1 = src8[5]; + y0 = (r0 * 19595 + g0 * 38470 + b0 * 7471) >> 16; + y1 = (r1 * 19595 + g1 * 38470 + b1 * 7471) >> 16; + u0 = yu[(b0 - y0) / 8]; + u1 = yu[(b1 - y1) / 8]; + v0 = yv[(r0 - y0) / 8]; + v1 = yv[(r1 - y1) / 8]; + y0 = 16 + 219 * y0 / 255; + y1 = 16 + 219 * y1 / 255; + + *dst++ = (y0 << 24) | (v0 << 16) | (y0 << 8) | u0; + *dst++ = (y1 << 24) | (v1 << 16) | (y1 << 8) | u1; + } + } + else { + for (; pixels >= 2; src8 += 3*2, dst++, pixels -= 2) + { + r0 = src8[0], g0 = src8[1], b0 = src8[2]; + r1 = src8[3], g1 = src8[4], b1 = src8[5]; + y0 = (r0 * 19595 + g0 * 38470 + b0 * 7471) >> 16; + y1 = (r1 * 19595 + g1 * 38470 + b1 * 7471) >> 16; + u0 = yu[(b0 - y0) / 8]; + v0 = yv[(r0 - y0) / 8]; + y0 = 16 + 219 * y0 / 255; + y1 = 16 + 219 * y1 / 255; + + *dst = (y1 << 24) | (v0 << 16) | (y0 << 8) | u0; + } + } } diff --git a/frontend/cspace.h b/frontend/cspace.h index 61bddf90..e5931960 100644 --- a/frontend/cspace.h +++ b/frontend/cspace.h @@ -19,8 +19,8 @@ void bgr888_to_xrgb8888(void *dst, const void *src, int bytes); void bgr_to_uyvy_init(void); void rgb565_to_uyvy(void *d, const void *s, int pixels); -void bgr555_to_uyvy(void *d, const void *s, int pixels); -void bgr888_to_uyvy(void *d, const void *s, int pixels); +void bgr555_to_uyvy(void *d, const void *s, int pixels, int x2); +void bgr888_to_uyvy(void *d, const void *s, int pixels, int x2); #ifdef __cplusplus } diff --git a/frontend/libpicofe b/frontend/libpicofe index a8ded55f..80612f5f 160000 --- a/frontend/libpicofe +++ b/frontend/libpicofe @@ -1 +1 @@ -Subproject commit a8ded55fc9df952b5582a6da72e1de887e65a34b +Subproject commit 80612f5f31a3201e6c7f710109a9c8b48f6bb757 diff --git a/frontend/menu.c b/frontend/menu.c index 99ca5925..a5ffb7b4 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -94,6 +94,7 @@ typedef enum MA_OPT_SWFILTER, MA_OPT_GAMMA, MA_OPT_VOUT_MODE, + MA_OPT_VOUT_FULL, MA_OPT_SCANLINES, MA_OPT_SCANLINE_LEVEL, MA_OPT_CENTERING, @@ -132,7 +133,6 @@ static int bios_sel, gpu_plugsel, spu_plugsel; #ifndef UI_FEATURES_H #define MENU_BIOS_PATH "bios/" -#define MENU_SHOW_VARSCALER 0 #define MENU_SHOW_VOUTMODE 1 #define MENU_SHOW_SCALER2 0 #define MENU_SHOW_NUBS_BTNS 0 @@ -142,6 +142,12 @@ static int bios_sel, gpu_plugsel, spu_plugsel; #define MENU_SHOW_FULLSCREEN 1 #define MENU_SHOW_VOLUME 0 #endif +#ifndef MENU_SHOW_VARSCALER +#define MENU_SHOW_VARSCALER 0 +#endif +#ifndef MENU_SHOW_VARSCALER_C +#define MENU_SHOW_VARSCALER_C 0 +#endif static int min(int x, int y) { return x < y ? x : y; } static int max(int x, int y) { return x > y ? x : y; } @@ -1280,7 +1286,11 @@ static int menu_loop_keyconfig(int id, int keys) // ------------ gfx options menu ------------ static const char *men_scaler[] = { - "1x1", "integer scaled 2x", "scaled 4:3", "integer scaled 4:3", "fullscreen", "custom", NULL + "1x1", "integer scaled 2x", "scaled 4:3", "integer scaled 4:3", "fullscreen", +#if MENU_SHOW_VARSCALER_C + "custom", +#endif + NULL }; static const char *men_soft_filter[] = { "None", #ifdef HAVE_NEON32 @@ -1385,10 +1395,11 @@ static int menu_loop_cscaler(int id, int keys) static menu_entry e_menu_gfx_options[] = { - mee_enum ("Screen centering", MA_OPT_CENTERING, pl_rearmed_cbs.screen_centering_type, men_centering), + mee_enum ("PSX Screen centering", MA_OPT_CENTERING, pl_rearmed_cbs.screen_centering_type, men_centering), mee_enum ("Show overscan", MA_OPT_OVERSCAN, pl_rearmed_cbs.show_overscan, men_overscan), mee_enum_h ("Scaler", MA_OPT_VARSCALER, g_scaler, men_scaler, h_scaler), mee_enum ("Video output mode", MA_OPT_VOUT_MODE, plat_target.vout_method, men_dummy), + mee_onoff ("Fullscreen mode", MA_OPT_VOUT_FULL, plat_target.vout_fullscreen, 1), mee_onoff ("Software Scaling", MA_OPT_SCALER2, soft_scaling, 1), mee_enum ("Hardware Filter", MA_OPT_HWFILTER, plat_target.hwfilter, men_dummy), mee_enum_h ("Software Filter", MA_OPT_SWFILTER, soft_filter, men_soft_filter, h_soft_filter), @@ -2672,6 +2683,12 @@ void menu_init(void) me_enable(e_menu_gfx_options, MA_OPT_VOUT_MODE, plat_target.vout_methods != NULL); +#ifndef SDL_OVERLAY_2X + i = me_id2offset(e_menu_gfx_options, MA_OPT_VOUT_FULL); + e_menu_gfx_options[i].data = plat_target.vout_methods; + me_enable(e_menu_gfx_options, MA_OPT_VOUT_FULL, 0); +#endif + i = me_id2offset(e_menu_gfx_options, MA_OPT_HWFILTER); e_menu_gfx_options[i].data = plat_target.hwfilters; me_enable(e_menu_gfx_options, MA_OPT_HWFILTER, @@ -2685,7 +2702,7 @@ void menu_init(void) #endif me_enable(e_menu_gfx_options, MA_OPT_VARSCALER, MENU_SHOW_VARSCALER); me_enable(e_menu_gfx_options, MA_OPT_VOUT_MODE, MENU_SHOW_VOUTMODE); - me_enable(e_menu_gfx_options, MA_OPT_VARSCALER_C, MENU_SHOW_VARSCALER); + me_enable(e_menu_gfx_options, MA_OPT_VARSCALER_C, MENU_SHOW_VARSCALER_C); me_enable(e_menu_gfx_options, MA_OPT_SCALER2, MENU_SHOW_SCALER2); me_enable(e_menu_keyconfig, MA_CTRL_NUBS_BTNS, MENU_SHOW_NUBS_BTNS); me_enable(e_menu_keyconfig, MA_CTRL_VIBRATION, MENU_SHOW_VIBRATION); diff --git a/frontend/pandora/ui_feat.h b/frontend/pandora/ui_feat.h index 3bb808af..5eb3dc2f 100644 --- a/frontend/pandora/ui_feat.h +++ b/frontend/pandora/ui_feat.h @@ -4,6 +4,7 @@ #define MENU_BIOS_PATH "/pandora/appdata/pcsx_rearmed/bios/" #define BOOT_MSG "Booting up... (press SPACE for menu)" #define MENU_SHOW_VARSCALER 1 +#define MENU_SHOW_VARSCALER_C 1 #define MENU_SHOW_VOUTMODE 0 #define MENU_SHOW_SCALER2 0 #define MENU_SHOW_NUBS_BTNS 1 diff --git a/frontend/plat_sdl.c b/frontend/plat_sdl.c index 64cac7ce..3529d979 100644 --- a/frontend/plat_sdl.c +++ b/frontend/plat_sdl.c @@ -9,6 +9,7 @@ */ #include +#include #include #include "libpicofe/input.h" @@ -16,14 +17,18 @@ #include "libpicofe/menu.h" #include "libpicofe/fonts.h" #include "libpicofe/plat_sdl.h" +#include "libpicofe/plat.h" #include "libpicofe/gl.h" #include "cspace.h" #include "plugin_lib.h" #include "plugin.h" +#include "menu.h" #include "main.h" #include "plat.h" #include "revision.h" +#include "libpicofe/plat_sdl.c" + static const struct in_default_bind in_sdl_defbinds[] = { { SDLK_UP, IN_BINDTYPE_PLAYER12, DKEY_UP }, { SDLK_DOWN, IN_BINDTYPE_PLAYER12, DKEY_DOWN }, @@ -90,39 +95,45 @@ static const struct in_pdata in_sdl_platform_data = { static int psx_w = 256, psx_h = 240; static void *shadow_fb, *menubg_img; +static int resized, window_w, window_h; +static int vout_fullscreen_old; +static int forced_clears; +static int forced_flips; +static int sdl12_compat; static int in_menu; +static void handle_scaler_resize(int w, int h); static void centered_clear(void); -static void *setup_blit_callbacks(int w); - -static int change_video_mode(int force) -{ - int w, h, ret; - - if (in_menu) { - w = g_menuscreen_w; - h = g_menuscreen_h; - } - else { - w = psx_w; - h = psx_h; - } - - ret = plat_sdl_change_video_mode(w, h, force); - if (ret == 0 && plat_sdl_overlay == NULL && !plat_sdl_gl_active) - centered_clear(); - return ret; -} static void resize_cb(int w, int h) { - // used by some plugins.. + // used by some plugins... pl_rearmed_cbs.screen_w = w; pl_rearmed_cbs.screen_h = h; pl_rearmed_cbs.gles_display = gl_es_display; pl_rearmed_cbs.gles_surface = gl_es_surface; plugin_call_rearmed_cbs(); - setup_blit_callbacks(psx_w); +} + +static void sdl_event_handler(void *event_) +{ + SDL_Event *event = event_; + + switch (event->type) { + case SDL_VIDEORESIZE: + if (window_w != (event->resize.w & ~3) || window_h != (event->resize.h & ~1)) { + window_w = event->resize.w & ~3; + window_h = event->resize.h & ~1; + resized = 1; + } + return; + case SDL_ACTIVEEVENT: + // no need to redraw? + return; + default: + break; + } + plat_sdl_event_handler(event_); } static void quit_cb(void) @@ -140,6 +151,7 @@ static void get_layer_pos(int *x, int *y, int *w, int *h) void plat_init(void) { + const SDL_version *ver; int shadow_size; int ret; @@ -150,6 +162,10 @@ void plat_init(void) if (ret != 0) exit(1); + ver = SDL_Linked_Version(); + sdl12_compat = ver->patch >= 50; + printf("SDL %u.%u.%u compat=%d\n", ver->major, ver->minor, ver->patch, sdl12_compat); + in_menu = 1; SDL_WM_SetCaption("PCSX-ReARMed " REV, NULL); @@ -165,12 +181,19 @@ void plat_init(void) exit(1); } - in_sdl_init(&in_sdl_platform_data, plat_sdl_event_handler); + in_sdl_init(&in_sdl_platform_data, sdl_event_handler); in_probe(); pl_rearmed_cbs.only_16bpp = 1; pl_rearmed_cbs.pl_get_layer_pos = get_layer_pos; bgr_to_uyvy_init(); + + // to "finish" init and set SDL_RESIZABLE + plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, -1); + if (plat_sdl_overlay) { + printf("overlay: %08x hw=%d\n", plat_sdl_overlay->format, + plat_sdl_overlay->hw_overlay); + } } void plat_finish(void) @@ -186,22 +209,70 @@ void plat_gvideo_open(int is_pal) { } -static void uyvy_to_rgb565(void *d, const void *s, int pixels) +static void uyvy_to_rgb565(void *d, int pixels) { + const unsigned int *src = (const void *)plat_sdl_overlay->pixels[0]; + int x2 = plat_sdl_overlay->w >= psx_w * 2; unsigned short *dst = d; - const unsigned int *src = s; int v; // no colors, for now - for (; pixels > 0; src++, dst += 2, pixels -= 2) { - v = (*src >> 8) & 0xff; - v = (v - 16) * 255 / 219 / 8; - dst[0] = (v << 11) | (v << 6) | v; - - v = (*src >> 24) & 0xff; - v = (v - 16) * 255 / 219 / 8; - dst[1] = (v << 11) | (v << 6) | v; + if (x2) { + for (; pixels > 0; src++, dst++, pixels--) { + v = (*src >> 8) & 0xff; + v = (v - 16) * 255 / 219 / 8; + *dst = (v << 11) | (v << 6) | v; + } + } + else { + for (; pixels > 0; src++, dst += 2, pixels -= 2) { + v = (*src >> 8) & 0xff; + v = (v - 16) * 255 / 219 / 8; + dst[0] = (v << 11) | (v << 6) | v; + + v = (*src >> 24) & 0xff; + v = (v - 16) * 255 / 219 / 8; + dst[1] = (v << 11) | (v << 6) | v; + } + } +} + +static void overlay_resize(int force) +{ + int x2_mul = !in_menu && plat_target.vout_method > 1 ? 2 : 1; // lame + int w = in_menu ? g_menuscreen_w : psx_w; + int h = in_menu ? g_menuscreen_h : psx_h; + + if (!force && plat_sdl_overlay && w * x2_mul == plat_sdl_overlay->w + && h == plat_sdl_overlay->h) + return; + if (plat_sdl_overlay) + SDL_FreeYUVOverlay(plat_sdl_overlay); + plat_sdl_overlay = SDL_CreateYUVOverlay(w * x2_mul, h, SDL_UYVY_OVERLAY, + plat_sdl_screen); + if (plat_sdl_overlay) { + //printf("overlay: %dx%d %08x hw=%d\n", plat_sdl_overlay->w, plat_sdl_overlay->h, + // plat_sdl_overlay->format, plat_sdl_overlay->hw_overlay); + if (SDL_LockYUVOverlay(plat_sdl_overlay) == 0) { + plat_sdl_overlay_clear(); + SDL_UnlockYUVOverlay(plat_sdl_overlay); + } + } + else + fprintf(stderr, "overlay resize to %dx%d failed\n", w, h); + handle_scaler_resize(w, h); +} + +static void overlay_check_enable(void) +{ + // we no longer unconditionally call plat_sdl_change_video_mode() + // to not disturb the window, need to look for config change + if ((plat_target.vout_method == 0 || plat_sdl_gl_active) && plat_sdl_overlay) { + SDL_FreeYUVOverlay(plat_sdl_overlay); + plat_sdl_overlay = NULL; } + else if (plat_target.vout_method > 0 && !plat_sdl_gl_active) // lame + overlay_resize(0); } static void overlay_blit(int doffs, const void *src_, int w, int h, @@ -210,6 +281,7 @@ static void overlay_blit(int doffs, const void *src_, int w, int h, const unsigned short *src = src_; unsigned short *dst; int dstride = plat_sdl_overlay->w; + int x2 = dstride >= 2 * w; SDL_LockYUVOverlay(plat_sdl_overlay); dst = (void *)plat_sdl_overlay->pixels[0]; @@ -217,11 +289,11 @@ static void overlay_blit(int doffs, const void *src_, int w, int h, dst += doffs; if (bgr24) { for (; h > 0; dst += dstride, src += sstride, h--) - bgr888_to_uyvy(dst, src, w); + bgr888_to_uyvy(dst, src, w, x2); } else { for (; h > 0; dst += dstride, src += sstride, h--) - bgr555_to_uyvy(dst, src, w); + bgr555_to_uyvy(dst, src, w, x2); } SDL_UnlockYUVOverlay(plat_sdl_overlay); @@ -229,7 +301,11 @@ static void overlay_blit(int doffs, const void *src_, int w, int h, static void overlay_hud_print(int x, int y, const char *str, int bpp) { + int x2; SDL_LockYUVOverlay(plat_sdl_overlay); + x2 = plat_sdl_overlay->w >= psx_w * 2; + if (x2) + x *= 2; basic_text_out_uyvy_nf(plat_sdl_overlay->pixels[0], plat_sdl_overlay->w, x, y, str); SDL_UnlockYUVOverlay(plat_sdl_overlay); } @@ -241,13 +317,39 @@ static void centered_clear(void) int h = plat_sdl_screen->h; unsigned short *dst; - SDL_LockSurface(plat_sdl_screen); + if (SDL_MUSTLOCK(plat_sdl_screen)) + SDL_LockSurface(plat_sdl_screen); dst = plat_sdl_screen->pixels; for (; h > 0; dst += dstride, h--) memset(dst, 0, w * 2); - SDL_UnlockSurface(plat_sdl_screen); + if (SDL_MUSTLOCK(plat_sdl_screen)) + SDL_UnlockSurface(plat_sdl_screen); + + if (plat_sdl_overlay != NULL) { + // apply the parts not covered by the overlay + forced_flips = 3; + } +} + +static int adj_src_dst(const SDL_Surface *sfc, int w, int pp, int *h, + unsigned short **dst, const unsigned short **src) +{ + int line_w = w; + if (sfc->w > w) + *dst += (sfc->w - w) / 2; + else { + *src += (w - sfc->w) / 2; + line_w = sfc->w; + } + if (sfc->h > *h) + *dst += sfc->pitch * (sfc->h - *h) / 2 / 2; + else { + *src += pp * (*h - sfc->h) / 2; + *h = sfc->h; + } + return line_w; } static void centered_blit(int doffs, const void *src_, int w, int h, @@ -257,12 +359,12 @@ static void centered_blit(int doffs, const void *src_, int w, int h, unsigned short *dst; int dstride; - SDL_LockSurface(plat_sdl_screen); + if (SDL_MUSTLOCK(plat_sdl_screen)) + SDL_LockSurface(plat_sdl_screen); dst = plat_sdl_screen->pixels; dstride = plat_sdl_screen->pitch / 2; + w = adj_src_dst(plat_sdl_screen, w, sstride, &h, &dst, &src); - dst += doffs + (plat_sdl_screen->w - w) / 2; - dst += dstride * (plat_sdl_screen->h - h) / 2; if (bgr24) { for (; h > 0; dst += dstride, src += sstride, h--) bgr888_to_rgb565(dst, src, w * 3); @@ -272,7 +374,8 @@ static void centered_blit(int doffs, const void *src_, int w, int h, bgr555_to_rgb565(dst, src, w * 2); } - SDL_UnlockSurface(plat_sdl_screen); + if (SDL_MUSTLOCK(plat_sdl_screen)) + SDL_UnlockSurface(plat_sdl_screen); } static void centered_blit_menu(void) @@ -281,30 +384,39 @@ static void centered_blit_menu(void) int w = g_menuscreen_w; int h = g_menuscreen_h; unsigned short *dst; - int dstride; + int dstride, len; + + if (SDL_MUSTLOCK(plat_sdl_screen)) + SDL_LockSurface(plat_sdl_screen); - SDL_LockSurface(plat_sdl_screen); dst = plat_sdl_screen->pixels; dstride = plat_sdl_screen->pitch / 2; + len = adj_src_dst(plat_sdl_screen, w, g_menuscreen_pp, &h, &dst, &src); - dst += (plat_sdl_screen->w - w) / 2; - dst += dstride * (plat_sdl_screen->h - h) / 2; for (; h > 0; dst += dstride, src += g_menuscreen_pp, h--) - memcpy(dst, src, w * 2); + memcpy(dst, src, len * 2); - SDL_UnlockSurface(plat_sdl_screen); + if (SDL_MUSTLOCK(plat_sdl_screen)) + SDL_UnlockSurface(plat_sdl_screen); } static void centered_hud_print(int x, int y, const char *str, int bpp) { - x += (plat_sdl_screen->w - psx_w) / 2; - y += (plat_sdl_screen->h - psx_h) / 2; - SDL_LockSurface(plat_sdl_screen); + int w_diff, h_diff; + if (SDL_MUSTLOCK(plat_sdl_screen)) + SDL_LockSurface(plat_sdl_screen); + w_diff = plat_sdl_screen->w - psx_w; + h_diff = plat_sdl_screen->h - psx_h; + if (w_diff > 0) x += w_diff / 2; + if (h_diff > 0) y += h_diff / 2; + if (h_diff < 0) y += h_diff; + if (w_diff < 0 && x > 32) x += w_diff; basic_text_out16_nf(plat_sdl_screen->pixels, plat_sdl_screen->pitch / 2, x, y, str); - SDL_UnlockSurface(plat_sdl_screen); + if (SDL_MUSTLOCK(plat_sdl_screen)) + SDL_UnlockSurface(plat_sdl_screen); } -static void *setup_blit_callbacks(int w) +static void *setup_blit_callbacks(int w, int h) { pl_plat_clear = NULL; pl_plat_blit = NULL; @@ -318,43 +430,134 @@ static void *setup_blit_callbacks(int w) return shadow_fb; } else { - if (w == plat_sdl_screen->w) + pl_plat_clear = centered_clear; + + if (!SDL_MUSTLOCK(plat_sdl_screen) && w == plat_sdl_screen->w && + h == plat_sdl_screen->h) return plat_sdl_screen->pixels; + + pl_plat_blit = centered_blit; + pl_plat_hud_print = centered_hud_print; + } + return NULL; +} + +// not using plat_sdl_change_video_mode() since we need +// different size overlay vs plat_sdl_screen layer +static void change_mode(int w, int h) +{ + int set_w = w, set_h = h, had_overlay = 0; + if (plat_target.vout_fullscreen && (plat_target.vout_method != 0 || !sdl12_compat)) + set_w = fs_w, set_h = fs_h; + if (plat_sdl_screen->w != set_w || plat_sdl_screen->h != set_h || + plat_target.vout_fullscreen != vout_fullscreen_old) + { + Uint32 flags = plat_sdl_screen->flags; + if (plat_target.vout_fullscreen) + flags |= SDL_FULLSCREEN; else { - pl_plat_clear = centered_clear; - pl_plat_blit = centered_blit; - pl_plat_hud_print = centered_hud_print; + flags &= ~SDL_FULLSCREEN; + if (plat_sdl_is_windowed()) + flags |= SDL_RESIZABLE; // sdl12-compat 1.2.68 loses this flag + } + if (plat_sdl_overlay) { + SDL_FreeYUVOverlay(plat_sdl_overlay); + plat_sdl_overlay = NULL; + had_overlay = 1; } + SDL_PumpEvents(); + plat_sdl_screen = SDL_SetVideoMode(set_w, set_h, 16, flags); + //printf("mode: %dx%d %x -> %dx%d\n", set_w, set_h, flags, + // plat_sdl_screen->w, plat_sdl_screen->h); + assert(plat_sdl_screen); + if (vout_fullscreen_old && !plat_target.vout_fullscreen) + // why is this needed?? (on 1.2.68) + SDL_WM_GrabInput(SDL_GRAB_OFF); + // overlay needs the latest plat_sdl_screen + if (had_overlay) + overlay_resize(1); + centered_clear(); + vout_fullscreen_old = plat_target.vout_fullscreen; + } +} + +static void handle_scaler_resize(int w, int h) +{ + int ww = plat_sdl_screen->w; + int wh = plat_sdl_screen->h; + int layer_w_old = g_layer_w; + int layer_h_old = g_layer_h; + pl_update_layer_size(w, h, ww, wh); + if (layer_w_old != g_layer_w || layer_h_old != g_layer_h) + forced_clears = 3; +} + +static void handle_window_resize(void) +{ + // sdl12-compat: a hack to take advantage of sdl2 scaling + if (resized && (plat_target.vout_method != 0 || !sdl12_compat)) { + change_mode(window_w, window_h); + setup_blit_callbacks(psx_w, psx_h); + forced_clears = 3; + resized = 0; } - return NULL; } void *plat_gvideo_set_mode(int *w, int *h, int *bpp) { psx_w = *w; psx_h = *h; - change_video_mode(0); - if (plat_sdl_gl_active) - memset(shadow_fb, 0, psx_w * psx_h * 2); - return setup_blit_callbacks(*w); + + if (plat_sdl_overlay != NULL) + overlay_resize(0); + else if (plat_sdl_gl_active) + memset(shadow_fb, 0, (*w) * (*h) * 2); + else if (plat_target.vout_method == 0) // && sdl12_compat + change_mode(*w, *h); + + handle_scaler_resize(*w, *h); // override the value from pl_vout_set_mode() + return setup_blit_callbacks(*w, *h); } void *plat_gvideo_flip(void) { + void *ret = NULL; + int do_flip = 0; if (plat_sdl_overlay != NULL) { - SDL_Rect dstrect = { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h }; + SDL_Rect dstrect = { + (plat_sdl_screen->w - g_layer_w) / 2, + (plat_sdl_screen->h - g_layer_h) / 2, + g_layer_w, g_layer_h + }; + SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect); - return NULL; } else if (plat_sdl_gl_active) { gl_flip(shadow_fb, psx_w, psx_h); - return shadow_fb; + ret = shadow_fb; } - else { - // XXX: no locking, but should be fine with SDL_SWSURFACE? + else + do_flip |= 2; + + if (forced_flips > 0) { + forced_flips--; + do_flip |= 1; + } + if (do_flip) SDL_Flip(plat_sdl_screen); - return plat_sdl_screen->pixels; + handle_window_resize(); + if (do_flip) { + if (forced_clears > 0) { + forced_clears--; + centered_clear(); + } + if (!SDL_MUSTLOCK(plat_sdl_screen) && plat_sdl_screen->w == psx_w && + plat_sdl_screen->h == psx_h && (do_flip & 2)) { + ret = plat_sdl_screen->pixels; + } } + assert(ret || pl_plat_clear != NULL); + return ret; } void plat_gvideo_close(void) @@ -363,35 +566,65 @@ void plat_gvideo_close(void) void plat_video_menu_enter(int is_rom_loaded) { - int force_mode_change = 0; - in_menu = 1; /* surface will be lost, must adjust pl_vout_buf for menu bg */ if (plat_sdl_overlay != NULL) - uyvy_to_rgb565(menubg_img, plat_sdl_overlay->pixels[0], psx_w * psx_h); + uyvy_to_rgb565(menubg_img, psx_w * psx_h); else if (plat_sdl_gl_active) memcpy(menubg_img, shadow_fb, psx_w * psx_h * 2); - else - memcpy(menubg_img, plat_sdl_screen->pixels, psx_w * psx_h * 2); + else { + unsigned short *dst = menubg_img; + const unsigned short *src; + int h; + if (SDL_MUSTLOCK(plat_sdl_screen)) + SDL_LockSurface(plat_sdl_screen); + src = plat_sdl_screen->pixels; + src += (plat_sdl_screen->w - psx_w) / 2; + src += plat_sdl_screen->pitch * (plat_sdl_screen->h - psx_h) / 2 / 2; + for (h = psx_h; h > 0; dst += psx_w, src += plat_sdl_screen->pitch / 2, h--) + memcpy(dst, src, psx_w * 2); + if (SDL_MUSTLOCK(plat_sdl_screen)) + SDL_UnlockSurface(plat_sdl_screen); + } pl_vout_buf = menubg_img; - /* gles plugin messes stuff up.. */ - if (pl_rearmed_cbs.gpu_caps & GPU_CAP_OWNS_DISPLAY) - force_mode_change = 1; - - change_video_mode(force_mode_change); + if (plat_target.vout_method == 0) + change_mode(g_menuscreen_w, g_menuscreen_h); + else + overlay_check_enable(); + centered_clear(); } void plat_video_menu_begin(void) { + void *old_ovl = plat_sdl_overlay; + static int g_scaler_old; + int scaler_changed = g_scaler_old != g_scaler; + g_scaler_old = g_scaler; + if (plat_target.vout_fullscreen != vout_fullscreen_old || + (plat_target.vout_fullscreen && scaler_changed)) { + change_mode(g_menuscreen_w, g_menuscreen_h); + } + else + overlay_check_enable(); + handle_scaler_resize(g_menuscreen_w, g_menuscreen_h); + + if (old_ovl != plat_sdl_overlay || scaler_changed) + centered_clear(); g_menuscreen_ptr = shadow_fb; } void plat_video_menu_end(void) { + int do_flip = 0; + if (plat_sdl_overlay != NULL) { - SDL_Rect dstrect = { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h }; + SDL_Rect dstrect = { + (plat_sdl_screen->w - g_layer_w) / 2, + (plat_sdl_screen->h - g_layer_h) / 2, + g_layer_w, g_layer_h + }; SDL_LockYUVOverlay(plat_sdl_overlay); rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb, @@ -405,21 +638,31 @@ void plat_video_menu_end(void) } else { centered_blit_menu(); - SDL_Flip(plat_sdl_screen); + do_flip |= 2; } + + if (forced_flips > 0) { + forced_flips--; + do_flip |= 1; + } + if (do_flip) + SDL_Flip(plat_sdl_screen); + + handle_window_resize(); g_menuscreen_ptr = NULL; } void plat_video_menu_leave(void) { - void *fb = NULL; - if (plat_sdl_overlay != NULL || plat_sdl_gl_active) - fb = shadow_fb; - else if (plat_sdl_screen) - fb = plat_sdl_screen->pixels; - if (fb) - memset(fb, 0, g_menuscreen_w * g_menuscreen_h * 2); in_menu = 0; + if (plat_sdl_overlay != NULL || plat_sdl_gl_active) + memset(shadow_fb, 0, g_menuscreen_w * g_menuscreen_h * 2); + + if (plat_target.vout_fullscreen) + change_mode(fs_w, fs_h); + else + overlay_check_enable(); + centered_clear(); } /* unused stuff */ diff --git a/frontend/plugin_lib.c b/frontend/plugin_lib.c index 98e86ea3..81998d5b 100644 --- a/frontend/plugin_lib.c +++ b/frontend/plugin_lib.c @@ -54,7 +54,7 @@ void *tsdev; void *pl_vout_buf; int g_layer_x, g_layer_y, g_layer_w, g_layer_h; static int pl_vout_w, pl_vout_h, pl_vout_bpp; /* output display/layer */ -static int pl_vout_scale_w, pl_vout_scale_h, pl_vout_yoffset; +static int pl_vout_scale_w, pl_vout_scale_h; static int psx_w, psx_h, psx_bpp; static int vsync_cnt; static int is_pal, frame_interval, frame_interval1024; @@ -178,7 +178,7 @@ static void print_hud(int x, int w, int h) } /* update scaler target size according to user settings */ -static void update_layer_size(int w, int h) +void pl_update_layer_size(int w, int h, int fw, int fh) { float mult; int imult; @@ -190,39 +190,45 @@ static void update_layer_size(int w, int h) case SCALE_2_2: g_layer_w = w; g_layer_h = h; - if (w * 2 <= g_menuscreen_w) + if (w * 2 <= fw) g_layer_w = w * 2; - if (h * 2 <= g_menuscreen_h) + if (h * 2 <= fh) g_layer_h = h * 2; break; case SCALE_4_3v2: - if (h > g_menuscreen_h || (240 < h && h <= 360)) - goto fractional_4_3; +#ifdef PANDORA + if (h <= fh && !(240 < h && h <= 360)) + { +#endif // 4:3 that prefers integer scaling - imult = g_menuscreen_h / h; + imult = fh / h; + if (imult < 1) + imult = 1; g_layer_w = w * imult; g_layer_h = h * imult; mult = (float)g_layer_w / (float)g_layer_h; if (mult < 1.25f || mult > 1.666f) g_layer_w = 4.0f/3.0f * (float)g_layer_h; - printf(" -> %dx%d %.1f\n", g_layer_w, g_layer_h, mult); + //printf(" -> %dx%d %.1f\n", g_layer_w, g_layer_h, mult); break; +#ifdef PANDORA + } +#endif - fractional_4_3: case SCALE_4_3: mult = 240.0f / (float)h * 4.0f / 3.0f; if (h > 256) mult *= 2.0f; - g_layer_w = mult * (float)g_menuscreen_h; - g_layer_h = g_menuscreen_h; - printf(" -> %dx%d %.1f\n", g_layer_w, g_layer_h, mult); + g_layer_w = mult * (float)fh; + g_layer_h = fh; + //printf(" -> %dx%d %.1f\n", g_layer_w, g_layer_h, mult); break; case SCALE_FULLSCREEN: - g_layer_w = g_menuscreen_w; - g_layer_h = g_menuscreen_h; + g_layer_w = fw; + g_layer_h = fh; break; default: @@ -230,11 +236,11 @@ static void update_layer_size(int w, int h) } if (g_scaler != SCALE_CUSTOM) { - g_layer_x = g_menuscreen_w / 2 - g_layer_w / 2; - g_layer_y = g_menuscreen_h / 2 - g_layer_h / 2; + g_layer_x = fw / 2 - g_layer_w / 2; + g_layer_y = fh / 2 - g_layer_h / 2; } - if (g_layer_w > g_menuscreen_w * 2) g_layer_w = g_menuscreen_w * 2; - if (g_layer_h > g_menuscreen_h * 2) g_layer_h = g_menuscreen_h * 2; + if (g_layer_w > fw * 2) g_layer_w = fw * 2; + if (g_layer_h > fh * 2) g_layer_h = fh * 2; } // XXX: this is platform specific really @@ -246,7 +252,6 @@ static inline int resolution_ok(int w, int h) static void pl_vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp) { int vout_w, vout_h, vout_bpp; - int buf_yoffset = 0; // special h handling, Wipeout likes to change it by 1-6 static int vsync_cnt_ms_prev; @@ -285,7 +290,7 @@ static void pl_vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp) vout_w *= pl_vout_scale_w; vout_h *= pl_vout_scale_h; - update_layer_size(vout_w, vout_h); + pl_update_layer_size(vout_w, vout_h, g_menuscreen_w, g_menuscreen_h); pl_vout_buf = plat_gvideo_set_mode(&vout_w, &vout_h, &vout_bpp); if (pl_vout_buf == NULL && pl_plat_blit == NULL) @@ -295,11 +300,7 @@ static void pl_vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp) pl_vout_w = vout_w; pl_vout_h = vout_h; pl_vout_bpp = vout_bpp; - pl_vout_yoffset = buf_yoffset; } - if (pl_vout_buf != NULL) - pl_vout_buf = (char *)pl_vout_buf - + pl_vout_yoffset * pl_vout_w * pl_vout_bpp / 8; menu_notify_mode_change(pl_vout_w, pl_vout_h, pl_vout_bpp); } @@ -317,7 +318,7 @@ static void pl_vout_flip(const void *vram_, int vram_ofs, int bgr24, unsigned char *dest = pl_vout_buf; const unsigned char *vram = vram_; int dstride = pl_vout_w, h1 = h; - int h_full = pl_vout_h - pl_vout_yoffset; + int h_full = pl_vout_h; int enhres = w > psx_w; int xoffs = 0, doffs; int hwrapped; @@ -465,9 +466,6 @@ out: // let's flip now pl_vout_buf = plat_gvideo_flip(); - if (pl_vout_buf != NULL) - pl_vout_buf = (char *)pl_vout_buf - + pl_vout_yoffset * pl_vout_w * pl_vout_bpp / 8; pl_rearmed_cbs.flip_cnt++; } diff --git a/frontend/plugin_lib.h b/frontend/plugin_lib.h index 855c716d..74a73729 100644 --- a/frontend/plugin_lib.h +++ b/frontend/plugin_lib.h @@ -48,6 +48,7 @@ void pl_force_clear(void); void pl_timing_prepare(int is_pal); void pl_frame_limit(void); +void pl_update_layer_size(int w, int h, int fw, int fh); // for communication with gpulib struct rearmed_cbs { -- 2.39.5 From 1ae743b1f67e225d74fa08839dc794630c1f8e7c Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 11 May 2025 21:27:12 +0300 Subject: [PATCH 05/16] frontend: use more traditional profile dir With backward compatibility to working dir, also can set 'HOME=' env var for the old behavior. notaz/pcsx_rearmed#375 --- Makefile | 2 +- frontend/main.c | 189 +++++++++++++++++++++++++++----------------- frontend/main.h | 27 ++++--- frontend/menu.c | 41 ++++------ frontend/plat_sdl.c | 12 ++- libpcsxcore/sio.c | 4 +- 6 files changed, 165 insertions(+), 110 deletions(-) diff --git a/Makefile b/Makefile index f56ca1a5..784ef19f 100644 --- a/Makefile +++ b/Makefile @@ -388,8 +388,8 @@ OBJS += frontend/libpicofe/linux/fbdev.o frontend/libpicofe/linux/xenv.o OBJS += frontend/libpicofe/linux/in_evdev.o OBJS += frontend/plat_pandora.o frontend/plat_omap.o frontend/main.o frontend/menu.o: CFLAGS += -include frontend/pandora/ui_feat.h +frontend/main.o frontend/plugin_lib.o: CFLAGS += -DPANDORA frontend/libpicofe/linux/plat.o: CFLAGS += -DPANDORA -frontend/plugin_lib.o: CFLAGS += -DPANDORA USE_PLUGIN_LIB = 1 USE_FRONTEND = 1 CFLAGS += -gdwarf-3 diff --git a/frontend/main.c b/frontend/main.c index 2aa6fbd7..6f581a8b 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -46,6 +46,7 @@ #endif #ifndef NO_FRONTEND +#include #include "libpicofe/input.h" #include "libpicofe/plat.h" #include "libpicofe/readpng.h" @@ -53,6 +54,11 @@ static void toggle_fast_forward(int force_off); static void check_profile(void); static void check_memcards(void); +static int get_gameid_filename(char *buf, int size, const char *fmt, int i); +static const char *get_home_dir(void); +#define MAKE_PATH(buf, dir, fname) \ + emu_make_path(buf, sizeof(buf), dir, fname) + #endif #ifndef BOOT_MSG #define BOOT_MSG "Booting up..." @@ -70,33 +76,6 @@ enum sched_action emu_action, emu_action_old; char hud_msg[64]; int hud_new_msg; -static inline void make_path(char *buf, size_t size, const char *dir, const char *fname) -{ - if (fname) - snprintf(buf, size, ".%s%s", dir, fname); - else - snprintf(buf, size, ".%s", dir); -} -#define MAKE_PATH(buf, dir, fname) \ - make_path(buf, sizeof(buf), dir, fname) - -static int get_gameid_filename(char *buf, int size, const char *fmt, int i) { - char trimlabel[33]; - int j; - - strncpy(trimlabel, CdromLabel, 32); - trimlabel[32] = 0; - for (j = 31; j >= 0; j--) - if (trimlabel[j] == ' ') - trimlabel[j] = 0; - else - continue; - - snprintf(buf, size, fmt, trimlabel, CdromId, i); - - return 0; -} - void set_cd_image(const char *fname) { SetIsoFile(fname); @@ -105,13 +84,23 @@ void set_cd_image(const char *fname) static void set_default_paths(void) { #ifndef NO_FRONTEND - snprintf(Config.PatchesDir, sizeof(Config.PatchesDir), "." PATCHES_DIR); + const char *home = get_home_dir(); + struct stat st; + MAKE_PATH(Config.PatchesDir, PATCHES_DIR, NULL); MAKE_PATH(Config.Mcd1, MEMCARD_DIR, "card1.mcd"); MAKE_PATH(Config.Mcd2, MEMCARD_DIR, "card2.mcd"); - strcpy(Config.BiosDir, "bios"); + MAKE_PATH(Config.BiosDir, BIOS_DIR, NULL); + + emu_make_data_path(Config.PluginsDir, "plugins", sizeof(Config.PluginsDir)); + + // prefer bios in working dir for compatibility + if (!strcmp(home, ".") && !stat("bios", &st)) + strcpy(Config.BiosDir, "bios"); + + SysPrintf("dirs: profile=%s" PCSX_DOT_DIR ", bios=%s, plugins=%s\n", + home, Config.BiosDir, Config.PluginsDir); #endif - strcpy(Config.PluginsDir, "plugins"); strcpy(Config.Gpu, "builtin_gpu"); strcpy(Config.Spu, "builtin_spu"); } @@ -246,12 +235,14 @@ do_state_slot: scrbuf = pl_prepare_screenshot(&w, &h, &bpp); get_gameid_filename(buf, sizeof(buf), - "screenshots/%.32s-%.9s.%d.png", ti); - ret = -1; + "%s" SCREENSHOTS_DIR "%.32s-%.9s.%d.png", ti); + ret = -2; if (scrbuf != 0 && bpp == 16) ret = writepng(buf, scrbuf, w, h); if (ret == 0) snprintf(hud_msg, sizeof(hud_msg), "SCREENSHOT TAKEN"); + else + SysPrintf("writepng %s: %d\n", buf, ret); break; } case SACTION_VOLUME_UP: @@ -508,6 +499,45 @@ void emu_core_ask_exit(void) #include #include +static const char *get_home_dir(void) +{ +#if defined(PANDORA) || !defined(__unix__) + return "."; +#else + static const char *home = NULL; + struct stat st; + if (home) + return home; + // for compatibility with older versions, look for .pcsx in the working dir + if (stat(PCSX_DOT_DIR + 1, &st) != 0) + home = getenv("HOME"); + if (home == NULL) + home = "."; + return home; +#endif +} + +void emu_make_path(char *buf, size_t size, const char *dir, const char *fname) +{ + const char *home = get_home_dir(); + if (fname) + snprintf(buf, size, "%s%s%s", home, dir, fname); + else + snprintf(buf, size, "%s%s", home, dir); +} + +void emu_make_data_path(char *buff, const char *end, int size) +{ + int pos, end_len; + + end_len = strlen(end); + pos = plat_get_root_dir(buff, size); + strncpy(buff + pos, end, size - pos); + buff[size - 1] = 0; + if (pos + end_len > size - 1) + printf("Warning: path truncated: %s\n", buff); +} + static void create_profile_dir(const char *directory) { char path[MAXPATHLEN]; @@ -522,12 +552,10 @@ static void check_profile(void) { create_profile_dir(BIOS_DIR); create_profile_dir(MEMCARD_DIR); create_profile_dir(STATES_DIR); - create_profile_dir(PLUGINS_DIR); - create_profile_dir(PLUGINS_CFG_DIR); create_profile_dir(CHEATS_DIR); create_profile_dir(PATCHES_DIR); - create_profile_dir(PCSX_DOT_DIR "cfg"); - create_profile_dir("/screenshots/"); + create_profile_dir(CFG_DIR); + create_profile_dir(SCREENSHOTS_DIR); } static void check_memcards(void) @@ -537,7 +565,8 @@ static void check_memcards(void) int i; for (i = 1; i <= 9; i++) { - snprintf(buf, sizeof(buf), ".%scard%d.mcd", MEMCARD_DIR, i); + snprintf(buf, sizeof(buf), "%s%scard%d.mcd", + get_home_dir(), MEMCARD_DIR, i); f = fopen(buf, "rb"); if (f == NULL) { @@ -639,7 +668,8 @@ int main(int argc, char *argv[]) // FIXME: this recovery doesn't work, just delete bad config and bail out // SysMessage("could not load plugins, retrying with defaults\n"); set_default_paths(); - snprintf(path, sizeof(path), "." PCSX_DOT_DIR "%s", cfgfile_basename); + snprintf(path, sizeof(path), "%s" PCSX_DOT_DIR "%s", + get_home_dir(), cfgfile_basename); remove(path); SysMessage("Failed loading plugins!"); return 1; @@ -749,52 +779,32 @@ static void toggle_fast_forward(int force_off) } static void SignalExit(int sig) { + SysPrintf("got signal %d\n", sig); // only to restore framebuffer/resolution on some devices plat_finish(); _exit(1); } -#endif - -void SysRunGui() { - printf("SysRunGui\n"); -} - -static void CALLBACK dummy_lace(void) -{ -} - -void SysReset() { - // rearmed hack: EmuReset() runs some code when real BIOS is used, - // but we usually do reset from menu while GPU is not open yet, - // so we need to prevent updateLace() call.. - void *real_lace = GPU_updateLace; - GPU_updateLace = dummy_lace; - g_emu_resetting = 1; - - // reset can run code, timing must be set - pl_timing_prepare(Config.PsxType); - EmuReset(); - - GPU_updateLace = real_lace; - g_emu_resetting = 0; -} +static int get_gameid_filename(char *buf, int size, const char *fmt, int i) { + char trimlabel[33]; + int j; -void SysClose() { - EmuShutdown(); - ReleasePlugins(); + strncpy(trimlabel, CdromLabel, 32); + trimlabel[32] = 0; + for (j = 31; j >= 0; j--) + if (trimlabel[j] == ' ') + trimlabel[j] = 0; + else + continue; - StopDebugger(); + snprintf(buf, size, fmt, get_home_dir(), trimlabel, CdromId, i); - if (emuLog != NULL && emuLog != stdout && emuLog != stderr) { - fclose(emuLog); - emuLog = NULL; - } + return 0; } int get_state_filename(char *buf, int size, int i) { return get_gameid_filename(buf, size, - "." STATES_DIR "%.32s-%.9s.%3.3d", i); + "%s" STATES_DIR "%.32s-%.9s.%3.3d", i); } int emu_check_state(int slot) @@ -841,6 +851,41 @@ int emu_load_state(int slot) return LoadState(fname); } +#endif // NO_FRONTEND + +static void CALLBACK dummy_lace(void) +{ +} + +void SysReset() { + // rearmed hack: EmuReset() runs some code when real BIOS is used, + // but we usually do reset from menu while GPU is not open yet, + // so we need to prevent updateLace() call.. + void *real_lace = GPU_updateLace; + GPU_updateLace = dummy_lace; + g_emu_resetting = 1; + + // reset can run code, timing must be set + pl_timing_prepare(Config.PsxType); + + EmuReset(); + + GPU_updateLace = real_lace; + g_emu_resetting = 0; +} + +void SysClose() { + EmuShutdown(); + ReleasePlugins(); + + StopDebugger(); + + if (emuLog != NULL && emuLog != stdout && emuLog != stderr) { + fclose(emuLog); + emuLog = NULL; + } +} + #ifndef HAVE_LIBRETRO #ifndef ANDROID diff --git a/frontend/main.h b/frontend/main.h index 1c249354..3c17f8c5 100644 --- a/frontend/main.h +++ b/frontend/main.h @@ -19,18 +19,24 @@ #ifndef __FRONTEND_MAIN_H__ #define __FRONTEND_MAIN_H__ +#include #include "config.h" -#define DEFAULT_MEM_CARD_1 "/.pcsx/memcards/card1.mcd" -#define DEFAULT_MEM_CARD_2 "/.pcsx/memcards/card2.mcd" -#define MEMCARD_DIR "/.pcsx/memcards/" -#define PLUGINS_DIR "/.pcsx/plugins/" -#define PLUGINS_CFG_DIR "/.pcsx/plugins/cfg/" #define PCSX_DOT_DIR "/.pcsx/" -#define STATES_DIR "/.pcsx/sstates/" -#define CHEATS_DIR "/.pcsx/cheats/" -#define PATCHES_DIR "/.pcsx/patches/" -#define BIOS_DIR "/bios/" +#define DEFAULT_MEM_CARD_1 PCSX_DOT_DIR "memcards/card1.mcd" +#define DEFAULT_MEM_CARD_2 PCSX_DOT_DIR "memcards/card2.mcd" +#define MEMCARD_DIR PCSX_DOT_DIR "memcards/" +#define STATES_DIR PCSX_DOT_DIR "sstates/" +#define CHEATS_DIR PCSX_DOT_DIR "cheats/" +#define PATCHES_DIR PCSX_DOT_DIR "patches/" +#define CFG_DIR PCSX_DOT_DIR "cfg/" +#ifndef PANDORA +#define BIOS_DIR PCSX_DOT_DIR "bios/" +#define SCREENSHOTS_DIR PCSX_DOT_DIR "screenshots/" +#else +#define BIOS_DIR "/bios/" +#define SCREENSHOTS_DIR "/screenshots/" +#endif extern char cfgfile_basename[MAXPATHLEN]; @@ -46,6 +52,9 @@ void emu_core_ask_exit(void); void emu_set_default_config(void); void emu_on_new_cd(int show_hud_msg); +void emu_make_path(char *buf, size_t size, const char *dir, const char *fname); +void emu_make_data_path(char *buff, const char *end, int size); + int get_state_filename(char *buf, int size, int i); int emu_check_state(int slot); int emu_save_state(int slot); diff --git a/frontend/menu.c b/frontend/menu.c index a5ffb7b4..0c4ebcea 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -132,7 +132,6 @@ static const char *memcards[32]; static int bios_sel, gpu_plugsel, spu_plugsel; #ifndef UI_FEATURES_H -#define MENU_BIOS_PATH "bios/" #define MENU_SHOW_VOUTMODE 1 #define MENU_SHOW_SCALER2 0 #define MENU_SHOW_NUBS_BTNS 0 @@ -152,18 +151,6 @@ static int bios_sel, gpu_plugsel, spu_plugsel; static int min(int x, int y) { return x < y ? x : y; } static int max(int x, int y) { return x > y ? x : y; } -void emu_make_path(char *buff, const char *end, int size) -{ - int pos, end_len; - - end_len = strlen(end); - pos = plat_get_root_dir(buff, size); - strncpy(buff + pos, end, size - pos); - buff[size - 1] = 0; - if (pos + end_len > size - 1) - printf("Warning: path truncated: %s\n", buff); -} - static int emu_check_save_file(int slot, int *time) { char fname[MAXPATHLEN]; @@ -508,10 +495,14 @@ static char *get_cd_label(void) static void make_cfg_fname(char *buf, size_t size, int is_game) { - if (is_game) - snprintf(buf, size, "." PCSX_DOT_DIR "cfg/%.32s-%.9s.cfg", get_cd_label(), CdromId); + char id_buf[64]; + if (is_game) { + snprintf(id_buf, sizeof(id_buf), "%.32s-%.9s.cfg", + get_cd_label(), CdromId); + emu_make_path(buf, size, CFG_DIR, id_buf); + } else - snprintf(buf, size, "." PCSX_DOT_DIR "%s", cfgfile_basename); + emu_make_path(buf, size, PCSX_DOT_DIR, cfgfile_basename); } static void keys_write_all(FILE *f); @@ -577,7 +568,7 @@ static int menu_do_last_cd_img(int is_get) FILE *f; int i, ret = -1; - snprintf(path, sizeof(path), "." PCSX_DOT_DIR "lastcdimg.txt"); + emu_make_path(path, sizeof(path), PCSX_DOT_DIR, "lastcdimg.txt"); f = fopen(path, is_get ? "r" : "w"); if (f == NULL) { ret = -1; @@ -1905,10 +1896,10 @@ static void handle_memcard_sel(void) { strcpy(Config.Mcd1, "none"); if (memcard1_sel != 0) - snprintf(Config.Mcd1, sizeof(Config.Mcd1), ".%s%s", MEMCARD_DIR, memcards[memcard1_sel]); + emu_make_path(Config.Mcd1, sizeof(Config.Mcd1), MEMCARD_DIR, memcards[memcard1_sel]); strcpy(Config.Mcd2, "none"); if (memcard2_sel != 0) - snprintf(Config.Mcd2, sizeof(Config.Mcd2), ".%s%s", MEMCARD_DIR, memcards[memcard2_sel]); + emu_make_path(Config.Mcd2, sizeof(Config.Mcd2), MEMCARD_DIR, memcards[memcard2_sel]); LoadMcds(Config.Mcd1, Config.Mcd2); draw_mc_bg(); } @@ -2005,8 +1996,7 @@ static void menu_bios_warn(void) int inp; static const char msg[] = "You don't seem to have copied any BIOS\n" - "files to\n" - MENU_BIOS_PATH "\n\n" + "files to\n%s\n\n" "While many games work fine with fake\n" "(HLE) BIOS, others (like MGS and FF8)\n" @@ -2020,7 +2010,7 @@ static void menu_bios_warn(void) "Press %s or %s to continue"; char tmp_msg[sizeof(msg) + 64]; - snprintf(tmp_msg, sizeof(tmp_msg), msg, + snprintf(tmp_msg, sizeof(tmp_msg), msg, Config.BiosDir, in_get_key_name(-1, -PBTN_MOK), in_get_key_name(-1, -PBTN_MBACK)); while (1) { @@ -2607,7 +2597,8 @@ do_plugins: #endif do_memcards: - dir = opendir("." MEMCARD_DIR); + emu_make_path(fname, sizeof(fname), MEMCARD_DIR, NULL); + dir = opendir(fname); if (dir == NULL) { perror("scan_bios_plugins memcards opendir"); return; @@ -2627,7 +2618,7 @@ do_memcards: if (ent->d_type != DT_REG && ent->d_type != DT_LNK) continue; - snprintf(fname, sizeof(fname), "." MEMCARD_DIR "%s", ent->d_name); + emu_make_path(fname, sizeof(fname), MEMCARD_DIR, ent->d_name); if (stat(fname, &st) != 0) { printf("bad memcard file: %s\n", ent->d_name); continue; @@ -2671,7 +2662,7 @@ void menu_init(void) exit(1); } - emu_make_path(buff, "skin/background.png", sizeof(buff)); + emu_make_data_path(buff, "skin/background.png", sizeof(buff)); readpng(g_menubg_src_ptr, buff, READPNG_BG, g_menuscreen_w, g_menuscreen_h); i = plat_target.cpu_clock_set != NULL diff --git a/frontend/plat_sdl.c b/frontend/plat_sdl.c index 3529d979..4c397194 100644 --- a/frontend/plat_sdl.c +++ b/frontend/plat_sdl.c @@ -665,10 +665,18 @@ void plat_video_menu_leave(void) centered_clear(); } -/* unused stuff */ void *plat_prepare_screenshot(int *w, int *h, int *bpp) { - return 0; + if (plat_sdl_screen && !SDL_MUSTLOCK(plat_sdl_screen) && + plat_sdl_overlay == NULL && !plat_sdl_gl_active) + { + *w = plat_sdl_screen->pitch / 2; + *h = plat_sdl_screen->h; + *bpp = 16; + return plat_sdl_screen->pixels; + } + fprintf(stderr, "screenshot not implemented in current mode\n"); + return NULL; } void plat_trigger_vibrate(int pad, int low, int high) diff --git a/libpcsxcore/sio.c b/libpcsxcore/sio.c index 0bc763ca..c28c0554 100644 --- a/libpcsxcore/sio.c +++ b/libpcsxcore/sio.c @@ -455,8 +455,10 @@ void CreateMcd(char *mcd) { int i = 0, j; f = fopen(mcd, "wb"); - if (f == NULL) + if (f == NULL) { + SysPrintf("CreateMcd: couldn't open %s\n", mcd); return; + } if (stat(mcd, &buf) != -1) { if ((buf.st_size == MCD_SIZE + 3904) || strstr(mcd, ".gme")) { -- 2.39.5 From f2af170079fa67860ddcc384b8e287fabf1ae7e6 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 12 May 2025 02:34:26 +0300 Subject: [PATCH 06/16] unbreak NO_FRONTEND build --- frontend/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/main.c b/frontend/main.c index 6f581a8b..5486ebd5 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -150,6 +150,8 @@ void emu_set_default_config(void) in_type[1] = PSE_PAD_TYPE_STANDARD; } +#ifndef NO_FRONTEND + void do_emu_action(void) { int ret; @@ -165,7 +167,6 @@ void do_emu_action(void) ret = emu_save_state(state_slot); snprintf(hud_msg, sizeof(hud_msg), ret == 0 ? "SAVED" : "FAIL!"); break; -#ifndef NO_FRONTEND case SACTION_ENTER_MENU: toggle_fast_forward(1); menu_loop(); @@ -269,7 +270,6 @@ do_state_slot: ret = padToggleAnalog(0); snprintf(hud_msg, sizeof(hud_msg), "ANALOG %s", ret ? "ON" : "OFF"); break; -#endif default: return; } @@ -277,6 +277,8 @@ do_state_slot: hud_new_msg = 3; } +#endif + static char basic_lcase(char c) { if ('A' <= c && c <= 'Z') -- 2.39.5 From c9b09029749a2ed4ad5ff9c79495dd5588adcfa5 Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 15 May 2025 00:46:37 +0300 Subject: [PATCH 07/16] frontend: rework sdl gl vout_method --- frontend/libpicofe | 2 +- frontend/plat_sdl.c | 161 ++++++++++++++++++++++++++++------- plugins/gpu-gles/gpulib_if.c | 51 +++++++++-- 3 files changed, 175 insertions(+), 39 deletions(-) diff --git a/frontend/libpicofe b/frontend/libpicofe index 80612f5f..ab0990ab 160000 --- a/frontend/libpicofe +++ b/frontend/libpicofe @@ -1 +1 @@ -Subproject commit 80612f5f31a3201e6c7f710109a9c8b48f6bb757 +Subproject commit ab0990ab434971e1ab1f7ebda61ce368bb7a4d11 diff --git a/frontend/plat_sdl.c b/frontend/plat_sdl.c index 4c397194..f207d2ae 100644 --- a/frontend/plat_sdl.c +++ b/frontend/plat_sdl.c @@ -12,6 +12,7 @@ #include #include +#include "../libpcsxcore/plugins.h" #include "libpicofe/input.h" #include "libpicofe/in_sdl.h" #include "libpicofe/menu.h" @@ -95,21 +96,36 @@ static const struct in_pdata in_sdl_platform_data = { static int psx_w = 256, psx_h = 240; static void *shadow_fb, *menubg_img; -static int resized, window_w, window_h; static int vout_fullscreen_old; static int forced_clears; static int forced_flips; static int sdl12_compat; +static int resized; static int in_menu; +static int gl_w_prev, gl_h_prev; +static float gl_vertices[] = { + -1.0f, 1.0f, 0.0f, // 0 0 1 + 1.0f, 1.0f, 0.0f, // 1 ^ + -1.0f, -1.0f, 0.0f, // 2 | 2 3 + 1.0f, -1.0f, 0.0f, // 3 +--> +}; + +static void handle_window_resize(void); static void handle_scaler_resize(int w, int h); static void centered_clear(void); -static void resize_cb(int w, int h) +static int plugin_owns_display(void) +{ + // if true, a plugin is drawing and flipping + return (pl_rearmed_cbs.gpu_caps & GPU_CAP_OWNS_DISPLAY); +} + +static void plugin_update(void) { // used by some plugins... - pl_rearmed_cbs.screen_w = w; - pl_rearmed_cbs.screen_h = h; + pl_rearmed_cbs.screen_w = plat_sdl_screen->w; + pl_rearmed_cbs.screen_h = plat_sdl_screen->h; pl_rearmed_cbs.gles_display = gl_es_display; pl_rearmed_cbs.gles_surface = gl_es_surface; plugin_call_rearmed_cbs(); @@ -125,6 +141,15 @@ static void sdl_event_handler(void *event_) window_w = event->resize.w & ~3; window_h = event->resize.h & ~1; resized = 1; + if (!in_menu && plat_sdl_gl_active && plugin_owns_display()) { + // the plugin flips by itself so resize has to be handled here + handle_window_resize(); + if (GPU_open != NULL) { + int ret = GPU_open(&gpuDisp, "PCSX", NULL); + if (ret) + fprintf(stderr, "GPU_open: %d\n", ret); + } + } } return; case SDL_ACTIVEEVENT: @@ -156,7 +181,6 @@ void plat_init(void) int ret; plat_sdl_quit_cb = quit_cb; - plat_sdl_resize_cb = resize_cb; ret = plat_sdl_init(); if (ret != 0) @@ -188,12 +212,10 @@ void plat_init(void) bgr_to_uyvy_init(); - // to "finish" init and set SDL_RESIZABLE - plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, -1); - if (plat_sdl_overlay) { - printf("overlay: %08x hw=%d\n", plat_sdl_overlay->format, - plat_sdl_overlay->hw_overlay); - } + assert(plat_sdl_screen); + plugin_update(); + if (plat_target.vout_method == vout_mode_gl) + gl_w_prev = plat_sdl_screen->w, gl_h_prev = plat_sdl_screen->h; } void plat_finish(void) @@ -258,21 +280,11 @@ static void overlay_resize(int force) SDL_UnlockYUVOverlay(plat_sdl_overlay); } } - else + else { fprintf(stderr, "overlay resize to %dx%d failed\n", w, h); - handle_scaler_resize(w, h); -} - -static void overlay_check_enable(void) -{ - // we no longer unconditionally call plat_sdl_change_video_mode() - // to not disturb the window, need to look for config change - if ((plat_target.vout_method == 0 || plat_sdl_gl_active) && plat_sdl_overlay) { - SDL_FreeYUVOverlay(plat_sdl_overlay); - plat_sdl_overlay = NULL; + plat_target.vout_method = 0; } - else if (plat_target.vout_method > 0 && !plat_sdl_gl_active) // lame - overlay_resize(0); + handle_scaler_resize(w, h); } static void overlay_blit(int doffs, const void *src_, int w, int h, @@ -310,6 +322,58 @@ static void overlay_hud_print(int x, int y, const char *str, int bpp) SDL_UnlockYUVOverlay(plat_sdl_overlay); } +static void gl_finish_pl(void) +{ + if (plugin_owns_display() && GPU_close != NULL) + GPU_close(); + gl_finish(); +} + +static void gl_resize(void) +{ + int w = in_menu ? g_menuscreen_w : psx_w; + int h = in_menu ? g_menuscreen_h : psx_h; + + if (plugin_owns_display()) + w = plat_sdl_screen->w, h = plat_sdl_screen->h; + if (plat_sdl_gl_active) { + if (w == gl_w_prev && h == gl_h_prev) + return; + gl_finish_pl(); + } + plat_sdl_gl_active = (gl_init(display, window, &gl_quirks, w, h) == 0); + if (plat_sdl_gl_active) + gl_w_prev = w, gl_h_prev = h; + else { + fprintf(stderr, "warning: could not init GL.\n"); + plat_target.vout_method = 0; + } + handle_scaler_resize(w, h); + plugin_update(); + forced_flips = 0; // interferes with gl +} + +static void overlay_or_gl_check_enable(void) +{ + int ovl_on = plat_target.vout_method == vout_mode_overlay || + plat_target.vout_method == vout_mode_overlay2x; + int gl_on = plat_target.vout_method == vout_mode_gl; + if (!gl_on && plat_sdl_gl_active) { + gl_finish_pl(); + pl_rearmed_cbs.gles_display = gl_es_display; + pl_rearmed_cbs.gles_surface = gl_es_surface; + plat_sdl_gl_active = 0; + } + if (!ovl_on && plat_sdl_overlay) { + SDL_FreeYUVOverlay(plat_sdl_overlay); + plat_sdl_overlay = NULL; + } + if (ovl_on) + overlay_resize(0); + else if (gl_on) + gl_resize(); +} + static void centered_clear(void) { int dstride = plat_sdl_screen->pitch / 2; @@ -317,6 +381,11 @@ static void centered_clear(void) int h = plat_sdl_screen->h; unsigned short *dst; + if (plat_sdl_gl_active) { + gl_clear(); + return; + } + if (SDL_MUSTLOCK(plat_sdl_screen)) SDL_LockSurface(plat_sdl_screen); dst = plat_sdl_screen->pixels; @@ -446,7 +515,7 @@ static void *setup_blit_callbacks(int w, int h) // different size overlay vs plat_sdl_screen layer static void change_mode(int w, int h) { - int set_w = w, set_h = h, had_overlay = 0; + int set_w = w, set_h = h, had_overlay = 0, had_gl = 0; if (plat_target.vout_fullscreen && (plat_target.vout_method != 0 || !sdl12_compat)) set_w = fs_w, set_h = fs_h; if (plat_sdl_screen->w != set_w || plat_sdl_screen->h != set_h || @@ -465,6 +534,11 @@ static void change_mode(int w, int h) plat_sdl_overlay = NULL; had_overlay = 1; } + if (plat_sdl_gl_active) { + gl_finish_pl(); + plat_sdl_gl_active = 0; + had_gl = 1; + } SDL_PumpEvents(); plat_sdl_screen = SDL_SetVideoMode(set_w, set_h, 16, flags); //printf("mode: %dx%d %x -> %dx%d\n", set_w, set_h, flags, @@ -473,10 +547,15 @@ static void change_mode(int w, int h) if (vout_fullscreen_old && !plat_target.vout_fullscreen) // why is this needed?? (on 1.2.68) SDL_WM_GrabInput(SDL_GRAB_OFF); + if (vout_mode_gl != -1) + update_wm_display_window(); // overlay needs the latest plat_sdl_screen if (had_overlay) overlay_resize(1); + if (had_gl) + gl_resize(); centered_clear(); + plugin_update(); vout_fullscreen_old = plat_target.vout_fullscreen; } } @@ -487,9 +566,20 @@ static void handle_scaler_resize(int w, int h) int wh = plat_sdl_screen->h; int layer_w_old = g_layer_w; int layer_h_old = g_layer_h; + float w_mul, h_mul; + int x, y; pl_update_layer_size(w, h, ww, wh); if (layer_w_old != g_layer_w || layer_h_old != g_layer_h) forced_clears = 3; + + w_mul = 2.0f / ww; + h_mul = 2.0f / wh; + x = (ww - g_layer_w) / 2; + y = (wh - g_layer_h) / 2; + gl_vertices[3*0+0] = gl_vertices[3*2+0] = -1.0f + x * w_mul; + gl_vertices[3*1+0] = gl_vertices[3*3+0] = -1.0f + (x + g_layer_w) * w_mul; + gl_vertices[3*2+1] = gl_vertices[3*3+1] = -1.0f + y * h_mul; + gl_vertices[3*0+1] = gl_vertices[3*1+1] = -1.0f + (y + g_layer_h) * h_mul; } static void handle_window_resize(void) @@ -499,8 +589,8 @@ static void handle_window_resize(void) change_mode(window_w, window_h); setup_blit_callbacks(psx_w, psx_h); forced_clears = 3; - resized = 0; } + resized = 0; } void *plat_gvideo_set_mode(int *w, int *h, int *bpp) @@ -508,10 +598,15 @@ void *plat_gvideo_set_mode(int *w, int *h, int *bpp) psx_w = *w; psx_h = *h; + if (plat_sdl_gl_active && plugin_owns_display()) + return NULL; + if (plat_sdl_overlay != NULL) overlay_resize(0); - else if (plat_sdl_gl_active) + else if (plat_sdl_gl_active) { memset(shadow_fb, 0, (*w) * (*h) * 2); + gl_resize(); + } else if (plat_target.vout_method == 0) // && sdl12_compat change_mode(*w, *h); @@ -529,11 +624,10 @@ void *plat_gvideo_flip(void) (plat_sdl_screen->h - g_layer_h) / 2, g_layer_w, g_layer_h }; - SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect); } else if (plat_sdl_gl_active) { - gl_flip(shadow_fb, psx_w, psx_h); + gl_flip_v(shadow_fb, psx_w, psx_h, g_scaler != SCALE_FULLSCREEN ? gl_vertices : NULL); ret = shadow_fb; } else @@ -592,7 +686,7 @@ void plat_video_menu_enter(int is_rom_loaded) if (plat_target.vout_method == 0) change_mode(g_menuscreen_w, g_menuscreen_h); else - overlay_check_enable(); + overlay_or_gl_check_enable(); centered_clear(); } @@ -607,7 +701,7 @@ void plat_video_menu_begin(void) change_mode(g_menuscreen_w, g_menuscreen_h); } else - overlay_check_enable(); + overlay_or_gl_check_enable(); handle_scaler_resize(g_menuscreen_w, g_menuscreen_h); if (old_ovl != plat_sdl_overlay || scaler_changed) @@ -634,7 +728,8 @@ void plat_video_menu_end(void) SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect); } else if (plat_sdl_gl_active) { - gl_flip(g_menuscreen_ptr, g_menuscreen_w, g_menuscreen_h); + gl_flip_v(g_menuscreen_ptr, g_menuscreen_w, g_menuscreen_h, + g_scaler != SCALE_FULLSCREEN ? gl_vertices : NULL); } else { centered_blit_menu(); @@ -661,7 +756,7 @@ void plat_video_menu_leave(void) if (plat_target.vout_fullscreen) change_mode(fs_w, fs_h); else - overlay_check_enable(); + overlay_or_gl_check_enable(); centered_clear(); } diff --git a/plugins/gpu-gles/gpulib_if.c b/plugins/gpu-gles/gpulib_if.c index 7207a09d..a09b3fb1 100644 --- a/plugins/gpu-gles/gpulib_if.c +++ b/plugins/gpu-gles/gpulib_if.c @@ -22,6 +22,8 @@ #include "gpuPrim.c" #include "hud.c" +static int is_opened; + static const short dispWidths[8] = {256,320,512,640,368,384,512,640}; short g_m1,g_m2,g_m3; short DrawSemiTrans; @@ -315,6 +317,9 @@ if(bUp) updateDisplay(); // yeah, real update (swap #define GPUwriteStatus_ext GPUwriteStatus_ext // for gpulib to see this void GPUwriteStatus_ext(unsigned int gdata) { + if (!is_opened) + return; + switch((gdata>>24)&0xff) { case 0x00: @@ -478,8 +483,6 @@ switch((gdata>>24)&0xff) #include "../gpulib/gpu.c" -static int is_opened; - static void set_vram(void *vram) { psxVub=vram; @@ -506,6 +509,34 @@ int renderer_init(void) return 0; } +static void clear_gl_state_for_menu(void) +{ + static const GLenum caps[] = { + GL_ALPHA_TEST, GL_BLEND, GL_COLOR_LOGIC_OP, GL_COLOR_MATERIAL, + GL_CULL_FACE, GL_DEPTH_TEST, GL_FOG, GL_LIGHTING, GL_NORMALIZE, + GL_POLYGON_OFFSET_FILL, GL_RESCALE_NORMAL, GL_SAMPLE_ALPHA_TO_COVERAGE, + GL_SAMPLE_ALPHA_TO_ONE, GL_SAMPLE_COVERAGE, GL_SCISSOR_TEST, GL_STENCIL_TEST + }; + static const GLenum cstates[] = { + GL_COLOR_ARRAY, GL_NORMAL_ARRAY, GL_POINT_SIZE_ARRAY_OES + }; + size_t i; + for (i = 0; i < sizeof(caps) / sizeof(caps[0]); i++) + glDisable(caps[i]); + for (i = 0; i < 6; i++) + glDisable(GL_CLIP_PLANE0 + i); + for (i = 0; i < 8; i++) + glDisable(GL_LIGHT0 + i); + for (i = 0; i < sizeof(cstates) / sizeof(cstates[0]); i++) + glDisableClientState(cstates[i]); + + glColor4ub(255, 255, 255, 255); + glLoadIdentity(); + glEnable(GL_TEXTURE_2D); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); +} + void renderer_finish(void) { } @@ -687,6 +718,10 @@ long GPUopen(unsigned long *disp, char *cap, char *cfg) { int ret; + if (is_opened) { + fprintf(stderr, "double GPUopen\n"); + return -1; + } iResX = cbs->screen_w; iResY = cbs->screen_h; rRatioRect.left = rRatioRect.top=0; @@ -708,9 +743,12 @@ long GPUopen(unsigned long *disp, char *cap, char *cfg) long GPUclose(void) { + if (!is_opened) + return 0; is_opened = 0; KillDisplayLists(); + clear_gl_state_for_menu(); GLcleanup(); // close OGL return 0; } @@ -740,9 +778,12 @@ void renderer_set_config(const struct rearmed_cbs *cbs_) cbs->pl_set_gpu_caps(GPU_CAP_OWNS_DISPLAY); if (is_opened && cbs->gles_display != NULL && cbs->gles_surface != NULL) { - // HACK.. - GPUclose(); - GPUopen(NULL, NULL, NULL); + if (cbs->gles_display != display || cbs->gles_surface != surface) { + // HACK... + fprintf(stderr, "gles reinit hack\n"); + GPUclose(); + GPUopen(NULL, NULL, NULL); + } } set_vram(gpu.vram); -- 2.39.5 From 3a998763125441004bc61b79c2e1c24dc3c11b0a Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 21 May 2025 00:48:28 +0300 Subject: [PATCH 08/16] frontend: improve sdl gamepad support notaz/pcsx_rearmed#379 --- frontend/libpicofe | 2 +- frontend/menu.c | 11 +++++++++++ frontend/plat_sdl.c | 10 ++++++++++ frontend/plugin_lib.c | 8 +++++++- 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/frontend/libpicofe b/frontend/libpicofe index ab0990ab..5d8d9079 160000 --- a/frontend/libpicofe +++ b/frontend/libpicofe @@ -1 +1 @@ -Subproject commit ab0990ab434971e1ab1f7ebda61ce368bb7a4d11 +Subproject commit 5d8d9079236d022e7f0db795aa18616856d24451 diff --git a/frontend/menu.c b/frontend/menu.c index 0c4ebcea..851d3a81 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -436,6 +436,10 @@ static const struct { CE_INTVAL(memcard2_sel), CE_INTVAL(g_autostateld_opt), CE_INTVAL(cd_buf_count), + CE_INTVAL_N("adev0_axis0", in_adev_axis[0][0]), + CE_INTVAL_N("adev0_axis1", in_adev_axis[0][1]), + CE_INTVAL_N("adev1_axis0", in_adev_axis[1][0]), + CE_INTVAL_N("adev1_axis1", in_adev_axis[1][1]), CE_INTVAL_N("adev0_is_nublike", in_adev_is_nublike[0]), CE_INTVAL_N("adev1_is_nublike", in_adev_is_nublike[1]), CE_INTVAL_V(frameskip, 4), @@ -1113,6 +1117,10 @@ static void keys_load_all(const char *cfg) static int key_config_loop_wrap(int id, int keys) { + int d; + + for (d = 0; d < IN_MAX_DEVS; d++) + in_set_config_int(d, IN_CFG_ANALOG_MAP_ULDR, 0); switch (id) { case MA_CTRL_PLAYER1: key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 0); @@ -1126,6 +1134,9 @@ static int key_config_loop_wrap(int id, int keys) default: break; } + for (d = 0; d < IN_MAX_DEVS; d++) + in_set_config_int(d, IN_CFG_ANALOG_MAP_ULDR, 1); + return 0; } diff --git a/frontend/plat_sdl.c b/frontend/plat_sdl.c index f207d2ae..00273147 100644 --- a/frontend/plat_sdl.c +++ b/frontend/plat_sdl.c @@ -660,6 +660,8 @@ void plat_gvideo_close(void) void plat_video_menu_enter(int is_rom_loaded) { + int d; + in_menu = 1; /* surface will be lost, must adjust pl_vout_buf for menu bg */ @@ -688,6 +690,9 @@ void plat_video_menu_enter(int is_rom_loaded) else overlay_or_gl_check_enable(); centered_clear(); + + for (d = 0; d < IN_MAX_DEVS; d++) + in_set_config_int(d, IN_CFG_ANALOG_MAP_ULDR, 1); } void plat_video_menu_begin(void) @@ -749,6 +754,8 @@ void plat_video_menu_end(void) void plat_video_menu_leave(void) { + int d; + in_menu = 0; if (plat_sdl_overlay != NULL || plat_sdl_gl_active) memset(shadow_fb, 0, g_menuscreen_w * g_menuscreen_h * 2); @@ -758,6 +765,9 @@ void plat_video_menu_leave(void) else overlay_or_gl_check_enable(); centered_clear(); + + for (d = 0; d < IN_MAX_DEVS; d++) + in_set_config_int(d, IN_CFG_ANALOG_MAP_ULDR, 0); } void *plat_prepare_screenshot(int *w, int *h, int *bpp) diff --git a/frontend/plugin_lib.c b/frontend/plugin_lib.c index 81998d5b..324fede5 100644 --- a/frontend/plugin_lib.c +++ b/frontend/plugin_lib.c @@ -45,7 +45,13 @@ int multitap1; int multitap2; int in_analog_left[8][2] = {{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 }}; int in_analog_right[8][2] = {{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 }}; -int in_adev[2] = { -1, -1 }, in_adev_axis[2][2] = {{ 0, 1 }, { 0, 1 }}; +int in_adev[2] = { -1, -1 }; +int in_adev_axis[2][2] = +#ifdef PANDORA + {{ 0, 1 }, { 0, 1 }}; +#else + {{ 0, 1 }, { 2, 3 }}; +#endif int in_adev_is_nublike[2]; unsigned short in_keystate[8]; int in_mouse[8][2]; -- 2.39.5 From 961cb15e444ee38a96acdf1d3f3068ea2c39b052 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 21 May 2025 02:00:40 +0300 Subject: [PATCH 09/16] spu: deal with some reverb overflows still possible but hopefully won't happen in practice libretro/pcsx_rearmed#890 --- plugins/dfsound/reverb.c | 52 +++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/plugins/dfsound/reverb.c b/plugins/dfsound/reverb.c index 081369ca..c736c1cc 100644 --- a/plugins/dfsound/reverb.c +++ b/plugins/dfsound/reverb.c @@ -105,11 +105,12 @@ static void MixREVERB(int *SSumLR, int *RVB, int ns_to, int curr_addr, int mrsame_m2o = rvb->mRSAME + space - 1; int mldiff_m2o = rvb->mLDIFF + space - 1; int mrdiff_m2o = rvb->mRDIFF + space - 1; - int vCOMB1 = rvb->vCOMB1, vCOMB2 = rvb->vCOMB2; - int vCOMB3 = rvb->vCOMB3, vCOMB4 = rvb->vCOMB4; - int vAPF1 = rvb->vAPF1, vAPF2 = rvb->vAPF2; + int vCOMB1 = rvb->vCOMB1 >> 1, vCOMB2 = rvb->vCOMB2 >> 1; + int vCOMB3 = rvb->vCOMB3 >> 1, vCOMB4 = rvb->vCOMB4 >> 1; + int vAPF1 = rvb->vAPF1 >> 1, vAPF2 = rvb->vAPF2 >> 1; + int vLIN = rvb->vLIN >> 1, vRIN = rvb->vRIN >> 1; + int vWALL = rvb->vWALL >> 1; int vIIR = rvb->vIIR; - int vWALL = rvb->vWALL; int ns; #if P_HAVE_PTHREAD || defined(WANT_THREAD_CODE) @@ -122,23 +123,26 @@ static void MixREVERB(int *SSumLR, int *RVB, int ns_to, int curr_addr, for (ns = 0; ns < ns_to * 2; ) { - int Lin = RVB[ns] * rvb->vLIN; - int Rin = RVB[ns+1] * rvb->vRIN; - int mlsame_m2 = g_buffer(mlsame_m2o) << 15; // -1 - int mrsame_m2 = g_buffer(mrsame_m2o) << 15; - int mldiff_m2 = g_buffer(mldiff_m2o) << 15; - int mrdiff_m2 = g_buffer(mrdiff_m2o) << 15; + int Lin = RVB[ns]; + int Rin = RVB[ns+1]; + int mlsame_m2 = g_buffer(mlsame_m2o) << (15-1); + int mrsame_m2 = g_buffer(mrsame_m2o) << (15-1); + int mldiff_m2 = g_buffer(mldiff_m2o) << (15-1); + int mrdiff_m2 = g_buffer(mrdiff_m2o) << (15-1); int Lout, Rout, out0[2], out1[2]; + ssat32_to_16(Lin); Lin *= vLIN; + ssat32_to_16(Rin); Rin *= vRIN; + // from nocash psx-spx mlsame_m2 += ((Lin + g_buffer(rvb->dLSAME) * vWALL - mlsame_m2) >> 15) * vIIR; mrsame_m2 += ((Rin + g_buffer(rvb->dRSAME) * vWALL - mrsame_m2) >> 15) * vIIR; mldiff_m2 += ((Lin + g_buffer(rvb->dLDIFF) * vWALL - mldiff_m2) >> 15) * vIIR; mrdiff_m2 += ((Rin + g_buffer(rvb->dRDIFF) * vWALL - mrdiff_m2) >> 15) * vIIR; - mlsame_m2 >>= 15; s_buffer_w(rvb->mLSAME, mlsame_m2); - mrsame_m2 >>= 15; s_buffer_w(rvb->mRSAME, mrsame_m2); - mldiff_m2 >>= 15; s_buffer_w(rvb->mLDIFF, mldiff_m2); - mrdiff_m2 >>= 15; s_buffer_w(rvb->mRDIFF, mrdiff_m2); + mlsame_m2 >>= (15-1); s_buffer_w(rvb->mLSAME, mlsame_m2); + mrsame_m2 >>= (15-1); s_buffer_w(rvb->mRSAME, mrsame_m2); + mldiff_m2 >>= (15-1); s_buffer_w(rvb->mLDIFF, mldiff_m2); + mrdiff_m2 >>= (15-1); s_buffer_w(rvb->mRDIFF, mrdiff_m2); Lout = vCOMB1 * g_buffer(rvb->mLCOMB1) + vCOMB2 * g_buffer(rvb->mLCOMB2) + vCOMB3 * g_buffer(rvb->mLCOMB3) + vCOMB4 * g_buffer(rvb->mLCOMB4); @@ -147,24 +151,24 @@ static void MixREVERB(int *SSumLR, int *RVB, int ns_to, int curr_addr, preload(SSumLR + ns + 64*2/4 - 4); - Lout -= vAPF1 * g_buffer(rvb->mLAPF1_dAPF1); Lout >>= 15; - Rout -= vAPF1 * g_buffer(rvb->mRAPF1_dAPF1); Rout >>= 15; + Lout -= vAPF1 * g_buffer(rvb->mLAPF1_dAPF1); Lout >>= (15-1); + Rout -= vAPF1 * g_buffer(rvb->mRAPF1_dAPF1); Rout >>= (15-1); s_buffer_w(rvb->mLAPF1, Lout); s_buffer_w(rvb->mRAPF1, Rout); - Lout = Lout * vAPF1 + (g_buffer(rvb->mLAPF1_dAPF1) << 15); - Rout = Rout * vAPF1 + (g_buffer(rvb->mRAPF1_dAPF1) << 15); + Lout = Lout * vAPF1 + (g_buffer(rvb->mLAPF1_dAPF1) << (15-1)); + Rout = Rout * vAPF1 + (g_buffer(rvb->mRAPF1_dAPF1) << (15-1)); preload(RVB + ns + 64*2/4 - 4); - Lout -= vAPF2 * g_buffer(rvb->mLAPF2_dAPF2); Lout >>= 15; - Rout -= vAPF2 * g_buffer(rvb->mRAPF2_dAPF2); Rout >>= 15; + Lout -= vAPF2 * g_buffer(rvb->mLAPF2_dAPF2); Lout >>= (15-1); + Rout -= vAPF2 * g_buffer(rvb->mRAPF2_dAPF2); Rout >>= (15-1); s_buffer_w(rvb->mLAPF2, Lout); s_buffer_w(rvb->mRAPF2, Rout); - Lout = Lout * vAPF2 + (g_buffer(rvb->mLAPF2_dAPF2) << 15); - Rout = Rout * vAPF2 + (g_buffer(rvb->mRAPF2_dAPF2) << 15); + Lout = Lout * vAPF2 + (g_buffer(rvb->mLAPF2_dAPF2) << (15-1)); + Rout = Rout * vAPF2 + (g_buffer(rvb->mRAPF2_dAPF2) << (15-1)); - out0[0] = out1[0] = (Lout >> 15) * rvb->VolLeft >> 15; - out0[1] = out1[1] = (Rout >> 15) * rvb->VolRight >> 15; + out0[0] = out1[0] = (Lout >> (15-1)) * rvb->VolLeft >> 15; + out0[1] = out1[1] = (Rout >> (15-1)) * rvb->VolRight >> 15; if (do_filter) reverb_interpolate(sb, curr_addr, out0, out1); -- 2.39.5 From 14f53a56ba9a673803e338ea4e50a2257627741c Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 21 May 2025 02:53:41 +0300 Subject: [PATCH 10/16] cdrom: fix wrong volumes on state load libretro/pcsx_rearmed#890 --- libpcsxcore/cdrom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index df958bab..50255c80 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -1811,7 +1811,7 @@ int cdrFreeze(void *f, int Mode) { Find_CurTrack(cdr.SetSectorPlay); } if (!cdr.Muted) - ll = cdr.AttenuatorLeftToLeft, lr = cdr.AttenuatorLeftToLeft, + ll = cdr.AttenuatorLeftToLeft, lr = cdr.AttenuatorLeftToRight, rl = cdr.AttenuatorRightToLeft, rr = cdr.AttenuatorRightToRight; SPU_setCDvol(ll, lr, rl, rr, psxRegs.cycle); } -- 2.39.5 From 9fdb6c4eb0f8a046f295b954a543ed3f857ab475 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 21 May 2025 02:54:37 +0300 Subject: [PATCH 11/16] spu: ssat is ARMv6, not v7 --- plugins/dfsound/spu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index 0954be5d..c14f6469 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -33,7 +33,7 @@ #include "arm_features.h" #endif -#ifdef HAVE_ARMV7 +#ifdef HAVE_ARMV6 #define ssat32_to_16(v) \ asm("ssat %0,#16,%1" : "=r" (v) : "r" (v)) #else -- 2.39.5 From 7192adbe18dab4fbf1375bff43dfa54f3b4d04e6 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 21 May 2025 00:54:58 +0300 Subject: [PATCH 12/16] frontend: more gl options --- frontend/libpicofe | 2 +- frontend/menu.c | 16 +++++++++------- frontend/menu.h | 1 + frontend/plat_sdl.c | 23 ++++++++++++++++------- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/frontend/libpicofe b/frontend/libpicofe index 5d8d9079..ee0dca9e 160000 --- a/frontend/libpicofe +++ b/frontend/libpicofe @@ -1 +1 @@ -Subproject commit 5d8d9079236d022e7f0db795aa18616856d24451 +Subproject commit ee0dca9e10ef44d7900c1158cd8025eb86064aeb diff --git a/frontend/menu.c b/frontend/menu.c index 851d3a81..6144b2c8 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -99,6 +99,7 @@ typedef enum MA_OPT_SCANLINE_LEVEL, MA_OPT_CENTERING, MA_OPT_OVERSCAN, + MA_OPT_VSYNC, } menu_id; static int last_vout_w, last_vout_h, last_vout_bpp; @@ -1410,7 +1411,7 @@ static menu_entry e_menu_gfx_options[] = mee_range_h ("Scanline brightness", MA_OPT_SCANLINE_LEVEL, scanline_level, 0, 100, h_scanline_l), #endif mee_range_h ("Gamma adjustment", MA_OPT_GAMMA, g_gamma, 1, 200, h_gamma), -// mee_onoff ("Vsync", 0, vsync, 1), + mee_onoff ("OpenGL Vsync", MA_OPT_VSYNC, g_opts, OPT_VSYNC), mee_cust_h ("Setup custom scaler", MA_OPT_VARSCALER_C, menu_loop_cscaler, NULL, h_cscaler), mee_end, }; @@ -2693,13 +2694,14 @@ void menu_init(void) i = me_id2offset(e_menu_gfx_options, MA_OPT_HWFILTER); e_menu_gfx_options[i].data = plat_target.hwfilters; - me_enable(e_menu_gfx_options, MA_OPT_HWFILTER, - plat_target.hwfilters != NULL); - - me_enable(e_menu_gfx_options, MA_OPT_GAMMA, - plat_target.gamma_set != NULL); + me_enable(e_menu_gfx_options, MA_OPT_HWFILTER, plat_target.hwfilters != NULL); + if (plat_target.hwfilters && !strcmp(plat_target.hwfilters[0], "linear")) + e_menu_gfx_options[i].name = "OpenGL filter"; + else + me_enable(e_menu_gfx_options, MA_OPT_VSYNC, 0); -#ifdef HAVE_PRE_ARMV7 + me_enable(e_menu_gfx_options, MA_OPT_GAMMA, plat_target.gamma_set != NULL); +#ifdef HAVE_NEON32 me_enable(e_menu_gfx_options, MA_OPT_SWFILTER, 0); #endif me_enable(e_menu_gfx_options, MA_OPT_VARSCALER, MENU_SHOW_VARSCALER); diff --git a/frontend/menu.h b/frontend/menu.h index 9d60e882..26643af8 100644 --- a/frontend/menu.h +++ b/frontend/menu.h @@ -15,6 +15,7 @@ enum g_opts_opts { OPT_NO_FRAMELIM = 1 << 2, OPT_SHOWSPU = 1 << 3, OPT_TSGUN_NOTRIGGER = 1 << 4, + OPT_VSYNC = 1 << 5, }; enum g_scaler_opts { diff --git a/frontend/plat_sdl.c b/frontend/plat_sdl.c index 00273147..ab056b06 100644 --- a/frontend/plat_sdl.c +++ b/frontend/plat_sdl.c @@ -103,7 +103,7 @@ static int sdl12_compat; static int resized; static int in_menu; -static int gl_w_prev, gl_h_prev; +static int gl_w_prev, gl_h_prev, gl_quirks_prev; static float gl_vertices[] = { -1.0f, 1.0f, 0.0f, // 0 0 1 1.0f, 1.0f, 0.0f, // 1 ^ @@ -176,12 +176,15 @@ static void get_layer_pos(int *x, int *y, int *w, int *h) void plat_init(void) { + static const char *hwfilters[] = { "linear", "nearest", NULL }; const SDL_version *ver; int shadow_size; int ret; plat_sdl_quit_cb = quit_cb; + old_fullscreen = -1; // hack + ret = plat_sdl_init(); if (ret != 0) exit(1); @@ -216,6 +219,8 @@ void plat_init(void) plugin_update(); if (plat_target.vout_method == vout_mode_gl) gl_w_prev = plat_sdl_screen->w, gl_h_prev = plat_sdl_screen->h; + if (vout_mode_gl != -1) + plat_target.hwfilters = hwfilters; } void plat_finish(void) @@ -334,16 +339,22 @@ static void gl_resize(void) int w = in_menu ? g_menuscreen_w : psx_w; int h = in_menu ? g_menuscreen_h : psx_h; + gl_quirks &= ~(GL_QUIRK_SCALING_NEAREST | GL_QUIRK_VSYNC_ON); + if (plat_target.hwfilter) // inverted from plat_sdl_gl_scaling() + gl_quirks |= GL_QUIRK_SCALING_NEAREST; + if (g_opts & OPT_VSYNC) + gl_quirks |= GL_QUIRK_VSYNC_ON; + if (plugin_owns_display()) w = plat_sdl_screen->w, h = plat_sdl_screen->h; if (plat_sdl_gl_active) { - if (w == gl_w_prev && h == gl_h_prev) + if (w == gl_w_prev && h == gl_h_prev && gl_quirks == gl_quirks_prev) return; gl_finish_pl(); } plat_sdl_gl_active = (gl_init(display, window, &gl_quirks, w, h) == 0); if (plat_sdl_gl_active) - gl_w_prev = w, gl_h_prev = h; + gl_w_prev = w, gl_h_prev = h, gl_quirks_prev = gl_quirks; else { fprintf(stderr, "warning: could not init GL.\n"); plat_target.vout_method = 0; @@ -705,8 +716,7 @@ void plat_video_menu_begin(void) (plat_target.vout_fullscreen && scaler_changed)) { change_mode(g_menuscreen_w, g_menuscreen_h); } - else - overlay_or_gl_check_enable(); + overlay_or_gl_check_enable(); handle_scaler_resize(g_menuscreen_w, g_menuscreen_h); if (old_ovl != plat_sdl_overlay || scaler_changed) @@ -762,8 +772,7 @@ void plat_video_menu_leave(void) if (plat_target.vout_fullscreen) change_mode(fs_w, fs_h); - else - overlay_or_gl_check_enable(); + overlay_or_gl_check_enable(); centered_clear(); for (d = 0; d < IN_MAX_DEVS; d++) -- 2.39.5 From 15ada67d24a0aab93ff2c62f2ddfa7b2dcf5fc08 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 23 May 2025 01:50:11 +0300 Subject: [PATCH 13/16] deps: switch gnu_lightning to a github mirror The original is sometimes down, breaking CI. --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 97221aa3..dcf97001 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,7 +12,7 @@ url = https://github.com/pcercuei/lightrec.git [submodule "deps/lightning"] path = deps/lightning - url = https://git.savannah.gnu.org/git/lightning.git + url = https://github.com/notaz/gnu_lightning.git [submodule "deps/libretro-common"] path = deps/libretro-common url = https://github.com/libretro/libretro-common.git -- 2.39.5 From ef701b2e2e4b602e30be6fc5e2ece870db2a6e2c Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 27 May 2025 21:08:30 +0300 Subject: [PATCH 14/16] configure: drop the old brcm stuff --- configure | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/configure b/configure index 806f7dff..40827bd0 100755 --- a/configure +++ b/configure @@ -519,17 +519,6 @@ EOF fi fi -# check for VideoCore stuff for Raspberry Pi -if [ -d /opt/vc/include -a -d /opt/vc/lib -a "$VIDEOCORE" != "no" ]; then - CFLAGS_GLES="$CFLAGS_GLES -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux" - LDLIBS_GLES="$LDLIBS_GLES -L/opt/vc/lib" - if [ -f /opt/vc/lib/libbcm_host.so ]; then - LDLIBS_GLES="$LDLIBS_GLES -lbcm_host" - fi - need_xlib="yes" - VIDEOCORE="yes" -fi - # check for GLES headers cat > $TMPC < @@ -538,10 +527,7 @@ int main(void) { return (int)eglGetDisplay( (EGLNativeDisplayType)0 ); } EOF -if [ "$VIDEOCORE" = "yes" ] && compile_binary $CFLAGS_GLES -lbrcmEGL -lbrcmGLESv2 $LDLIBS_GLES; then - have_gles="yes" - LDLIBS_GLES="-lbrcmEGL -lbrcmGLESv2 $LDLIBS_GLES" -elif compile_binary $CFLAGS_GLES -lEGL -lGLES_CM $LDLIBS_GLES; then +if compile_binary $CFLAGS_GLES -lEGL -lGLES_CM $LDLIBS_GLES; then have_gles="yes" LDLIBS_GLES="-lEGL -lGLES_CM $LDLIBS_GLES" elif compile_binary $CFLAGS_GLES -lEGL -lGLESv1_CM $LDLIBS_GLES; then -- 2.39.5 From 86e02a02b5d578c1821049aa26b9e1be0ba1936d Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 28 May 2025 01:30:17 +0300 Subject: [PATCH 15/16] frontend: update libpicofe --- Makefile | 3 ++- configure | 4 +++- frontend/libpicofe | 2 +- frontend/menu.c | 4 ++-- frontend/plat_sdl.c | 4 ++-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 784ef19f..1a9576a3 100644 --- a/Makefile +++ b/Makefile @@ -373,7 +373,8 @@ OBJS += frontend/libpicofe/linux/in_evdev.o endif ifeq "$(HAVE_GLES)" "1" OBJS += frontend/libpicofe/gl.o frontend/libpicofe/gl_platform.o -LDLIBS += $(LDLIBS_GLES) +OBJS += frontend/libpicofe/gl_loader.o +#LDLIBS += $(LDLIBS_GLES) # loaded dynamically now frontend/libpicofe/plat_sdl.o: CFLAGS += -DHAVE_GLES $(CFLAGS_GLES) frontend/libpicofe/gl_platform.o: CFLAGS += -DHAVE_GLES $(CFLAGS_GLES) frontend/libpicofe/gl.o: CFLAGS += -DHAVE_GLES $(CFLAGS_GLES) diff --git a/configure b/configure index 40827bd0..64bb76af 100755 --- a/configure +++ b/configure @@ -533,6 +533,8 @@ if compile_binary $CFLAGS_GLES -lEGL -lGLES_CM $LDLIBS_GLES; then elif compile_binary $CFLAGS_GLES -lEGL -lGLESv1_CM $LDLIBS_GLES; then have_gles="yes" LDLIBS_GLES="-lEGL -lGLESv1_CM $LDLIBS_GLES" +elif compile_object $CFLAGS_GLES; then + have_gles="yes" fi if check_c64_tools; then @@ -549,7 +551,7 @@ if [ "$have_dynamic" = "yes" ]; then if [ "$builtin_gpu" != "unai" ]; then plugins="$plugins plugins/gpu_unai/gpu_unai.so" fi - if [ "$have_gles" = "yes" ]; then + if [ "$have_gles" = "yes" -a "x$LDLIBS_GLES" != "x" ]; then plugins="$plugins plugins/gpu-gles/gpu_gles.so" fi if [ "$have_neon_gpu" = "yes" -a "$builtin_gpu" != "neon" ]; then diff --git a/frontend/libpicofe b/frontend/libpicofe index ee0dca9e..50d625e8 160000 --- a/frontend/libpicofe +++ b/frontend/libpicofe @@ -1 +1 @@ -Subproject commit ee0dca9e10ef44d7900c1158cd8025eb86064aeb +Subproject commit 50d625e820f5db49f97124dd3fe2291f31044227 diff --git a/frontend/menu.c b/frontend/menu.c index 6144b2c8..b50f05ad 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -1404,8 +1404,8 @@ static menu_entry e_menu_gfx_options[] = mee_enum ("Video output mode", MA_OPT_VOUT_MODE, plat_target.vout_method, men_dummy), mee_onoff ("Fullscreen mode", MA_OPT_VOUT_FULL, plat_target.vout_fullscreen, 1), mee_onoff ("Software Scaling", MA_OPT_SCALER2, soft_scaling, 1), - mee_enum ("Hardware Filter", MA_OPT_HWFILTER, plat_target.hwfilter, men_dummy), mee_enum_h ("Software Filter", MA_OPT_SWFILTER, soft_filter, men_soft_filter, h_soft_filter), + mee_enum ("Hardware Filter", MA_OPT_HWFILTER, plat_target.hwfilter, men_dummy), #ifdef HAVE_NEON32 mee_enum ("Scanlines", MA_OPT_SCANLINES, scanlines, men_scanlines), mee_range_h ("Scanline brightness", MA_OPT_SCANLINE_LEVEL, scanline_level, 0, 100, h_scanline_l), @@ -2701,7 +2701,7 @@ void menu_init(void) me_enable(e_menu_gfx_options, MA_OPT_VSYNC, 0); me_enable(e_menu_gfx_options, MA_OPT_GAMMA, plat_target.gamma_set != NULL); -#ifdef HAVE_NEON32 +#ifndef HAVE_NEON32 me_enable(e_menu_gfx_options, MA_OPT_SWFILTER, 0); #endif me_enable(e_menu_gfx_options, MA_OPT_VARSCALER, MENU_SHOW_VARSCALER); diff --git a/frontend/plat_sdl.c b/frontend/plat_sdl.c index ab056b06..955dec49 100644 --- a/frontend/plat_sdl.c +++ b/frontend/plat_sdl.c @@ -331,7 +331,7 @@ static void gl_finish_pl(void) { if (plugin_owns_display() && GPU_close != NULL) GPU_close(); - gl_finish(); + gl_destroy(); } static void gl_resize(void) @@ -352,7 +352,7 @@ static void gl_resize(void) return; gl_finish_pl(); } - plat_sdl_gl_active = (gl_init(display, window, &gl_quirks, w, h) == 0); + plat_sdl_gl_active = (gl_create(window, &gl_quirks, w, h) == 0); if (plat_sdl_gl_active) gl_w_prev = w, gl_h_prev = h, gl_quirks_prev = gl_quirks; else { -- 2.39.5 From b2ba218e2abcd85e27eedfa5a6ea76007451f75d Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 18 Jun 2025 20:37:31 +0300 Subject: [PATCH 16/16] frontend: update libpicofe, fix missed callbacks could crash on bios boot --- frontend/libpicofe | 2 +- frontend/plat_sdl.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/libpicofe b/frontend/libpicofe index 50d625e8..da09f8f2 160000 --- a/frontend/libpicofe +++ b/frontend/libpicofe @@ -1 +1 @@ -Subproject commit 50d625e820f5db49f97124dd3fe2291f31044227 +Subproject commit da09f8f20da6548e1debf4abb9840eb9f130678d diff --git a/frontend/plat_sdl.c b/frontend/plat_sdl.c index 955dec49..09b17783 100644 --- a/frontend/plat_sdl.c +++ b/frontend/plat_sdl.c @@ -774,6 +774,7 @@ void plat_video_menu_leave(void) change_mode(fs_w, fs_h); overlay_or_gl_check_enable(); centered_clear(); + setup_blit_callbacks(psx_w, psx_h); for (d = 0; d < IN_MAX_DEVS; d++) in_set_config_int(d, IN_CFG_ANALOG_MAP_ULDR, 0); -- 2.39.5