diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 377b012253..3a51f61b15 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -962,20 +962,20 @@ template class mem_func_beptr_t : public mem_func template class mem_func_ptr_t : public mem_base_t { - __forceinline void call_func(bool is_async) + __forceinline RT call_func(bool is_async) const { Callback cb; cb.SetAddr(this->m_addr); - cb.Branch(!is_async); + return (RT)cb.Branch(!is_async); } public: - __forceinline void operator()() + __forceinline RT operator()() const { - call_func(false); + return call_func(false); } - __forceinline void async() + __forceinline void async() const { call_func(true); } @@ -984,21 +984,21 @@ public: template class mem_func_ptr_t : public mem_base_t { - __forceinline void call_func(bool is_async, T... args) + __forceinline RT call_func(bool is_async, T... args) const { Callback cb; cb.SetAddr(this->m_addr); cb.Handle(_func_arg::get_value(args)...); - cb.Branch(!is_async); + return (RT)cb.Branch(!is_async); } public: - __forceinline void operator()(T... args) + __forceinline RT operator()(T... args) const { - call_func(false, args...); + return call_func(false, args...); } - __forceinline void async(T... args) + __forceinline void async(T... args) const { call_func(true, args...); } diff --git a/rpcs3/Emu/SysCalls/Callback.cpp b/rpcs3/Emu/SysCalls/Callback.cpp index 0c7785fac4..02fb9dc9cf 100644 --- a/rpcs3/Emu/SysCalls/Callback.cpp +++ b/rpcs3/Emu/SysCalls/Callback.cpp @@ -52,7 +52,7 @@ void Callback::Handle(u64 _a1, u64 _a2, u64 _a3, u64 _a4) m_has_data = true; } -void Callback::Branch(bool wait) +u64 Callback::Branch(bool wait) { m_has_data = false; @@ -67,7 +67,7 @@ again: if (Emu.IsStopped()) { LOG_WARNING(HLE, "Callback::Branch() aborted"); - return; + return 0; } Sleep(1); } @@ -81,7 +81,7 @@ again: if (Emu.IsStopped()) { LOG_WARNING(HLE, "Callback::Branch() aborted"); - return; + return 0; } thr.Stop(); @@ -102,7 +102,7 @@ again: if (!wait) { - return; + return 0; } while (thr.IsAlive()) @@ -110,10 +110,12 @@ again: if (Emu.IsStopped()) { LOG_WARNING(HLE, "Callback::Branch(true) aborted (end)"); - return; + return 0; } Sleep(1); } + + return thr.GetExitStatus(); } void Callback::SetName(const std::string& name) diff --git a/rpcs3/Emu/SysCalls/Callback.h b/rpcs3/Emu/SysCalls/Callback.h index 093fc13379..ce9023b1b0 100644 --- a/rpcs3/Emu/SysCalls/Callback.h +++ b/rpcs3/Emu/SysCalls/Callback.h @@ -24,7 +24,7 @@ public: Callback(u32 slot = 0, u64 addr = 0); void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0); - void Branch(bool wait); + u64 Branch(bool wait); void SetName(const std::string& name); operator bool() const; diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp new file mode 100644 index 0000000000..e339a6143e --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp @@ -0,0 +1,445 @@ +#include "stdafx.h" +#include "Utilities/Log.h" +#include "Emu/Memory/Memory.h" +#include "Emu/System.h" +#include "Emu/Cell/PPUThread.h" +#include "Emu/SysCalls/SC_FUNC.h" +#include "Emu/SysCalls/Modules.h" + +#include "cellSysutil.h" +#include "cellMsgDialog.h" + +extern Module *cellSysutil; + +enum MsgDialogState +{ + msgDialogNone, + msgDialogOpen, + msgDialogClose, + msgDialogAbort, +}; + +std::atomic g_msg_dialog_state(msgDialogNone); +wxDialog* g_msg_dialog = nullptr; +wxGauge* m_gauge1 = nullptr; +wxGauge* m_gauge2 = nullptr; +wxStaticText* m_text1 = nullptr; +wxStaticText* m_text2 = nullptr; +u64 m_wait_until; + +int cellMsgDialogOpen2(u32 type, mem_list_ptr_t msgString, mem_func_ptr_t callback, u32 userData, u32 extParam) +{ + cellSysutil->Warning("cellMsgDialogOpen2(type=0x%x, msgString_addr=0x%x, callback_addr=0x%x, userData=0x%x, extParam=0x%x)", + type, msgString.GetAddr(), callback.GetAddr(), userData, extParam); + + if (!msgString.IsGood() || !callback.IsGood()) + { + return CELL_EFAULT; + } + + //type |= CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE; + //type |= CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO; + + MsgDialogState old = msgDialogNone; + if (!g_msg_dialog_state.compare_exchange_strong(old, msgDialogOpen)) + { + return CELL_SYSUTIL_ERROR_BUSY; + } + + thread t("MsgDialog thread", [=]() + { + switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE) + { + case CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL: LOG_WARNING(Log::HLE, "%s", msgString.GetString()); break; + case CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR: LOG_ERROR(Log::HLE, "%s", msgString.GetString()); break; + } + + switch (type & CELL_MSGDIALOG_TYPE_SE_MUTE) // TODO + { + case CELL_MSGDIALOG_TYPE_SE_MUTE_OFF: break; + case CELL_MSGDIALOG_TYPE_SE_MUTE_ON: break; + } + + switch (type & CELL_MSGDIALOG_TYPE_BG) // TODO + { + case CELL_MSGDIALOG_TYPE_BG_INVISIBLE: break; + case CELL_MSGDIALOG_TYPE_BG_VISIBLE: break; + } + + switch (type & CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR) // TODO + { + case CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NO: break; + default: break; + } + + u64 status = CELL_MSGDIALOG_BUTTON_NONE; + + volatile bool m_signal = false; + wxGetApp().CallAfter([&]() + { + wxWindow* parent = nullptr; // TODO: align it better + + m_gauge1 = nullptr; + m_gauge2 = nullptr; + m_text1 = nullptr; + m_text2 = nullptr; + wxButton* m_button_ok = nullptr; + wxButton* m_button_yes = nullptr; + wxButton* m_button_no = nullptr; + + g_msg_dialog = new wxDialog(parent, wxID_ANY, type & CELL_MSGDIALOG_TYPE_SE_TYPE ? "" : "Error", wxDefaultPosition, wxDefaultSize); + + g_msg_dialog->SetExtraStyle(g_msg_dialog->GetExtraStyle() | wxWS_EX_TRANSIENT); + + wxSizer* sizer1 = new wxBoxSizer(wxVERTICAL); + + wxStaticText* m_text = new wxStaticText(g_msg_dialog, wxID_ANY, wxString(msgString.GetString(), wxConvUTF8)); + sizer1->Add(m_text, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 16); + + switch (type & CELL_MSGDIALOG_TYPE_PROGRESSBAR) + { + case CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE: + m_gauge2 = new wxGauge(g_msg_dialog, wxID_ANY, 100, wxDefaultPosition, wxSize(300, -1), wxGA_HORIZONTAL | wxGA_SMOOTH); + m_text2 = new wxStaticText(g_msg_dialog, wxID_ANY, ""); + m_text2->SetAutoLayout(true); + + case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE: + m_gauge1 = new wxGauge(g_msg_dialog, wxID_ANY, 100, wxDefaultPosition, wxSize(300, -1), wxGA_HORIZONTAL | wxGA_SMOOTH); + m_text1 = new wxStaticText(g_msg_dialog, wxID_ANY, ""); + m_text1->SetAutoLayout(true); + + case CELL_MSGDIALOG_TYPE_PROGRESSBAR_NONE: + break; + } + + if (m_gauge1) + { + sizer1->Add(m_text1, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 8); + sizer1->Add(m_gauge1, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, 16); + m_gauge1->SetValue(0); + } + if (m_gauge2) + { + sizer1->Add(m_text2, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 8); + sizer1->Add(m_gauge2, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, 16); + m_gauge2->SetValue(0); + } + + wxBoxSizer* buttons = new wxBoxSizer(wxHORIZONTAL); + + switch (type & CELL_MSGDIALOG_TYPE_BUTTON_TYPE) + { + case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_NONE: + break; + + case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO: + m_button_yes = new wxButton(g_msg_dialog, wxID_YES); + buttons->Add(m_button_yes, 0, wxALIGN_CENTER_HORIZONTAL | wxRIGHT, 8); + m_button_no = new wxButton(g_msg_dialog, wxID_NO); + buttons->Add(m_button_no, 0, wxALIGN_CENTER_HORIZONTAL, 16); + + sizer1->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 16); + break; + + case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK: + m_button_ok = new wxButton(g_msg_dialog, wxID_OK); + buttons->Add(m_button_ok, 0, wxALIGN_CENTER_HORIZONTAL, 16); + + sizer1->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 16); + break; + } + + sizer1->AddSpacer(16); + + g_msg_dialog->SetSizerAndFit(sizer1); + g_msg_dialog->Centre(wxBOTH); + g_msg_dialog->Show(); + g_msg_dialog->Enable(); + + g_msg_dialog->Bind(wxEVT_BUTTON, [&](wxCommandEvent& event) + { + status = (event.GetId() == wxID_NO) ? CELL_MSGDIALOG_BUTTON_NO : CELL_MSGDIALOG_BUTTON_YES /* OK */; + g_msg_dialog->Hide(); + m_wait_until = get_system_time(); + g_msg_dialog_state = msgDialogClose; + }); + + + g_msg_dialog->Bind(wxEVT_CLOSE_WINDOW, [&](wxCloseEvent& event) + { + if (type & CELL_MSGDIALOG_TYPE_DISABLE_CANCEL) + { + } + else + { + status = CELL_MSGDIALOG_BUTTON_ESCAPE; + g_msg_dialog->Hide(); + m_wait_until = get_system_time(); + g_msg_dialog_state = msgDialogClose; + } + }); + + m_signal = true; + }); + + while (!m_signal) + { + Sleep(1); + } + + while (g_msg_dialog_state == msgDialogOpen || get_system_time() < m_wait_until) + { + if (Emu.IsStopped()) + { + g_msg_dialog_state = msgDialogAbort; + break; + } + Sleep(1); + } + + if (callback && (g_msg_dialog_state != msgDialogAbort)) + callback.async(status, userData); + + wxGetApp().CallAfter([&]() + { + delete g_msg_dialog; + g_msg_dialog = nullptr; + }); + + g_msg_dialog_state = msgDialogNone; + }); + t.detach(); + + return CELL_OK; +} + +int cellMsgDialogOpenErrorCode(u32 errorCode, mem_func_ptr_t callback, mem_ptr_t userData, u32 extParam) +{ + cellSysutil->Warning("cellMsgDialogOpenErrorCode(errorCode=0x%x, callback_addr=0x%x, userData=%d, extParam=%d)", + errorCode, callback.GetAddr(), userData, extParam); + + std::string errorMessage; + switch (errorCode) + { + // Generic errors + case 0x80010001: errorMessage = "The resource is temporarily unavailable."; break; + case 0x80010002: errorMessage = "Invalid argument or flag."; break; + case 0x80010003: errorMessage = "The feature is not yet implemented."; break; + case 0x80010004: errorMessage = "Memory allocation failed."; break; + case 0x80010005: errorMessage = "The resource with the specified identifier does not exist."; break; + case 0x80010006: errorMessage = "The file does not exist."; break; + case 0x80010007: errorMessage = "The file is in unrecognized format / The file is not a valid ELF file."; break; + case 0x80010008: errorMessage = "Resource deadlock is avoided."; break; + case 0x80010009: errorMessage = "Operation not permitted."; break; + case 0x8001000A: errorMessage = "The device or resource is bus."; break; + case 0x8001000B: errorMessage = "The operation is timed ou."; break; + case 0x8001000C: errorMessage = "The operation is aborte."; break; + case 0x8001000D: errorMessage = "Invalid memory access."; break; + case 0x8001000F: errorMessage = "State of the target thread is invalid."; break; + case 0x80010010: errorMessage = "Alignment is invalid."; break; + case 0x80010011: errorMessage = "Shortage of the kernel resources."; break; + case 0x80010012: errorMessage = "The file is a directory."; break; + case 0x80010013: errorMessage = "Operation canceled."; break; + case 0x80010014: errorMessage = "Entry already exists."; break; + case 0x80010015: errorMessage = "Port is already connected."; break; + case 0x80010016: errorMessage = "Port is not connected."; break; + case 0x80010017: errorMessage = "Failure in authorizing SELF. Program authentication fail."; break; + case 0x80010018: errorMessage = "The file is not MSELF."; break; + case 0x80010019: errorMessage = "System version error."; break; + case 0x8001001A: errorMessage = "Fatal system error occurred while authorizing SELF. SELF auth failure."; break; + case 0x8001001B: errorMessage = "Math domain violation."; break; + case 0x8001001C: errorMessage = "Math range violation."; break; + case 0x8001001D: errorMessage = "Illegal multi-byte sequence in input."; break; + case 0x8001001E: errorMessage = "File position error."; break; + case 0x8001001F: errorMessage = "Syscall was interrupted."; break; + case 0x80010020: errorMessage = "File too large."; break; + case 0x80010021: errorMessage = "Too many links."; break; + case 0x80010022: errorMessage = "File table overflow."; break; + case 0x80010023: errorMessage = "No space left on device."; break; + case 0x80010024: errorMessage = "Not a TTY."; break; + case 0x80010025: errorMessage = "Broken pipe."; break; + case 0x80010026: errorMessage = "Read-only filesystem."; break; + case 0x80010027: errorMessage = "Illegal seek."; break; + case 0x80010028: errorMessage = "Arg list too long."; break; + case 0x80010029: errorMessage = "Access violation."; break; + case 0x8001002A: errorMessage = "Invalid file descriptor."; break; + case 0x8001002B: errorMessage = "Filesystem mounting failed."; break; + case 0x8001002C: errorMessage = "Too many files open."; break; + case 0x8001002D: errorMessage = "No device."; break; + case 0x8001002E: errorMessage = "Not a directory."; break; + case 0x8001002F: errorMessage = "No such device or IO."; break; + case 0x80010030: errorMessage = "Cross-device link error."; break; + case 0x80010031: errorMessage = "Bad Message."; break; + case 0x80010032: errorMessage = "In progress."; break; + case 0x80010033: errorMessage = "Message size error."; break; + case 0x80010034: errorMessage = "Name too long."; break; + case 0x80010035: errorMessage = "No lock."; break; + case 0x80010036: errorMessage = "Not empty."; break; + case 0x80010037: errorMessage = "Not supported."; break; + case 0x80010038: errorMessage = "File-system specific error."; break; + case 0x80010039: errorMessage = "Overflow occured."; break; + case 0x8001003A: errorMessage = "Filesystem not mounted."; break; + case 0x8001003B: errorMessage = "Not SData."; break; + case 0x8001003C: errorMessage = "Incorrect version in sys_load_param."; break; + case 0x8001003D: errorMessage = "Pointer is null."; break; + case 0x8001003E: errorMessage = "Pointer is null."; break; + default: errorMessage = "An error has occurred."; break; + } + + char errorCodeHex[9]; + sprintf(errorCodeHex, "%08x", errorCode); + errorMessage.append("\n("); + errorMessage.append(errorCodeHex); + errorMessage.append(")\n"); + + u64 status; + int res = rMessageBox(errorMessage, rGetApp().GetAppName(), rICON_ERROR | rOK); + switch (res) + { + case rOK: status = CELL_MSGDIALOG_BUTTON_OK; break; + default: + if (res) + { + status = CELL_MSGDIALOG_BUTTON_INVALID; + break; + } + + status = CELL_MSGDIALOG_BUTTON_NONE; + break; + } + + if (callback) + callback(status, userData); + + return CELL_OK; +} + +int cellMsgDialogClose(float delay) +{ + cellSysutil->Warning("cellMsgDialogClose(delay=%f)", delay); + + MsgDialogState old = msgDialogOpen; + if (!g_msg_dialog_state.compare_exchange_strong(old, msgDialogClose)) + { + if (old == msgDialogNone) + { + return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; + } + else + { + return CELL_SYSUTIL_ERROR_BUSY; + } + } + + if (delay < 0.0f) delay = 0.0f; + m_wait_until = get_system_time() + (u64)(delay * 1000); + return CELL_OK; +} + +int cellMsgDialogAbort() +{ + cellSysutil->Warning("cellMsgDialogAbort()"); + + MsgDialogState old = msgDialogOpen; + if (!g_msg_dialog_state.compare_exchange_strong(old, msgDialogAbort)) + { + if (old == msgDialogNone) + { + return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; + } + else + { + return CELL_SYSUTIL_ERROR_BUSY; + } + } + + m_wait_until = get_system_time(); + return CELL_OK; +} + +int cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, mem_list_ptr_t msgString) +{ + if (!msgString.IsGood()) + { + cellSysutil->Error("cellMsgDialogProgressBarSetMsg(progressBarIndex=%d, msgString_addr=0x%x): CELL_EFAULT", + progressBarIndex, msgString.GetAddr()); + return CELL_EFAULT; + } + + cellSysutil->Warning("cellMsgDialogProgressBarSetMsg(progressBarIndex=%d, msgString_addr=0x%x): '%s'", + progressBarIndex, msgString.GetAddr(), msgString.GetString()); + + if (g_msg_dialog_state != msgDialogOpen) + { + return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; + } + + if (progressBarIndex >= (u32)(bool)m_gauge1 + (u32)(bool)m_gauge2) + { + return CELL_MSGDIALOG_ERROR_PARAM; + } + + std::string text(msgString.GetString()); + + wxGetApp().CallAfter([text, progressBarIndex]() + { + if (g_msg_dialog && !Emu.IsStopped()) + { + if (progressBarIndex == 0 && m_text1) m_text1->SetLabelText(fmt::FromUTF8(text)); + if (progressBarIndex == 1 && m_text2) m_text2->SetLabelText(fmt::FromUTF8(text)); + g_msg_dialog->Layout(); + g_msg_dialog->Fit(); + } + }); + return CELL_OK; +} + +int cellMsgDialogProgressBarReset(u32 progressBarIndex) +{ + cellSysutil->Warning("cellMsgDialogProgressBarReset(progressBarIndex=%d)", progressBarIndex); + + if (g_msg_dialog_state != msgDialogOpen) + { + return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; + } + + if (progressBarIndex >= (u32)(bool)m_gauge1 + (u32)(bool)m_gauge2) + { + return CELL_MSGDIALOG_ERROR_PARAM; + } + + wxGetApp().CallAfter([=]() + { + if (g_msg_dialog) + { + if (progressBarIndex == 0 && m_gauge1) m_gauge1->SetValue(0); + if (progressBarIndex == 1 && m_gauge2) m_gauge2->SetValue(0); + } + }); + return CELL_OK; +} + +int cellMsgDialogProgressBarInc(u32 progressBarIndex, u32 delta) +{ + cellSysutil->Warning("cellMsgDialogProgressBarInc(progressBarIndex=%d, delta=%d)", progressBarIndex, delta); + + if (g_msg_dialog_state != msgDialogOpen) + { + return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; + } + + if (progressBarIndex >= (u32)(bool)m_gauge1 + (u32)(bool)m_gauge2) + { + return CELL_MSGDIALOG_ERROR_PARAM; + } + + wxGetApp().CallAfter([=]() + { + if (g_msg_dialog) + { + if (progressBarIndex == 0 && m_gauge1) m_gauge1->SetValue(m_gauge1->GetValue() + delta); + if (progressBarIndex == 1 && m_gauge2) m_gauge2->SetValue(m_gauge2->GetValue() + delta); + } + }); + return CELL_OK; +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h new file mode 100644 index 0000000000..33b8ab667c --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h @@ -0,0 +1,91 @@ +#pragma once + +enum +{ + CELL_MSGDIALOG_ERROR_PARAM = 0x8002b301, + CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED = 0x8002b302, +}; + +enum CellMsgDialogType +{ + CELL_MSGDIALOG_DIALOG_TYPE_ERROR = 0x00000000, + CELL_MSGDIALOG_DIALOG_TYPE_NORMAL = 0x00000001, + CELL_MSGDIALOG_BUTTON_TYPE_NONE = 0x00000000, + CELL_MSGDIALOG_BUTTON_TYPE_YESNO = 0x00000010, + CELL_MSGDIALOG_DEFAULT_CURSOR_YES = 0x00000000, + CELL_MSGDIALOG_DEFAULT_CURSOR_NO = 0x00000100, +}; + +enum +{ + CELL_MSGDIALOG_TYPE_SE_TYPE = 1 << 0, + CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR = 0 << 0, + CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL = 1 << 0, +}; + +enum +{ + CELL_MSGDIALOG_TYPE_SE_MUTE = 1 << 1, + CELL_MSGDIALOG_TYPE_SE_MUTE_OFF = 0 << 1, + CELL_MSGDIALOG_TYPE_SE_MUTE_ON = 1 << 1, +}; + +enum +{ + CELL_MSGDIALOG_TYPE_BG = 1 << 2, + CELL_MSGDIALOG_TYPE_BG_VISIBLE = 0 << 2, + CELL_MSGDIALOG_TYPE_BG_INVISIBLE = 1 << 2, +}; + +enum +{ + CELL_MSGDIALOG_TYPE_BUTTON_TYPE = 3 << 4, + CELL_MSGDIALOG_TYPE_BUTTON_TYPE_NONE = 0 << 4, + CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO = 1 << 4, + CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK = 2 << 4, +}; + +enum +{ + CELL_MSGDIALOG_TYPE_DISABLE_CANCEL = 1 << 7, + CELL_MSGDIALOG_TYPE_DISABLE_CANCEL_OFF = 0 << 7, + CELL_MSGDIALOG_TYPE_DISABLE_CANCEL_ON = 1 << 7, +}; + +enum +{ + CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR = 1 << 8, + CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NONE = 0 << 8, + CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_YES = 0 << 8, + CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NO = 1 << 8, + CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_OK = 0 << 8, +}; + +enum +{ + CELL_MSGDIALOG_TYPE_PROGRESSBAR = 3 << 12, + CELL_MSGDIALOG_TYPE_PROGRESSBAR_NONE = 0 << 12, + CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE = 1 << 12, + CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE = 2 << 12, +}; + +enum +{ + CELL_MSGDIALOG_BUTTON_NONE = -1, + CELL_MSGDIALOG_BUTTON_INVALID = 0, + CELL_MSGDIALOG_BUTTON_OK = 1, + CELL_MSGDIALOG_BUTTON_YES = 1, + CELL_MSGDIALOG_BUTTON_NO = 2, + CELL_MSGDIALOG_BUTTON_ESCAPE = 3, +}; + +typedef void(*CellMsgDialogCallback)(int buttonType, u32 userData); + +int cellMsgDialogOpen2(u32 type, mem_list_ptr_t msgString, mem_func_ptr_t callback, u32 userData, u32 extParam); +int cellMsgDialogOpenErrorCode(u32 errorCode, mem_func_ptr_t callback, mem_ptr_t userData, u32 extParam); + +int cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, mem_list_ptr_t msgString); +int cellMsgDialogProgressBarReset(u32 progressBarIndex); +int cellMsgDialogProgressBarInc(u32 progressBarIndex, u32 delta); +int cellMsgDialogClose(float delay); +int cellMsgDialogAbort(); \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index b8bf9ec0a2..304f2fd22a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -10,11 +10,11 @@ #include "cellSysutil.h" #include "cellSysutil_SaveData.h" +#include "cellMsgDialog.h" #include "cellGame.h" #include "Loader/PSF.h" -typedef void (*CellMsgDialogCallback)(int buttonType, mem_ptr_t userData); typedef void (*CellHddGameStatCallback)(mem_ptr_t cbResult, mem_ptr_t get, mem_ptr_t set); @@ -381,160 +381,6 @@ int cellSysutilUnregisterCallback(int slot) return CELL_OK; } -int cellMsgDialogOpen2(u32 type, mem_list_ptr_t msgString, mem_func_ptr_t callback, mem_ptr_t userData, u32 extParam) -{ - cellSysutil->Warning("cellMsgDialogOpen2(type=0x%x, msgString_addr=0x%x, callback_addr=0x%x, userData=0x%x, extParam=0x%x)", - type, msgString.GetAddr(), callback.GetAddr(), userData.GetAddr(), extParam); - - long style = 0; - - if(type & CELL_MSGDIALOG_DIALOG_TYPE_NORMAL) - { - style |= rICON_EXCLAMATION; - } - else - { - style |= rICON_ERROR; - } - - if(type & CELL_MSGDIALOG_BUTTON_TYPE_YESNO) - { - style |= rYES_NO; - } - else - { - style |= rOK; - } - - int res = rMessageBox(std::string(msgString.GetString()), rGetApp().GetAppName(), style); - - u64 status; - - switch(res) - { - case rOK: status = CELL_MSGDIALOG_BUTTON_OK; break; - case rYES: status = CELL_MSGDIALOG_BUTTON_YES; break; - case rNO: status = CELL_MSGDIALOG_BUTTON_NO; break; - - default: - if(res) - { - status = CELL_MSGDIALOG_BUTTON_INVALID; - break; - } - - status = CELL_MSGDIALOG_BUTTON_NONE; - break; - } - - if(callback) - callback(status, userData); - - return CELL_OK; -} - -int cellMsgDialogOpenErrorCode(u32 errorCode, mem_func_ptr_t callback, mem_ptr_t userData, u32 extParam) -{ - cellSysutil->Warning("cellMsgDialogOpenErrorCode(errorCode=0x%x, callback_addr=0x%x, userData=%d, extParam=%d)", - errorCode, callback.GetAddr(), userData, extParam); - - std::string errorMessage; - switch(errorCode) - { - // Generic errors - case 0x80010001: errorMessage = "The resource is temporarily unavailable."; break; - case 0x80010002: errorMessage = "Invalid argument or flag."; break; - case 0x80010003: errorMessage = "The feature is not yet implemented."; break; - case 0x80010004: errorMessage = "Memory allocation failed."; break; - case 0x80010005: errorMessage = "The resource with the specified identifier does not exist."; break; - case 0x80010006: errorMessage = "The file does not exist."; break; - case 0x80010007: errorMessage = "The file is in unrecognized format / The file is not a valid ELF file."; break; - case 0x80010008: errorMessage = "Resource deadlock is avoided."; break; - case 0x80010009: errorMessage = "Operation not permitted."; break; - case 0x8001000A: errorMessage = "The device or resource is bus."; break; - case 0x8001000B: errorMessage = "The operation is timed ou."; break; - case 0x8001000C: errorMessage = "The operation is aborte."; break; - case 0x8001000D: errorMessage = "Invalid memory access."; break; - case 0x8001000F: errorMessage = "State of the target thread is invalid."; break; - case 0x80010010: errorMessage = "Alignment is invalid."; break; - case 0x80010011: errorMessage = "Shortage of the kernel resources."; break; - case 0x80010012: errorMessage = "The file is a directory."; break; - case 0x80010013: errorMessage = "Operation canceled."; break; - case 0x80010014: errorMessage = "Entry already exists."; break; - case 0x80010015: errorMessage = "Port is already connected."; break; - case 0x80010016: errorMessage = "Port is not connected."; break; - case 0x80010017: errorMessage = "Failure in authorizing SELF. Program authentication fail."; break; - case 0x80010018: errorMessage = "The file is not MSELF."; break; - case 0x80010019: errorMessage = "System version error."; break; - case 0x8001001A: errorMessage = "Fatal system error occurred while authorizing SELF. SELF auth failure."; break; - case 0x8001001B: errorMessage = "Math domain violation."; break; - case 0x8001001C: errorMessage = "Math range violation."; break; - case 0x8001001D: errorMessage = "Illegal multi-byte sequence in input."; break; - case 0x8001001E: errorMessage = "File position error."; break; - case 0x8001001F: errorMessage = "Syscall was interrupted."; break; - case 0x80010020: errorMessage = "File too large."; break; - case 0x80010021: errorMessage = "Too many links."; break; - case 0x80010022: errorMessage = "File table overflow."; break; - case 0x80010023: errorMessage = "No space left on device."; break; - case 0x80010024: errorMessage = "Not a TTY."; break; - case 0x80010025: errorMessage = "Broken pipe."; break; - case 0x80010026: errorMessage = "Read-only filesystem."; break; - case 0x80010027: errorMessage = "Illegal seek."; break; - case 0x80010028: errorMessage = "Arg list too long."; break; - case 0x80010029: errorMessage = "Access violation."; break; - case 0x8001002A: errorMessage = "Invalid file descriptor."; break; - case 0x8001002B: errorMessage = "Filesystem mounting failed."; break; - case 0x8001002C: errorMessage = "Too many files open."; break; - case 0x8001002D: errorMessage = "No device."; break; - case 0x8001002E: errorMessage = "Not a directory."; break; - case 0x8001002F: errorMessage = "No such device or IO."; break; - case 0x80010030: errorMessage = "Cross-device link error."; break; - case 0x80010031: errorMessage = "Bad Message."; break; - case 0x80010032: errorMessage = "In progress."; break; - case 0x80010033: errorMessage = "Message size error."; break; - case 0x80010034: errorMessage = "Name too long."; break; - case 0x80010035: errorMessage = "No lock."; break; - case 0x80010036: errorMessage = "Not empty."; break; - case 0x80010037: errorMessage = "Not supported."; break; - case 0x80010038: errorMessage = "File-system specific error."; break; - case 0x80010039: errorMessage = "Overflow occured."; break; - case 0x8001003A: errorMessage = "Filesystem not mounted."; break; - case 0x8001003B: errorMessage = "Not SData."; break; - case 0x8001003C: errorMessage = "Incorrect version in sys_load_param."; break; - case 0x8001003D: errorMessage = "Pointer is null."; break; - case 0x8001003E: errorMessage = "Pointer is null."; break; - default: errorMessage = "An error has occurred."; break; - } - - char errorCodeHex [9]; - sprintf(errorCodeHex, "%08x", errorCode); - errorMessage.append("\n("); - errorMessage.append(errorCodeHex); - errorMessage.append(")\n"); - - u64 status; - int res = rMessageBox(errorMessage, rGetApp().GetAppName(), rICON_ERROR | rOK); - switch(res) - { - case rOK: status = CELL_MSGDIALOG_BUTTON_OK; break; - default: - if(res) - { - status = CELL_MSGDIALOG_BUTTON_INVALID; - break; - } - - status = CELL_MSGDIALOG_BUTTON_NONE; - break; - } - - if(callback) - callback(status, userData); - - return CELL_OK; -} - - int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option) { cellSysutil->Warning("cellAudioOutGetSoundAvailability(audioOut=%d, type=%d, fs=0x%x, option=%d)", @@ -1023,6 +869,11 @@ void cellSysutil_init() cellSysutil->AddFunc(0x7603d3db, cellMsgDialogOpen2); cellSysutil->AddFunc(0x3e22cb4b, cellMsgDialogOpenErrorCode); + cellSysutil->AddFunc(0x9d6af72a, cellMsgDialogProgressBarSetMsg); + cellSysutil->AddFunc(0x7bc2c8a8, cellMsgDialogProgressBarReset); + cellSysutil->AddFunc(0x94862702, cellMsgDialogProgressBarInc); + cellSysutil->AddFunc(0x20543730, cellMsgDialogClose); + cellSysutil->AddFunc(0x62b0f803, cellMsgDialogAbort); cellSysutil->AddFunc(0xf4e3caa0, cellAudioOutGetState); cellSysutil->AddFunc(0x4692ab35, cellAudioOutConfigure); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.h b/rpcs3/Emu/SysCalls/Modules/cellSysutil.h index 134c496cf4..c701590692 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.h @@ -1,5 +1,16 @@ #pragma once +enum +{ + CELL_SYSUTIL_ERROR_TYPE = 0x8002b101, + CELL_SYSUTIL_ERROR_VALUE = 0x8002b102, + CELL_SYSUTIL_ERROR_SIZE = 0x8002b103, + CELL_SYSUTIL_ERROR_NUM = 0x8002b104, + CELL_SYSUTIL_ERROR_BUSY = 0x8002b105, + CELL_SYSUTIL_ERROR_STATUS = 0x8002b106, + CELL_SYSUTIL_ERROR_MEMORY = 0x8002b107, +}; + // Parameter IDs enum { @@ -103,17 +114,6 @@ enum CELL_SYSUTIL_PAD_RUMBLE_ON = 1, }; - -enum -{ - CELL_MSGDIALOG_BUTTON_NONE = -1, - CELL_MSGDIALOG_BUTTON_INVALID = 0, - CELL_MSGDIALOG_BUTTON_OK = 1, - CELL_MSGDIALOG_BUTTON_YES = 1, - CELL_MSGDIALOG_BUTTON_NO = 2, - CELL_MSGDIALOG_BUTTON_ESCAPE = 3, -}; - enum { CELL_SYSCACHE_RET_OK_CLEARED = 0, @@ -129,19 +129,6 @@ enum CELL_SYSCACHE_ERROR_NOTMOUNTED = 0x8002bc04, // We don't really need to simulate the mounting, so this is probably useless }; -enum CellMsgDialogType -{ - CELL_MSGDIALOG_DIALOG_TYPE_ERROR = 0x00000000, - CELL_MSGDIALOG_DIALOG_TYPE_NORMAL = 0x00000001, - - CELL_MSGDIALOG_BUTTON_TYPE_NONE = 0x00000000, - CELL_MSGDIALOG_BUTTON_TYPE_YESNO = 0x00000010, - - CELL_MSGDIALOG_DEFAULT_CURSOR_YES = 0x00000000, - CELL_MSGDIALOG_DEFAULT_CURSOR_NO = 0x00000100, -}; - - // cellSysutil: cellHddGame enum { diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index fb34b8f476..0e7ffa8e21 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -144,6 +144,7 @@ + @@ -342,6 +343,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index cc85fc9f6c..377aeab4d4 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -587,6 +587,9 @@ Utilities + + Emu\SysCalls\Modules + @@ -1075,5 +1078,8 @@ Emu\SysCalls\Modules + + Emu\SysCalls\Modules + \ No newline at end of file