1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 18:53:28 +01:00

cellSysutil: Implement DRAWING callbacks

Also fixed a minor race in cellUserInfo regarding status of dialog
This commit is contained in:
Eladash 2022-05-30 16:31:01 +03:00 committed by Megamouse
parent 248809ca1f
commit f5beaabded
7 changed files with 80 additions and 11 deletions

View File

@ -155,10 +155,17 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString,
return CELL_SYSUTIL_ERROR_BUSY;
}
if (s32 ret = sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_BEGIN, 0); ret < 0)
{
return CellSysutilError{ret + 0u};
}
g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE;
const auto res = manager->create<rsx::overlays::message_dialog>()->show(is_blocking, msgString.get_ptr(), _type, [callback, userData](s32 status)
{
sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_END, 0);
if (callback)
{
sysutil_register_cb([=](ppu_thread& ppu) -> s32
@ -179,6 +186,11 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString,
return CELL_SYSUTIL_ERROR_BUSY;
}
if (s32 ret = sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_BEGIN, 0); ret < 0)
{
return CellSysutilError{ret + 0u};
}
dlg->type = _type;
dlg->on_close = [callback, userData, wptr = std::weak_ptr<MsgDialogBase>(dlg)](s32 status)
@ -187,6 +199,8 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString,
if (dlg && dlg->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Close))
{
sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_END, 0);
if (callback)
{
sysutil_register_cb([=](ppu_thread& ppu) -> s32
@ -208,11 +222,14 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString,
auto& ppu = *get_current_cpu_thread();
lv2_obj::sleep(ppu);
// PS3 memory must not be accessed by Main thread
std::string msg_string = msgString.get_ptr();
// Run asynchronously in GUI thread
Emu.CallFromMainThread([&]()
Emu.CallFromMainThread([&, msg_string = std::move(msg_string)]()
{
g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE;
dlg->Create(msgString.get_ptr());
dlg->Create(msg_string);
lv2_obj::awake(&ppu);
});
@ -487,6 +504,7 @@ error_code cellMsgDialogAbort()
g_fxo->get<msg_dlg_thread>().wait_until = 0;
g_fxo->get<msg_info>().remove(); // this shouldn't call on_close
input::SetIntercepted(false); // so we need to reenable the pads here
sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_END, 0);
return CELL_OK;
}

View File

@ -47,6 +47,8 @@ struct sysutil_cb_manager
atomic_t<registered_cb> callbacks[4]{};
lf_queue<std::function<s32(ppu_thread&)>> registered;
atomic_t<bool> draw_cb_started{};
};
extern void sysutil_register_cb(std::function<s32(ppu_thread&)>&& cb)
@ -56,12 +58,29 @@ extern void sysutil_register_cb(std::function<s32(ppu_thread&)>&& cb)
cbm.registered.push(std::move(cb));
}
extern u32 sysutil_send_system_cmd(u64 status, u64 param)
extern s32 sysutil_send_system_cmd(u64 status, u64 param)
{
u32 count = 0;
s32 count = 0;
if (auto cbm = g_fxo->try_get<sysutil_cb_manager>())
{
if (status == CELL_SYSUTIL_DRAWING_BEGIN)
{
if (cbm->draw_cb_started.exchange(true))
{
cellSysutil.error("Tried to enqueue a second or more DRAWING_BEGIN callback!");
return CELL_SYSUTIL_ERROR_BUSY;
}
}
else if (status == CELL_SYSUTIL_DRAWING_END)
{
if (!cbm->draw_cb_started.exchange(false))
{
cellSysutil.error("Tried to enqueue a DRAWING_END callback without a BEGIN callback!");
return -1;
}
}
for (sysutil_cb_manager::registered_cb cb : cbm->callbacks)
{
if (cb.first)

View File

@ -301,5 +301,5 @@ struct CellSysCacheParam
};
extern void sysutil_register_cb(std::function<s32(ppu_thread&)>&&);
extern u32 sysutil_send_system_cmd(u64 status, u64 param);
extern s32 sysutil_send_system_cmd(u64 status, u64 param);
s32 sysutil_check_name_string(const char* src, s32 minlen, s32 maxlen);

View File

@ -157,6 +157,11 @@ error_code cellUserInfoSelectUser_ListType(vm::ptr<CellUserInfoTypeSet> listType
return CELL_USERINFO_ERROR_BUSY;
}
if (s32 ret = sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_BEGIN, 0); ret < 0)
{
return CELL_USERINFO_ERROR_BUSY;
}
const std::string title = listType->title.get_ptr();
const u32 focused = listType->focus;
@ -178,6 +183,10 @@ error_code cellUserInfoSelectUser_ListType(vm::ptr<CellUserInfoTypeSet> listType
cellUserInfo.warning("cellUserInfoSelectUser_ListType: callback_result=%s, selected_user_id=%d, selected_username='%s'", callback_result, selected_user_id, selected_username);
g_fxo->get<user_info_manager>().dialog_opened = false;
sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_END, 0);
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
vm::var<CellUserInfoUserStat> selectUser;
@ -189,8 +198,6 @@ error_code cellUserInfoSelectUser_ListType(vm::ptr<CellUserInfoTypeSet> listType
funcSelect(ppu, callback_result, selectUser, userdata);
return CELL_OK;
});
g_fxo->get<user_info_manager>().dialog_opened = false;
});
return result;
@ -258,6 +265,11 @@ error_code cellUserInfoSelectUser_SetList(vm::ptr<CellUserInfoListSet> setList,
return CELL_USERINFO_ERROR_BUSY;
}
if (s32 ret = sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_BEGIN, 0); ret < 0)
{
return CELL_USERINFO_ERROR_BUSY;
}
const std::string title = setList->title.get_ptr();
const u32 focused = setList->focus;
@ -279,6 +291,10 @@ error_code cellUserInfoSelectUser_SetList(vm::ptr<CellUserInfoListSet> setList,
cellUserInfo.warning("cellUserInfoSelectUser_SetList: callback_result=%s, selected_user_id=%d, selected_username='%s'", callback_result, selected_user_id, selected_username);
g_fxo->get<user_info_manager>().dialog_opened = false;
sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_END, 0);
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
vm::var<CellUserInfoUserStat> selectUser;
@ -290,8 +306,6 @@ error_code cellUserInfoSelectUser_SetList(vm::ptr<CellUserInfoListSet> setList,
funcSelect(ppu, callback_result, selectUser, userdata);
return CELL_OK;
});
g_fxo->get<user_info_manager>().dialog_opened = false;
});
return result;

