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/gfx/drivers/ps2_gfx.c b/gfx/drivers/ps2_gfx.c index f4d32b1e50..8dea3c530b 100644 --- a/gfx/drivers/ps2_gfx.c +++ b/gfx/drivers/ps2_gfx.c @@ -27,10 +27,54 @@ #define GS_TEXT GS_SETREG_RGBA(0x80,0x80,0x80,0x80) /* turn black GS Screen */ #define GS_BLACK GS_SETREG_RGBA(0x00,0x00,0x00,0x80) +/* default alpha logic */ +#define GS_DEFAULT_ALPHA GS_SETREG_ALPHA(0, 1, 0, 1, 0) -#define NTSC_WIDTH 640 -#define NTSC_HEIGHT 448 +#define NUM_RM_VMODES 8 +#define PS2_RESOLUTION_LAST NUM_RM_VMODES - 1 +#define RM_VMODE_AUTO 0 +enum rm_aratio { + RM_ARATIO_4_3 = 0, + RM_ARATIO_16_9, +}; + +// RM Vmode -> GS Vmode conversion table +struct rm_mode +{ + char mode; + char hsync; // In KHz + short int width; + short int height; + short int passes; + short int VCK; + short int interlace; + short int field; + short int aratio; + 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[64]; +}; + +static struct rm_mode rm_mode_table[NUM_RM_VMODES] = { + // 24 bit color mode with black borders + {-1, 16, 640, -1, 1, 4, GS_INTERLACED, GS_FIELD, RM_ARATIO_4_3, -1, 15, "AUTO"}, // AUTO + {GS_MODE_PAL, 16, 640, 512, 1, 4, GS_INTERLACED, GS_FIELD, RM_ARATIO_4_3, 16, 15, "PAL@50Hz"}, // PAL@50Hz + {GS_MODE_NTSC, 16, 640, 448, 1, 4, GS_INTERLACED, GS_FIELD, RM_ARATIO_4_3, 14, 15, "NTSC@60Hz"}, // NTSC@60Hz + {GS_MODE_PAL, 16, 640, 256, 1, 2, GS_NONINTERLACED, GS_FIELD, RM_ARATIO_4_3, 16, 15, "PAL@50Hz"}, // PAL@50Hz + {GS_MODE_NTSC, 16, 640, 224, 1, 2, GS_NONINTERLACED, GS_FIELD, RM_ARATIO_4_3, 14, 15, "NTSC@60Hz"}, // NTSC@60Hz + {GS_MODE_DTV_480P, 31, 640, 448, 1, 2, GS_NONINTERLACED, GS_FRAME, RM_ARATIO_4_3, 14, 15, "DTV480P@60Hz"}, // DTV480P@60Hz + {GS_MODE_DTV_576P, 31, 640, 512, 1, 2, GS_NONINTERLACED, GS_FRAME, RM_ARATIO_4_3, 16, 15, "DTV576P@50Hz"}, // DTV576P@50Hz + {GS_MODE_VGA_640_60, 31, 640, 480, 1, 2, GS_NONINTERLACED, GS_FRAME, RM_ARATIO_4_3, 1, 1, "VGA640x480@60Hz"}, // VGA640x480@60Hz + // 24 bit color mode full screen, multi-pass (2 passes, HIRES) + // {GS_MODE_PAL, 16, 704, 576, 2, 4, GS_INTERLACED, GS_FIELD, RM_ARATIO_4_3, 12, 11, "PAL@50Hz"}, // PAL@50Hz + // {GS_MODE_NTSC, 16, 704, 480, 2, 4, GS_INTERLACED, GS_FIELD, RM_ARATIO_4_3, 10, 11, "NTSC@60Hz"}, // NTSC@60Hz + // {GS_MODE_DTV_480P, 31, 704, 480, 2, 2, GS_NONINTERLACED, GS_FRAME, RM_ARATIO_4_3, 10, 11, "DTV480P@60Hz"}, // DTV480P@60Hz + // {GS_MODE_DTV_576P, 31, 704, 576, 2, 2, GS_NONINTERLACED, GS_FRAME, RM_ARATIO_4_3, 12, 11, "DTV576P@50Hz"}, // DTV576P@50Hz + // 16 bit color mode full screen, multi-pass (3 passes, HIRES) + // {GS_MODE_DTV_720P, 31, 1280, 720, 3, 1, GS_NONINTERLACED, GS_FRAME, RM_ARATIO_16_9, 1, 1, "HDTV720P@60Hz"}, // HDTV720P@60Hz + // {GS_MODE_DTV_1080I, 31, 1920, 1080, 3, 1, GS_INTERLACED, GS_FRAME, RM_ARATIO_16_9, 1, 1, "HDTV1080I@60Hz"}, // HDTV1080I@60Hz +}; typedef struct ps2_video { /* I need to create this additional field @@ -41,6 +85,11 @@ typedef struct ps2_video int vsync_callback_id; bool force_aspect; + int8_t vmode; + bool hires; + int video_window_offset_x; + int video_window_offset_y; + int PSM; int menu_filter; int core_filter; @@ -66,7 +115,108 @@ static int vsync_handler() return 0; } -static GSGLOBAL *init_GSGlobal(void) +static void rmEnd(ps2_video_t *ps2) +{ + if (!ps2->gsGlobal) + return; + + if (ps2->hires) + { + gsKit_hires_deinit_global(ps2->gsGlobal); + } + else + { + gsKit_deinit_global(ps2->gsGlobal); + } + ps2->vmode = -1; +} + +static void updateOffSetsIfNeeded(ps2_video_t *ps2) +{ + 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("RENDERMAN Change offset: %d, %d\n", ps2->video_window_offset_x, ps2->video_window_offset_y); +} + +static int rmSetMode(ps2_video_t *ps2, int force) +{ + global_t *global = global_get_ptr(); + + // we don't want to set the vmode without a reason... + int changed = (ps2->vmode != global->console.screen.resolutions.current.id || force); + if (changed) { + // Cleanup previous gsKit instance + if (ps2->vmode >= 0) + rmEnd(ps2); + + ps2->vmode = global->console.screen.resolutions.current.id; + ps2->hires = (rm_mode_table[ps2->vmode].passes > 1) ? 1 : 0; + + if (ps2->hires) { + ps2->gsGlobal = gsKit_hires_init_global(); + } else { + ps2->gsGlobal = gsKit_init_global(); + } + ps2->gsGlobal->Mode = rm_mode_table[ps2->vmode].mode; + ps2->gsGlobal->Width = rm_mode_table[ps2->vmode].width; + ps2->gsGlobal->Height = rm_mode_table[ps2->vmode].height; + ps2->gsGlobal->Interlace = rm_mode_table[ps2->vmode].interlace; + ps2->gsGlobal->Field = rm_mode_table[ps2->vmode].field; + ps2->gsGlobal->PSM = GS_PSM_CT16; + ps2->gsGlobal->PSMZ = GS_PSMZ_16S; + ps2->gsGlobal->DoubleBuffering = GS_SETTING_OFF; + 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; + + if (ps2->hires) { + gsKit_hires_init_screen(ps2->gsGlobal, rm_mode_table[ps2->vmode].passes); + } else { + gsKit_init_screen(ps2->gsGlobal); + gsKit_mode_switch(ps2->gsGlobal, GS_ONESHOT); + } + + gsKit_set_test(ps2->gsGlobal, GS_ZTEST_OFF); + gsKit_set_primalpha(ps2->gsGlobal, GS_DEFAULT_ALPHA, 0); + + // reset the contents of the screen to avoid garbage being displayed + if (ps2->hires) { + gsKit_hires_sync(ps2->gsGlobal); + gsKit_hires_flip(ps2->gsGlobal); + } else { + gsKit_clear(ps2->gsGlobal, GS_BLACK); + gsKit_sync_flip(ps2->gsGlobal); + } + + RARCH_LOG("RENDERMAN New vmode: %d, %d x %d\n", ps2->vmode, ps2->gsGlobal->Width, ps2->gsGlobal->Height); + } + + updateOffSetsIfNeeded(ps2); + + return changed; +} + +static void rmInit(ps2_video_t *ps2) { ee_sema_t sema; sema.init_count = 0; @@ -74,42 +224,19 @@ static GSGLOBAL *init_GSGlobal(void) sema.option = 0; vsync_sema_id = CreateSema(&sema); - GSGLOBAL *gsGlobal = gsKit_init_global(); + short int mode = gsKit_check_rom(); - gsGlobal->Mode = GS_MODE_NTSC; - gsGlobal->Interlace = GS_INTERLACED; - gsGlobal->Field = GS_FIELD; - gsGlobal->Width = NTSC_WIDTH; - gsGlobal->Height = NTSC_HEIGHT; + rm_mode_table[RM_VMODE_AUTO].mode = mode; + rm_mode_table[RM_VMODE_AUTO].height = (mode == GS_MODE_PAL) ? 512 : 448; + rm_mode_table[RM_VMODE_AUTO].PAR1 = (mode == GS_MODE_PAL) ? 16 : 14; - 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, + 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 */ + // 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; -} - -static void deinit_GSGlobal(GSGLOBAL *gsGlobal) -{ - gsKit_clear(gsGlobal, GS_BLACK); - gsKit_vram_clear(gsGlobal); - gsKit_deinit_global(gsGlobal); + rmSetMode(ps2, 1); } /* Copy of gsKit_sync_flip, but without the 'flip' */ @@ -148,7 +275,7 @@ static GSTEXTURE *prepare_new_texture(void) static void init_ps2_video(ps2_video_t *ps2) { - ps2->gsGlobal = init_GSGlobal(); + rmInit(ps2); gsKit_TexManager_init(ps2->gsGlobal); ps2->vp.x = 0; @@ -162,6 +289,11 @@ static void init_ps2_video(ps2_video_t *ps2) ps2->menuTexture = prepare_new_texture(); ps2->coreTexture = prepare_new_texture(); + ps2->vmode = 0; + ps2->hires = false; + 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_version = RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION; @@ -300,6 +432,9 @@ 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; @@ -382,7 +517,7 @@ static void ps2_gfx_free(void *data) 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); @@ -393,6 +528,13 @@ 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; } +static void ps2_set_video_mode(void *data, unsigned fbWidth, unsigned lines, + bool fullscreen) +{ + ps2_video_t *ps2 = (ps2_video_t*)data; + 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; @@ -400,6 +542,49 @@ static void ps2_set_filtering(void *data, unsigned index, bool smooth, bool ctx_ ps2->menu_filter = smooth ? GS_FILTER_LINEAR : GS_FILTER_NEAREST; } +static void ps2_get_video_output_size(void *data, + unsigned *width, unsigned *height) +{ + global_t *global = global_get_ptr(); + if (!global) + return; + + /* If the current index is out of bound default it to zero */ + if (global->console.screen.resolutions.current.id > PS2_RESOLUTION_LAST) + global->console.screen.resolutions.current.id = 0; + + *width = rm_mode_table[ + global->console.screen.resolutions.current.id].width; + *height = rm_mode_table[ + global->console.screen.resolutions.current.id].height; +} + +static void ps2_get_video_output_prev(void *data) +{ + global_t *global = global_get_ptr(); + + if (global->console.screen.resolutions.current.id == 0) + { + global->console.screen.resolutions.current.id = PS2_RESOLUTION_LAST; + return; + } + + global->console.screen.resolutions.current.id--; +} + +static void ps2_get_video_output_next(void *data) +{ + global_t *global = global_get_ptr(); + + if (global->console.screen.resolutions.current.id >= PS2_RESOLUTION_LAST) + { + global->console.screen.resolutions.current.id = 0; + return; + } + + global->console.screen.resolutions.current.id++; +} + static void ps2_set_texture_frame(void *data, const void *frame, bool rgb32, unsigned width, unsigned height, float alpha) { @@ -448,12 +633,12 @@ static const video_poke_interface_t ps2_poke_interface = { NULL, /* get_flags */ NULL, NULL, - NULL, + ps2_set_video_mode, NULL, /* get_refresh_rate */ ps2_set_filtering, - NULL, /* get_video_output_size */ - NULL, /* get_video_output_prev */ - NULL, /* get_video_output_next */ + 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 */ diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 2e5cdf5aba..0767090d22 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -6757,7 +6757,7 @@ 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; diff --git a/menu/cbs/menu_cbs_start.c b/menu/cbs/menu_cbs_start.c index 29fb73ed4a..b5faec684a 100644 --- a/menu/cbs/menu_cbs_start.c +++ b/menu/cbs/menu_cbs_start.c @@ -486,7 +486,7 @@ 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; global_t *global = global_get_ptr(); diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 17025f3a02..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()) diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 8f21b64dab..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")) @@ -11417,7 +11417,7 @@ static bool setting_append_list( parent_group, general_write_handler, general_read_handler); - menu_settings_list_current_add_range(list, list_info, -24, 24, 1, true, true); + menu_settings_list_current_add_range(list, list_info, -50, 50, 1, true, true); CONFIG_INT( list, list_info, @@ -11430,7 +11430,7 @@ static bool setting_append_list( parent_group, general_write_handler, general_read_handler); - menu_settings_list_current_add_range(list, list_info, -24, 24, 1, true, true); + menu_settings_list_current_add_range(list, list_info, -50, 50, 1, true, true); #endif CONFIG_UINT( diff --git a/retroarch.c b/retroarch.c index 9ee3337208..c4ca2c1b79 100644 --- a/retroarch.c +++ b/retroarch.c @@ -7194,7 +7194,7 @@ bool command_event(enum event_command cmd, void *data) } break; case CMD_EVENT_SET_PER_GAME_RESOLUTION: -#if defined(GEKKO) +#if defined(GEKKO) || defined(PS2) { unsigned width = 0, height = 0;