implement CELL_PAD_INFO_INTERCEPTED

This commit is contained in:
Megamouse 2018-12-30 02:34:15 +01:00
parent 8ad14c4ada
commit 6f7b25de90
13 changed files with 250 additions and 153 deletions

View file

@ -87,7 +87,12 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
if (auto manager = fxm::get<rsx::overlays::display_manager>()) if (auto manager = fxm::get<rsx::overlays::display_manager>())
{ {
manager->create<rsx::overlays::message_dialog>()->show(msgString.get_ptr(), _type, [callback, userData](s32 status) if (manager->get<rsx::overlays::message_dialog>())
{
return CELL_SYSUTIL_ERROR_BUSY;
}
const auto res = manager->create<rsx::overlays::message_dialog>()->show(msgString.get_ptr(), _type, [callback, userData](s32 status)
{ {
if (callback) if (callback)
{ {
@ -99,7 +104,7 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
} }
}); });
return CELL_OK; return res;
} }
const auto dlg = fxm::import<MsgDialogBase>(Emu.GetCallbacks().get_msg_dialog); const auto dlg = fxm::import<MsgDialogBase>(Emu.GetCallbacks().get_msg_dialog);
@ -128,8 +133,12 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
fxm::remove<MsgDialogBase>(); fxm::remove<MsgDialogBase>();
} }
pad::SetIntercepted(false);
}; };
pad::SetIntercepted(true);
atomic_t<bool> result(false); atomic_t<bool> result(false);
// Run asynchronously in GUI thread // Run asynchronously in GUI thread

View file

@ -1,6 +1,8 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
#include "pad_thread.h"
#include "cellSysutil.h" #include "cellSysutil.h"
#include "cellOskDialog.h" #include "cellOskDialog.h"
@ -22,14 +24,28 @@ s32 cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dialogPara
for (u32 i = 0; (i < maxLength) && (inputFieldInfo->init_text[i] != 0); i++) for (u32 i = 0; (i < maxLength) && (inputFieldInfo->init_text[i] != 0); i++)
s_osk_text[i] = inputFieldInfo->init_text[i]; s_osk_text[i] = inputFieldInfo->init_text[i];
const auto osk = Emu.GetCallbacks().get_msg_dialog(); const auto osk = fxm::import<MsgDialogBase>(Emu.GetCallbacks().get_msg_dialog);
if (!osk)
{
return CELL_SYSUTIL_ERROR_BUSY;
}
bool result = false; bool result = false;
osk->on_close = [&](s32 status) osk->on_close = [wptr = std::weak_ptr<MsgDialogBase>(osk)](s32 status)
{ {
const auto osk = wptr.lock();
if (osk && osk->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Close))
{
fxm::remove<MsgDialogBase>();
}
if (status != CELL_MSGDIALOG_BUTTON_OK) sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED, 0); if (status != CELL_MSGDIALOG_BUTTON_OK) sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED, 0);
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0); sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0);
result = true;
pad::SetIntercepted(false);
}; };
osk->on_osk_input_entered = [&]() osk->on_osk_input_entered = [&]()
@ -37,9 +53,12 @@ s32 cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dialogPara
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED, 0); sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED, 0);
}; };
pad::SetIntercepted(true);
Emu.CallAfter([&]() Emu.CallAfter([&]()
{ {
osk->CreateOsk("On Screen Keyboard", s_osk_text, maxLength); osk->CreateOsk("On Screen Keyboard", s_osk_text, maxLength);
result = true;
}); });
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_LOADED, 0); sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_LOADED, 0);
@ -78,6 +97,21 @@ s32 cellOskDialogGetSize(vm::ptr<u16> width, vm::ptr<u16> height, vm::ptr<CellOs
s32 cellOskDialogAbort() s32 cellOskDialogAbort()
{ {
cellOskDialog.warning("cellOskDialogAbort()"); cellOskDialog.warning("cellOskDialogAbort()");
const auto dlg = fxm::get<MsgDialogBase>();
if (!dlg)
{
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
}
if (!dlg->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Abort))
{
return CELL_SYSUTIL_ERROR_BUSY;
}
verify(HERE), fxm::remove<MsgDialogBase>();
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0); sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0);
return CELL_OK; return CELL_OK;
} }
@ -220,9 +254,9 @@ s32 cellOskDialogExtSetPointerEnable(b8 enable)
return CELL_OK; return CELL_OK;
} }
s32 cellOskDialogExtUpdatePointerDisplayPos() s32 cellOskDialogExtUpdatePointerDisplayPos(/*const CellOskDialogPoint pos*/)
{ {
cellOskDialog.todo("cellOskDialogExtUpdatePointerDisplayPos"); // Missing arguments cellOskDialog.todo("cellOskDialogExtUpdatePointerDisplayPos(posX=%f, posY=%f)"/*, pos.x, pos.y*/);
return CELL_OK; return CELL_OK;
} }

