diff --git a/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp b/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp index 538b414342..96b803e15a 100644 --- a/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp +++ b/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp @@ -90,6 +90,23 @@ void fmt_class_string::format(std::string& out, u64 arg) }); } +struct CellGameUpdateResult +{ + be_t status; // CellGameUpdateResultStatus + be_t error_code; + char app_ver[CELL_GAME_SYSP_APP_VER_SIZE]; + char padding[2]; +}; + +struct CellGameUpdateParam +{ + be_t size; + be_t cid; +}; + +using CellGameUpdateCallback = void(s32 status, s32 error_code, vm::ptr userdata); +using CellGameUpdateCallbackEx = void(vm::ptr result, vm::ptr userdata); + error_code cellNetCtlInit() { cellNetCtl.warning("cellNetCtlInit()"); diff --git a/rpcs3/Emu/Cell/Modules/cellNetCtl.h b/rpcs3/Emu/Cell/Modules/cellNetCtl.h index 7b4cf807e0..b5f031a088 100644 --- a/rpcs3/Emu/Cell/Modules/cellNetCtl.h +++ b/rpcs3/Emu/Cell/Modules/cellNetCtl.h @@ -1,7 +1,5 @@ #pragma once -#include "cellGame.h" - #include "Emu/Memory/vm_ptr.h" // Error Codes @@ -335,20 +333,3 @@ enum CELL_GAMEUPDATE_RESULT_STATUS_ABORTED = 6, CELL_GAMEUPDATE_RESULT_STATUS_SYSTEM_UPDATE_NEEDED = 7 }; - -struct CellGameUpdateResult -{ - be_t status; // CellGameUpdateResultStatus - be_t error_code; - char app_ver[CELL_GAME_SYSP_APP_VER_SIZE]; - char padding[2]; -}; - -struct CellGameUpdateParam -{ - be_t size; - be_t cid; -}; - -using CellGameUpdateCallback = void(s32 status, s32 error_code, vm::ptr userdata); -using CellGameUpdateCallbackEx = void(vm::ptr result, vm::ptr userdata); diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 57481f0a17..c990a14684 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -377,6 +377,9 @@ true + + true + true @@ -611,6 +614,9 @@ true + + true + true @@ -689,6 +695,7 @@ + @@ -1354,6 +1361,16 @@ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg" + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DHAVE_SDL2 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\libsdl-org\SDL\include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg" + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index a0789c9f96..de35dad43e 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -927,6 +927,15 @@ Gui\progress + + Gui\dev tools + + + Generated Files\Debug + + + Generated Files\Release + @@ -1372,6 +1381,9 @@ Form Files + + Gui\dev tools + diff --git a/rpcs3/rpcs3qt/CMakeLists.txt b/rpcs3/rpcs3qt/CMakeLists.txt index f25ece7343..6813c1f9fd 100644 --- a/rpcs3/rpcs3qt/CMakeLists.txt +++ b/rpcs3/rpcs3qt/CMakeLists.txt @@ -80,6 +80,7 @@ set(SRC_FILES shortcut_settings.cpp skylander_dialog.cpp syntax_highlighter.cpp + system_cmd_dialog.cpp tooltips.cpp trophy_manager_dialog.cpp trophy_notification_frame.cpp diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 2f32f244e2..9b819e1ae5 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -33,6 +33,7 @@ #include "shortcut_utils.h" #include "config_checker.h" #include "shortcut_dialog.h" +#include "system_cmd_dialog.h" #include #include @@ -1878,6 +1879,12 @@ void main_window::OnEmuStop() { m_kernel_explorer->close(); } + + // Close systen command dialog if running + if (m_system_cmd_dialog) + { + m_system_cmd_dialog->close(); + } } void main_window::OnEmuReady() const @@ -1925,6 +1932,7 @@ void main_window::EnableMenus(bool enabled) const ui->toolsmemory_viewerAct->setEnabled(enabled); ui->toolsRsxDebuggerAct->setEnabled(enabled); ui->toolsStringSearchAct->setEnabled(enabled); + ui->toolsSystemCommandsAct->setEnabled(enabled); ui->actionCreate_RSX_Capture->setEnabled(enabled); ui->actionCreate_Savestate->setEnabled(enabled); } @@ -2539,6 +2547,17 @@ void main_window::CreateConnects() idm::make(this, make_basic_ppu_disasm()); }); + connect(ui->toolsSystemCommandsAct, &QAction::triggered, this, [this] + { + if (Emu.IsStopped()) return; + if (!m_system_cmd_dialog) + { + m_system_cmd_dialog = new system_cmd_dialog(this); + connect(m_system_cmd_dialog, &QDialog::finished, this, [this]() { m_system_cmd_dialog = nullptr; }); + } + m_system_cmd_dialog->show(); + }); + connect(ui->toolsDecryptSprxLibsAct, &QAction::triggered, this, &main_window::DecryptSPRXLibraries); connect(ui->toolsExtractMSELFAct, &QAction::triggered, this, &main_window::ExtractMSELF); diff --git a/rpcs3/rpcs3qt/main_window.h b/rpcs3/rpcs3qt/main_window.h index 13a4d42925..f4f86c87e4 100644 --- a/rpcs3/rpcs3qt/main_window.h +++ b/rpcs3/rpcs3qt/main_window.h @@ -24,6 +24,7 @@ class gui_settings; class emu_settings; class persistent_settings; class kernel_explorer; +class system_cmd_dialog; struct gui_game_info; @@ -182,6 +183,7 @@ private: debugger_frame* m_debugger_frame = nullptr; game_list_frame* m_game_list_frame = nullptr; kernel_explorer* m_kernel_explorer = nullptr; + system_cmd_dialog* m_system_cmd_dialog = nullptr; std::shared_ptr m_gui_settings; std::shared_ptr m_emu_settings; std::shared_ptr m_persistent_settings; diff --git a/rpcs3/rpcs3qt/main_window.ui b/rpcs3/rpcs3qt/main_window.ui index e9ad162c66..99d33c2a85 100644 --- a/rpcs3/rpcs3qt/main_window.ui +++ b/rpcs3/rpcs3qt/main_window.ui @@ -275,6 +275,7 @@ + @@ -1245,6 +1246,14 @@ Shortcuts + + + false + + + System Commands + + diff --git a/rpcs3/rpcs3qt/system_cmd_dialog.cpp b/rpcs3/rpcs3qt/system_cmd_dialog.cpp new file mode 100644 index 0000000000..45ce75dbc5 --- /dev/null +++ b/rpcs3/rpcs3qt/system_cmd_dialog.cpp @@ -0,0 +1,175 @@ +#include "stdafx.h" +#include "system_cmd_dialog.h" + +#include "Emu/System.h" +#include "Emu/Cell/Modules/cellSysutil.h" +#include "Emu/Cell/Modules/cellNetCtl.h" +#include "Emu/Cell/Modules/cellOskDialog.h" + +#include +#include +#include +#include +#include +#include + +LOG_CHANNEL(gui_log, "GUI"); + +system_cmd_dialog::system_cmd_dialog(QWidget* parent) + : QDialog(parent) +{ + setWindowTitle(tr("System Commands | %1").arg(QString::fromStdString(Emu.GetTitleAndTitleID()))); + setObjectName("system_cmd_dialog"); + setAttribute(Qt::WA_DeleteOnClose); + + QPushButton* button_send = new QPushButton(tr("Send Command"), this); + connect(button_send, &QAbstractButton::clicked, this, &system_cmd_dialog::send_command); + + QPushButton* button_send_custom = new QPushButton(tr("Send Custom Command"), this); + connect(button_send_custom, &QAbstractButton::clicked, this, &system_cmd_dialog::send_custom_command); + + const QFont mono = QFontDatabase::systemFont(QFontDatabase::FixedFont); + + m_value_input = new QLineEdit(); + m_value_input->setFont(mono); + m_value_input->setMaxLength(18); + m_value_input->setValidator(new QRegularExpressionValidator(QRegularExpression("^(0[xX])?0*[a-fA-F0-9]{0,8}$"))); + m_value_input->setPlaceholderText(QString("0x%1").arg(0, 16, 16, QChar('0'))); + + m_custom_command_input = new QLineEdit(); + m_custom_command_input->setFont(mono); + m_custom_command_input->setMaxLength(18); + m_custom_command_input->setValidator(new QRegularExpressionValidator(QRegularExpression("^(0[xX])?0*[a-fA-F0-9]{0,8}$"))); + m_custom_command_input->setPlaceholderText(QString("0x%1").arg(0, 16, 16, QChar('0'))); + + m_command_box = new QComboBox(); + + const std::map commands + { + { CELL_SYSUTIL_REQUEST_EXITGAME, "CELL_SYSUTIL_REQUEST_EXITGAME " }, + { CELL_SYSUTIL_DRAWING_BEGIN, "CELL_SYSUTIL_DRAWING_BEGIN" }, + { CELL_SYSUTIL_DRAWING_END, "CELL_SYSUTIL_DRAWING_END" }, + { CELL_SYSUTIL_SYSTEM_MENU_OPEN, "CELL_SYSUTIL_SYSTEM_MENU_OPEN" }, + { CELL_SYSUTIL_SYSTEM_MENU_CLOSE, "CELL_SYSUTIL_SYSTEM_MENU_CLOSE" }, + { CELL_SYSUTIL_BGMPLAYBACK_PLAY, "CELL_SYSUTIL_BGMPLAYBACK_PLAY" }, + { CELL_SYSUTIL_BGMPLAYBACK_STOP, "CELL_SYSUTIL_BGMPLAYBACK_STOP" }, + { CELL_SYSUTIL_NP_INVITATION_SELECTED, "CELL_SYSUTIL_NP_INVITATION_SELECTED" }, + { CELL_SYSUTIL_NP_DATA_MESSAGE_SELECTED, "CELL_SYSUTIL_NP_DATA_MESSAGE_SELECTED" }, + { CELL_SYSUTIL_SYSCHAT_START, "CELL_SYSUTIL_SYSCHAT_START" }, + { CELL_SYSUTIL_SYSCHAT_STOP, "CELL_SYSUTIL_SYSCHAT_STOP" }, + { CELL_SYSUTIL_SYSCHAT_VOICE_STREAMING_RESUMED, "CELL_SYSUTIL_SYSCHAT_VOICE_STREAMING_RESUMED" }, + { CELL_SYSUTIL_SYSCHAT_VOICE_STREAMING_PAUSED, "CELL_SYSUTIL_SYSCHAT_VOICE_STREAMING_PAUSED" }, + { CELL_SYSUTIL_NET_CTL_NETSTART_LOADED, "CELL_SYSUTIL_NET_CTL_NETSTART_LOADED" }, + { CELL_SYSUTIL_NET_CTL_NETSTART_FINISHED, "CELL_SYSUTIL_NET_CTL_NETSTART_FINISHED" }, + { CELL_SYSUTIL_NET_CTL_NETSTART_UNLOADED, "CELL_SYSUTIL_NET_CTL_NETSTART_UNLOADED" }, + { CELL_SYSUTIL_OSKDIALOG_LOADED, "CELL_SYSUTIL_OSKDIALOG_LOADED" }, + { CELL_SYSUTIL_OSKDIALOG_FINISHED, "CELL_SYSUTIL_OSKDIALOG_FINISHED" }, + { CELL_SYSUTIL_OSKDIALOG_UNLOADED, "CELL_SYSUTIL_OSKDIALOG_UNLOADED" }, + { CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED, "CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED" }, + { CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED, "CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED" }, + { CELL_SYSUTIL_OSKDIALOG_INPUT_DEVICE_CHANGED, "CELL_SYSUTIL_OSKDIALOG_INPUT_DEVICE_CHANGED" }, + { CELL_SYSUTIL_OSKDIALOG_DISPLAY_CHANGED, "CELL_SYSUTIL_OSKDIALOG_DISPLAY_CHANGED" }, + }; + + for (const auto& [status, text] : commands) + { + m_command_box->addItem(text, static_cast(status)); + } + + QGroupBox* commands_group = new QGroupBox(tr("Select Command")); + QHBoxLayout* hbox_commands = new QHBoxLayout(); + hbox_commands->addWidget(m_command_box); + commands_group->setLayout(hbox_commands); + + QGroupBox* custom_commands_group = new QGroupBox(tr("Select Custom Command")); + QHBoxLayout* hbox_custom_commands = new QHBoxLayout(); + hbox_custom_commands->addWidget(m_custom_command_input); + custom_commands_group->setLayout(hbox_custom_commands); + + QGroupBox* value_group = new QGroupBox(tr("Select Value")); + QHBoxLayout* hbox_value = new QHBoxLayout(); + hbox_value->addWidget(m_value_input); + value_group->setLayout(hbox_value); + + QHBoxLayout* hbox_buttons = new QHBoxLayout(); + hbox_buttons->addWidget(button_send); + hbox_buttons->addWidget(button_send_custom); + + QVBoxLayout* vbox_panel = new QVBoxLayout(); + vbox_panel->addWidget(commands_group); + vbox_panel->addWidget(custom_commands_group); + vbox_panel->addWidget(value_group); + vbox_panel->addLayout(hbox_buttons); + setLayout(vbox_panel); +} + +system_cmd_dialog::~system_cmd_dialog() +{ +} + +void system_cmd_dialog::send_command() +{ + bool ok = false; + + const qulonglong status = m_command_box->currentData().toULongLong(&ok); + if (!ok) + { + gui_log.error("system_cmd_dialog::send_command: command can not be converted to qulonglong: %s", m_command_box->currentText().toStdString()); + QMessageBox::warning(this, tr("Listen!"), tr("The selected command is bugged.\nPlease contact a developer.")); + return; + } + + const qulonglong param = hex_value(m_value_input->text(), ok); + if (!ok) + { + gui_log.error("system_cmd_dialog::send_command: value can not be converted to qulonglong: %s", m_value_input->text().toStdString()); + QMessageBox::information(this, tr("Listen!"), tr("Please select a proper value first.")); + return; + } + + send_cmd(status, param); +} + +void system_cmd_dialog::send_custom_command() +{ + bool ok = false; + + const qulonglong status = hex_value(m_custom_command_input->text(), ok); + if (!ok) + { + gui_log.error("system_cmd_dialog::send_custom_command: command can not be converted to qulonglong: %s", m_custom_command_input->text().toStdString()); + QMessageBox::information(this, tr("Listen!"), tr("Please select a proper custom command first.")); + return; + } + + const qulonglong param = hex_value(m_value_input->text(), ok); + if (!ok) + { + gui_log.error("system_cmd_dialog::send_custom_command: value can not be converted to qulonglong: %s", m_value_input->text().toStdString()); + QMessageBox::information(this, tr("Listen!"), tr("Please select a proper value first.")); + return; + } + + send_cmd(status, param); +} + +void system_cmd_dialog::send_cmd(qulonglong status, qulonglong param) const +{ + if (Emu.IsStopped()) + { + return; + } + + gui_log.warning("User triggered sysutil_send_system_cmd(status=0x%x, param=0x%x) in system_cmd_dialog", status, param); + + if (s32 ret = sysutil_send_system_cmd(status, param); ret < 0) + { + gui_log.error("sysutil_send_system_cmd(status=0x%x, param=0x%x) failed with 0x%x", status, param, ret); + } +} + +qulonglong system_cmd_dialog::hex_value(QString text, bool& ok) const +{ + if (!text.startsWith("0x")) text.prepend("0x"); + return text.toULongLong(&ok, 16); +} diff --git a/rpcs3/rpcs3qt/system_cmd_dialog.h b/rpcs3/rpcs3qt/system_cmd_dialog.h new file mode 100644 index 0000000000..c661421902 --- /dev/null +++ b/rpcs3/rpcs3qt/system_cmd_dialog.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +class system_cmd_dialog : public QDialog +{ + Q_OBJECT + +public: + system_cmd_dialog(QWidget* parent = nullptr); + ~system_cmd_dialog(); + +private Q_SLOTS: + void send_command(); + void send_custom_command(); + +private: + void send_cmd(qulonglong status, qulonglong param) const; + qulonglong hex_value(QString text, bool& ok) const; + + QLineEdit* m_value_input = nullptr; + QLineEdit* m_custom_command_input = nullptr; + QComboBox* m_command_box = nullptr; +};