1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

input: add buzz config file

Adds a buzz.yml and implements a generic way to save actual DS3 mapping independent of pad handlers
This commit is contained in:
Megamouse 2023-05-20 12:31:33 +02:00
parent cbe1628cf2
commit 7b9a36be7d
12 changed files with 316 additions and 59 deletions

View File

@ -506,7 +506,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
// Prepare callback variables
vm::var<CellOskDialogKeyMessage> keyMessage(key_message);
vm::var<u32> action(CELL_OSKDIALOG_CHANGE_NO_EVENT);
vm::var<u16[], vm::page_allocator<>> pActionInfo(string_to_send.size(), string_to_send.data());
vm::var<u16[], vm::page_allocator<>> pActionInfo(::narrow<u32>(string_to_send.size()), string_to_send.data());
// Create helpers for logging
std::u16string utf16_string(reinterpret_cast<const char16_t*>(string_to_send.data()), string_to_send.size());

View File

@ -35,7 +35,7 @@ error_code sys_hid_manager_open(u64 device_type, u64 port_no, vm::ptr<u32> handl
if (device_type == 1)
{
cellPadInit(7);
cellPadSetPortSetting(port_no /* 0 */, CELL_PAD_SETTING_LDD | CELL_PAD_SETTING_PRESS_ON | CELL_PAD_SETTING_SENSOR_ON);
cellPadSetPortSetting(::narrow<u32>(port_no) /* 0 */, CELL_PAD_SETTING_LDD | CELL_PAD_SETTING_PRESS_ON | CELL_PAD_SETTING_SENSOR_ON);
}
return CELL_OK;

View File

@ -5,7 +5,7 @@
#include "Emu/Cell/lv2/sys_usbd.h"
#include "Input/pad_thread.h"
LOG_CHANNEL(buzz_log);
LOG_CHANNEL(buzz_log, "BUZZ");
usb_device_buzz::usb_device_buzz(u32 first_controller, u32 last_controller, const std::array<u8, 7>& location)
: usb_device_emulated(location)
@ -17,6 +17,11 @@ usb_device_buzz::usb_device_buzz(u32 first_controller, u32 last_controller, cons
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_INTERFACE, UsbDeviceInterface{0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00}));
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_HID, UsbDeviceHID{0x0111, 0x33, 0x01, 0x22, 0x004e}));
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_ENDPOINT, UsbDeviceEndpoint{0x81, 0x03, 0x0008, 0x0A}));
if (!m_cfg.load())
{
buzz_log.notice("Could not load buzz config. Using defaults.");
}
}
usb_device_buzz::~usb_device_buzz()
@ -72,10 +77,12 @@ void usb_device_buzz::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint*/
const auto handler = pad::get_current_handler();
const auto& pads = handler->GetPads();
ensure(pads.size() > m_last_controller);
ensure(m_cfg.players.size() > m_last_controller);
for (u32 i = m_first_controller, index = 0; i <= m_last_controller; i++, index++)
{
const auto& pad = pads[i];
const cfg_buzzer* cfg = m_cfg.players[i];
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
{
@ -89,26 +96,24 @@ void usb_device_buzz::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint*/
continue;
}
if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2)
if (const auto btn = cfg->find_button(button.m_offset, button.m_outKeyCode))
{
switch (button.m_outKeyCode)
switch (btn.value())
{
case CELL_PAD_CTRL_R1:
case buzz_btn::red:
buf[2 + (0 + 5 * index) / 8] |= 1 << ((0 + 5 * index) % 8); // Red
break;
case CELL_PAD_CTRL_TRIANGLE:
buf[2 + (4 + 5 * index) / 8] |= 1 << ((4 + 5 * index) % 8); // Blue
break;
case CELL_PAD_CTRL_SQUARE:
buf[2 + (3 + 5 * index) / 8] |= 1 << ((3 + 5 * index) % 8); // Orange
break;
case CELL_PAD_CTRL_CIRCLE:
buf[2 + (2 + 5 * index) / 8] |= 1 << ((2 + 5 * index) % 8); // Green
break;
case CELL_PAD_CTRL_CROSS:
case buzz_btn::yellow:
buf[2 + (1 + 5 * index) / 8] |= 1 << ((1 + 5 * index) % 8); // Yellow
break;
default:
case buzz_btn::green:
buf[2 + (2 + 5 * index) / 8] |= 1 << ((2 + 5 * index) % 8); // Green
break;
case buzz_btn::orange:
buf[2 + (3 + 5 * index) / 8] |= 1 << ((3 + 5 * index) % 8); // Orange
break;
case buzz_btn::blue:
buf[2 + (4 + 5 * index) / 8] |= 1 << ((4 + 5 * index) % 8); // Blue
break;
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "Emu/Io/usb_device.h"
#include "Emu/Io/buzz_config.h"
class usb_device_buzz : public usb_device_emulated
{
@ -14,4 +15,5 @@ public:
private:
u32 m_first_controller;
u32 m_last_controller;
cfg_buzz m_cfg;
};

View File

@ -0,0 +1,78 @@
#include "stdafx.h"
#include "buzz_config.h"
LOG_CHANNEL(buzz_log, "BUZZ");
std::optional<buzz_btn> cfg_buzzer::find_button(u32 offset, u32 keycode) const
{
if (const auto it = buttons.find(offset); it != buttons.cend())
{
if (const auto it2 = it->second.find(keycode); it2 != it->second.cend())
{
return it2->second;
}
}
return std::nullopt;
}
bool cfg_buzz::load()
{
bool result = false;
const std::string cfg_name = fs::get_config_dir() + "config/buzz.yml";
buzz_log.notice("Loading buzz config: %s", cfg_name);
from_default();
for (cfg_buzzer* player : players)
{
player->buttons.clear();
}
if (fs::file cfg_file{ cfg_name, fs::read })
{
if (std::string content = cfg_file.to_string(); !content.empty())
{
result = from_string(content);
}
}
else
{
save();
}
for (cfg_buzzer* player : players)
{
const auto set_button = [&player](pad_button pbtn, buzz_btn bbtn)
{
const u32 offset = pad_button_offset(pbtn);
const u32 keycode = pad_button_keycode(pbtn);
player->buttons[(offset >> 8) & 0xFF][keycode & 0xFF] = bbtn;
};
set_button(player->red, buzz_btn::red);
set_button(player->yellow, buzz_btn::yellow);
set_button(player->green, buzz_btn::green);
set_button(player->orange, buzz_btn::orange);
set_button(player->blue, buzz_btn::blue);
}
return result;
}
void cfg_buzz::save() const
{
const std::string cfg_name = fs::get_config_dir() + "config/buzz.yml";
buzz_log.notice("Saving buzz config to '%s'", cfg_name);
if (!fs::create_path(fs::get_parent_dir(cfg_name)))
{
buzz_log.fatal("Failed to create path: %s (%s)", cfg_name, fs::g_tls_error);
}
fs::pending_file cfg_file(cfg_name);
if (!cfg_file.file || (cfg_file.file.write(to_string()), !cfg_file.commit()))
{
buzz_log.error("Failed to save buzz config to '%s' (error=%s)", cfg_name, fs::g_tls_error);
}
}

View File

@ -0,0 +1,45 @@
#pragma once
#include "Utilities/Config.h"
#include "pad_types.h"
#include <array>
enum class buzz_btn
{
red,
yellow,
green,
orange,
blue
};
struct cfg_buzzer final : cfg::node
{
cfg_buzzer(node* owner, const std::string& name) : cfg::node(owner, name) {}
cfg::_enum<pad_button> red{ this, "Red", pad_button::R1 };
cfg::_enum<pad_button> yellow{ this, "Yellow", pad_button::cross };
cfg::_enum<pad_button> green{ this, "Green", pad_button::circle };
cfg::_enum<pad_button> orange{ this, "Orange", pad_button::square };
cfg::_enum<pad_button> blue{ this, "Blue", pad_button::triangle };
std::map<u32, std::map<u32, buzz_btn>> buttons;
std::optional<buzz_btn> find_button(u32 offset, u32 keycode) const;
};
struct cfg_buzz final : cfg::node
{
cfg_buzzer player1{ this, "Player 1" };
cfg_buzzer player2{ this, "Player 2" };
cfg_buzzer player3{ this, "Player 3" };
cfg_buzzer player4{ this, "Player 4" };
cfg_buzzer player5{ this, "Player 5" };
cfg_buzzer player6{ this, "Player 6" };
cfg_buzzer player7{ this, "Player 7" };
std::array<cfg_buzzer*, 7> players{ &player1, &player2, &player3, &player4, &player5, &player6, &player7 }; // Thanks gcc!
bool load();
void save() const;
};

109
rpcs3/Emu/Io/pad_types.cpp Normal file
View File

@ -0,0 +1,109 @@
#include "stdafx.h"
#include "pad_types.h"
template <>
void fmt_class_string<pad_button>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](pad_button value)
{
switch (value)
{
case pad_button::dpad_up: return "D-Pad Up";
case pad_button::dpad_down: return "D-Pad Down";
case pad_button::dpad_left: return "D-Pad Left";
case pad_button::dpad_right: return "D-Pad Right";
case pad_button::select: return "Select";
case pad_button::start: return "Start";
case pad_button::ps: return "PS";
case pad_button::triangle: return "Triangle";
case pad_button::circle: return "Circle";
case pad_button::square: return "Square";
case pad_button::cross: return "Cross";
case pad_button::L1: return "L1";
case pad_button::R1: return "R1";
case pad_button::L2: return "L2";
case pad_button::R2: return "R2";
case pad_button::L3: return "L3";
case pad_button::R3: return "R3";
case pad_button::ls_up: return "Left Stick Up";
case pad_button::ls_down: return "Left Stick Down";
case pad_button::ls_left: return "Left Stick Left";
case pad_button::ls_right: return "Left Stick Right";
case pad_button::rs_up: return "Right Stick Up";
case pad_button::rs_down: return "Right Stick Down";
case pad_button::rs_left: return "Right Stick Left";
case pad_button::rs_right: return "Right Stick Right";
case pad_button::pad_button_max_enum: return unknown;
}
return unknown;
});
}
u32 pad_button_offset(pad_button button)
{
switch (button)
{
case pad_button::dpad_up: return CELL_PAD_BTN_OFFSET_DIGITAL1;
case pad_button::dpad_down: return CELL_PAD_BTN_OFFSET_DIGITAL1;
case pad_button::dpad_left: return CELL_PAD_BTN_OFFSET_DIGITAL1;
case pad_button::dpad_right: return CELL_PAD_BTN_OFFSET_DIGITAL1;
case pad_button::select: return CELL_PAD_BTN_OFFSET_DIGITAL1;
case pad_button::start: return CELL_PAD_BTN_OFFSET_DIGITAL1;
case pad_button::ps: return CELL_PAD_BTN_OFFSET_DIGITAL1;
case pad_button::triangle: return CELL_PAD_BTN_OFFSET_DIGITAL2;
case pad_button::circle: return CELL_PAD_BTN_OFFSET_DIGITAL2;
case pad_button::square: return CELL_PAD_BTN_OFFSET_DIGITAL2;
case pad_button::cross: return CELL_PAD_BTN_OFFSET_DIGITAL2;
case pad_button::L1: return CELL_PAD_BTN_OFFSET_DIGITAL2;
case pad_button::R1: return CELL_PAD_BTN_OFFSET_DIGITAL2;
case pad_button::L2: return CELL_PAD_BTN_OFFSET_DIGITAL2;
case pad_button::R2: return CELL_PAD_BTN_OFFSET_DIGITAL2;
case pad_button::L3: return CELL_PAD_BTN_OFFSET_DIGITAL1;
case pad_button::R3: return CELL_PAD_BTN_OFFSET_DIGITAL1;
case pad_button::ls_up: return CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y;
case pad_button::ls_down: return CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y;
case pad_button::ls_left: return CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X;
case pad_button::ls_right: return CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X;
case pad_button::rs_up: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y;
case pad_button::rs_down: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y;
case pad_button::rs_left: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X;
case pad_button::rs_right: return CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X;
case pad_button::pad_button_max_enum: return 0;
}
return 0;
}
u32 pad_button_keycode(pad_button button)
{
switch (button)
{
case pad_button::dpad_up: return CELL_PAD_CTRL_UP;
case pad_button::dpad_down: return CELL_PAD_CTRL_DOWN;
case pad_button::dpad_left: return CELL_PAD_CTRL_LEFT;
case pad_button::dpad_right: return CELL_PAD_CTRL_RIGHT;
case pad_button::select: return CELL_PAD_CTRL_SELECT;
case pad_button::start: return CELL_PAD_CTRL_START;
case pad_button::ps: return CELL_PAD_CTRL_PS;
case pad_button::triangle: return CELL_PAD_CTRL_TRIANGLE;
case pad_button::circle: return CELL_PAD_CTRL_CIRCLE;
case pad_button::square: return CELL_PAD_CTRL_SQUARE;
case pad_button::cross: return CELL_PAD_CTRL_CROSS;
case pad_button::L1: return CELL_PAD_CTRL_L1;
case pad_button::R1: return CELL_PAD_CTRL_R1;
case pad_button::L2: return CELL_PAD_CTRL_L2;
case pad_button::R2: return CELL_PAD_CTRL_R2;
case pad_button::L3: return CELL_PAD_CTRL_L3;
case pad_button::R3: return CELL_PAD_CTRL_R3;
case pad_button::ls_up: return 0;
case pad_button::ls_down: return 0;
case pad_button::ls_left: return 0;
case pad_button::ls_right: return 0;
case pad_button::rs_up: return 0;
case pad_button::rs_down: return 0;
case pad_button::rs_left: return 0;
case pad_button::rs_right: return 0;
case pad_button::pad_button_max_enum: return 0;
}
return 0;
}

