From 05ac272c3fdb6c773a007fe865a268c80beca39b Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Wed, 3 Mar 2021 21:43:20 +1000 Subject: [PATCH] GameSettings: Add multitap mode --- src/core/settings.cpp | 4 +-- src/duckstation-qt/gamepropertiesdialog.cpp | 19 ++++++++++ src/duckstation-qt/gamepropertiesdialog.ui | 22 ++++++++---- src/frontend-common/game_list.h | 2 +- src/frontend-common/game_settings.cpp | 40 +++++++++++++++------ src/frontend-common/game_settings.h | 1 + 6 files changed, 68 insertions(+), 20 deletions(-) diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 55b4c574d..061477cf9 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -885,8 +885,8 @@ const char* Settings::GetMemoryCardTypeDisplayName(MemoryCardType type) static std::array s_multitap_enable_mode_names = {{"Disabled", "Port1Only", "Port2Only", "BothPorts"}}; static std::array s_multitap_enable_mode_display_names = { - {TRANSLATABLE("MultitapMode", "Disabled"), TRANSLATABLE("MultitapMode", "Enable on Port 1 only"), - TRANSLATABLE("MultitapMode", "Enable on Port 2 only"), TRANSLATABLE("MultitapMode", "Enable on Ports 1 and 2")}}; + {TRANSLATABLE("MultitapMode", "Disabled"), TRANSLATABLE("MultitapMode", "Enable on Port 1 Only"), + TRANSLATABLE("MultitapMode", "Enable on Port 2 Only"), TRANSLATABLE("MultitapMode", "Enable on Ports 1 and 2")}}; std::optional Settings::ParseMultitapModeName(const char* str) { diff --git a/src/duckstation-qt/gamepropertiesdialog.cpp b/src/duckstation-qt/gamepropertiesdialog.cpp index 2c972a3c4..02f88ea24 100644 --- a/src/duckstation-qt/gamepropertiesdialog.cpp +++ b/src/duckstation-qt/gamepropertiesdialog.cpp @@ -152,6 +152,12 @@ void GamePropertiesDialog::setupAdditionalUi() qApp->translate("GPUTextureFilter", Settings::GetTextureFilterDisplayName(static_cast(i)))); } + m_ui.userMultitapMode->addItem(tr("(unchanged)")); + for (u32 i = 0; i < static_cast(MultitapMode::Count); i++) + { + m_ui.userMultitapMode->addItem( + qApp->translate("MultitapMode", Settings::GetMultitapModeDisplayName(static_cast(i)))); + } m_ui.userControllerType1->addItem(tr("(unchanged)")); for (u32 i = 0; i < static_cast(ControllerType::Count); i++) { @@ -409,6 +415,11 @@ void GamePropertiesDialog::populateGameSettings() populateBooleanUserSetting(m_ui.userPGXPProjectionPrecision, gs.gpu_pgxp_projection_precision); populateBooleanUserSetting(m_ui.userPGXPDepthBuffer, gs.gpu_pgxp_depth_buffer); + if (gs.multitap_mode.has_value()) + { + QSignalBlocker sb(m_ui.userMultitapMode); + m_ui.userMultitapMode->setCurrentIndex(static_cast(gs.multitap_mode.value()) + 1); + } if (gs.controller_1_type.has_value()) { QSignalBlocker sb(m_ui.userControllerType1); @@ -605,6 +616,14 @@ void GamePropertiesDialog::connectUi() connectBooleanUserSetting(m_ui.userPGXPProjectionPrecision, &m_game_settings.gpu_pgxp_projection_precision); connectBooleanUserSetting(m_ui.userPGXPDepthBuffer, &m_game_settings.gpu_pgxp_depth_buffer); + connect(m_ui.userMultitapMode, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) { + if (index <= 0) + m_game_settings.multitap_mode.reset(); + else + m_game_settings.multitap_mode = static_cast(index - 1); + saveGameSettings(); + }); + connect(m_ui.userControllerType1, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) { if (index <= 0) m_game_settings.controller_1_type.reset(); diff --git a/src/duckstation-qt/gamepropertiesdialog.ui b/src/duckstation-qt/gamepropertiesdialog.ui index 27a381609..c37a4d4a6 100644 --- a/src/duckstation-qt/gamepropertiesdialog.ui +++ b/src/duckstation-qt/gamepropertiesdialog.ui @@ -613,36 +613,46 @@ Controller Settings - + Controller 1 Type: - + - + Controller 2 Type: - + - + Input Profile For Bindings: - + + + + + Multitap Mode: + + + + + + diff --git a/src/frontend-common/game_list.h b/src/frontend-common/game_list.h index 30946d5c4..7169efa41 100644 --- a/src/frontend-common/game_list.h +++ b/src/frontend-common/game_list.h @@ -132,7 +132,7 @@ private: enum : u32 { GAME_LIST_CACHE_SIGNATURE = 0x45434C47, - GAME_LIST_CACHE_VERSION = 23 + GAME_LIST_CACHE_VERSION = 24 }; using DatabaseMap = std::unordered_map; diff --git a/src/frontend-common/game_settings.cpp b/src/frontend-common/game_settings.cpp index 9ba52eae6..8b51da081 100644 --- a/src/frontend-common/game_settings.cpp +++ b/src/frontend-common/game_settings.cpp @@ -128,9 +128,9 @@ bool Entry::LoadFromStream(ByteStream* stream) !ReadOptionalFromStream(stream, &gpu_force_ntsc_timings) || !ReadOptionalFromStream(stream, &gpu_texture_filter) || !ReadOptionalFromStream(stream, &gpu_widescreen_hack) || !ReadOptionalFromStream(stream, &gpu_pgxp) || !ReadOptionalFromStream(stream, &gpu_pgxp_projection_precision) || - !ReadOptionalFromStream(stream, &gpu_pgxp_depth_buffer) || !ReadOptionalFromStream(stream, &controller_1_type) || - !ReadOptionalFromStream(stream, &controller_2_type) || !ReadOptionalFromStream(stream, &memory_card_1_type) || - !ReadOptionalFromStream(stream, &memory_card_2_type) || + !ReadOptionalFromStream(stream, &gpu_pgxp_depth_buffer) || !ReadOptionalFromStream(stream, &multitap_mode) || + !ReadOptionalFromStream(stream, &controller_1_type) || !ReadOptionalFromStream(stream, &controller_2_type) || + !ReadOptionalFromStream(stream, &memory_card_1_type) || !ReadOptionalFromStream(stream, &memory_card_2_type) || !ReadStringFromStream(stream, &memory_card_1_shared_path) || !ReadStringFromStream(stream, &memory_card_2_shared_path) || !ReadStringFromStream(stream, &input_profile_name)) { @@ -178,9 +178,10 @@ bool Entry::SaveToStream(ByteStream* stream) const WriteOptionalToStream(stream, gpu_scaled_dithering) && WriteOptionalToStream(stream, gpu_force_ntsc_timings) && WriteOptionalToStream(stream, gpu_texture_filter) && WriteOptionalToStream(stream, gpu_widescreen_hack) && WriteOptionalToStream(stream, gpu_pgxp) && WriteOptionalToStream(stream, gpu_pgxp_projection_precision) && - WriteOptionalToStream(stream, gpu_pgxp_depth_buffer) && WriteOptionalToStream(stream, controller_1_type) && - WriteOptionalToStream(stream, controller_2_type) && WriteOptionalToStream(stream, memory_card_1_type) && - WriteOptionalToStream(stream, memory_card_2_type) && WriteStringToStream(stream, memory_card_1_shared_path) && + WriteOptionalToStream(stream, gpu_pgxp_depth_buffer) && WriteOptionalToStream(stream, multitap_mode) && + WriteOptionalToStream(stream, controller_1_type) && WriteOptionalToStream(stream, controller_2_type) && + WriteOptionalToStream(stream, memory_card_1_type) && WriteOptionalToStream(stream, memory_card_2_type) && + WriteStringToStream(stream, memory_card_1_shared_path) && WriteStringToStream(stream, memory_card_2_shared_path) && WriteStringToStream(stream, input_profile_name); } @@ -294,6 +295,9 @@ static void ParseIniSection(Entry* entry, const char* section, const CSimpleIniA if (cvalue) entry->gpu_pgxp_depth_buffer = StringUtil::FromChars(cvalue); + cvalue = ini.GetValue(section, "MultitapMode", nullptr); + if (cvalue) + entry->multitap_mode = Settings::ParseMultitapModeName(cvalue); cvalue = ini.GetValue(section, "Controller1Type", nullptr); if (cvalue) entry->controller_1_type = Settings::ParseControllerTypeName(cvalue); @@ -401,11 +405,8 @@ static void StoreIniSection(const Entry& entry, const char* section, CSimpleIniA if (entry.gpu_pgxp_depth_buffer.has_value()) ini.SetValue(section, "GPUPGXPDepthBuffer", entry.gpu_pgxp_depth_buffer.value() ? "true" : "false"); - if (entry.controller_1_type.has_value()) - ini.SetValue(section, "Controller1Type", Settings::GetControllerTypeName(entry.controller_1_type.value())); - if (entry.controller_2_type.has_value()) - ini.SetValue(section, "Controller2Type", Settings::GetControllerTypeName(entry.controller_2_type.value())); - + if (entry.multitap_mode.has_value()) + ini.SetValue(section, "MultitapMode", Settings::GetMultitapModeName(entry.multitap_mode.value())); if (entry.controller_1_type.has_value()) ini.SetValue(section, "Controller1Type", Settings::GetControllerTypeName(entry.controller_1_type.value())); if (entry.controller_2_type.has_value()) @@ -448,6 +449,7 @@ u32 Entry::GetUserSettingsCount() const count += BoolToUInt32(gpu_pgxp.has_value()); count += BoolToUInt32(gpu_pgxp_projection_precision.has_value()); count += BoolToUInt32(gpu_pgxp_depth_buffer.has_value()); + count += BoolToUInt32(multitap_mode.has_value()); count += BoolToUInt32(controller_1_type.has_value()); count += BoolToUInt32(controller_2_type.has_value()); count += BoolToUInt32(memory_card_1_type.has_value()); @@ -600,6 +602,13 @@ static std::optional GetEntryValueForKey(const Entry& entry, const else return entry.gpu_pgxp_depth_buffer.value() ? "true" : "false"; } + else if (key == "MultitapMode") + { + if (!entry.multitap_mode.has_value()) + return std::nullopt; + else + return Settings::GetMultitapModeName(entry.multitap_mode.value()); + } else if (key == "Controller1Type") { if (!entry.controller_1_type.has_value()) @@ -817,6 +826,13 @@ static void SetEntryValueForKey(Entry& entry, const std::string_view& key, const else entry.gpu_pgxp_depth_buffer = StringUtil::FromChars(value.value()).value_or(false); } + else if (key == "MultitapMode") + { + if (!value.has_value()) + entry.multitap_mode.reset(); + else + entry.multitap_mode = Settings::ParseMultitapModeName(value->c_str()); + } else if (key == "Controller1Type") { if (!value.has_value()) @@ -1047,6 +1063,8 @@ void Entry::ApplySettings(bool display_osd_messages) const if (gpu_pgxp_depth_buffer.has_value()) g_settings.gpu_pgxp_depth_buffer = gpu_pgxp_depth_buffer.value(); + if (multitap_mode.has_value()) + g_settings.multitap_mode = multitap_mode.value(); if (controller_1_type.has_value()) g_settings.controller_types[0] = controller_1_type.value(); if (controller_2_type.has_value()) diff --git a/src/frontend-common/game_settings.h b/src/frontend-common/game_settings.h index dc4b8fb52..dc08e5d75 100644 --- a/src/frontend-common/game_settings.h +++ b/src/frontend-common/game_settings.h @@ -72,6 +72,7 @@ struct Entry std::optional gpu_pgxp; std::optional gpu_pgxp_projection_precision; std::optional gpu_pgxp_depth_buffer; + std::optional multitap_mode; std::optional controller_1_type; std::optional controller_2_type; std::optional memory_card_1_type;