diff --git a/lang/English.ini b/lang/English.ini index 0566651d9..23faadd4a 100644 --- a/lang/English.ini +++ b/lang/English.ini @@ -141,6 +141,9 @@ D10X = "10x" D100X = "100x" DRAW_DISTANCE = "Draw Distance" DYNOS_PACKS = "DynOS Packs" +ANTIALIASING = "Anti-aliasing" +OFF = "Off" +MUST_RESTART = "You must restart the game for some changes to take effect." [DYNOS] DYNOS = "DYNOS" diff --git a/lang/French.ini b/lang/French.ini index f4ba7ecb4..6f9e45605 100644 --- a/lang/French.ini +++ b/lang/French.ini @@ -141,6 +141,10 @@ D10X = "x10" D100X = "x100" DRAW_DISTANCE = "Distance d'affichage" DYNOS_PACKS = "Packs DynOS" +ANTIALIASING = "Anti-aliasing" +OFF = "Off" +MUST_RESTART = "You must restart the game for some changes to take effect." + [DYNOS] DYNOS = "DYNOS" diff --git a/lang/German.ini b/lang/German.ini index 017abd180..d4c8037b5 100644 --- a/lang/German.ini +++ b/lang/German.ini @@ -141,6 +141,9 @@ D10X = "10x" D100X = "100x" DRAW_DISTANCE = "Sichtweite" DYNOS_PACKS = "DynOS Packs" +ANTIALIASING = "Anti-aliasing" +OFF = "Off" +MUST_RESTART = "You must restart the game for some changes to take effect." [DYNOS] DYNOS = "DYNOS" diff --git a/lang/Italian.ini b/lang/Italian.ini index 6fc9b5b28..fbb04c4bd 100644 --- a/lang/Italian.ini +++ b/lang/Italian.ini @@ -139,6 +139,9 @@ D10X = "10x" D100X = "100x" DRAW_DISTANCE = "Distanza di simulazione" DYNOS_PACKS = "Pacchetti DynOS" +ANTIALIASING = "Anti-aliasing" +OFF = "Off" +MUST_RESTART = "You must restart the game for some changes to take effect." [DYNOS] DYNOS = "DYNOS" diff --git a/lang/Portuguese.ini b/lang/Portuguese.ini index cf11772fd..7970905bd 100644 --- a/lang/Portuguese.ini +++ b/lang/Portuguese.ini @@ -141,6 +141,9 @@ D10X = "10x" D100X = "100x" DRAW_DISTANCE = "Draw Distance" DYNOS_PACKS = "DynOS Packs" +ANTIALIASING = "Anti-aliasing" +OFF = "Off" +MUST_RESTART = "You must restart the game for some changes to take effect." [DYNOS] DYNOS = "DYNOS" diff --git a/lang/Spanish.ini b/lang/Spanish.ini index 8a1efb178..214fc6ec8 100644 --- a/lang/Spanish.ini +++ b/lang/Spanish.ini @@ -141,6 +141,9 @@ D10X = "10x" D100X = "100x" DRAW_DISTANCE = "Distancia de dibujado" DYNOS_PACKS = "Packs de DynOS" +ANTIALIASING = "Anti-aliasing" +OFF = "Off" +MUST_RESTART = "You must restart the game for some changes to take effect." [DYNOS] DYNOS = "DYNOS" diff --git a/src/pc/configfile.c b/src/pc/configfile.c index ac7be1aa7..3a8384123 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -66,6 +66,7 @@ ConfigWindow configWindow = { .fullscreen = false, .exiting_fullscreen = false, .settings_changed = false, + .msaa = 0, }; unsigned int configFiltering = 1; // 0=force nearest, 1=linear, (TODO) 2=three-point unsigned int configMasterVolume = 30; // 0 - MAX_VOLUME @@ -165,6 +166,7 @@ static const struct ConfigOption options[] = { {.name = "window_h", .type = CONFIG_TYPE_UINT, .uintValue = &configWindow.h}, {.name = "vsync", .type = CONFIG_TYPE_BOOL, .boolValue = &configWindow.vsync}, {.name = "texture_filtering", .type = CONFIG_TYPE_UINT, .uintValue = &configFiltering}, + {.name = "msaa", .type = CONFIG_TYPE_UINT, .uintValue = &configWindow.msaa}, {.name = "master_volume", .type = CONFIG_TYPE_UINT, .uintValue = &configMasterVolume}, {.name = "music_volume", .type = CONFIG_TYPE_UINT, .uintValue = &configMusicVolume}, {.name = "sfx_volume", .type = CONFIG_TYPE_UINT, .uintValue = &configSfxVolume}, diff --git a/src/pc/configfile.h b/src/pc/configfile.h index eabde56a2..13d100135 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -25,6 +25,7 @@ typedef struct { bool fullscreen; bool exiting_fullscreen; bool settings_changed; + unsigned int msaa; } ConfigWindow; extern ConfigWindow configWindow; diff --git a/src/pc/djui/djui_gfx.c b/src/pc/djui/djui_gfx.c index 6a2586b4c..8990b7f26 100644 --- a/src/pc/djui/djui_gfx.c +++ b/src/pc/djui/djui_gfx.c @@ -58,10 +58,10 @@ f32 djui_gfx_get_scale(void) { ///////////////////////////////////////////// static const Vtx vertex_djui_image[] = { - {{{ 0, -1, 0 }, 0, { 0, 512 }, { 0xff, 0xff, 0xff, 0xff }}}, - {{{ 1, -1, 0 }, 0, { 512, 512 }, { 0xff, 0xff, 0xff, 0xff }}}, - {{{ 1, 0, 0 }, 0, { 512, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, - {{{ 0, 0, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 0, -1, 0 }, 0, { 0, 2048 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 1, -1, 0 }, 0, { 2048, 2048 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 1, 0, 0 }, 0, { 2048, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 0, 0, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, }; const Gfx dl_djui_image[] = { @@ -71,7 +71,7 @@ const Gfx dl_djui_image[] = { gsDPSetRenderMode(G_RM_XLU_SURF, G_RM_XLU_SURF2), gsDPSetTextureFilter(G_TF_POINT), gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON), - gsDPLoadTextureBlock(NULL, G_IM_FMT_RGBA, G_IM_SIZ_16b, 16, 16, 0, G_TX_CLAMP, G_TX_CLAMP, 5, 5, G_TX_NOLOD, G_TX_NOLOD), + gsDPLoadTextureBlock(NULL, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 0, 0, 0, 0), gsSPExecuteDjui(G_TEXOVERRIDE_DJUI), gsSPVertex(vertex_djui_image, 4, 0), gsSPExecuteDjui(G_TEXCLIP_DJUI), @@ -121,10 +121,10 @@ void djui_gfx_render_texture_tile(const u8* texture, u32 w, u32 h, u32 bitSize, f32 aspect = tileH ? ((f32)tileW / (f32)tileH) : 1; // I don't know why adding 1 to all of the UVs seems to fix rendering, but it does... - vtx[0] = (Vtx) {{{ 0, -1, 0 }, 0, { ( tileX * 512) / w + 1, ((tileY + tileH) * 512) / h }, { 0xff, 0xff, 0xff, 0xff }}}; - vtx[1] = (Vtx) {{{ 1 * aspect, -1, 0 }, 0, { ((tileX + tileW) * 512) / w + 1, ((tileY + tileH) * 512) / h }, { 0xff, 0xff, 0xff, 0xff }}}; - vtx[2] = (Vtx) {{{ 1 * aspect, 0, 0 }, 0, { ((tileX + tileW) * 512) / w + 1, ( tileY * 512) / h }, { 0xff, 0xff, 0xff, 0xff }}}; - vtx[3] = (Vtx) {{{ 0, 0, 0 }, 0, { ( tileX * 512) / w + 1, ( tileY * 512) / h }, { 0xff, 0xff, 0xff, 0xff }}}; + vtx[0] = (Vtx) {{{ 0, -1, 0 }, 0, { ( tileX * 2048.0f) / (f32)w, ((tileY + tileH) * 2048.0f) / (f32)h }, { 0xff, 0xff, 0xff, 0xff }}}; + vtx[1] = (Vtx) {{{ 1 * aspect, -1, 0 }, 0, { ((tileX + tileW) * 2048.0f) / (f32)w, ((tileY + tileH) * 2048.0f) / (f32)h }, { 0xff, 0xff, 0xff, 0xff }}}; + vtx[2] = (Vtx) {{{ 1 * aspect, 0, 0 }, 0, { ((tileX + tileW) * 2048.0f) / (f32)w, ( tileY * 2048.0f) / (f32)h }, { 0xff, 0xff, 0xff, 0xff }}}; + vtx[3] = (Vtx) {{{ 0, 0, 0 }, 0, { ( tileX * 2048.0f) / (f32)w, ( tileY * 2048.0f) / (f32)h }, { 0xff, 0xff, 0xff, 0xff }}}; gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING); gDPSetCombineMode(gDisplayListHead++, G_CC_FADEA, G_CC_FADEA); @@ -134,7 +134,7 @@ void djui_gfx_render_texture_tile(const u8* texture, u32 w, u32 h, u32 bitSize, gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); gDPSetTextureOverrideDjui(gDisplayListHead++, texture, djui_gfx_power_of_two(w), djui_gfx_power_of_two(h), bitSize); - gDPLoadTextureBlockWithoutTexture(gDisplayListHead++, NULL, G_IM_FMT_RGBA, G_IM_SIZ_16b, 16, 16, 0, G_TX_CLAMP, G_TX_CLAMP, 5, 5, G_TX_NOLOD, G_TX_NOLOD); + gDPLoadTextureBlockWithoutTexture(gDisplayListHead++, NULL, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 0, 0, 0, 0); *(gDisplayListHead++) = (Gfx) gsSPExecuteDjui(G_TEXOVERRIDE_DJUI); diff --git a/src/pc/djui/djui_panel_display.c b/src/pc/djui/djui_panel_display.c index d3dc50b63..bfec8630a 100644 --- a/src/pc/djui/djui_panel_display.c +++ b/src/pc/djui/djui_panel_display.c @@ -2,11 +2,18 @@ #include "djui_panel.h" #include "djui_panel_menu.h" #include "djui_panel_dynos.h" -#include "src/pc/utils/misc.h" -#include "src/pc/configfile.h" +#include "pc/gfx/gfx_window_manager_api.h" +#include "pc/pc_main.h" +#include "pc/utils/misc.h" +#include "pc/configfile.h" + +#define MSAA_ORIGINAL_UNSET ((u32)-1) static struct DjuiInputbox* sFrameLimitInput = NULL; static struct DjuiSelectionbox* sInterpolationSelectionBox = NULL; +static struct DjuiText* sRestartText = NULL; +static u32 sMsaaSelection = 0; +static u32 sMsaaOriginal = MSAA_ORIGINAL_UNSET; static void djui_panel_display_apply(UNUSED struct DjuiBase* caller) { configWindow.settings_changed = true; @@ -29,9 +36,29 @@ static void djui_panel_display_frame_limit_text_change(struct DjuiBase* caller) djui_base_set_enabled(&sInterpolationSelectionBox->base, (configFrameLimit > 30 || (configFrameLimit <= 30 && configUncappedFramerate))); } +static void djui_panel_display_msaa_change(UNUSED struct DjuiBase* caller) { + switch (sMsaaSelection) { + case 1: configWindow.msaa = 2; break; + case 2: configWindow.msaa = 4; break; + case 3: configWindow.msaa = 8; break; + case 4: configWindow.msaa = 16; break; + default: configWindow.msaa = 0; break; + } + + if (sMsaaOriginal != configWindow.msaa) { + djui_text_set_text(sRestartText, DLANG(DISPLAY, MUST_RESTART)); + } else { + djui_text_set_text(sRestartText, ""); + } +} + void djui_panel_display_create(struct DjuiBase* caller) { struct DjuiThreePanel* panel = djui_panel_menu_create(DLANG(DISPLAY, DISPLAY)); struct DjuiBase* body = djui_three_panel_get_body(panel); + struct DjuiSelectionbox* msaa = NULL; + + // save original msaa value + if (sMsaaOriginal == MSAA_ORIGINAL_UNSET) { sMsaaOriginal = configWindow.msaa; } { djui_checkbox_create(body, DLANG(DISPLAY, FULLSCREEN), &configWindow.fullscreen, djui_panel_display_apply); @@ -43,7 +70,7 @@ void djui_panel_display_create(struct DjuiBase* caller) { #endif djui_checkbox_create(body, DLANG(DISPLAY, VSYNC), &configWindow.vsync, djui_panel_display_apply); - djui_checkbox_create(body, DLANG(DISPLAY, UNCAPPED_FRAMERATE), &configUncappedFramerate, djui_panel_display_apply); + djui_checkbox_create(body, DLANG(DISPLAY, UNCAPPED_FRAMERATE), &configUncappedFramerate, djui_panel_display_uncapped_change); struct DjuiRect* rect1 = djui_rect_container_create(body, 32); { @@ -75,12 +102,40 @@ void djui_panel_display_create(struct DjuiBase* caller) { char* filterChoices[3] = { DLANG(DISPLAY, NEAREST), DLANG(DISPLAY, LINEAR), DLANG(DISPLAY, TRIPOINT) }; djui_selectionbox_create(body, DLANG(DISPLAY, FILTERING), filterChoices, 3, &configFiltering, NULL); + int maxMsaa = wm_api->get_max_msaa(); + if (maxMsaa >= 2) { + if (configWindow.msaa >= 16) { sMsaaSelection = 4; } + else if (configWindow.msaa >= 8) { sMsaaSelection = 3; } + else if (configWindow.msaa >= 4) { sMsaaSelection = 2; } + else if (configWindow.msaa >= 2) { sMsaaSelection = 1; } + else { sMsaaSelection = 0; } + + int choiceCount = 2; + if (maxMsaa >= 16) { choiceCount = 5; } + else if (maxMsaa >= 8) { choiceCount = 4; } + else if (maxMsaa >= 4) { choiceCount = 3; } + + char* msaaChoices[5] = { DLANG(DISPLAY, OFF), "2x", "4x", "8x", "16x" }; + msaa = djui_selectionbox_create(body, DLANG(DISPLAY, ANTIALIASING), msaaChoices, choiceCount, &sMsaaSelection, djui_panel_display_msaa_change); + } + char* drawDistanceChoices[6] = { DLANG(DISPLAY, D0P5X), DLANG(DISPLAY, D1X), DLANG(DISPLAY, D1P5X), DLANG(DISPLAY, D3X), DLANG(DISPLAY, D10X), DLANG(DISPLAY, D100X) }; djui_selectionbox_create(body, DLANG(DISPLAY, DRAW_DISTANCE), drawDistanceChoices, 6, &configDrawDistance, NULL); djui_button_create(body, DLANG(DISPLAY, DYNOS_PACKS), DJUI_BUTTON_STYLE_NORMAL, djui_panel_dynos_create); djui_button_create(body, DLANG(MENU, BACK), DJUI_BUTTON_STYLE_BACK, djui_panel_menu_back); + + sRestartText = djui_text_create(body, ""); + djui_text_set_alignment(sRestartText, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP); + djui_base_set_color(&sRestartText->base, 255, 100, 100, 255); + djui_base_set_size_type(&sRestartText->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); + djui_base_set_size(&sRestartText->base, 1.0f, 64); + } + + // force the restart text to update + if (msaa) { + djui_panel_display_msaa_change(&msaa->base); } djui_panel_add(caller, panel, NULL); diff --git a/src/pc/gfx/gfx_dummy.c b/src/pc/gfx/gfx_dummy.c index 1844b3647..e494bc7e4 100644 --- a/src/pc/gfx/gfx_dummy.c +++ b/src/pc/gfx/gfx_dummy.c @@ -80,6 +80,10 @@ static void gfx_dummy_wm_delay(u32 ms) { sleep_ms(ms); } +static int gfx_dummy_get_max_msaa(void) { + return 0; +} + static void gfx_dummy_wm_swap_buffers_begin(void) { } @@ -201,7 +205,8 @@ struct GfxWindowManagerAPI gfx_dummy_wm_api = { gfx_dummy_wm_get_clipboard_text, gfx_dummy_wm_set_clipboard_text, gfx_dummy_wm_set_cursor_visible, - gfx_dummy_wm_delay + gfx_dummy_wm_delay, + gfx_dummy_get_max_msaa, }; struct GfxRenderingAPI gfx_dummy_renderer_api = { diff --git a/src/pc/gfx/gfx_dxgi.cpp b/src/pc/gfx/gfx_dxgi.cpp index 33a8ba615..c62b9e628 100644 --- a/src/pc/gfx/gfx_dxgi.cpp +++ b/src/pc/gfx/gfx_dxgi.cpp @@ -655,6 +655,10 @@ void gfx_dxgi_delay(u32 ms) { Sleep(ms); } +static int gfx_dxgi_get_max_msaa(void) { + return 0; +} + HWND gfx_dxgi_get_h_wnd(void) { return dxgi.h_wnd; } @@ -724,6 +728,7 @@ struct GfxWindowManagerAPI gfx_dxgi = { gfx_dxgi_set_clipboard_text, gfx_dxgi_set_cursor_visible, gfx_dxgi_delay, + gfx_dxgi_get_max_msaa, }; #endif diff --git a/src/pc/gfx/gfx_sdl1.c b/src/pc/gfx/gfx_sdl1.c index ef9f2ae0b..9b278fed4 100644 --- a/src/pc/gfx/gfx_sdl1.c +++ b/src/pc/gfx/gfx_sdl1.c @@ -180,6 +180,10 @@ static void gfx_sdl_delay(u32 ms) { SDL_Delay(ms); } +static int gfx_sdl_get_max_msaa(void) { + return 0; +} + static void gfx_sdl_shutdown(void) { if (SDL_WasInit(0)) SDL_Quit(); @@ -208,6 +212,7 @@ struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_set_clipboard_text, gfx_sdl_set_cursor_visible, gfx_sdl_delay, + gfx_sdl_get_max_msaa, }; #endif // BACKEND_WM diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index 62277b3f0..fcd88a911 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -39,6 +39,10 @@ #include "pc/utils/misc.h" #include "pc/mods/mod_import.h" +#ifndef GL_MAX_SAMPLES +#define GL_MAX_SAMPLES 0x8D57 +#endif + // TODO: figure out if this shit even works #ifdef VERSION_EU # define FRAMERATE 25 @@ -106,6 +110,11 @@ static void gfx_sdl_init(const char *window_title) { SDL_Init(SDL_INIT_VIDEO); SDL_StartTextInput(); + if (configWindow.msaa > 0) { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, configWindow.msaa); + } + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); @@ -115,9 +124,6 @@ static void gfx_sdl_init(const char *window_title) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); #endif - //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); - int xpos = (configWindow.x == WAPI_WIN_CENTERPOS) ? SDL_WINDOWPOS_CENTERED : configWindow.x; int ypos = (configWindow.y == WAPI_WIN_CENTERPOS) ? SDL_WINDOWPOS_CENTERED : configWindow.y; @@ -242,6 +248,13 @@ static void gfx_sdl_delay(u32 ms) { SDL_Delay(ms); } +static int gfx_sdl_get_max_msaa(void) { + int maxSamples = 0; + glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); + if (maxSamples > 16) { maxSamples = 16; } + return maxSamples; +} + static void gfx_sdl_shutdown(void) { if (SDL_WasInit(0)) { if (ctx) { SDL_GL_DeleteContext(ctx); ctx = NULL; } @@ -273,6 +286,7 @@ struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_set_clipboard_text, gfx_sdl_set_cursor_visible, gfx_sdl_delay, + gfx_sdl_get_max_msaa, }; #endif // BACKEND_WM diff --git a/src/pc/gfx/gfx_window_manager_api.h b/src/pc/gfx/gfx_window_manager_api.h index f2d457eb9..7fd8d8074 100644 --- a/src/pc/gfx/gfx_window_manager_api.h +++ b/src/pc/gfx/gfx_window_manager_api.h @@ -26,6 +26,7 @@ struct GfxWindowManagerAPI { void (*set_clipboard_text)(char*); void (*set_cursor_visible)(bool); void (*delay)(unsigned int ms); + int (*get_max_msaa)(void); }; #endif