From 3482313e2fed8f342415ead43c76cc2e09b6e92d Mon Sep 17 00:00:00 2001 From: Albert Liu <45282415+ggrtk@users.noreply.github.com> Date: Mon, 1 Mar 2021 14:59:59 -0800 Subject: [PATCH] Multitap: Add option to enable only on port 2 --- src/core/multitap.cpp | 29 ++++++++++--------- src/core/multitap.h | 11 +++----- src/core/pad.cpp | 9 ------ src/core/pad.h | 3 +- src/core/settings.cpp | 40 +++++++++++++++------------ src/core/settings.h | 5 ++-- src/core/system.cpp | 19 +++++++++---- src/core/types.h | 1 + src/frontend-common/fullscreen_ui.cpp | 13 ++++----- 9 files changed, 64 insertions(+), 66 deletions(-) diff --git a/src/core/multitap.cpp b/src/core/multitap.cpp index 5516e900a..2f9501463 100644 --- a/src/core/multitap.cpp +++ b/src/core/multitap.cpp @@ -7,9 +7,8 @@ #include "pad.h" Log_SetChannel(Multitap); -Multitap::Multitap(u32 index) : m_index(index) +Multitap::Multitap() { - m_index = index; Reset(); } @@ -24,6 +23,16 @@ void Multitap::Reset() m_transfer_buffer.fill(0xFF); } +void Multitap::SetEnable(bool enable, u32 base_index) +{ + if (m_enabled != enable || m_base_index != base_index) + { + m_enabled = enable; + m_base_index = base_index; + Reset(); + } +} + bool Multitap::DoState(StateWrapper& sw) { sw.Do(&m_transfer_state); @@ -48,19 +57,9 @@ void Multitap::ResetTransferState() // Controller and memory card transfer resets are handled in the Pad class } -Controller* Multitap::GetControllerForSlot(u32 slot) const -{ - return g_pad.GetController(m_index * 4 + slot); -} - -MemoryCard* Multitap::GetMemoryCardForSlot(u32 slot) const -{ - return g_pad.GetMemoryCard(m_index * 4 + slot); -} - bool Multitap::TransferController(u32 slot, const u8 data_in, u8* data_out) const { - Controller* const selected_controller = GetControllerForSlot(slot); + Controller* const selected_controller = g_pad.GetController(m_base_index + slot); if (!selected_controller) { *data_out = 0xFF; @@ -72,7 +71,7 @@ bool Multitap::TransferController(u32 slot, const u8 data_in, u8* data_out) cons bool Multitap::TransferMemoryCard(u32 slot, const u8 data_in, u8* data_out) const { - MemoryCard* const selected_memcard = GetMemoryCardForSlot(slot); + MemoryCard* const selected_memcard = g_pad.GetMemoryCard(m_base_index + slot); if (!selected_memcard) { *data_out = 0xFF; @@ -198,7 +197,7 @@ bool Multitap::Transfer(const u8 data_in, u8* data_out) case TransferState::SingleController: { - // TODO: Check if the transfer buffer get wiped when transitioning to/from this mode + // TODO: Check if the transfer buffer gets wiped when transitioning to/from this mode ack = TransferController(m_selected_slot, data_in, data_out); diff --git a/src/core/multitap.h b/src/core/multitap.h index d77de809d..701a696f4 100644 --- a/src/core/multitap.h +++ b/src/core/multitap.h @@ -8,26 +8,23 @@ class Multitap final { public: - Multitap(u32 index); + Multitap(); void Reset(); - ALWAYS_INLINE void SetEnable(bool enable) { m_enabled = enable; }; + void SetEnable(bool enable, u32 base_index); ALWAYS_INLINE bool IsEnabled() const { return m_enabled; }; bool DoState(StateWrapper& sw); void ResetTransferState(); bool Transfer(const u8 data_in, u8* data_out); - ALWAYS_INLINE bool IsReadingMemoryCard() { return m_enabled && m_transfer_state == TransferState::MemoryCard; }; + ALWAYS_INLINE bool IsReadingMemoryCard() { return IsEnabled() && m_transfer_state == TransferState::MemoryCard; }; private: ALWAYS_INLINE static constexpr u8 GetMultitapIDByte() { return 0x80; }; ALWAYS_INLINE static constexpr u8 GetStatusByte() { return 0x5A; }; - Controller* GetControllerForSlot(u32 slot) const; - MemoryCard* GetMemoryCardForSlot(u32 slot) const; - bool TransferController(u32 slot, const u8 data_in, u8* data_out) const; bool TransferMemoryCard(u32 slot, const u8 data_in, u8* data_out) const; @@ -51,6 +48,6 @@ private: std::array m_transfer_buffer{}; - u32 m_index; + u32 m_base_index; bool m_enabled = false; }; diff --git a/src/core/pad.cpp b/src/core/pad.cpp index 044a8d909..4b48e2231 100644 --- a/src/core/pad.cpp +++ b/src/core/pad.cpp @@ -247,15 +247,6 @@ void Pad::SetMemoryCard(u32 slot, std::unique_ptr dev) m_memory_cards[slot] = std::move(dev); } -void Pad::SetMultitapEnable(u32 port, bool enable) -{ - if (m_multitaps[port].IsEnabled() != enable) - { - m_multitaps[port].SetEnable(enable); - m_multitaps[port].Reset(); - } -} - u32 Pad::ReadRegister(u32 offset) { switch (offset) diff --git a/src/core/pad.h b/src/core/pad.h index d25130e9f..2bed1f626 100644 --- a/src/core/pad.h +++ b/src/core/pad.h @@ -30,7 +30,6 @@ public: void SetMemoryCard(u32 slot, std::unique_ptr dev); Multitap* GetMultitap(u32 slot) { return &m_multitaps[slot]; }; - void SetMultitapEnable(u32 port, bool enable); u32 ReadRegister(u32 offset); void WriteRegister(u32 offset, u32 value); @@ -116,7 +115,7 @@ private: std::array, NUM_CONTROLLER_AND_CARD_PORTS> m_controllers; std::array, NUM_CONTROLLER_AND_CARD_PORTS> m_memory_cards; - std::array m_multitaps = {Multitap(0), Multitap(1)}; + std::array m_multitaps; std::unique_ptr m_transfer_event; State m_state = State::Idle; diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 3d810e6cb..55b4c574d 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -78,26 +78,32 @@ bool Settings::HasAnyPerGameMemoryCards() const }); } -bool Settings::IsMultitapEnabledOnPort(u32 port) const +std::array Settings::GeneratePortLabels() const { - if (port < NUM_MULTITAPS) + static constexpr std::array, static_cast(MultitapMode::Count)> + multitap_enabled_on_port = {{{false, false}, {true, false}, {false, true}, {true, true}}}; + + std::array labels; + + u32 logical_port = 0; + for (u32 physical_port = 0; physical_port < NUM_MULTITAPS; physical_port++) { - switch (multitap_mode) + if (multitap_enabled_on_port[static_cast(multitap_mode)][physical_port]) { - case MultitapMode::Disabled: - return false; - - case MultitapMode::Port1Only: - return port == 0u; - - case MultitapMode::BothPorts: - return true; - - DefaultCaseIsUnreachable(); + for (u32 i = 0; i < 4; i++) + { + labels[logical_port] = TinyString::FromFormat("Port %u%c", physical_port + 1u, 'A' + i); + logical_port++; + } + } + else + { + labels[logical_port] = TinyString::FromFormat("Port %u", physical_port + 1u); + logical_port++; } } - return false; + return labels; } void Settings::CPUOverclockPercentToFraction(u32 percent, u32* numerator, u32* denominator) @@ -877,10 +883,10 @@ const char* Settings::GetMemoryCardTypeDisplayName(MemoryCardType type) return s_memory_card_type_display_names[static_cast(type)]; } -static std::array s_multitap_enable_mode_names = {{"Disabled", "Port1Only", "BothPorts"}}; -static std::array s_multitap_enable_mode_display_names = { +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 Ports 1 and 2")}}; + 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/core/settings.h b/src/core/settings.h index 24f931439..1531bb11e 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -1,5 +1,6 @@ #pragma once #include "common/log.h" +#include "common/string.h" #include "types.h" #include #include @@ -219,6 +220,8 @@ struct Settings MultitapMode multitap_mode = MultitapMode::Disabled; + std::array GeneratePortLabels() const; + LOGLEVEL log_level = LOGLEVEL_INFO; std::string log_filter; bool log_to_console = false; @@ -254,8 +257,6 @@ struct Settings bool HasAnyPerGameMemoryCards() const; - bool IsMultitapEnabledOnPort(u32 port) const; - static void CPUOverclockPercentToFraction(u32 percent, u32* numerator, u32* denominator); static u32 CPUOverclockFractionToPercent(u32 numerator, u32 denominator); diff --git a/src/core/system.cpp b/src/core/system.cpp index ec5585939..e801e6d06 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -1861,22 +1861,29 @@ void UpdateMultitaps() { case MultitapMode::Disabled: { - g_pad.SetMultitapEnable(0, false); - g_pad.SetMultitapEnable(1, false); + g_pad.GetMultitap(0)->SetEnable(false, 0); + g_pad.GetMultitap(1)->SetEnable(false, 0); } break; case MultitapMode::Port1Only: { - g_pad.SetMultitapEnable(0, true); - g_pad.SetMultitapEnable(1, false); + g_pad.GetMultitap(0)->SetEnable(true, 0); + g_pad.GetMultitap(1)->SetEnable(false, 0); + } + break; + + case MultitapMode::Port2Only: + { + g_pad.GetMultitap(0)->SetEnable(false, 0); + g_pad.GetMultitap(1)->SetEnable(true, 1); } break; case MultitapMode::BothPorts: { - g_pad.SetMultitapEnable(0, true); - g_pad.SetMultitapEnable(1, true); + g_pad.GetMultitap(0)->SetEnable(true, 0); + g_pad.GetMultitap(1)->SetEnable(true, 4); } break; } diff --git a/src/core/types.h b/src/core/types.h index 8083c54d8..30a383aee 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -147,6 +147,7 @@ enum class MultitapMode { Disabled, Port1Only, + Port2Only, BothPorts, Count }; diff --git a/src/frontend-common/fullscreen_ui.cpp b/src/frontend-common/fullscreen_ui.cpp index 16747eb71..fedf2422a 100644 --- a/src/frontend-common/fullscreen_ui.cpp +++ b/src/frontend-common/fullscreen_ui.cpp @@ -1573,17 +1573,14 @@ void DrawSettingsWindow() TinyString section; TinyString key; + std::array port_labels = s_settings_copy.GeneratePortLabels(); + for (u32 port = 0; port < NUM_CONTROLLER_AND_CARD_PORTS; port++) { - u32 console_port = port / 4u; - if (s_settings_copy.IsMultitapEnabledOnPort(console_port)) - MenuHeading(TinyString::FromFormat("Port %u%c", console_port + 1u, 'A' + (port % 4u))); - else if (port < 2u) - MenuHeading(TinyString::FromFormat("Port %u", port + 1u)); - else if (port % 4u == 0u && s_settings_copy.IsMultitapEnabledOnPort(0)) - MenuHeading(TinyString::FromFormat("Port %u", console_port + 1u)); - else + if (port_labels[port].IsEmpty()) continue; + else + MenuHeading(port_labels[port]); settings_changed |= EnumChoiceButton( TinyString::FromFormat(ICON_FA_GAMEPAD " Controller Type##type%u", port),