Merge pull request #1720 from ggrtk/multitap

Multitap: Add option to enable only on port 2
This commit is contained in:
Connor McLaughlin 2021-03-02 15:14:50 +10:00 committed by GitHub
commit 3f698d6ed9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 64 additions and 66 deletions

View File

@ -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);

View File

@ -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<u8, 32> m_transfer_buffer{};
u32 m_index;
u32 m_base_index;
bool m_enabled = false;
};

View File

@ -247,15 +247,6 @@ void Pad::SetMemoryCard(u32 slot, std::unique_ptr<MemoryCard> 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)

View File

@ -30,7 +30,6 @@ public:
void SetMemoryCard(u32 slot, std::unique_ptr<MemoryCard> 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<std::unique_ptr<Controller>, NUM_CONTROLLER_AND_CARD_PORTS> m_controllers;
std::array<std::unique_ptr<MemoryCard>, NUM_CONTROLLER_AND_CARD_PORTS> m_memory_cards;
std::array<Multitap, NUM_MULTITAPS> m_multitaps = {Multitap(0), Multitap(1)};
std::array<Multitap, NUM_MULTITAPS> m_multitaps;
std::unique_ptr<TimingEvent> m_transfer_event;
State m_state = State::Idle;

View File

@ -78,26 +78,32 @@ bool Settings::HasAnyPerGameMemoryCards() const
});
}
bool Settings::IsMultitapEnabledOnPort(u32 port) const
std::array<TinyString, NUM_CONTROLLER_AND_CARD_PORTS> Settings::GeneratePortLabels() const
{
if (port < NUM_MULTITAPS)
static constexpr std::array<std::array<bool, NUM_MULTITAPS>, static_cast<size_t>(MultitapMode::Count)>
multitap_enabled_on_port = {{{false, false}, {true, false}, {false, true}, {true, true}}};
std::array<TinyString, NUM_CONTROLLER_AND_CARD_PORTS> 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<size_t>(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<int>(type)];
}
static std::array<const char*, 3> s_multitap_enable_mode_names = {{"Disabled", "Port1Only", "BothPorts"}};
static std::array<const char*, 3> s_multitap_enable_mode_display_names = {
static std::array<const char*, 4> s_multitap_enable_mode_names = {{"Disabled", "Port1Only", "Port2Only", "BothPorts"}};
static std::array<const char*, 4> 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<MultitapMode> Settings::ParseMultitapModeName(const char* str)
{

View File

@ -1,5 +1,6 @@
#pragma once
#include "common/log.h"
#include "common/string.h"
#include "types.h"
#include <array>
#include <optional>
@ -219,6 +220,8 @@ struct Settings
MultitapMode multitap_mode = MultitapMode::Disabled;
std::array<TinyString, NUM_CONTROLLER_AND_CARD_PORTS> 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);

View File

@ -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;
}

View File

@ -147,6 +147,7 @@ enum class MultitapMode
{
Disabled,
Port1Only,
Port2Only,
BothPorts,
Count
};

View File

@ -1573,17 +1573,14 @@ void DrawSettingsWindow()
TinyString section;
TinyString key;
std::array<TinyString, NUM_CONTROLLER_AND_CARD_PORTS> 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),