View File

@ -1768,7 +1768,7 @@ void Emulator::Resume()
}
}
u32 sysutil_send_system_cmd(u64 status, u64 param);
s32 sysutil_send_system_cmd(u64 status, u64 param);
void process_qt_events();
void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op)

View File

@ -1315,7 +1315,7 @@ void main_window::HandlePupInstallation(const QString& file_path, const QString&
}
// This is ugly, but PS3 headers shall not be included there.
extern u32 sysutil_send_system_cmd(u64 status, u64 param);
extern s32 sysutil_send_system_cmd(u64 status, u64 param);
void main_window::DecryptSPRXLibraries()
{

View File

@ -5,21 +5,37 @@
#include "Emu/IdManager.h"
#include "Emu/Io/interception.h"
#include "Emu/RSX/Overlays/overlay_save_dialog.h"
#include "Emu/Cell/Modules/cellSysutil.h"
#include "Utilities/Thread.h"
#include "util/logs.hpp"
LOG_CHANNEL(cellSaveData);
s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay)
{
// TODO: Implement proper error checking in savedata_op?
const bool use_end = sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_BEGIN, 0) >= 0;
if (!use_end)
{
cellSaveData.error("ShowSaveDataList(): Not able to notify DRAWING_BEGIN callback because one has already been sent!");
}
// TODO: Install native shell as an Emu callback
if (auto manager = g_fxo->try_get<rsx::overlays::display_manager>())
{
const s32 result = manager->create<rsx::overlays::save_dialog>()->show(save_entries, focused, op, listSet, enable_overlay);
if (result != rsx::overlays::user_interface::selection_code::error)
{
if (use_end) sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_END, 0);
return result;
}
}
if (!Emu.HasGui())
{
if (use_end) sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_END, 0);
return -2;
}
@ -45,5 +61,7 @@ s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries,
input::SetIntercepted(false);
if (use_end) sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_END, 0);
return selection.load();
}