View file

@ -94,7 +94,7 @@ enum CellOskDialogType
enum enum
{ {
CELL_OSKDIALOG_STRING_SIZE = 512, //Theroretical maxium for osk input, games can specify a lower limit CELL_OSKDIALOG_STRING_SIZE = 512, // Theroretical maximum for osk input, games can specify a lower limit
}; };
struct CellOskDialogInputFieldInfo struct CellOskDialogInputFieldInfo

View file

@ -10,6 +10,11 @@
// TODO: HLE info (constants, structs, etc.) should not be available here // TODO: HLE info (constants, structs, etc.) should not be available here
enum SystemInfo
{
CELL_PAD_INFO_INTERCEPTED = 0x00000001
};
enum PortStatus enum PortStatus
{ {
CELL_PAD_STATUS_DISCONNECTED = 0x00000000, CELL_PAD_STATUS_DISCONNECTED = 0x00000000,

View file

@ -9,6 +9,134 @@ namespace rsx
// Singleton instance declaration // Singleton instance declaration
fontmgr* fontmgr::m_instance = nullptr; fontmgr* fontmgr::m_instance = nullptr;
s32 user_interface::run_input_loop()
{
std::array<std::chrono::steady_clock::time_point, CELL_PAD_MAX_PORT_NUM> timestamp;
timestamp.fill(std::chrono::steady_clock::now());
std::array<std::array<bool, 8>, CELL_PAD_MAX_PORT_NUM> button_state;
for (auto& state : button_state)
{
state.fill(true);
}
input_timer.Start();
{
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_current_handler();
handler->SetIntercepted(true);
}
while (!exit)
{
if (Emu.IsStopped())
return selection_code::canceled;
std::this_thread::sleep_for(1ms);
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_current_handler();
const PadInfo& rinfo = handler->GetInfo();
if (Emu.IsPaused() || !rinfo.now_connect)
{
continue;
}
int pad_index = -1;
for (const auto &pad : handler->GetPads())
{
if (++pad_index >= CELL_PAD_MAX_PORT_NUM)
{
LOG_FATAL(RSX, "The native overlay cannot handle more than 7 pads! Current number of pads: %d", pad_index + 1);
continue;
}
for (auto &button : pad->m_buttons)
{
u8 button_id = 255;
if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1)
{
switch (button.m_outKeyCode)
{
case CELL_PAD_CTRL_LEFT:
button_id = pad_button::dpad_left;
break;
case CELL_PAD_CTRL_RIGHT:
button_id = pad_button::dpad_right;
break;
case CELL_PAD_CTRL_DOWN:
button_id = pad_button::dpad_down;
break;
case CELL_PAD_CTRL_UP:
button_id = pad_button::dpad_up;
break;
}
}
else if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2)
{
switch (button.m_outKeyCode)
{
case CELL_PAD_CTRL_TRIANGLE:
button_id = pad_button::triangle;
break;
case CELL_PAD_CTRL_CIRCLE:
button_id = g_cfg.sys.enter_button_assignment == enter_button_assign::circle ? pad_button::cross : pad_button::circle;
break;
case CELL_PAD_CTRL_SQUARE:
button_id = pad_button::square;
break;
case CELL_PAD_CTRL_CROSS:
button_id = g_cfg.sys.enter_button_assignment == enter_button_assign::circle ? pad_button::circle : pad_button::cross;
break;
}
}
if (button_id < 255)
{
if (button.m_pressed)
{
if (button_id < 4) // d-pad button
{
if (!button_state[pad_index][button_id] || input_timer.GetMsSince(timestamp[pad_index]) > 400)
{
// d-pad button was not pressed, or was pressed more than 400ms ago
timestamp[pad_index] = std::chrono::steady_clock::now();
on_button_pressed(static_cast<pad_button>(button_id));
}
}
else if (!button_state[pad_index][button_id])
{
// button was not pressed
on_button_pressed(static_cast<pad_button>(button_id));
}
}
button_state[pad_index][button_id] = button.m_pressed;
}
if (button.m_flush)
{
button.m_pressed = false;
button.m_flush = false;
button.m_value = 0;
}
if (exit)
return 0;
}
}
refresh();
}
// Unreachable
return 0;
}
void user_interface::close() void user_interface::close()
{ {
// Force unload // Force unload
@ -24,6 +152,12 @@ namespace rsx
manager->remove(uid); manager->remove(uid);
} }
{
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_current_handler();
handler->SetIntercepted(false);
}
if (on_close) if (on_close)
on_close(return_code); on_close(return_code);
} }

