Added three new mappable buttons for when using Triforce games

Changed the window title text for the gamecube controller interface when the Triforce Baseboard is connected
Added new buttons: test, service and coin to the Triforce Baseboard UI
Changed code to use new buttons
This commit is contained in:
crediar 2025-07-29 15:39:16 +02:00
commit f2932352e5
8 changed files with 72 additions and 17 deletions

View file

@ -17,7 +17,8 @@ class Buttons;
enum class GBAPadGroup
{
DPad,
Buttons
Buttons,
Triforce
};
class GBAPad : public ControllerEmu::EmulatedController

View file

@ -34,6 +34,7 @@ static const u16 trigger_bitmasks[] = {
static const u16 dpad_bitmasks[] = {PAD_BUTTON_UP, PAD_BUTTON_DOWN, PAD_BUTTON_LEFT,
PAD_BUTTON_RIGHT};
static const u8 triforce_bitmask[] = { PAD_SWITCH_TEST, PAD_SWITCH_SERVICE, PAD_SWITCH_COIN };
GCPad::GCPad(const unsigned int index) : m_index(index)
{
@ -68,6 +69,13 @@ GCPad::GCPad(const unsigned int index) : m_index(index)
m_dpad->AddInput(Translatability::Translate, named_direction);
}
// triforce
groups.emplace_back(m_triforce = new ControllerEmu::Buttons(TRIFORCE_GROUP));
for (const char* named_button : { TEST_BUTTON, SERVICE_BUTTON, COIN_BUTTON })
{
m_triforce->AddInput(Translatability::DoNotTranslate, named_button);
}
// Microphone
groups.emplace_back(m_mic = new ControllerEmu::Buttons(MIC_GROUP));
m_mic->AddInput(Translatability::Translate, _trans("Button"));
@ -119,6 +127,8 @@ ControllerEmu::ControlGroup* GCPad::GetGroup(PadGroup group)
return m_mic;
case PadGroup::Options:
return m_options;
case PadGroup::Triforce:
return m_triforce;
default:
return nullptr;
}
@ -150,6 +160,9 @@ GCPadStatus GCPad::GetInput() const
// dpad
m_dpad->GetState(&pad.button, dpad_bitmasks, m_input_override_function);
// triforce
m_triforce->GetState(&pad.switches, triforce_bitmask, m_input_override_function);
// sticks
const auto main_stick_state = m_main_stick->GetState(m_input_override_function);
pad.stickX = MapFloat<u8>(main_stick_state.x, GCPadStatus::MAIN_STICK_CENTER_X, 1);
@ -202,6 +215,11 @@ void GCPad::LoadDefaults(const ControllerInterface& ciface)
m_dpad->SetControlExpression(2, "`F`"); // Left
m_dpad->SetControlExpression(3, "`H`"); // Right
// Triforce
m_dpad->SetControlExpression(0, "`1`"); // Test
m_dpad->SetControlExpression(1, "`2`"); // Service
m_dpad->SetControlExpression(2, "`3`"); // Coin
// C Stick
m_c_stick->SetControlExpression(0, "`I`"); // Up
m_c_stick->SetControlExpression(1, "`K`"); // Down

View file

@ -29,7 +29,8 @@ enum class PadGroup
Triggers,
Rumble,
Mic,
Options
Options,
Triforce
};
class GCPad : public ControllerEmu::EmulatedController
@ -61,6 +62,7 @@ public:
static constexpr const char* RUMBLE_GROUP = _trans("Rumble");
static constexpr const char* MIC_GROUP = _trans("Microphone");
static constexpr const char* OPTIONS_GROUP = _trans("Options");
static constexpr const char* TRIFORCE_GROUP = _trans("Triforce");
static constexpr const char* A_BUTTON = "A";
static constexpr const char* B_BUTTON = "B";
@ -69,6 +71,11 @@ public:
static constexpr const char* Z_BUTTON = "Z";
static constexpr const char* START_BUTTON = "Start";
// Special Triforce buttons
static constexpr const char* TEST_BUTTON = "Test";
static constexpr const char* SERVICE_BUTTON = "Service";
static constexpr const char* COIN_BUTTON = "Coin";
// i18n: The left trigger button (labeled L on real controllers)
static constexpr const char* L_DIGITAL = _trans("L");
// i18n: The right trigger button (labeled R on real controllers)
@ -87,6 +94,7 @@ private:
ControllerEmu::ControlGroup* m_rumble;
ControllerEmu::Buttons* m_mic;
ControllerEmu::ControlGroup* m_options;
ControllerEmu::Buttons* m_triforce;
ControllerEmu::SettingValue<bool> m_always_connected_setting;

