mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Dialog: Respect accessThread priority on shutdown.
This influences shutdown timing.
This commit is contained in:
parent
d066b39334
commit
52c5f4bf95
4 changed files with 118 additions and 25 deletions
|
@ -41,15 +41,10 @@ PSPDialog::DialogStatus PSPDialog::GetStatus() {
|
|||
if (pendingStatusTicks != 0 && CoreTiming::GetTicks() >= pendingStatusTicks) {
|
||||
bool changeAllowed = true;
|
||||
if (pendingStatus == SCE_UTILITY_STATUS_NONE && status == SCE_UTILITY_STATUS_SHUTDOWN) {
|
||||
if (volatileLocked_) {
|
||||
FinishVolatile();
|
||||
UtilityCancelVolatileUnlock();
|
||||
volatileLocked_ = false;
|
||||
}
|
||||
FinishVolatile();
|
||||
} else if (pendingStatus == SCE_UTILITY_STATUS_RUNNING && status == SCE_UTILITY_STATUS_INITIALIZE) {
|
||||
if (!volatileLocked_) {
|
||||
volatileLocked_ = KernelVolatileMemLock(0, 0, 0) == 0;
|
||||
UtilityCancelVolatileUnlock();
|
||||
changeAllowed = volatileLocked_;
|
||||
}
|
||||
}
|
||||
|
@ -72,16 +67,11 @@ PSPDialog::DialogStatus PSPDialog::GetStatus() {
|
|||
void PSPDialog::ChangeStatus(DialogStatus newStatus, int delayUs) {
|
||||
if (delayUs <= 0) {
|
||||
if (newStatus == SCE_UTILITY_STATUS_NONE && status == SCE_UTILITY_STATUS_SHUTDOWN) {
|
||||
if (volatileLocked_) {
|
||||
FinishVolatile();
|
||||
UtilityCancelVolatileUnlock();
|
||||
volatileLocked_ = false;
|
||||
}
|
||||
FinishVolatile();
|
||||
} else if (newStatus == SCE_UTILITY_STATUS_RUNNING && status == SCE_UTILITY_STATUS_INITIALIZE) {
|
||||
if (!volatileLocked_) {
|
||||
// TODO: Should probably make the status pending instead?
|
||||
volatileLocked_ = KernelVolatileMemLock(0, 0, 0) == 0;
|
||||
UtilityCancelVolatileUnlock();
|
||||
}
|
||||
}
|
||||
status = newStatus;
|
||||
|
@ -89,20 +79,27 @@ void PSPDialog::ChangeStatus(DialogStatus newStatus, int delayUs) {
|
|||
} else {
|
||||
pendingStatus = newStatus;
|
||||
pendingStatusTicks = CoreTiming::GetTicks() + usToCycles(delayUs);
|
||||
if (volatileLocked_ && newStatus == SCE_UTILITY_STATUS_NONE && status == SCE_UTILITY_STATUS_SHUTDOWN) {
|
||||
UtilityScheduleVolatileUnlock(usToCycles(delayUs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PSPDialog::FinishVolatile() {
|
||||
if (volatileLocked_ && KernelVolatileMemUnlock(0) == 0) {
|
||||
if (!volatileLocked_)
|
||||
return;
|
||||
|
||||
if (KernelVolatileMemUnlock(0) == 0) {
|
||||
volatileLocked_ = false;
|
||||
// Simulate modifications to volatile memory.
|
||||
Memory::Memset(PSP_GetVolatileMemoryStart(), 0, PSP_GetVolatileMemoryEnd() - PSP_GetVolatileMemoryStart());
|
||||
}
|
||||
}
|
||||
|
||||
int PSPDialog::FinishShutdown() {
|
||||
if (ReadStatus() != SCE_UTILITY_STATUS_SHUTDOWN)
|
||||
return -1;
|
||||
ChangeStatus(SCE_UTILITY_STATUS_NONE, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PSPDialog::ChangeStatusInit(int delayUs) {
|
||||
status = SCE_UTILITY_STATUS_INITIALIZE;
|
||||
ChangeStatus(SCE_UTILITY_STATUS_RUNNING, delayUs);
|
||||
|
@ -110,7 +107,11 @@ void PSPDialog::ChangeStatusInit(int delayUs) {
|
|||
|
||||
void PSPDialog::ChangeStatusShutdown(int delayUs) {
|
||||
status = SCE_UTILITY_STATUS_SHUTDOWN;
|
||||
ChangeStatus(SCE_UTILITY_STATUS_NONE, delayUs);
|
||||
auto params = GetCommonParam();
|
||||
if (params)
|
||||
UtilityDialogShutdown(DialogType(), delayUs, params->accessThread);
|
||||
else
|
||||
ChangeStatus(SCE_UTILITY_STATUS_NONE, delayUs);
|
||||
}
|
||||
|
||||
void PSPDialog::StartDraw()
|
||||
|
|
|
@ -86,6 +86,7 @@ public:
|
|||
void EndDraw();
|
||||
|
||||
void FinishVolatile();
|
||||
int FinishShutdown();
|
||||
|
||||
protected:
|
||||
PPGeStyle FadedStyle(PPGeAlign align, float scale);
|
||||
|
|
|
@ -27,8 +27,10 @@
|
|||
#include "Core/Config.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HLE/HLEHelperThread.h"
|
||||
#include "Core/HLE/FunctionWrappers.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/MIPS/MIPSCodeUtils.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
|
@ -142,18 +144,28 @@ static PSPGamedataInstallDialog gamedataInstallDialog(UTILITY_DIALOG_GAMEDATAINS
|
|||
static int oldStatus = 100; //random value
|
||||
static std::map<int, u32> currentlyLoadedModules;
|
||||
static int volatileUnlockEvent = -1;
|
||||
static HLEHelperThread *accessThread = nullptr;
|
||||
|
||||
static void CleanupDialogThreads() {
|
||||
if (accessThread && accessThread->Stopped()) {
|
||||
delete accessThread;
|
||||
accessThread = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void ActivateDialog(UtilityDialogType type) {
|
||||
if (!currentDialogActive) {
|
||||
currentDialogType = type;
|
||||
currentDialogActive = true;
|
||||
}
|
||||
CleanupDialogThreads();
|
||||
}
|
||||
|
||||
static void DeactivateDialog() {
|
||||
if (currentDialogActive) {
|
||||
currentDialogActive = false;
|
||||
}
|
||||
CleanupDialogThreads();
|
||||
}
|
||||
|
||||
static void UtilityVolatileUnlock(u64 userdata, int cyclesLate) {
|
||||
|
@ -175,7 +187,7 @@ void __UtilityInit() {
|
|||
}
|
||||
|
||||
void __UtilityDoState(PointerWrap &p) {
|
||||
auto s = p.Section("sceUtility", 1, 3);
|
||||
auto s = p.Section("sceUtility", 1, 4);
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
|
@ -205,6 +217,22 @@ void __UtilityDoState(PointerWrap &p) {
|
|||
volatileUnlockEvent = -1;
|
||||
}
|
||||
CoreTiming::RestoreRegisterEvent(volatileUnlockEvent, "UtilityVolatileUnlock", UtilityVolatileUnlock);
|
||||
|
||||
bool hasAccessThread = accessThread != nullptr;
|
||||
if (s >= 4) {
|
||||
Do(p, hasAccessThread);
|
||||
if (hasAccessThread) {
|
||||
Do(p, accessThread);
|
||||
}
|
||||
} else {
|
||||
hasAccessThread = false;
|
||||
}
|
||||
|
||||
if (!hasAccessThread && accessThread) {
|
||||
accessThread->Forget();
|
||||
delete accessThread;
|
||||
accessThread = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void __UtilityShutdown() {
|
||||
|
@ -214,14 +242,67 @@ void __UtilityShutdown() {
|
|||
netDialog.Shutdown(true);
|
||||
screenshotDialog.Shutdown(true);
|
||||
gamedataInstallDialog.Shutdown(true);
|
||||
|
||||
if (accessThread) {
|
||||
delete accessThread;
|
||||
accessThread = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UtilityScheduleVolatileUnlock(s64 cyclesIntoFuture) {
|
||||
CoreTiming::ScheduleEvent(cyclesIntoFuture, volatileUnlockEvent, 0);
|
||||
void UtilityDialogShutdown(int type, int delayUs, int priority) {
|
||||
// Break it up so better-priority rescheduling happens.
|
||||
// The windows aren't this regular, but close.
|
||||
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, type),
|
||||
(u32_le)MIPS_MAKE_JR_RA(),
|
||||
(u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityFinishDialog"),
|
||||
};
|
||||
|
||||
CleanupDialogThreads();
|
||||
_assert_(accessThread == nullptr);
|
||||
accessThread = new HLEHelperThread("ScePafJob", insts, (uint32_t)ARRAY_SIZE(insts), priority, 0x200);
|
||||
accessThread->Start(partDelay, 0);
|
||||
}
|
||||
|
||||
void UtilityCancelVolatileUnlock() {
|
||||
CoreTiming::UnscheduleEvent(volatileUnlockEvent, 0);
|
||||
static int UtilityWorkUs(int us) {
|
||||
// This blocks, but other better priority threads can get time.
|
||||
// Simulate this by allowing a reschedule.
|
||||
hleEatMicro(us);
|
||||
hleReSchedule("utility work");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int UtilityFinishDialog(int type) {
|
||||
switch (type) {
|
||||
case UTILITY_DIALOG_NONE:
|
||||
break;
|
||||
case UTILITY_DIALOG_SAVEDATA:
|
||||
return hleLogSuccessI(SCEUTILITY, saveDialog.FinishShutdown());
|
||||
case UTILITY_DIALOG_MSG:
|
||||
return hleLogSuccessI(SCEUTILITY, msgDialog.FinishShutdown());
|
||||
case UTILITY_DIALOG_OSK:
|
||||
return hleLogSuccessI(SCEUTILITY, oskDialog.FinishShutdown());
|
||||
case UTILITY_DIALOG_NET:
|
||||
return hleLogSuccessI(SCEUTILITY, netDialog.FinishShutdown());
|
||||
case UTILITY_DIALOG_SCREENSHOT:
|
||||
return hleLogSuccessI(SCEUTILITY, screenshotDialog.FinishShutdown());
|
||||
case UTILITY_DIALOG_GAMESHARING:
|
||||
return hleLogError(SCEUTILITY, -1, "unimplemented");
|
||||
case UTILITY_DIALOG_GAMEDATAINSTALL:
|
||||
return hleLogSuccessI(SCEUTILITY, gamedataInstallDialog.FinishShutdown());
|
||||
}
|
||||
return hleLogError(SCEUTILITY, 0, "invalid dialog type?");
|
||||
}
|
||||
|
||||
static int sceUtilitySavedataInitStart(u32 paramAddr)
|
||||
|
@ -251,7 +332,7 @@ static int sceUtilitySavedataShutdownStart() {
|
|||
|
||||
DeactivateDialog();
|
||||
int ret = saveDialog.Shutdown();
|
||||
hleEatCycles(90000);
|
||||
hleEatCycles(30000);
|
||||
return hleLogSuccessX(SCEUTILITY, ret);
|
||||
}
|
||||
|
||||
|
@ -270,6 +351,7 @@ static int sceUtilitySavedataGetStatus()
|
|||
DEBUG_LOG(SCEUTILITY, "%08x=sceUtilitySavedataGetStatus()", status);
|
||||
}
|
||||
hleEatCycles(200);
|
||||
CleanupDialogThreads();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -429,6 +511,7 @@ static int sceUtilityMsgDialogGetStatus()
|
|||
oldStatus = status;
|
||||
DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityMsgDialogGetStatus()", status);
|
||||
}
|
||||
CleanupDialogThreads();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -502,6 +585,7 @@ static int sceUtilityOskGetStatus()
|
|||
oldStatus = status;
|
||||
DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityOskGetStatus()", status);
|
||||
}
|
||||
CleanupDialogThreads();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -544,6 +628,7 @@ static int sceUtilityNetconfGetStatus() {
|
|||
oldStatus = status;
|
||||
return hleLogSuccessI(SCEUTILITY, status);
|
||||
}
|
||||
CleanupDialogThreads();
|
||||
return hleLogSuccessVerboseI(SCEUTILITY, status);
|
||||
}
|
||||
|
||||
|
@ -613,6 +698,7 @@ static int sceUtilityScreenshotGetStatus()
|
|||
oldStatus = status;
|
||||
WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotGetStatus()", status);
|
||||
}
|
||||
CleanupDialogThreads();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -678,6 +764,7 @@ static int sceUtilityGamedataInstallGetStatus()
|
|||
|
||||
int status = gamedataInstallDialog.GetStatus();
|
||||
DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityGamedataInstallGetStatus()", status);
|
||||
CleanupDialogThreads();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -893,6 +980,7 @@ static int sceUtilityGameSharingGetStatus()
|
|||
}
|
||||
|
||||
ERROR_LOG(SCEUTILITY, "UNIMPL sceUtilityGameSharingGetStatus()");
|
||||
CleanupDialogThreads();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1055,6 +1143,10 @@ const HLEFunction sceUtility[] =
|
|||
{0X70267ADF, nullptr, "sceUtility_70267ADF", '?', "" },
|
||||
{0XECE1D3E5, nullptr, "sceUtility_ECE1D3E5", '?', "" },
|
||||
{0XEF3582B2, nullptr, "sceUtility_EF3582B2", '?', "" },
|
||||
|
||||
// Fake functions for PPSSPP's use.
|
||||
{0xC0DE0001, &WrapI_I<UtilityFinishDialog>, "__UtilityFinishDialog", 'i', "i" },
|
||||
{0xC0DE0002, &WrapI_I<UtilityWorkUs>, "__UtilityWorkUs", 'i', "i" },
|
||||
};
|
||||
|
||||
void Register_sceUtility()
|
||||
|
|
|
@ -83,7 +83,6 @@ void __UtilityInit();
|
|||
void __UtilityDoState(PointerWrap &p);
|
||||
void __UtilityShutdown();
|
||||
|
||||
void UtilityScheduleVolatileUnlock(s64 cyclesIntoFuture);
|
||||
void UtilityCancelVolatileUnlock();
|
||||
void UtilityDialogShutdown(int type, int delayUs, int priority);
|
||||
|
||||
void Register_sceUtility();
|
||||
|
|
Loading…
Add table
Reference in a new issue