View file

@ -80,127 +80,7 @@ namespace rsx
void close(); void close();
s32 run_input_loop() s32 run_input_loop();
{
std::array<std::chrono::steady_clock::time_point, CELL_PAD_MAX_PORT_NUM> timestamp;
timestamp.fill(std::chrono::steady_clock::now());
std::array<std::array<bool, 8>, CELL_PAD_MAX_PORT_NUM> button_state;
for (auto& state : button_state)
{
state.fill(true);
}
input_timer.Start();
while (!exit)
{
if (Emu.IsStopped())
return selection_code::canceled;
std::this_thread::sleep_for(1ms);
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_current_handler();
const PadInfo& rinfo = handler->GetInfo();
if (Emu.IsPaused() || !rinfo.now_connect)
{
continue;
}
int pad_index = -1;
for (const auto &pad : handler->GetPads())
{
if (++pad_index >= CELL_PAD_MAX_PORT_NUM)
{
LOG_FATAL(RSX, "The native overlay cannot handle more than 7 pads! Current number of pads: %d", pad_index + 1);
continue;
}
for (auto &button : pad->m_buttons)
{
u8 button_id = 255;
if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1)
{
switch (button.m_outKeyCode)
{
case CELL_PAD_CTRL_LEFT:
button_id = pad_button::dpad_left;
break;
case CELL_PAD_CTRL_RIGHT:
button_id = pad_button::dpad_right;
break;
case CELL_PAD_CTRL_DOWN:
button_id = pad_button::dpad_down;
break;
case CELL_PAD_CTRL_UP:
button_id = pad_button::dpad_up;
break;
}
}
else if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2)
{
switch (button.m_outKeyCode)
{
case CELL_PAD_CTRL_TRIANGLE:
button_id = pad_button::triangle;
break;
case CELL_PAD_CTRL_CIRCLE:
button_id = g_cfg.sys.enter_button_assignment == enter_button_assign::circle ? pad_button::cross : pad_button::circle;
break;
case CELL_PAD_CTRL_SQUARE:
button_id = pad_button::square;
break;
case CELL_PAD_CTRL_CROSS:
button_id = g_cfg.sys.enter_button_assignment == enter_button_assign::circle ? pad_button::circle : pad_button::cross;
break;
}
}
if (button_id < 255)
{
if (button.m_pressed)
{
if (button_id < 4) // d-pad button
{
if (!button_state[pad_index][button_id] || input_timer.GetMsSince(timestamp[pad_index]) > 400)
{
// d-pad button was not pressed, or was pressed more than 400ms ago
timestamp[pad_index] = std::chrono::steady_clock::now();
on_button_pressed(static_cast<pad_button>(button_id));
}
}
else if (!button_state[pad_index][button_id])
{
// button was not pressed
on_button_pressed(static_cast<pad_button>(button_id));
}
}
button_state[pad_index][button_id] = button.m_pressed;
}
if (button.m_flush)
{
button.m_pressed = false;
button.m_flush = false;
button.m_value = 0;
}
if (exit)
return 0;
}
}
refresh();
}
// Unreachable
return 0;
}
}; };
class display_manager class display_manager

View file