View file

@ -1546,7 +1546,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length)
PadStatus = Pad::GetStatus(0);
// Test button
if (PadStatus.button & PAD_TRIGGER_Z)
if (PadStatus.switches&PAD_SWITCH_TEST)
{
// Trying to access the test menu without SegaBoot present will cause a crash
if (AMMediaboard::GetTestMenu())
@ -1581,7 +1581,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length)
if (PadStatus.button & PAD_BUTTON_START)
player_data[0] |= 0x80;
// Service button
if (PadStatus.button & PAD_BUTTON_X)
if (PadStatus.switches&PAD_SWITCH_SERVICE)
player_data[0] |= 0x40;
// Boost
if (PadStatus.button & PAD_BUTTON_Y)
@ -1639,7 +1639,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length)
if (PadStatus.button & PAD_BUTTON_START)
player_data[0] |= 0x80;
// Service button
if (PadStatus.button & PAD_BUTTON_X)
if (PadStatus.switches&PAD_SWITCH_SERVICE)
player_data[0] |= 0x40;
// Boost
if (PadStatus.button & PAD_BUTTON_Y)
@ -1689,7 +1689,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length)
if (PadStatus.button & PAD_BUTTON_START)
player_data[0] |= 0x80;
// Service button
if (PadStatus.button & PAD_BUTTON_X)
if (PadStatus.switches&PAD_SWITCH_SERVICE)
player_data[0] |= 0x40;
// Long Pass
if (PadStatus.button & PAD_TRIGGER_L)
@ -1721,7 +1721,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length)
if (PadStatus.button & PAD_BUTTON_START)
player_data[0] |= 0x80;
// Service button
if (PadStatus.button & PAD_BUTTON_X)
if (PadStatus.switches&PAD_SWITCH_SERVICE)
player_data[0] |= 0x40;
// Long Pass
if (PadStatus.button & PAD_TRIGGER_L)
@ -1762,7 +1762,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length)
if (PadStatus.button & PAD_BUTTON_START)
player_data[0] |= 0x80;
// Service button
if (PadStatus.button & PAD_BUTTON_X)
if (PadStatus.switches&PAD_SWITCH_SERVICE)
player_data[0] |= 0x40;
// A
if (PadStatus.button & PAD_BUTTON_B)
@ -1813,7 +1813,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length)
if (PadStatus.button & PAD_BUTTON_START)
player_data[0] |= 0x80;
// Service button
if (PadStatus.button & PAD_BUTTON_X)
if (PadStatus.switches&PAD_SWITCH_SERVICE)
player_data[0] |= 0x40;
// Switch 1
if (PadStatus.button & PAD_BUTTON_A)
@ -1843,11 +1843,11 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length)
{
GCPadStatus PadStatus;
PadStatus = Pad::GetStatus(i);
if ((PadStatus.button & PAD_BUTTON_X) && !m_coin_pressed[i])
if ((PadStatus.switches&PAD_SWITCH_COIN) && !m_coin_pressed[i])
{
m_coin[i]++;
}
m_coin_pressed[i] = PadStatus.button & PAD_BUTTON_X;
m_coin_pressed[i] = PadStatus.switches & PAD_SWITCH_COIN;
message.addData((m_coin[i] >> 8) & 0x3f);
message.addData(m_coin[i] & 0xff);
}

View file

@ -8,6 +8,10 @@
#include "Core/HW/GCPad.h"
#include "Core/HW/GCPadEmu.h"
#include "Core/HW/SI/SI.h"
#include "Core/HW/SI/SI_DeviceAMBaseboard.h"
#include "Core/Config/MainSettings.h"
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
#include "InputCommon/InputConfig.h"
@ -23,8 +27,13 @@ void GCPadEmu::CreateMainLayout()
layout->addWidget(CreateGroupBox(tr("Buttons"), Pad::GetGroup(GetPort(), PadGroup::Buttons)), 0,
0);
layout->addWidget(CreateGroupBox(tr("D-Pad"), Pad::GetGroup(GetPort(), PadGroup::DPad)), 1, 0, -1,
1);
layout->addWidget(CreateGroupBox(tr("D-Pad"), Pad::GetGroup(GetPort(), PadGroup::DPad)), 1, 0 );
if (Config::Get(Config::GetInfoForSIDevice(0)) == SerialInterface::SIDevices::SIDEVICE_AM_BASEBOARD)
{
layout->addWidget(CreateGroupBox(tr("Triforce"), Pad::GetGroup(GetPort(), PadGroup::Triforce)), 2, 0);
}
layout->addWidget(
CreateGroupBox(tr("Control Stick"), Pad::GetGroup(GetPort(), PadGroup::MainStick)), 0, 1, -1,
1);

