Skip to content

Commit

Permalink
input: use keyboard consumers to seperate cell and overlay logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Megamouse committed Apr 26, 2024
1 parent 6fc7fa3 commit fcba193
Show file tree
Hide file tree
Showing 8 changed files with 268 additions and 106 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ yaml-cpp.pc
# miniupnp
/3rdparty/miniupnp/x64/*

# opencv
/3rdparty/opencv/*

# llvm
/3rdparty/llvm/llvm_build

Expand Down
90 changes: 59 additions & 31 deletions rpcs3/Emu/Cell/Modules/cellKb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,37 @@ KeyboardHandlerBase::KeyboardHandlerBase(utils::serial* ar)
return;
}

(*ar)(m_info.max_connect);
u32 max_connect = 0;

if (m_info.max_connect)
(*ar)(max_connect);

if (max_connect)
{
Emu.PostponeInitCode([this]()
Emu.PostponeInitCode([this, max_connect]()
{
Init(m_info.max_connect);
std::lock_guard<std::mutex> lock(m_mutex);
AddConsumer(keyboard_consumer::identifier::cellKb, max_connect);
auto lk = init.init();
});
}
}

void KeyboardHandlerBase::save(utils::serial& ar)
{
u32 max_connect = 0;
const auto inited = init.access();

ar(inited ? m_info.max_connect : 0);
if (inited)
{
std::lock_guard<std::mutex> lock(m_mutex);

if (auto it = m_consumers.find(keyboard_consumer::identifier::cellKb); it != m_consumers.end())
{
max_connect = it->second.GetInfo().max_connect;
}
}

ar(max_connect);
}

error_code cellKbInit(ppu_thread& ppu, u32 max_connect)
Expand All @@ -79,7 +93,9 @@ error_code cellKbInit(ppu_thread& ppu, u32 max_connect)
}

sys_config_start(ppu);
handler.Init(std::min(max_connect, 7u));

std::lock_guard<std::mutex> lock(handler.m_mutex);
handler.AddConsumer(keyboard_consumer::identifier::cellKb, std::min(max_connect, 7u));

return CELL_OK;
}
Expand All @@ -95,6 +111,11 @@ error_code cellKbEnd(ppu_thread& ppu)
if (!init)
return CELL_KB_ERROR_UNINITIALIZED;

{
std::lock_guard<std::mutex> lock(handler.m_mutex);
handler.RemoveConsumer(keyboard_consumer::identifier::cellKb);
}

// TODO
sys_config_stop(ppu);
return CELL_OK;
Expand All @@ -116,12 +137,13 @@ error_code cellKbClearBuf(u32 port_no)

std::lock_guard<std::mutex> lock(handler.m_mutex);

const KbInfo& current_info = handler.GetInfo();
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);
const KbInfo& current_info = consumer.GetInfo();

if (port_no >= handler.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
if (port_no >= consumer.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
return not_an_error(CELL_KB_ERROR_NO_DEVICE);

KbData& current_data = handler.GetData(port_no);
KbData& current_data = consumer.GetData(port_no);
current_data.len = 0;
current_data.led = 0;
current_data.mkey = 0;
Expand Down Expand Up @@ -298,8 +320,9 @@ error_code cellKbGetInfo(vm::ptr<CellKbInfo> info)
std::memset(info.get_ptr(), 0, info.size());

std::lock_guard<std::mutex> lock(handler.m_mutex);
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);

const KbInfo& current_info = handler.GetInfo();
const KbInfo& current_info = consumer.GetInfo();
info->max_connect = current_info.max_connect;
info->now_connect = current_info.now_connect;
info->info = current_info.info;
Expand Down Expand Up @@ -327,13 +350,13 @@ error_code cellKbRead(u32 port_no, vm::ptr<CellKbData> data)
return CELL_KB_ERROR_INVALID_PARAMETER;

std::lock_guard<std::mutex> lock(handler.m_mutex);
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);
const KbInfo& current_info = consumer.GetInfo();

const KbInfo& current_info = handler.GetInfo();

if (port_no >= handler.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
if (port_no >= consumer.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
return not_an_error(CELL_KB_ERROR_NO_DEVICE);

KbData& current_data = handler.GetData(port_no);
KbData& current_data = consumer.GetData(port_no);

if (current_info.is_null_handler || (current_info.info & CELL_KB_INFO_INTERCEPTED) || !is_input_allowed())
{
Expand All @@ -355,7 +378,7 @@ error_code cellKbRead(u32 port_no, vm::ptr<CellKbData> data)
data->keycode[i] = current_data.buttons[i].m_keyCode;
}

KbConfig& current_config = handler.GetConfig(port_no);
KbConfig& current_config = consumer.GetConfig(port_no);

// For single character mode to work properly we need to "flush" the buffer after reading or else we'll constantly get the same key presses with each call.
// Actual key repeats are handled by adding a new key code to the buffer periodically. Key releases are handled in a similar fashion.
Expand Down Expand Up @@ -383,12 +406,13 @@ error_code cellKbSetCodeType(u32 port_no, u32 type)
if (port_no >= CELL_KB_MAX_KEYBOARDS || type > CELL_KB_CODETYPE_ASCII)
return CELL_KB_ERROR_INVALID_PARAMETER;

if (port_no >= handler.GetKeyboards().size())
return CELL_OK;

std::lock_guard<std::mutex> lock(handler.m_mutex);
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);

if (port_no >= consumer.GetKeyboards().size())
return CELL_OK;

KbConfig& current_config = handler.GetConfig(port_no);
KbConfig& current_config = consumer.GetConfig(port_no);
current_config.code_type = type;

// can also return CELL_KB_ERROR_SYS_SETTING_FAILED
Expand All @@ -413,12 +437,13 @@ error_code cellKbSetLEDStatus(u32 port_no, u8 led)
if (led > 7)
return CELL_KB_ERROR_SYS_SETTING_FAILED;

if (port_no >= handler.GetKeyboards().size() || handler.GetInfo().status[port_no] != CELL_KB_STATUS_CONNECTED)
return CELL_KB_ERROR_FATAL;

std::lock_guard<std::mutex> lock(handler.m_mutex);
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);

KbData& current_data = handler.GetData(port_no);
if (port_no >= consumer.GetKeyboards().size() || consumer.GetInfo().status[port_no] != CELL_KB_STATUS_CONNECTED)
return CELL_KB_ERROR_FATAL;

KbData& current_data = consumer.GetData(port_no);
current_data.led = static_cast<u32>(led);

return CELL_OK;
Expand All @@ -438,16 +463,17 @@ error_code cellKbSetReadMode(u32 port_no, u32 rmode)
if (port_no >= CELL_KB_MAX_KEYBOARDS || rmode > CELL_KB_RMODE_PACKET)
return CELL_KB_ERROR_INVALID_PARAMETER;

if (port_no >= handler.GetKeyboards().size())
return CELL_OK;

std::lock_guard<std::mutex> lock(handler.m_mutex);
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);

KbConfig& current_config = handler.GetConfig(port_no);
if (port_no >= consumer.GetKeyboards().size())
return CELL_OK;

KbConfig& current_config = consumer.GetConfig(port_no);
current_config.read_mode = rmode;

// Key repeat must be disabled in packet mode. But let's just always enable it otherwise.
Keyboard& keyboard = handler.GetKeyboards()[port_no];
Keyboard& keyboard = consumer.GetKeyboards()[port_no];
keyboard.m_key_repeat = rmode != CELL_KB_RMODE_PACKET;

// can also return CELL_KB_ERROR_SYS_SETTING_FAILED
Expand All @@ -471,16 +497,18 @@ error_code cellKbGetConfiguration(u32 port_no, vm::ptr<CellKbConfig> config)

std::lock_guard<std::mutex> lock(handler.m_mutex);

const KbInfo& current_info = handler.GetInfo();
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);

const KbInfo& current_info = consumer.GetInfo();

if (port_no >= handler.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
if (port_no >= consumer.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
return not_an_error(CELL_KB_ERROR_NO_DEVICE);

// tests show that config is checked only after the device's status
if (!config)
return CELL_KB_ERROR_INVALID_PARAMETER;

const KbConfig& current_config = handler.GetConfig(port_no);
const KbConfig& current_config = consumer.GetConfig(port_no);
config->arrange = current_config.arrange;
config->read_mode = current_config.read_mode;
config->code_type = current_config.code_type;
Expand Down
101 changes: 97 additions & 4 deletions rpcs3/Emu/Io/KeyboardHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include "KeyboardHandler.h"
#include "Utilities/StrUtil.h"

LOG_CHANNEL(input_log, "Input");

template <>
void fmt_class_string<CellKbMappingType>::format(std::string& out, u64 arg)
{
Expand Down Expand Up @@ -40,12 +42,85 @@ void fmt_class_string<CellKbMappingType>::format(std::string& out, u64 arg)
});
}

void KeyboardHandlerBase::Key(u32 code, bool pressed, const std::u32string& key)
template <>
void fmt_class_string<keyboard_consumer::identifier>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](keyboard_consumer::identifier value)
{
switch (value)
{
STR_CASE(keyboard_consumer::identifier::unknown);
STR_CASE(keyboard_consumer::identifier::overlays);
STR_CASE(keyboard_consumer::identifier::cellKb);
}

return unknown;
});
}

keyboard_consumer& KeyboardHandlerBase::AddConsumer(keyboard_consumer::identifier id, u32 max_connect)
{
auto it = m_consumers.find(id);
if (it == m_consumers.end())
{
input_log.notice("Adding keyboard consumer with id %s.", id);
keyboard_consumer& consumer = m_consumers[id];
consumer = keyboard_consumer(id);
Init(consumer, max_connect);
return consumer;
}

return it->second;
}

keyboard_consumer& KeyboardHandlerBase::GetConsumer(keyboard_consumer::identifier id)
{
auto it = m_consumers.find(id);
if (it == m_consumers.end())
{
fmt::throw_exception("No keyboard consumer with id %s", id);
}

return it->second;
}

void KeyboardHandlerBase::RemoveConsumer(keyboard_consumer::identifier id)
{
auto it = m_consumers.find(id);
if (it != m_consumers.end())
{
input_log.notice("Removing keyboard consumer with id %s.", id);
m_consumers.erase(id);
}
}

bool KeyboardHandlerBase::HandleKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key)
{
bool consumed = false;

std::lock_guard<std::mutex> lock(m_mutex);

for (auto& [id, consumer] : m_consumers)
{
consumed |= consumer.ConsumeKey(code, pressed, is_auto_repeat, key);
}

return consumed;
}

bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key)
{
bool consumed = false;

for (Keyboard& keyboard : m_keyboards)
{
if (is_auto_repeat && !keyboard.m_key_repeat)
{
continue;
}

consumed = true;

KbData& data = keyboard.m_data;
const KbConfig& config = keyboard.m_config;

Expand Down Expand Up @@ -163,9 +238,11 @@ void KeyboardHandlerBase::Key(u32 code, bool pressed, const std::u32string& key)
}
}
}

return consumed;
}

bool KeyboardHandlerBase::IsMetaKey(u32 code)
bool keyboard_consumer::IsMetaKey(u32 code)
{
return code == Key_Control
|| code == Key_Shift
Expand All @@ -178,6 +255,14 @@ void KeyboardHandlerBase::SetIntercepted(bool intercepted)
{
std::lock_guard<std::mutex> lock(m_mutex);

for (auto& [id, consumer] : m_consumers)
{
consumer.SetIntercepted(intercepted);
}
}

void keyboard_consumer::SetIntercepted(bool intercepted)
{
m_info.info = intercepted ? CELL_KB_INFO_INTERCEPTED : 0;

if (intercepted)
Expand All @@ -196,17 +281,25 @@ void KeyboardHandlerBase::SetIntercepted(bool intercepted)
}

void KeyboardHandlerBase::ReleaseAllKeys()
{
for (auto& [id, consumer] : m_consumers)
{
consumer.ReleaseAllKeys();
}
}

void keyboard_consumer::ReleaseAllKeys()
{
for (Keyboard& keyboard : m_keyboards)
{
for (const auto& [key_code, button] : keyboard.m_keys)
{
Key(button.m_keyCode, false, {});
ConsumeKey(button.m_keyCode, false, false, {});
}

for (const std::u32string& key : keyboard.m_extra_data.pressed_keys)
{
Key(CELL_KEYC_NO_EVENT, false, key);
ConsumeKey(CELL_KEYC_NO_EVENT, false, false, key);
}

keyboard.m_extra_data.pressed_keys.clear();
Expand Down
Loading

0 comments on commit fcba193

Please sign in to comment.