From c4b4ce46b8c2d58016415f1a5d711a7b95ed7837 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 29 Dec 2019 01:01:54 +0100 Subject: [PATCH] cellSaveData: don't pause apps during dialogs --- rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp | 177 ++++++++---------- rpcs3/Emu/Cell/Modules/cellSaveData.cpp | 43 +++-- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 2 +- .../RSX/Overlays/overlay_message_dialog.cpp | 26 ++- rpcs3/Emu/RSX/Overlays/overlays.h | 2 +- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 2 +- 6 files changed, 137 insertions(+), 115 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp index c552be59c9..c605e5a493 100644 --- a/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp @@ -92,35 +92,98 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr msgString, { 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); - const error_code res = cellMsgDialogOpen2(type, msgString, callback, userData, extParam); + const MsgDialogType _type{ type }; - if (res == CELL_OK && is_blocking) + if (auto manager = g_fxo->get()) { - if (auto manager = g_fxo->get()) + if (manager->get()) { - while (auto dlg = manager->get()) - { - if (Emu.IsStopped()) - { - break; - } - dlg->refresh(); - } + return CELL_SYSUTIL_ERROR_BUSY; } - else + + g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE; + + const auto res = manager->create()->show(is_blocking, msgString.get_ptr(), _type, [callback, userData](s32 status) { - while (auto dlg = g_fxo->get()->get()) + if (callback) { - if (Emu.IsStopped() || dlg->state != MsgDialogState::Open) + sysutil_register_cb([=](ppu_thread& ppu) -> s32 { - break; - } - std::this_thread::yield(); + callback(ppu, status, userData); + return CELL_OK; + }); } + }); + + return res; + } + + const auto dlg = g_fxo->get()->make(); + + if (!dlg) + { + return CELL_SYSUTIL_ERROR_BUSY; + } + + dlg->type = _type; + + dlg->on_close = [callback, userData, wptr = std::weak_ptr(dlg)](s32 status) + { + const auto dlg = wptr.lock(); + + if (dlg && dlg->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Close)) + { + if (callback) + { + sysutil_register_cb([=](ppu_thread& ppu) -> s32 + { + callback(ppu, status, userData); + return CELL_OK; + }); + } + + g_fxo->get()->remove(); + } + + pad::SetIntercepted(false); + }; + + pad::SetIntercepted(true); + + auto& ppu = *get_current_cpu_thread(); + lv2_obj::sleep(ppu); + + // Run asynchronously in GUI thread + Emu.CallAfter([&]() + { + g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE; + dlg->Create(msgString.get_ptr()); + lv2_obj::awake(&ppu); + }); + + while (!ppu.state.test_and_reset(cpu_flag::signal)) + { + if (ppu.is_stopped()) + { + return 0; + } + + thread_ctrl::wait(); + } + + if (is_blocking) + { + while (auto dlg = g_fxo->get()->get()) + { + if (Emu.IsStopped() || dlg->state != MsgDialogState::Open) + { + break; + } + std::this_thread::yield(); } } - return res; + return CELL_OK; } void exit_game(s32/* buttonType*/, vm::ptr/* userData*/) @@ -216,84 +279,8 @@ error_code cellMsgDialogOpen2(u32 type, vm::cptr msgString, vm::ptrget()) - { - if (manager->get()) - { - return CELL_SYSUTIL_ERROR_BUSY; - } - g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE; - - const auto res = manager->create()->show(msgString.get_ptr(), _type, [callback, userData](s32 status) - { - if (callback) - { - sysutil_register_cb([=](ppu_thread& ppu) -> s32 - { - callback(ppu, status, userData); - return CELL_OK; - }); - } - }); - - return res; - } - - const auto dlg = g_fxo->get()->make(); - - if (!dlg) - { - return CELL_SYSUTIL_ERROR_BUSY; - } - - dlg->type = _type; - - dlg->on_close = [callback, userData, wptr = std::weak_ptr(dlg)](s32 status) - { - const auto dlg = wptr.lock(); - - if (dlg && dlg->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Close)) - { - if (callback) - { - sysutil_register_cb([=](ppu_thread& ppu) -> s32 - { - callback(ppu, status, userData); - return CELL_OK; - }); - } - - g_fxo->get()->remove(); - } - - pad::SetIntercepted(false); - }; - - pad::SetIntercepted(true); - - auto& ppu = *get_current_cpu_thread(); - lv2_obj::sleep(ppu); - - // Run asynchronously in GUI thread - Emu.CallAfter([&]() - { - g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE; - dlg->Create(msgString.get_ptr()); - lv2_obj::awake(&ppu); - }); - - while (!ppu.state.test_and_reset(cpu_flag::signal)) - { - if (ppu.is_stopped()) - { - return 0; - } - - thread_ctrl::wait(); - } - - return CELL_OK; + return open_msg_dialog(false, type, msgString, callback, userData, extParam); } error_code cellMsgDialogOpen(u32 type, vm::cptr msgString, vm::ptr callback, vm::ptr userData, vm::ptr extParam) diff --git a/rpcs3/Emu/Cell/Modules/cellSaveData.cpp b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp index 809f43ff67..5b1373b01d 100644 --- a/rpcs3/Emu/Cell/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp @@ -173,15 +173,14 @@ static error_code select_and_delete(ppu_thread& ppu) selected = save_dialog->ShowSaveDataList(save_entries, focused, SAVEDATA_OP_LIST_DELETE, vm::null); } - // Reschedule - if (ppu.check_state()) - { - return 0; - } - // Abort if dialog was canceled or selection is invalid in this context if (selected < 0) { + // Reschedule + if (ppu.check_state()) + { + return 0; + } return CELL_CANCEL; } @@ -196,6 +195,12 @@ static error_code select_and_delete(ppu_thread& ppu) std::string msg = "Do you really want to delete this entry?\n\n" + info; error_code res = open_msg_dialog(true, CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO, vm::make_str(msg)); + // Reschedule + if (ppu.check_state()) + { + return 0; + } + if (res != CELL_OK) { return CELL_SAVEDATA_ERROR_INTERNAL; @@ -805,15 +810,14 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v selected = -2; } - // Reschedule - if (ppu.check_state()) - { - return 0; - } - // Cancel selected in UI if (selected == -2) { + // Reschedule + if (ppu.check_state()) + { + return 0; + } return CELL_CANCEL; } @@ -836,6 +840,12 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v // Get user confirmation error_code res = open_msg_dialog(true, CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO, vm::make_str(message)); + // Reschedule + if (ppu.check_state()) + { + return 0; + } + if (res != CELL_OK) { return CELL_SAVEDATA_ERROR_INTERNAL; @@ -918,6 +928,9 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v if (fixedSet->option != CELL_SAVEDATA_OPTION_NOCONFIRM) { + // Yield + lv2_obj::sleep(ppu); + std::string message; if (selected == -1) @@ -934,6 +947,12 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v // Get user confirmation error_code res = open_msg_dialog(true, CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO, vm::make_str(message)); + // Reschedule + if (ppu.check_state()) + { + return 0; + } + if (res != CELL_OK) { return CELL_SAVEDATA_ERROR_INTERNAL; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 0a4073d16d..81107446a8 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -927,7 +927,7 @@ void GLGSRender::on_init_thread() dlg = g_fxo->get()->create(!!g_cfg.video.shader_preloading_dialog.use_custom_background); dlg->progress_bar_set_taskbar_index(-1); - dlg->show("Loading precompiled shaders from disk...", type, [](s32 status) + dlg->show(false, "Loading precompiled shaders from disk...", type, [](s32 status) { if (status != CELL_OK) Emu.Stop(); diff --git a/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp b/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp index c077ddd070..4309cd8753 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp @@ -57,7 +57,7 @@ namespace rsx if (background_image->data) { - f32 color = (100 - g_cfg.video.shader_preloading_dialog.darkening_strength) / 100.f; + const f32 color = (100 - g_cfg.video.shader_preloading_dialog.darkening_strength) / 100.f; background_poster.fore_color = color4f(color, color, color, 1.); background.back_color.a = 0.f; @@ -154,7 +154,7 @@ namespace rsx close(); } - error_code message_dialog::show(const std::string& text, const MsgDialogType& type, std::function on_close) + error_code message_dialog::show(bool is_blocking, const std::string& text, const MsgDialogType& type, std::function on_close) { num_progress_bars = type.progress_bar_count; if (num_progress_bars) @@ -197,18 +197,34 @@ namespace rsx interactive = true; ok_only = true; break; - case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO: interactive = true; break; + case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO: + interactive = true; + break; + default: + break; } this->on_close = std::move(on_close); if (interactive) { - thread_ctrl::spawn("dialog input thread", [&] { + if (is_blocking) + { if (auto error = run_input_loop()) { LOG_ERROR(RSX, "Dialog input loop exited with error code=%d", error); + return error; } - }); + } + else + { + thread_ctrl::spawn("dialog input thread", [&] + { + if (auto error = run_input_loop()) + { + LOG_ERROR(RSX, "Dialog input loop exited with error code=%d", error); + } + }); + } } return CELL_OK; diff --git a/rpcs3/Emu/RSX/Overlays/overlays.h b/rpcs3/Emu/RSX/Overlays/overlays.h index 70080c3d31..1558babd3d 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.h +++ b/rpcs3/Emu/RSX/Overlays/overlays.h @@ -485,7 +485,7 @@ namespace rsx void on_button_pressed(pad_button button_press) override; - error_code show(const std::string& text, const MsgDialogType& type, std::function on_close); + error_code show(bool is_blocking, const std::string& text, const MsgDialogType& type, std::function on_close); u32 progress_bar_count(); void progress_bar_set_taskbar_index(s32 index); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index c7fd087fe9..e862c897c5 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1895,7 +1895,7 @@ void VKGSRender::on_init_thread() dlg = g_fxo->get()->create(!!g_cfg.video.shader_preloading_dialog.use_custom_background); dlg->progress_bar_set_taskbar_index(-1); - dlg->show("Loading precompiled shaders from disk...", type, [](s32 status) + dlg->show(false, "Loading precompiled shaders from disk...", type, [](s32 status) { if (status != CELL_OK) Emu.Stop();