View File

@ -6,6 +6,41 @@
#include <vector>
enum class pad_button : u8
{
dpad_up = 0,
dpad_down,
dpad_left,
dpad_right,
select,
start,
ps,
triangle,
circle,
square,
cross,
L1,
R1,
L2,
R2,
L3,
R3,
ls_up,
ls_down,
ls_left,
ls_right,
rs_up,
rs_down,
rs_left,
rs_right,
pad_button_max_enum
};
u32 pad_button_offset(pad_button button);
u32 pad_button_keycode(pad_button button);
enum SystemInfo
{
CELL_PAD_INFO_INTERCEPTED = 0x00000001

View File

@ -59,10 +59,10 @@ namespace rsx
std::array<steady_clock::time_point, CELL_PAD_MAX_PORT_NUM> initial_timestamp;
initial_timestamp.fill(steady_clock::now());
std::array<u8, CELL_PAD_MAX_PORT_NUM> last_auto_repeat_button;
std::array<pad_button, CELL_PAD_MAX_PORT_NUM> last_auto_repeat_button;
last_auto_repeat_button.fill(pad_button::pad_button_max_enum);
std::array<std::array<bool, pad_button::pad_button_max_enum>, CELL_PAD_MAX_PORT_NUM> last_button_state;
std::array<std::array<bool, static_cast<u32>(pad_button::pad_button_max_enum)>, CELL_PAD_MAX_PORT_NUM> last_button_state;
for (auto& state : last_button_state)
{
// Initialize last button states as pressed to avoid unwanted button presses when entering the dialog.
@ -77,18 +77,20 @@ namespace rsx
input::SetIntercepted(true);
}
const auto handle_button_press = [&](u8 button_id, bool pressed, int pad_index)
const auto handle_button_press = [&](pad_button button_id, bool pressed, int pad_index)
{
if (button_id >= pad_button::pad_button_max_enum)
{
return;
}
bool& last_state = last_button_state[pad_index][static_cast<u32>(button_id)];
if (pressed)
{
const bool is_auto_repeat_button = m_auto_repeat_buttons.contains(button_id);
if (!last_button_state[pad_index][button_id])
if (!last_state)
{
// The button was not pressed before, so this is a new button press. Reset auto-repeat.
timestamp[pad_index] = steady_clock::now();
@ -113,13 +115,13 @@ namespace rsx
}
}
}
else if (last_button_state[pad_index][button_id] && last_auto_repeat_button[pad_index] == button_id)
else if (last_state && last_auto_repeat_button[pad_index] == button_id)
{
// We stopped pressing an auto-repeat button, so re-enable auto-repeat for other buttons.
last_auto_repeat_button[pad_index] = pad_button::pad_button_max_enum;
}
last_button_state[pad_index][button_id] = pressed;
last_state = pressed;
};
while (!m_stop_input_loop)
@ -239,7 +241,7 @@ namespace rsx
for (const Button& button : pad->m_buttons)
{
u8 button_id = pad_button::pad_button_max_enum;
pad_button button_id = pad_button::pad_button_max_enum;
if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1)
{
switch (button.m_outKeyCode)
@ -316,8 +318,8 @@ namespace rsx
for (const AnalogStick& stick : pad->m_sticks)
{
u8 button_id = pad_button::pad_button_max_enum;
u8 release_id = pad_button::pad_button_max_enum;
pad_button button_id = pad_button::pad_button_max_enum;
pad_button release_id = pad_button::pad_button_max_enum;
// Let's say sticks are only pressed if they are almost completely tilted. Otherwise navigation feels really wacky.
const bool pressed = stick.m_value < 30 || stick.m_value > 225;

View File

@ -3,6 +3,7 @@
#include "overlay_controls.h"
#include "Emu/IdManager.h"
#include "Emu/Io/pad_types.h"
#include "Utilities/mutex.h"
#include "Utilities/Timer.h"
@ -18,38 +19,6 @@ namespace rsx
{
namespace overlays
{
enum pad_button : u8
{
dpad_up = 0,
dpad_down,
dpad_left,
dpad_right,
select,
start,
ps,
triangle,
circle,
square,
cross,
L1,
R1,
L2,
R2,
L3,
R3,
ls_up,
ls_down,
ls_left,
ls_right,
rs_up,
rs_down,
rs_left,
rs_right,
pad_button_max_enum
};
// Bitfield of UI signals to overlay manager
enum status_bits : u32
{
@ -96,7 +65,7 @@ namespace rsx
protected:
Timer m_input_timer;
u64 m_auto_repeat_ms_interval = m_auto_repeat_ms_interval_default;
std::set<u8> m_auto_repeat_buttons = {
std::set<pad_button> m_auto_repeat_buttons = {
pad_button::dpad_up,
pad_button::dpad_down,
pad_button::dpad_left,

View File

@ -68,8 +68,10 @@
<ClCompile Include="Emu\Cell\Modules\sys_crashdump.cpp" />
<ClCompile Include="Emu\Cell\Modules\HLE_PATCHES.cpp" />
<ClCompile Include="Emu\games_config.cpp" />
<ClCompile Include="Emu\Io\buzz_config.cpp" />
<ClCompile Include="Emu\Io\camera_config.cpp" />
<ClCompile Include="Emu\Io\midi_config_types.cpp" />
<ClCompile Include="Emu\Io\pad_types.cpp" />
<ClCompile Include="Emu\Io\RB3MidiGuitar.cpp" />
<ClCompile Include="Emu\Io\RB3MidiKeyboard.cpp" />
<ClCompile Include="Emu\Io\recording_config.cpp" />
@ -504,6 +506,7 @@
<ClInclude Include="Emu\config_mode.h" />
<ClInclude Include="Emu\CPU\sse2neon.h" />
<ClInclude Include="Emu\games_config.h" />
<ClInclude Include="Emu\Io\buzz_config.h" />
<ClInclude Include="Emu\Io\camera_config.h" />
<ClInclude Include="Emu\Io\camera_handler_base.h" />
<ClInclude Include="Emu\Io\midi_config_types.h" />

View File

@ -1162,6 +1162,12 @@
<ClCompile Include="Emu\Io\midi_config_types.cpp">
<Filter>Emu\Io</Filter>
</ClCompile>
<ClCompile Include="Emu\Io\buzz_config.cpp">
<Filter>Emu\Io</Filter>
</ClCompile>
<ClCompile Include="Emu\Io\pad_types.cpp">
<Filter>Emu\Io</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Crypto\aes.h">
@ -2344,6 +2350,9 @@
<ClInclude Include="Emu\Io\midi_config_types.h">
<Filter>Emu\Io</Filter>
</ClInclude>
<ClInclude Include="Emu\Io\buzz_config.h">
<Filter>Emu\Io</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">