View file

@ -24,6 +24,9 @@
#include "Common/IniFile.h"
#include "Common/StringUtil.h"
#include "Core/HW/SI/SI.h"
#include "Core/HW/SI/SI_DeviceAMBaseboard.h"
#include "DolphinQt/Config/Mapping/FreeLookGeneral.h"
#include "DolphinQt/Config/Mapping/FreeLookRotation.h"
#include "DolphinQt/Config/Mapping/GBAPadEmu.h"
@ -437,8 +440,16 @@ void MappingWindow::SetMappingType(MappingWindow::Type type)
case Type::MAPPING_GC_DANCEMAT:
case Type::MAPPING_GCPAD:
widget = new GCPadEmu(this);
setWindowTitle(tr("GameCube Controller at Port %1").arg(GetPort() + 1));
AddWidget(tr("GameCube Controller"), widget);
if (Config::Get(Config::GetInfoForSIDevice(GetPort())) == SerialInterface::SIDevices::SIDEVICE_AM_BASEBOARD)
{
setWindowTitle(tr("Triforce Baseboard at Port %1").arg(GetPort() + 1));
AddWidget(tr("Triforce Baseboard"), widget);
}
else
{
setWindowTitle(tr("GameCube Controller at Port %1").arg(GetPort() + 1));
AddWidget(tr("GameCube Controller"), widget);
}
break;
case Type::MAPPING_GC_MICROPHONE:
widget = new GCMicrophone(this);

View file

@ -28,6 +28,13 @@ enum PadButton
PAD_BUTTON_START = 0x1000,
};
enum SwitchButton
{
PAD_SWITCH_TEST = 0x0001,
PAD_SWITCH_SERVICE = 0x0002,
PAD_SWITCH_COIN = 0x0004,
};
struct GCPadStatus
{
u16 button = 0; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits
@ -39,6 +46,8 @@ struct GCPadStatus
u8 triggerRight = 0; // 0 <= triggerRight <= 255
u8 analogA = 0; // 0 <= analogA <= 255
u8 analogB = 0; // 0 <= analogB <= 255
//Triforce
u8 switches = 0;
bool isConnected = true;
static const u8 MAIN_STICK_CENTER_X = 0x80;

View file

@ -25,7 +25,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Languages", "..\Languages\L
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LZO", "..\Externals\LZO\LZO.vcxproj", "{AB993F38-C31D-4897-B139-A620C42BC565}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lz4", "..\Externals\LZ4\LZ4.vcxproj", "{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LZ4", "..\Externals\lz4\LZ4.vcxproj", "{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "..\Externals\miniupnpc\miniupnpc.vcxproj", "{31643FDB-1BB8-4965-9DE7-000FC88D35AE}"
EndProject
@ -186,7 +186,6 @@ Global
{31643FDB-1BB8-4965-9DE7-000FC88D35AE}.Debug|ARM64.ActiveCfg = Debug|ARM64
{31643FDB-1BB8-4965-9DE7-000FC88D35AE}.Debug|ARM64.Build.0 = Debug|ARM64
{31643FDB-1BB8-4965-9DE7-000FC88D35AE}.Debug|x64.ActiveCfg = Debug|x64
{31643FDB-1BB8-4965-9DE7-000FC88D35AE}.Debug|x64.Build.0 = Debug|x64
{31643FDB-1BB8-4965-9DE7-000FC88D35AE}.Release|ARM64.ActiveCfg = Release|ARM64
{31643FDB-1BB8-4965-9DE7-000FC88D35AE}.Release|ARM64.Build.0 = Release|ARM64
{31643FDB-1BB8-4965-9DE7-000FC88D35AE}.Release|x64.ActiveCfg = Release|x64