@ -316,9 +316,11 @@ void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std
switch (status) switch (status)
{ {
case JOYERR_UNPLUGGED: case JOYERR_UNPLUGGED:
{
return fail_callback(padId); return fail_callback(padId);
}
case JOYERR_NOERROR: case JOYERR_NOERROR:
{
auto data = GetButtonValues(js_info, js_caps); auto data = GetButtonValues(js_info, js_caps);
// Check for each button in our list if its corresponding (maybe remapped) button or axis was pressed. // Check for each button in our list if its corresponding (maybe remapped) button or axis was pressed.
@ -421,6 +423,9 @@ void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std
break; break;
} }
default:
break;
}
} }
void mm_joystick_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold) void mm_joystick_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold)

View file

@ -57,8 +57,10 @@ void pad_thread::Init()
} }
} }
const u32 system_info = m_info.system_info;
std::memset(&m_info, 0, sizeof(m_info)); std::memset(&m_info, 0, sizeof(m_info));
m_info.now_connect = 0; m_info.now_connect = 0;
m_info.system_info |= system_info;
m_pads.clear(); m_pads.clear();
handlers.clear(); handlers.clear();
@ -147,6 +149,18 @@ void pad_thread::SetEnabled(bool enabled)
is_enabled = enabled; is_enabled = enabled;
} }
void pad_thread::SetIntercepted(bool intercepted)
{
if (intercepted)
{
m_info.system_info |= CELL_PAD_INFO_INTERCEPTED;
}
else
{
m_info.system_info &= ~CELL_PAD_INFO_INTERCEPTED;
}
}
void pad_thread::ThreadFunc() void pad_thread::ThreadFunc()
{ {
active = true; active = true;

View file

@ -25,6 +25,7 @@ public:
void Init(); void Init();
void Reset(); void Reset();
void SetEnabled(bool enabled); void SetEnabled(bool enabled);
void SetIntercepted(bool intercepted);
protected: protected:
void ThreadFunc(); void ThreadFunc();
@ -36,7 +37,7 @@ protected:
void *curthread; void *curthread;
void *curwindow; void *curwindow;
PadInfo m_info; PadInfo m_info{ 0, 0 };
std::vector<std::shared_ptr<Pad>> m_pads; std::vector<std::shared_ptr<Pad>> m_pads;
atomic_t<bool> active{ false }; atomic_t<bool> active{ false };
@ -54,4 +55,11 @@ namespace pad
{ {
return verify(HERE, g_current.load()); return verify(HERE, g_current.load());
}; };
static inline void SetIntercepted(bool intercepted)
{
std::lock_guard lock(g_pad_mutex);
const auto handler = get_current_handler();
handler->SetIntercepted(intercepted);
}
} }

View file

@ -18,6 +18,8 @@ s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries,
atomic_t<bool> dlg_result(false); atomic_t<bool> dlg_result(false);
atomic_t<s32> selection; atomic_t<s32> selection;
pad::SetIntercepted(true);
Emu.CallAfter([&]() Emu.CallAfter([&]()
{ {
save_data_list_dialog sdid(save_entries, focused, op, listSet); save_data_list_dialog sdid(save_entries, focused, op, listSet);
@ -31,5 +33,7 @@ s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries,
thread_ctrl::wait_for(1000); thread_ctrl::wait_for(1000);
} }
pad::SetIntercepted(false);
return selection.load(); return selection.load();
} }

View file

@ -328,6 +328,7 @@ void xinput_pad_handler::ThreadProc()
switch (result) switch (result)
{ {
case ERROR_DEVICE_NOT_CONNECTED: case ERROR_DEVICE_NOT_CONNECTED:
{
if (last_connection_status[i] == true) if (last_connection_status[i] == true)
{ {
LOG_ERROR(HLE, "XInput device %d disconnected", padnum); LOG_ERROR(HLE, "XInput device %d disconnected", padnum);
@ -337,8 +338,9 @@ void xinput_pad_handler::ThreadProc()
connected--; connected--;
} }
continue; continue;
}
case ERROR_SUCCESS: case ERROR_SUCCESS:
{
if (last_connection_status[i] == false) if (last_connection_status[i] == false)
{ {
LOG_SUCCESS(HLE, "XInput device %d reconnected", padnum); LOG_SUCCESS(HLE, "XInput device %d reconnected", padnum);
@ -437,7 +439,9 @@ void xinput_pad_handler::ThreadProc()
m_dev->last_vibration = clock(); m_dev->last_vibration = clock();
} }
} }
break;
}
default:
break; break;
} }
} }