From 8f6bfe078b6523d04dd1cbefa4ef0acf135a6e25 Mon Sep 17 00:00:00 2001 From: VoxelTek <53562267+VoxelTek@users.noreply.github.com> Date: Thu, 24 Jul 2025 03:33:39 +1000 Subject: [PATCH] Add MSAA to `isle-config`, improve Exclusive Fullscreen resolution options. (#638) * Add dropdown for exclusive fullscreen resolutions * Add MSAA support * Make clang-format happy * Fix tab order * Make clang-format happy again --- CONFIG/MainDlg.cpp | 127 ++++++++++++++++++++++----- CONFIG/MainDlg.h | 9 +- CONFIG/config.cpp | 30 ++++++- CONFIG/config.h | 4 + CONFIG/res/maindialog.ui | 180 +++++++++++++++++++++++++++++++-------- ISLE/isleapp.cpp | 18 +++- ISLE/isleapp.h | 3 + 7 files changed, 307 insertions(+), 64 deletions(-) diff --git a/CONFIG/MainDlg.cpp b/CONFIG/MainDlg.cpp index 3f69d096..55f06cf3 100644 --- a/CONFIG/MainDlg.cpp +++ b/CONFIG/MainDlg.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -54,15 +56,18 @@ CMainDialog::CMainDialog(QWidget* pParent) : QDialog(pParent) this, &CMainDialog::OnRadiobuttonTextureHighQuality ); + + connect(m_ui->windowedRadioButton, &QRadioButton::toggled, this, &CMainDialog::OnRadioWindowed); + connect(m_ui->fullscreenRadioButton, &QRadioButton::toggled, this, &CMainDialog::OnRadioFullscreen); + connect(m_ui->exFullscreenRadioButton, &QRadioButton::toggled, this, &CMainDialog::OnRadioExclusiveFullscreen); connect(m_ui->devicesList, &QListWidget::currentRowChanged, this, &CMainDialog::OnList3DevicesSelectionChanged); connect(m_ui->musicCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxMusic); connect(m_ui->sound3DCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckbox3DSound); - connect(m_ui->fullscreenCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxFullscreen); - connect(m_ui->exclusiveFullscreenCheckbox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxExclusiveFullscreen); connect(m_ui->rumbleCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxRumble); connect(m_ui->textureCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxTexture); connect(m_ui->touchComboBox, &QComboBox::currentIndexChanged, this, &CMainDialog::TouchControlsChanged); connect(m_ui->transitionTypeComboBox, &QComboBox::currentIndexChanged, this, &CMainDialog::TransitionTypeChanged); + connect(m_ui->exFullResComboBox, &QComboBox::currentIndexChanged, this, &CMainDialog::ExclusiveResolutionChanged); connect(m_ui->okButton, &QPushButton::clicked, this, &CMainDialog::accept); connect(m_ui->cancelButton, &QPushButton::clicked, this, &CMainDialog::reject); connect(m_ui->launchButton, &QPushButton::clicked, this, &CMainDialog::launch); @@ -81,6 +86,9 @@ CMainDialog::CMainDialog(QWidget* pParent) : QDialog(pParent) connect(m_ui->maxActorsSlider, &QSlider::valueChanged, this, &CMainDialog::MaxActorsChanged); connect(m_ui->maxActorsSlider, &QSlider::sliderMoved, this, &CMainDialog::MaxActorsChanged); + connect(m_ui->msaaSlider, &QSlider::valueChanged, this, &CMainDialog::MSAAChanged); + connect(m_ui->msaaSlider, &QSlider::sliderMoved, this, &CMainDialog::MSAAChanged); + connect(m_ui->aspectRatioComboBox, &QComboBox::currentIndexChanged, this, &CMainDialog::AspectRatioChanged); connect(m_ui->xResSpinBox, &QSpinBox::valueChanged, this, &CMainDialog::XResChanged); connect(m_ui->yResSpinBox, &QSpinBox::valueChanged, this, &CMainDialog::YResChanged); @@ -164,6 +172,23 @@ bool CMainDialog::OnInitDialog() m_ui->maxActorsSlider->setValue(currentConfigApp->m_max_actors); m_ui->maxActorsNum->setNum(currentConfigApp->m_max_actors); + m_ui->exFullResComboBox->clear(); + + int displayModeCount; + displayModes = SDL_GetFullscreenDisplayModes(SDL_GetPrimaryDisplay(), &displayModeCount); + + for (int i = 0; i < displayModeCount; ++i) { + QString mode = + QString("%1x%2 @ %3Hz").arg(displayModes[i]->w).arg(displayModes[i]->h).arg(displayModes[i]->refresh_rate); + m_ui->exFullResComboBox->addItem(mode); + + if ((displayModes[i]->w == currentConfigApp->m_exf_x_res) && + (displayModes[i]->h == currentConfigApp->m_exf_y_res) && + (displayModes[i]->refresh_rate == currentConfigApp->m_exf_fps)) { + m_ui->exFullResComboBox->setCurrentIndex(i); + } + } + UpdateInterface(); return true; } @@ -258,18 +283,30 @@ void CMainDialog::UpdateInterface() else { m_ui->textureQualityHighRadioButton->setChecked(true); } + if (currentConfigApp->m_exclusive_full_screen) { + m_ui->exFullscreenRadioButton->setChecked(true); + m_ui->resolutionBox->setEnabled(false); + m_ui->exFullResContainer->setEnabled(true); + } + else { + m_ui->resolutionBox->setEnabled(true); + m_ui->exFullResContainer->setEnabled(false); + if (currentConfigApp->m_full_screen) { + m_ui->fullscreenRadioButton->setChecked(true); + } + else { + m_ui->windowedRadioButton->setChecked(true); + } + } m_ui->musicCheckBox->setChecked(currentConfigApp->m_music); - m_ui->fullscreenCheckBox->setChecked(currentConfigApp->m_full_screen); - m_ui->exclusiveFullscreenCheckbox->setEnabled(currentConfigApp->m_full_screen); - m_ui->exclusiveFullscreenCheckbox->setChecked(currentConfigApp->m_exclusive_full_screen); m_ui->rumbleCheckBox->setChecked(currentConfigApp->m_haptic); m_ui->touchComboBox->setCurrentIndex(currentConfigApp->m_touch_scheme); m_ui->transitionTypeComboBox->setCurrentIndex(currentConfigApp->m_transition_type); m_ui->dataPath->setText(QString::fromStdString(currentConfigApp->m_cd_path)); m_ui->savePath->setText(QString::fromStdString(currentConfigApp->m_save_path)); + m_ui->textureCheckBox->setChecked(currentConfigApp->m_texture_load); m_ui->texturePath->setText(QString::fromStdString(currentConfigApp->m_texture_path)); - m_ui->texturePath->setEnabled(currentConfigApp->m_texture_load); m_ui->texturePathOpen->setEnabled(currentConfigApp->m_texture_load); @@ -277,6 +314,13 @@ void CMainDialog::UpdateInterface() m_ui->xResSpinBox->setValue(currentConfigApp->m_x_res); m_ui->yResSpinBox->setValue(currentConfigApp->m_y_res); m_ui->framerateSpinBox->setValue(static_cast(std::round(1000.0f / currentConfigApp->m_frame_delta))); + + m_ui->maxLoDSlider->setValue((int) (currentConfigApp->m_max_lod * 10)); + m_ui->LoDNum->setNum(currentConfigApp->m_max_lod); + m_ui->maxActorsSlider->setValue(currentConfigApp->m_max_actors); + m_ui->maxActorsNum->setNum(currentConfigApp->m_max_actors); + m_ui->msaaSlider->setValue(log2(currentConfigApp->m_msaa)); + m_ui->msaaNum->setNum(currentConfigApp->m_msaa); } // FUNCTION: CONFIG 0x004045e0 @@ -336,6 +380,42 @@ void CMainDialog::OnRadiobuttonTextureHighQuality(bool checked) } } +void CMainDialog::OnRadioWindowed(bool checked) +{ + if (checked) { + currentConfigApp->m_full_screen = false; + currentConfigApp->m_exclusive_full_screen = false; + m_ui->resolutionBox->setEnabled(true); + m_ui->exFullResContainer->setEnabled(false); + m_modified = true; + UpdateInterface(); + } +} + +void CMainDialog::OnRadioFullscreen(bool checked) +{ + if (checked) { + currentConfigApp->m_full_screen = true; + currentConfigApp->m_exclusive_full_screen = false; + m_ui->resolutionBox->setEnabled(true); + m_ui->exFullResContainer->setEnabled(false); + m_modified = true; + UpdateInterface(); + } +} + +void CMainDialog::OnRadioExclusiveFullscreen(bool checked) +{ + if (checked) { + currentConfigApp->m_full_screen = true; + currentConfigApp->m_exclusive_full_screen = true; + m_ui->resolutionBox->setEnabled(false); + m_ui->exFullResContainer->setEnabled(true); + m_modified = true; + UpdateInterface(); + } +} + // FUNCTION: CONFIG 0x004048c0 void CMainDialog::OnCheckboxMusic(bool checked) { @@ -344,21 +424,6 @@ void CMainDialog::OnCheckboxMusic(bool checked) UpdateInterface(); } -void CMainDialog::OnCheckboxFullscreen(bool checked) -{ - currentConfigApp->m_full_screen = checked; - m_ui->exclusiveFullscreenCheckbox->setEnabled(checked); - m_modified = true; - UpdateInterface(); -} - -void CMainDialog::OnCheckboxExclusiveFullscreen(bool checked) -{ - currentConfigApp->m_exclusive_full_screen = checked; - m_modified = true; - UpdateInterface(); -} - void CMainDialog::OnCheckboxRumble(bool checked) { currentConfigApp->m_haptic = checked; @@ -387,6 +452,15 @@ void CMainDialog::TransitionTypeChanged(int index) UpdateInterface(); } +void CMainDialog::ExclusiveResolutionChanged(int index) +{ + currentConfigApp->m_exf_x_res = displayModes[index]->w; + currentConfigApp->m_exf_y_res = displayModes[index]->h; + currentConfigApp->m_exf_fps = displayModes[index]->refresh_rate; + m_modified = true; + UpdateInterface(); +} + void CMainDialog::SelectDataPathDialog() { QString data_path = QString::fromStdString(currentConfigApp->m_cd_path); @@ -458,15 +532,22 @@ void CMainDialog::SavePathEdited() void CMainDialog::MaxLoDChanged(int value) { currentConfigApp->m_max_lod = static_cast(value) / 10.0f; - m_ui->LoDNum->setNum(value); m_modified = true; + UpdateInterface(); } void CMainDialog::MaxActorsChanged(int value) { currentConfigApp->m_max_actors = value; - m_ui->maxActorsNum->setNum(value); m_modified = true; + UpdateInterface(); +} + +void CMainDialog::MSAAChanged(int value) +{ + currentConfigApp->m_msaa = exp2(value); + m_modified = true; + UpdateInterface(); } void CMainDialog::SelectTexturePathDialog() diff --git a/CONFIG/MainDlg.h b/CONFIG/MainDlg.h index ece4dbfd..c453c785 100644 --- a/CONFIG/MainDlg.h +++ b/CONFIG/MainDlg.h @@ -7,6 +7,7 @@ #include #include +#include namespace Ui { @@ -29,6 +30,7 @@ class CMainDialog : public QDialog { bool m_modified = false; bool m_advanced = false; Ui::MainDialog* m_ui = nullptr; + SDL_DisplayMode** displayModes; void keyReleaseEvent(QKeyEvent* event) override; bool OnInitDialog(); @@ -40,13 +42,15 @@ private slots: void OnRadiobuttonModelHighQuality(bool checked); void OnRadiobuttonTextureLowQuality(bool checked); void OnRadiobuttonTextureHighQuality(bool checked); + void OnRadioWindowed(bool checked); + void OnRadioFullscreen(bool checked); + void OnRadioExclusiveFullscreen(bool checked); void OnCheckboxMusic(bool checked); - void OnCheckboxFullscreen(bool checked); - void OnCheckboxExclusiveFullscreen(bool checked); void OnCheckboxRumble(bool checked); void OnCheckboxTexture(bool checked); void TouchControlsChanged(int index); void TransitionTypeChanged(int index); + void ExclusiveResolutionChanged(int index); void accept() override; void reject() override; void launch(); @@ -56,6 +60,7 @@ private slots: void SavePathEdited(); void MaxLoDChanged(int value); void MaxActorsChanged(int value); + void MSAAChanged(int value); void SelectTexturePathDialog(); void TexturePathEdited(); void XResChanged(int i); diff --git a/CONFIG/config.cpp b/CONFIG/config.cpp index d0f1dda6..fd61fbb8 100644 --- a/CONFIG/config.cpp +++ b/CONFIG/config.cpp @@ -68,8 +68,9 @@ bool CConfigApp::InitInstance() } SDL_DestroyWindow(window); m_aspect_ratio = 0; - m_x_res = 640; - m_y_res = 480; + m_exf_x_res = m_x_res = 640; + m_exf_y_res = m_y_res = 480; + m_exf_fps = 60.00f; m_frame_delta = 10.0f; m_driver = NULL; m_device = NULL; @@ -83,6 +84,7 @@ bool CConfigApp::InitInstance() m_3d_video_ram = FALSE; m_joystick_index = -1; m_display_bit_depth = 16; + m_msaa = 1; m_haptic = TRUE; m_touch_scheme = 2; m_texture_load = TRUE; @@ -181,11 +183,15 @@ bool CConfigApp::ReadRegisterSettings() m_joystick_index = iniparser_getint(dict, "isle:JoystickIndex", m_joystick_index); m_max_lod = iniparser_getdouble(dict, "isle:Max LOD", m_max_lod); m_max_actors = iniparser_getint(dict, "isle:Max Allowed Extras", m_max_actors); + m_msaa = iniparser_getint(dict, "isle:MSAA", m_msaa); m_texture_load = iniparser_getboolean(dict, "extensions:texture loader", m_texture_load); m_texture_path = iniparser_getstring(dict, "texture loader:texture path", m_texture_path.c_str()); m_aspect_ratio = iniparser_getint(dict, "isle:Aspect Ratio", m_aspect_ratio); m_x_res = iniparser_getint(dict, "isle:Horizontal Resolution", m_x_res); m_y_res = iniparser_getint(dict, "isle:Vertical Resolution", m_y_res); + m_exf_x_res = iniparser_getint(dict, "isle:Exclusive X Resolution", m_exf_x_res); + m_exf_y_res = iniparser_getint(dict, "isle:Exclusive Y Resolution", m_exf_y_res); + m_exf_fps = iniparser_getdouble(dict, "isle:Exclusive Framerate", m_exf_fps); m_frame_delta = iniparser_getdouble(dict, "isle:Frame Delta", m_frame_delta); iniparser_freedict(dict); return true; @@ -259,6 +265,22 @@ bool CConfigApp::ValidateSettings() m_touch_scheme = 2; is_modified = TRUE; } + if (m_exclusive_full_screen && !m_full_screen) { + m_full_screen = TRUE; + is_modified = TRUE; + } + if (!(m_msaa & (m_msaa - 1))) { // Check if MSAA is power of 2 (1, 2, 4, 8, etc) + m_msaa = exp2(round(log2(m_msaa))); // Closest power of 2 + is_modified = TRUE; + } + if (m_msaa > 16) { + m_msaa = 16; + is_modified = TRUE; + } + else if (m_msaa < 1) { + m_msaa = 1; + is_modified = TRUE; + } return is_modified; } @@ -337,6 +359,7 @@ void CConfigApp::WriteRegisterSettings() const iniparser_set(dict, "isle:savepath", m_save_path.c_str()); SetIniInt(dict, "isle:Display Bit Depth", m_display_bit_depth); + SetIniInt(dict, "isle:MSAA", m_msaa); SetIniBool(dict, "isle:Flip Surfaces", m_flip_surfaces); SetIniBool(dict, "isle:Full Screen", m_full_screen); SetIniBool(dict, "isle:Exclusive Full Screen", m_exclusive_full_screen); @@ -367,6 +390,9 @@ void CConfigApp::WriteRegisterSettings() const SetIniInt(dict, "isle:Aspect Ratio", m_aspect_ratio); SetIniInt(dict, "isle:Horizontal Resolution", m_x_res); SetIniInt(dict, "isle:Vertical Resolution", m_y_res); + SetIniInt(dict, "isle:Exclusive X Resolution", m_exf_x_res); + SetIniInt(dict, "isle:Exclusive Y Resolution", m_exf_y_res); + iniparser_set(dict, "isle:Exclusive Framerate", std::to_string(m_exf_fps).c_str()); iniparser_set(dict, "isle:Frame Delta", std::to_string(m_frame_delta).c_str()); #undef SetIniBool diff --git a/CONFIG/config.h b/CONFIG/config.h index ad3321ac..964bad8c 100644 --- a/CONFIG/config.h +++ b/CONFIG/config.h @@ -62,11 +62,15 @@ class CConfigApp { int m_aspect_ratio; int m_x_res; int m_y_res; + int m_exf_x_res; + int m_exf_y_res; + float m_exf_fps; float m_frame_delta; LegoDeviceEnumerate* m_device_enumerator; MxDriver* m_driver; Direct3DDeviceInfo* m_device; int m_display_bit_depth; + int m_msaa; bool m_flip_surfaces; bool m_full_screen; bool m_exclusive_full_screen; diff --git a/CONFIG/res/maindialog.ui b/CONFIG/res/maindialog.ui index 5a0d3b31..e1a8bf3e 100644 --- a/CONFIG/res/maindialog.ui +++ b/CONFIG/res/maindialog.ui @@ -56,6 +56,9 @@ false + + fullscreenRadioContainer_2 + @@ -353,12 +356,18 @@ A higher setting will cause higher quality textures to be drawn regardless of di - 15 + 20 0 + + + 20 + 16777215 + + - 35 + 3.5 @@ -533,10 +542,16 @@ The game will gradually increase the number of actors until this maximum is reac - 15 + 20 0 + + + 20 + 16777215 + + 20 @@ -602,8 +617,59 @@ The game will gradually increase the number of actors until this maximum is reac General - - + + + + + + 0 + 0 + + + + <html><head/><body><p><span style=" font-weight:700;">Windowed:</span> Runs in a window, the initial resolution of which is dictated by Windowed Resolution. </p><p><span style=" font-weight:700;">Fullscreen:</span> Runs in a borderless window that consumes the entire screen. </p><p><span style=" font-weight:700;">Exclusive Fullscreen:</span> Grants the app full control of the display for better performance and lower input lag. May cause slower alt-tabbing.</p></body></html> + + + + 3 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Windowed + + + + + + + Fullscreen + + + + + + + Exclusive Fullscreen + + + + + + + <html><head/><body><p>Maximum framerate. Values above 100fps are untested.</p></body></html> @@ -622,33 +688,6 @@ The game will gradually increase the number of actors until this maximum is reac - - - - - - Toggle fullscreen display mode. - - - Fullscreen - - - - - - - false - - - Grants the app full control of the display for better performance and lower input lag. May cause slower alt-tabbing. - - - Exclusive Fullscreen - - - - - @@ -764,6 +803,72 @@ The game will gradually increase the number of actors until this maximum is reac + + + + false + + + Exclusive Fullscreen Resolution + + + + + + Resolution + + + + + + + + + + MSAA + + + + + + 0 + + + 4 + + + 1 + + + Qt::Orientation::Horizontal + + + QSlider::TickPosition::TicksBothSides + + + 1 + + + + + + + + 16 + 0 + + + + 1 + + + Qt::AlignmentFlag::AlignCenter + + + + + + @@ -772,7 +877,7 @@ The game will gradually increase the number of actors until this maximum is reac 20 - 40 + 0 @@ -860,7 +965,7 @@ The game will gradually increase the number of actors until this maximum is reac Settings for Texture Loader extension. - Texture Loader Extension + Texture Loader @@ -1007,12 +1112,15 @@ The game will gradually increase the number of actors until this maximum is reac maxLoDSlider maxActorsSlider devicesList - fullscreenCheckBox - exclusiveFullscreenCheckbox + windowedRadioButton + fullscreenRadioButton + exFullscreenRadioButton framerateSpinBox aspectRatioComboBox xResSpinBox yResSpinBox + exFullResComboBox + msaaSlider touchComboBox rumbleCheckBox textureCheckBox diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index ee440e8f..b2fab5fb 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -177,6 +177,9 @@ IsleApp::IsleApp() m_haptic = TRUE; m_xRes = 640; m_yRes = 480; + m_exclusiveXRes = m_xRes; + m_exclusiveYRes = m_yRes; + m_exclusiveFrameRate = 60.00f; m_frameRate = 100.0f; m_exclusiveFullScreen = FALSE; } @@ -915,7 +918,14 @@ MxResult IsleApp::SetupWindow() if (m_exclusiveFullScreen && m_fullScreen) { SDL_DisplayMode closestMode; SDL_DisplayID displayID = SDL_GetDisplayForWindow(window); - if (SDL_GetClosestFullscreenDisplayMode(displayID, m_xRes, m_yRes, m_frameRate, true, &closestMode)) { + if (SDL_GetClosestFullscreenDisplayMode( + displayID, + m_exclusiveXRes, + m_exclusiveYRes, + m_exclusiveFrameRate, + true, + &closestMode + )) { SDL_SetWindowFullscreenMode(window, &closestMode); } } @@ -1093,6 +1103,9 @@ bool IsleApp::LoadConfig() iniparser_set(dict, "isle:Haptic", m_haptic ? "true" : "false"); iniparser_set(dict, "isle:Horizontal Resolution", SDL_itoa(m_xRes, buf, 10)); iniparser_set(dict, "isle:Vertical Resolution", SDL_itoa(m_yRes, buf, 10)); + iniparser_set(dict, "isle:Exclusive X Resolution", SDL_itoa(m_exclusiveXRes, buf, 10)); + iniparser_set(dict, "isle:Exclusive Y Resolution", SDL_itoa(m_exclusiveYRes, buf, 10)); + iniparser_set(dict, "isle:Exclusive Framerate", SDL_itoa(m_exclusiveFrameRate, buf, 10)); iniparser_set(dict, "isle:Frame Delta", SDL_itoa(m_frameDelta, buf, 10)); #ifdef EXTENSIONS @@ -1167,6 +1180,9 @@ bool IsleApp::LoadConfig() m_haptic = iniparser_getboolean(dict, "isle:Haptic", m_haptic); m_xRes = iniparser_getint(dict, "isle:Horizontal Resolution", m_xRes); m_yRes = iniparser_getint(dict, "isle:Vertical Resolution", m_yRes); + m_exclusiveXRes = iniparser_getint(dict, "isle:Exclusive X Resolution", m_exclusiveXRes); + m_exclusiveYRes = iniparser_getint(dict, "isle:Exclusive Y Resolution", m_exclusiveXRes); + m_exclusiveFrameRate = iniparser_getdouble(dict, "isle:Exclusive Framerate", m_exclusiveFrameRate); if (!m_fullScreen) { m_videoParam.GetRect() = MxRect32(0, 0, (m_xRes - 1), (m_yRes - 1)); } diff --git a/ISLE/isleapp.h b/ISLE/isleapp.h index 4a23ea23..06c1b51f 100644 --- a/ISLE/isleapp.h +++ b/ISLE/isleapp.h @@ -109,6 +109,9 @@ class IsleApp { MxBool m_haptic; MxS32 m_xRes; MxS32 m_yRes; + MxS32 m_exclusiveXRes; + MxS32 m_exclusiveYRes; + MxFloat m_exclusiveFrameRate; MxFloat m_frameRate; MxBool m_exclusiveFullScreen; };