Merge pull request #1720 from ggrtk/multitap
Multitap: Add option to enable only on port 2
This commit is contained in:
commit
3f698d6ed9
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@ enum class MultitapMode
|
|||
{
|
||||
Disabled,
|
||||
Port1Only,
|
||||
Port2Only,
|
||||
BothPorts,
|
||||
Count
|
||||
};
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue