From 429b4594d0daedee6c5a6edf13ef30e36edbe7eb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 7 Apr 2021 18:07:48 -0700 Subject: [PATCH] Dialog: Use a thread to init dialogs too. --- Core/Dialog/PSPDialog.cpp | 20 +++++++++++++++++--- Core/Dialog/PSPDialog.h | 1 + Core/HLE/sceUtility.cpp | 36 ++++++++++++++++++++++++++++++++++++ Core/HLE/sceUtility.h | 1 + 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index f15ea6da63..e11837b65a 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -75,6 +75,7 @@ void PSPDialog::ChangeStatus(DialogStatus newStatus, int delayUs) { } } status = newStatus; + pendingStatus = newStatus; pendingStatusTicks = 0; } else { pendingStatus = newStatus; @@ -93,6 +94,13 @@ void PSPDialog::FinishVolatile() { } } +int PSPDialog::FinishInit() { + if (ReadStatus() != SCE_UTILITY_STATUS_INITIALIZE) + return -1; + ChangeStatus(SCE_UTILITY_STATUS_RUNNING, 0); + return 0; +} + int PSPDialog::FinishShutdown() { if (ReadStatus() != SCE_UTILITY_STATUS_SHUTDOWN) return -1; @@ -101,12 +109,18 @@ int PSPDialog::FinishShutdown() { } void PSPDialog::ChangeStatusInit(int delayUs) { - status = SCE_UTILITY_STATUS_INITIALIZE; - ChangeStatus(SCE_UTILITY_STATUS_RUNNING, delayUs); + ChangeStatus(SCE_UTILITY_STATUS_INITIALIZE, 0); + + auto params = GetCommonParam(); + if (params) + UtilityDialogInitialize(DialogType(), delayUs, params->accessThread); + else + ChangeStatus(SCE_UTILITY_STATUS_RUNNING, delayUs); } void PSPDialog::ChangeStatusShutdown(int delayUs) { - status = SCE_UTILITY_STATUS_SHUTDOWN; + ChangeStatus(SCE_UTILITY_STATUS_SHUTDOWN, 0); + auto params = GetCommonParam(); if (params) UtilityDialogShutdown(DialogType(), delayUs, params->accessThread); diff --git a/Core/Dialog/PSPDialog.h b/Core/Dialog/PSPDialog.h index e340314d18..54c95e217b 100644 --- a/Core/Dialog/PSPDialog.h +++ b/Core/Dialog/PSPDialog.h @@ -86,6 +86,7 @@ public: void EndDraw(); void FinishVolatile(); + int FinishInit(); int FinishShutdown(); protected: diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 82873e4896..dc6a6ba683 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -270,6 +270,30 @@ void __UtilityShutdown() { delete gamedataInstallDialog; } +void UtilityDialogInitialize(UtilityDialogType type, int delayUs, int priority) { + int partDelay = delayUs / 4; + const u32_le insts[] = { + // Make sure we don't discard/deadbeef 'em. + (u32_le)MIPS_MAKE_ORI(MIPS_REG_S0, MIPS_REG_A0, 0), + (u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityWorkUs"), + (u32_le)MIPS_MAKE_ORI(MIPS_REG_A0, MIPS_REG_S0, 0), + (u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityWorkUs"), + (u32_le)MIPS_MAKE_ORI(MIPS_REG_A0, MIPS_REG_S0, 0), + (u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityWorkUs"), + (u32_le)MIPS_MAKE_ORI(MIPS_REG_A0, MIPS_REG_S0, 0), + (u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityWorkUs"), + + (u32_le)MIPS_MAKE_ORI(MIPS_REG_A0, MIPS_REG_ZERO, (int)type), + (u32_le)MIPS_MAKE_JR_RA(), + (u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityInitDialog"), + }; + + CleanupDialogThreads(); + _assert_(accessThread == nullptr); + accessThread = new HLEHelperThread("ScePafJob", insts, (uint32_t)ARRAY_SIZE(insts), priority, 0x200); + accessThread->Start(partDelay, 0); +} + void UtilityDialogShutdown(UtilityDialogType type, int delayUs, int priority) { // Break it up so better-priority rescheduling happens. // The windows aren't this regular, but close. @@ -299,11 +323,22 @@ void UtilityDialogShutdown(UtilityDialogType type, int delayUs, int priority) { static int UtilityWorkUs(int us) { // This blocks, but other better priority threads can get time. // Simulate this by allowing a reschedule. + if (us > 1000) { + hleEatMicro(us - 400); + return hleDelayResult(0, "utility work", 400); + } hleEatMicro(us); hleReSchedule("utility work"); return 0; } +static int UtilityInitDialog(int type) { + PSPDialog *dialog = CurrentDialog((UtilityDialogType)type); + if (dialog) + return hleLogSuccessI(SCEUTILITY, dialog->FinishInit()); + return hleLogError(SCEUTILITY, 0, "invalid dialog type?"); +} + static int UtilityFinishDialog(int type) { PSPDialog *dialog = CurrentDialog((UtilityDialogType)type); if (dialog) @@ -1046,6 +1081,7 @@ const HLEFunction sceUtility[] = // Fake functions for PPSSPP's use. {0xC0DE0001, &WrapI_I, "__UtilityFinishDialog", 'i', "i" }, {0xC0DE0002, &WrapI_I, "__UtilityWorkUs", 'i', "i" }, + {0xC0DE0003, &WrapI_I, "__UtilityInitDialog", 'i', "i" }, }; void Register_sceUtility() diff --git a/Core/HLE/sceUtility.h b/Core/HLE/sceUtility.h index 1cc4798a0a..510b22ea72 100644 --- a/Core/HLE/sceUtility.h +++ b/Core/HLE/sceUtility.h @@ -94,6 +94,7 @@ void __UtilityInit(); void __UtilityDoState(PointerWrap &p); void __UtilityShutdown(); +void UtilityDialogInitialize(UtilityDialogType type, int delayUs, int priority); void UtilityDialogShutdown(UtilityDialogType type, int delayUs, int priority); void Register_sceUtility();