cellCrossControllerInitialize: add dialog

This commit is contained in:
Megamouse 2022-07-12 21:28:55 +02:00
parent cdef752a9c
commit 7499f875a6
6 changed files with 154 additions and 19 deletions

View file

@ -1,7 +1,11 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h" #include "Emu/Cell/PPUModule.h"
#include "Emu/IdManager.h"
#include "Emu/localized_string.h"
#include "cellSysutil.h" #include "cellSysutil.h"
#include "cellCrossController.h" #include "cellCrossController.h"
#include "cellMsgDialog.h"
LOG_CHANNEL(cellCrossController); LOG_CHANNEL(cellCrossController);
@ -33,15 +37,117 @@ void fmt_class_string<CellCrossControllerError>::format(std::string& out, u64 ar
}); });
} }
void finish_callback(ppu_thread& ppu, s32 button_type, vm::ptr<void> userdata); // Forward declaration
struct cross_controller
{
atomic_t<s32> status{0};
std::unique_ptr<named_thread<std::function<void()>>> connection_thread;
vm::ptr<CellCrossControllerCallback> callback = vm::null;
vm::ptr<void> userdata = vm::null;
void on_connection_established(s32 status)
{
ensure(!!callback);
close_msg_dialog();
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
callback(ppu, CELL_CROSS_CONTROLLER_STATUS_FINALIZED, status, vm::null, userdata);
return CELL_OK;
});
}
void run_thread(vm::cptr<CellCrossControllerPackageInfo> pPkgInfo)
{
ensure(!!pPkgInfo);
ensure(!!callback);
const std::string msg = fmt::format("%s\n\n%s",
get_localized_string(localized_string_id::CELL_CROSS_CONTROLLER_MSG, pPkgInfo->pTitle.get_ptr()),
get_localized_string(localized_string_id::CELL_CROSS_CONTROLLER_FW_MSG));
vm::bptr<CellMsgDialogCallback> msg_dialog_callback = vm::null;
msg_dialog_callback.set(g_fxo->get<ppu_function_manager>().func_addr(FIND_FUNC(finish_callback)));
// TODO: Show icons from comboplay_plugin.rco in dialog. Maybe use a new dialog or add an optional icon to this one.
error_code res = open_msg_dialog(false, CELL_MSGDIALOG_TYPE_DISABLE_CANCEL_OFF, vm::make_str(msg), msg_dialog_callback, userdata);
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
callback(ppu, CELL_CROSS_CONTROLLER_STATUS_INITIALIZED, res == CELL_OK ? CELL_OK : CELL_CROSS_CONTROLLER_ERROR_INTERNAL, vm::null, userdata);
return CELL_OK;
});
status = CELL_CROSS_CONTROLLER_STATUS_INITIALIZED;
connection_thread = std::make_unique<named_thread<std::function<void()>>>(fmt::format("Cross-Controller Thread"), [this]()
{
while (thread_ctrl::state() != thread_state::aborting)
{
if (Emu.IsPaused())
{
thread_ctrl::wait_for(10'000);
continue;
}
// TODO: establish connection to PS Vita
if (false)
{
on_connection_established(CELL_OK);
}
thread_ctrl::wait_for(1000);
}
status = CELL_CROSS_CONTROLLER_STATUS_FINALIZED;
});
}
void stop_thread()
{
if (connection_thread)
{
auto& thread = *connection_thread;
thread = thread_state::aborting;
thread();
connection_thread.reset();
}
};
};
void finish_callback(ppu_thread& ppu, s32 button_type, vm::ptr<void> userdata)
{
cross_controller& cc = g_fxo->get<cross_controller>();
// This function should only be called when the user canceled the dialog
ensure(cc.callback && button_type == CELL_MSGDIALOG_BUTTON_ESCAPE);
cc.callback(ppu, CELL_CROSS_CONTROLLER_STATUS_FINALIZED, CELL_CROSS_CONTROLLER_ERROR_CANCEL, vm::null, userdata);
cc.stop_thread();
}
error_code cellCrossControllerInitialize(vm::cptr<CellCrossControllerParam> pParam, vm::cptr<CellCrossControllerPackageInfo> pPkgInfo, vm::ptr<CellCrossControllerCallback> cb, vm::ptr<void> userdata) // LittleBigPlanet 2 and 3 error_code cellCrossControllerInitialize(vm::cptr<CellCrossControllerParam> pParam, vm::cptr<CellCrossControllerPackageInfo> pPkgInfo, vm::ptr<CellCrossControllerCallback> cb, vm::ptr<void> userdata) // LittleBigPlanet 2 and 3
{ {
cellCrossController.todo("cellCrossControllerInitialize(pParam=*0x%x, pPkgInfo=*0x%x, cb=*0x%x, userdata=*0x%x)", pParam, pPkgInfo, cb, userdata); cellCrossController.todo("cellCrossControllerInitialize(pParam=*0x%x, pPkgInfo=*0x%x, cb=*0x%x, userdata=*0x%x)", pParam, pPkgInfo, cb, userdata);
// TODO if (pParam)
//if (something) {
//{ cellCrossController.notice("cellCrossControllerInitialize: pParam: pPackageFileName=%s, pSignatureFileName=%s, pIconFileName=%s", pParam->pPackageFileName, pParam->pSignatureFileName, pParam->pIconFileName);
// return CELL_CROSS_CONTROLLER_ERROR_INVALID_STATE; }
//}
if (pPkgInfo)
{
cellCrossController.notice("cellCrossControllerInitialize: pPkgInfo: pTitle=%s, pTitleId=%s, pAppVer=%s", pPkgInfo->pTitle, pPkgInfo->pTitleId, pPkgInfo->pAppVer);
}
cross_controller& cc = g_fxo->get<cross_controller>();
if (cc.status == CELL_CROSS_CONTROLLER_STATUS_INITIALIZED) // TODO: confirm this logic
{
return CELL_CROSS_CONTROLLER_ERROR_INVALID_STATE;
}
if (!pParam || !pPkgInfo) if (!pParam || !pPkgInfo)
{ {
@ -73,13 +179,9 @@ error_code cellCrossControllerInitialize(vm::cptr<CellCrossControllerParam> pPar
return CELL_CROSS_CONTROLLER_ERROR_INVALID_VALUE; return CELL_CROSS_CONTROLLER_ERROR_INVALID_VALUE;
} }
sysutil_register_cb([=](ppu_thread& ppu) -> s32 cc.callback = cb;
{ cc.userdata = userdata;
cb(ppu, CELL_CROSS_CONTROLLER_STATUS_INITIALIZED, CELL_OK, vm::null, userdata); cc.run_thread(pPkgInfo);
cb(ppu, CELL_CROSS_CONTROLLER_STATUS_FINALIZED, CELL_OK, vm::null, userdata);
return CELL_OK;
});
return CELL_OK; return CELL_OK;
} }
@ -88,4 +190,7 @@ error_code cellCrossControllerInitialize(vm::cptr<CellCrossControllerParam> pPar
DECLARE(ppu_module_manager::cellCrossController)("cellCrossController", []() DECLARE(ppu_module_manager::cellCrossController)("cellCrossController", []()
{ {
REG_FUNC(cellCrossController, cellCrossControllerInitialize); REG_FUNC(cellCrossController, cellCrossControllerInitialize);
// Helper Function
REG_HIDDEN_FUNC(finish_callback);
}); });

View file

@ -144,7 +144,7 @@ error_code cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMs
// wrapper to call for other hle dialogs // wrapper to call for other hle dialogs
error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialogCallback> callback, vm::ptr<void> userData, vm::ptr<void> extParam) error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialogCallback> callback, vm::ptr<void> userData, vm::ptr<void> extParam)
{ {
cellSysutil.warning("open_msg_dialog(is_blocking=%d, type=0x%x, msgString=%s, callback=*0x%x, userData=*0x%x, extParam=*0x%x)", is_blocking, type, msgString, callback, userData, extParam); cellSysutil.notice("open_msg_dialog(is_blocking=%d, type=0x%x, msgString=%s, callback=*0x%x, userData=*0x%x, extParam=*0x%x)", is_blocking, type, msgString, callback, userData, extParam);
const MsgDialogType _type{ type }; const MsgDialogType _type{ type };
@ -263,6 +263,31 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString,
return CELL_OK; return CELL_OK;
} }
void close_msg_dialog()
{
cellSysutil.notice("close_msg_dialog()");
if (auto manager = g_fxo->try_get<rsx::overlays::display_manager>())
{
if (auto dlg = manager->get<rsx::overlays::message_dialog>())
{
g_fxo->get<msg_dlg_thread>().wait_until = 0;
dlg->close(false, true); // this doesn't call on_close
sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_END, 0);
return;
}
}
if (const auto dlg = g_fxo->get<msg_info>().get())
{
dlg->state = MsgDialogState::Close;
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);
}
}
void exit_game(s32/* buttonType*/, vm::ptr<void>/* userData*/) void exit_game(s32/* buttonType*/, vm::ptr<void>/* userData*/)
{ {
sysutil_send_system_cmd(CELL_SYSUTIL_REQUEST_EXITGAME, 0); sysutil_send_system_cmd(CELL_SYSUTIL_REQUEST_EXITGAME, 0);
@ -270,7 +295,7 @@ void exit_game(s32/* buttonType*/, vm::ptr<void>/* userData*/)
error_code open_exit_dialog(const std::string& message, bool is_exit_requested) error_code open_exit_dialog(const std::string& message, bool is_exit_requested)
{ {
cellSysutil.warning("open_exit_dialog(message=%s, is_exit_requested=%d)", message, is_exit_requested); cellSysutil.notice("open_exit_dialog(message=%s, is_exit_requested=%d)", message, is_exit_requested);
vm::bptr<CellMsgDialogCallback> callback = vm::null; vm::bptr<CellMsgDialogCallback> callback = vm::null;
@ -342,11 +367,6 @@ error_code cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMs
default: return CELL_MSGDIALOG_ERROR_PARAM; default: return CELL_MSGDIALOG_ERROR_PARAM;
} }
if (_type.se_mute_on)
{
// TODO
}
if (_type.se_normal) if (_type.se_normal)
{ {
cellSysutil.warning("%s", msgString); cellSysutil.warning("%s", msgString);

View file

@ -91,6 +91,7 @@ enum class MsgDialogState
extern atomic_t<s32> g_last_user_response; extern atomic_t<s32> g_last_user_response;
void close_msg_dialog();
error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialogCallback> callback = vm::null, vm::ptr<void> userData = vm::null, vm::ptr<void> extParam = vm::null); error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialogCallback> callback = vm::null, vm::ptr<void> userData = vm::null, vm::ptr<void> extParam = vm::null);
error_code open_exit_dialog(const std::string& message, bool is_exit_requested); error_code open_exit_dialog(const std::string& message, bool is_exit_requested);

View file

@ -4,5 +4,9 @@
u64 convert_to_timebased_time(u64 time); u64 convert_to_timebased_time(u64 time);
u64 get_timebased_time(); u64 get_timebased_time();
// Returns some relative time in microseconds, don't change this fact
u64 get_system_time(); u64 get_system_time();
// As get_system_time but obeys Clocks scaling setting. Microseconds.
u64 get_guest_system_time(u64 time = umax); u64 get_guest_system_time(u64 time = umax);

View file

@ -129,6 +129,9 @@ enum class localized_string_id
CELL_SAVEDATA_LOAD, CELL_SAVEDATA_LOAD,
CELL_SAVEDATA_OVERWRITE, CELL_SAVEDATA_OVERWRITE,
CELL_CROSS_CONTROLLER_MSG,
CELL_CROSS_CONTROLLER_FW_MSG,
RPCN_NO_ERROR, RPCN_NO_ERROR,
RPCN_ERROR_INVALID_INPUT, RPCN_ERROR_INVALID_INPUT,
RPCN_ERROR_WOLFSSL, RPCN_ERROR_WOLFSSL,

View file

@ -151,6 +151,8 @@ private:
case localized_string_id::CELL_SAVEDATA_DELETE: return tr("Delete this data?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...); case localized_string_id::CELL_SAVEDATA_DELETE: return tr("Delete this data?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_SAVEDATA_LOAD: return tr("Load this data?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...); case localized_string_id::CELL_SAVEDATA_LOAD: return tr("Load this data?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_SAVEDATA_OVERWRITE: return tr("Do you want to overwrite the saved data?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...); case localized_string_id::CELL_SAVEDATA_OVERWRITE: return tr("Do you want to overwrite the saved data?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_CROSS_CONTROLLER_MSG: return tr("Start [%0] on the PS Vita system.\nIf you have not installed [%0], go to [Remote Play] on the PS Vita system and start [Cross-Controller] from the LiveArea™ screen.", "Cross-Controller message").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_CROSS_CONTROLLER_FW_MSG: return tr("If your system software version on the PS Vita system is earlier than 1.80, you must update the system software to the latest version.", "Cross-Controller firmware message");
case localized_string_id::RPCN_NO_ERROR: return tr("RPCN: No Error"); case localized_string_id::RPCN_NO_ERROR: return tr("RPCN: No Error");
case localized_string_id::RPCN_ERROR_INVALID_INPUT: return tr("RPCN: Invalid Input (Wrong Host/Port)"); case localized_string_id::RPCN_ERROR_INVALID_INPUT: return tr("RPCN: Invalid Input (Wrong Host/Port)");
case localized_string_id::RPCN_ERROR_WOLFSSL: return tr("RPCN Connection Error: WolfSSL Error"); case localized_string_id::RPCN_ERROR_WOLFSSL: return tr("RPCN Connection Error: WolfSSL Error");