From 088a02bfdb15adfe7cb94f19b98cd5e253ee537c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 30 Mar 2025 14:02:29 +0200 Subject: [PATCH] Cleanup a lot of the bootup state management. --- Core/Config.cpp | 4 +- Core/Debugger/DisassemblyManager.cpp | 10 +- Core/Debugger/WebSocket.cpp | 4 - Core/Debugger/WebSocket/CPUCoreSubscriber.cpp | 9 +- .../WebSocket/GPURecordSubscriber.cpp | 2 +- .../Debugger/WebSocket/GPUStatsSubscriber.cpp | 4 +- Core/Debugger/WebSocket/GameBroadcaster.cpp | 6 +- Core/Debugger/WebSocket/GameSubscriber.cpp | 6 +- Core/Debugger/WebSocket/HLESubscriber.cpp | 2 +- Core/Debugger/WebSocket/ReplaySubscriber.cpp | 8 +- .../WebSocket/SteppingBroadcaster.cpp | 2 +- Core/HLE/sceKernel.cpp | 4 +- Core/MIPS/MIPSDebugInterface.cpp | 2 +- Core/MemMap.cpp | 2 +- Core/PSPLoaders.cpp | 17 -- Core/Reporting.cpp | 8 +- Core/SaveState.cpp | 11 +- Core/System.cpp | 241 ++++++++++-------- Core/System.h | 42 ++- GPU/Debugger/State.cpp | 2 +- GPU/GPU.cpp | 4 - GPU/GPU.h | 1 - UI/DiscordIntegration.cpp | 2 +- UI/DisplayLayoutScreen.cpp | 2 +- UI/EmuScreen.cpp | 87 +++---- UI/EmuScreen.h | 1 - UI/ImDebugger/ImDisasmView.cpp | 2 +- UI/PauseScreen.cpp | 3 +- android/jni/TestRunner.cpp | 4 +- headless/Headless.cpp | 4 +- 30 files changed, 239 insertions(+), 257 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index b4d8203e58..01243bc523 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1700,7 +1700,7 @@ Path Config::getGameConfigFile(const std::string &pGameId, bool *exists) { return iniFileNameFull; } -bool Config::saveGameConfig(const std::string &pGameId, const std::string &title) { +bool Config::saveGameConfig(const std::string &pGameId, const std::string &titleForComment) { if (pGameId.empty()) { return false; } @@ -1711,7 +1711,7 @@ bool Config::saveGameConfig(const std::string &pGameId, const std::string &title IniFile iniFile; Section *top = iniFile.GetOrCreateSection(""); - top->AddComment(StringFromFormat("Game config for %s - %s", pGameId.c_str(), title.c_str())); + top->AddComment(StringFromFormat("Game config for %s - %s", pGameId.c_str(), titleForComment.c_str())); PreSaveCleanup(true); diff --git a/Core/Debugger/DisassemblyManager.cpp b/Core/Debugger/DisassemblyManager.cpp index 16548279ba..b14d3984e3 100644 --- a/Core/Debugger/DisassemblyManager.cpp +++ b/Core/Debugger/DisassemblyManager.cpp @@ -196,7 +196,7 @@ void DisassemblyManager::analyze(u32 address, u32 size = 1024) while (address < end && start <= address) { - if (!PSP_IsInited()) + if (PSP_GetBootState() != BootState::Complete) return; std::lock_guard guard(entriesLock_); @@ -406,7 +406,7 @@ void DisassemblyManager::clear() DisassemblyFunction::DisassemblyFunction(u32 _address, u32 _size): address(_address), size(_size) { - if (!PSP_IsInited()) + if (PSP_GetBootState() != BootState::Complete) return; hash = computeHash(address,size); @@ -419,7 +419,7 @@ DisassemblyFunction::~DisassemblyFunction() { void DisassemblyFunction::recheck() { - if (!PSP_IsInited()) + if (PSP_GetBootState() != BootState::Complete) return; HashType newHash = computeHash(address,size); @@ -872,14 +872,14 @@ bool DisassemblyMacro::disassemble(u32 address, DisassemblyLineInfo &dest, bool DisassemblyData::DisassemblyData(u32 _address, u32 _size, DataType _type): address(_address), size(_size), type(_type) { - _dbg_assert_(PSP_IsInited()); + _dbg_assert_(PSP_GetBootState() == BootState::Complete); hash = computeHash(address,size); createLines(); } void DisassemblyData::recheck() { - if (!PSP_IsInited()) + if (PSP_GetBootState() != BootState::Complete) return; HashType newHash = computeHash(address,size); diff --git a/Core/Debugger/WebSocket.cpp b/Core/Debugger/WebSocket.cpp index 0d975cb340..4270e402de 100644 --- a/Core/Debugger/WebSocket.cpp +++ b/Core/Debugger/WebSocket.cpp @@ -99,10 +99,6 @@ static void UpdateConnected(int delta) { } static void WebSocketNotifyLifecycle(CoreLifecycle stage) { - // We'll likely already be locked during the reboot. - if (PSP_IsRebooting()) - return; - switch (stage) { case CoreLifecycle::STARTING: case CoreLifecycle::STOPPING: diff --git a/Core/Debugger/WebSocket/CPUCoreSubscriber.cpp b/Core/Debugger/WebSocket/CPUCoreSubscriber.cpp index 2446639c80..fda0721628 100644 --- a/Core/Debugger/WebSocket/CPUCoreSubscriber.cpp +++ b/Core/Debugger/WebSocket/CPUCoreSubscriber.cpp @@ -107,12 +107,15 @@ void WebSocketCPUResume(DebuggerRequest &req) { // - ticks: number of CPU cycles into emulation. void WebSocketCPUStatus(DebuggerRequest &req) { JsonWriter &json = req.Respond(); - json.writeBool("stepping", PSP_IsInited() && Core_IsStepping() && coreState != CORE_POWERDOWN); + + const bool pspInited = PSP_GetBootState() == BootState::Complete; + + json.writeBool("stepping", pspInited && Core_IsStepping() && coreState != CORE_POWERDOWN); json.writeBool("paused", GetUIState() != UISTATE_INGAME); // Avoid NULL deference. - json.writeUint("pc", PSP_IsInited() ? currentMIPS->pc : 0); + json.writeUint("pc", pspInited ? currentMIPS->pc : 0); // A double ought to be good enough for a 156 day debug session. - json.writeFloat("ticks", PSP_IsInited() ? CoreTiming::GetTicks() : 0); + json.writeFloat("ticks", pspInited ? CoreTiming::GetTicks() : 0); } // Retrieve all regs and their values (cpu.getAllRegs) diff --git a/Core/Debugger/WebSocket/GPURecordSubscriber.cpp b/Core/Debugger/WebSocket/GPURecordSubscriber.cpp index d8a54d2e30..1a8f9e413a 100644 --- a/Core/Debugger/WebSocket/GPURecordSubscriber.cpp +++ b/Core/Debugger/WebSocket/GPURecordSubscriber.cpp @@ -58,7 +58,7 @@ WebSocketGPURecordState::~WebSocketGPURecordState() { // // Note: recording may take a moment. void WebSocketGPURecordState::Dump(DebuggerRequest &req) { - if (!PSP_IsInited()) { + if (PSP_GetBootState() != BootState::Complete) { return req.Fail("CPU not started"); } diff --git a/Core/Debugger/WebSocket/GPUStatsSubscriber.cpp b/Core/Debugger/WebSocket/GPUStatsSubscriber.cpp index fec2a565a4..1c1147bd42 100644 --- a/Core/Debugger/WebSocket/GPUStatsSubscriber.cpp +++ b/Core/Debugger/WebSocket/GPUStatsSubscriber.cpp @@ -150,7 +150,7 @@ void WebSocketGPUStatsState::FlipListener() { // Note: stats are returned after the next flip completes (paused if CPU or GPU in break.) // Note: info and timing may not be accurate if certain settings are disabled. void WebSocketGPUStatsState::Get(DebuggerRequest &req) { - if (!PSP_IsInited()) + if (PSP_GetBootState() != BootState::Complete) return req.Fail("CPU not started"); std::lock_guard guard(pendingLock_); @@ -169,7 +169,7 @@ void WebSocketGPUStatsState::Get(DebuggerRequest &req) { // // Note: info and timing will be accurate after the first frame. void WebSocketGPUStatsState::Feed(DebuggerRequest &req) { - if (!PSP_IsInited()) + if (PSP_GetBootState() != BootState::Complete) return req.Fail("CPU not started"); bool enable = true; if (!req.ParamBool("enable", &enable, DebuggerParamType::OPTIONAL)) diff --git a/Core/Debugger/WebSocket/GameBroadcaster.cpp b/Core/Debugger/WebSocket/GameBroadcaster.cpp index c71f13d574..755f041728 100644 --- a/Core/Debugger/WebSocket/GameBroadcaster.cpp +++ b/Core/Debugger/WebSocket/GameBroadcaster.cpp @@ -27,7 +27,7 @@ struct GameStatusEvent { JsonWriter j; j.begin(); j.writeString("event", ev); - if (PSP_IsInited()) { + if (PSP_GetBootState() == BootState::Complete) { j.pushDict("game"); j.writeString("id", g_paramSFO.GetDiscID()); j.writeString("version", g_paramSFO.GetValueString("DISC_VERSION")); @@ -83,10 +83,10 @@ void GameBroadcaster::Broadcast(net::WebSocketServer *ws) { } else if (state == UISTATE_INGAME && prevState_ == UISTATE_PAUSEMENU) { ws->Send(GameStatusEvent{"game.resume"}); prevState_ = state; - } else if (state == UISTATE_INGAME && PSP_IsInited()) { + } else if (state == UISTATE_INGAME && PSP_GetBootState() == BootState::Complete) { ws->Send(GameStatusEvent{"game.start"}); prevState_ = state; - } else if (state == UISTATE_MENU && !PSP_IsInited() && !PSP_IsQuitting() && !PSP_IsRebooting()) { + } else if (state == UISTATE_MENU && PSP_GetBootState() != BootState::Complete) { ws->Send(GameStatusEvent{"game.quit"}); prevState_ = state; } diff --git a/Core/Debugger/WebSocket/GameSubscriber.cpp b/Core/Debugger/WebSocket/GameSubscriber.cpp index 94b62bf53f..a316f6aaf3 100644 --- a/Core/Debugger/WebSocket/GameSubscriber.cpp +++ b/Core/Debugger/WebSocket/GameSubscriber.cpp @@ -39,7 +39,7 @@ DebuggerSubscriber *WebSocketGameInit(DebuggerEventHandlerMap &map) { // // Response (same event name) with no extra data or error. void WebSocketGameReset(DebuggerRequest &req) { - if (!PSP_IsInited()) + if (PSP_GetBootState() != BootState::Complete) return req.Fail("Game not running"); bool needBreak = false; @@ -50,7 +50,7 @@ void WebSocketGameReset(DebuggerRequest &req) { PSP_CoreParameter().startBreak = true; std::string resetError; - if (!PSP_Reboot(&resetError)) { + if (PSP_Reboot(&resetError) != BootState::Complete) { ERROR_LOG(Log::Boot, "Error resetting: %s", resetError.c_str()); return req.Fail("Could not reset"); } @@ -73,7 +73,7 @@ void WebSocketGameReset(DebuggerRequest &req) { // - paused: boolean, true when gameplay is paused (not the same as stepping.) void WebSocketGameStatus(DebuggerRequest &req) { JsonWriter &json = req.Respond(); - if (PSP_IsInited()) { + if (PSP_GetBootState() == BootState::Complete) { json.pushDict("game"); json.writeString("id", g_paramSFO.GetDiscID()); json.writeString("version", g_paramSFO.GetValueString("DISC_VERSION")); diff --git a/Core/Debugger/WebSocket/HLESubscriber.cpp b/Core/Debugger/WebSocket/HLESubscriber.cpp index 10dd7bc152..9f6d28bfa3 100644 --- a/Core/Debugger/WebSocket/HLESubscriber.cpp +++ b/Core/Debugger/WebSocket/HLESubscriber.cpp @@ -101,7 +101,7 @@ void WebSocketHLEThreadList(DebuggerRequest &req) { } static bool ThreadInfoForStatus(DebuggerRequest &req, DebugThreadInfo *result) { - if (!PSP_IsInited()) { + if (PSP_GetBootState() != BootState::Complete) { req.Fail("CPU not active"); return false; } diff --git a/Core/Debugger/WebSocket/ReplaySubscriber.cpp b/Core/Debugger/WebSocket/ReplaySubscriber.cpp index db45d05096..9d518630eb 100644 --- a/Core/Debugger/WebSocket/ReplaySubscriber.cpp +++ b/Core/Debugger/WebSocket/ReplaySubscriber.cpp @@ -71,7 +71,7 @@ void WebSocketReplayAbort(DebuggerRequest &req) { // - version: unsigned integer, version number of data. // - base64: base64 encode of binary data. void WebSocketReplayFlush(DebuggerRequest &req) { - if (!PSP_IsInited()) + if (PSP_GetBootState() != BootState::Complete) return req.Fail("Game not running"); std::vector data; @@ -90,7 +90,7 @@ void WebSocketReplayFlush(DebuggerRequest &req) { // // Response (same event name) with no extra data. void WebSocketReplayExecute(DebuggerRequest &req) { - if (!PSP_IsInited()) + if (PSP_GetBootState() != BootState::Complete) return req.Fail("Game not running"); uint32_t version = -1; @@ -130,7 +130,7 @@ void WebSocketReplayStatus(DebuggerRequest &req) { // Response (same event name): // - value: unsigned integer, may have more than 32 integer bits. void WebSocketReplayTimeGet(DebuggerRequest &req) { - if (!PSP_IsInited()) + if (PSP_GetBootState() != BootState::Complete) return req.Fail("Game not running"); JsonWriter &json = req.Respond(); @@ -144,7 +144,7 @@ void WebSocketReplayTimeGet(DebuggerRequest &req) { // // Response (same event name) with no extra data. void WebSocketReplayTimeSet(DebuggerRequest &req) { - if (!PSP_IsInited()) + if (PSP_GetBootState() != BootState::Complete) return req.Fail("Game not running"); uint32_t value; diff --git a/Core/Debugger/WebSocket/SteppingBroadcaster.cpp b/Core/Debugger/WebSocket/SteppingBroadcaster.cpp index cdc6a64ec1..ec36d0378f 100644 --- a/Core/Debugger/WebSocket/SteppingBroadcaster.cpp +++ b/Core/Debugger/WebSocket/SteppingBroadcaster.cpp @@ -57,7 +57,7 @@ private: // // Sent unexpectedly with no other properties. void SteppingBroadcaster::Broadcast(net::WebSocketServer *ws) { - if (PSP_IsInited()) { + if (PSP_GetBootState() == BootState::Complete) { int steppingCounter = Core_GetSteppingCounter(); // We ignore CORE_POWERDOWN as a stepping state. if (coreState == CORE_STEPPING_CPU && steppingCounter != lastCounter_) { diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index b1aedc9113..a3804e5f06 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -326,9 +326,7 @@ std::string __KernelStateSummary() { return __KernelThreadingSummary(); } - -void sceKernelExitGame() -{ +void sceKernelExitGame() { INFO_LOG(Log::sceKernel, "sceKernelExitGame"); __KernelSwitchOffThread("game exited"); Core_Stop(); diff --git a/Core/MIPS/MIPSDebugInterface.cpp b/Core/MIPS/MIPSDebugInterface.cpp index b06049ba75..14d814b2a5 100644 --- a/Core/MIPS/MIPSDebugInterface.cpp +++ b/Core/MIPS/MIPSDebugInterface.cpp @@ -210,7 +210,7 @@ unsigned int MIPSDebugInterface::readMemory(unsigned int address) { bool MIPSDebugInterface::isAlive() { - return PSP_IsInited() && coreState != CORE_BOOT_ERROR && coreState != CORE_RUNTIME_ERROR && coreState != CORE_POWERDOWN; + return PSP_GetBootState() == BootState::Complete && coreState != CORE_BOOT_ERROR && coreState != CORE_RUNTIME_ERROR && coreState != CORE_POWERDOWN; } bool MIPSDebugInterface::isBreakpoint(unsigned int address) diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index 7b2bd955ab..5f3596ad45 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -313,7 +313,7 @@ bool Init() { } void Reinit() { - _assert_msg_(PSP_IsInited(), "Cannot reinit during startup/shutdown"); + _assert_msg_(PSP_GetBootState() == BootState::Complete, "Cannot reinit during startup/shutdown"); Core_NotifyLifecycle(CoreLifecycle::MEMORY_REINITING); Shutdown(); Init(); diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index ff24783d97..05720f8e1d 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -250,16 +250,6 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) { return false; } - // OK, pretty confident we have a PSP game. - if (g_paramSFO.IsValid()) { - std::string title = StringFromFormat("%s : %s", g_paramSFO.GetValueString("DISC_ID").c_str(), g_paramSFO.GetValueString("TITLE").c_str()); - INFO_LOG(Log::Loader, "%s", title.c_str()); - System_SetWindowTitle(title); - } else { - // Should have been loaded earlier in the process. - _dbg_assert_(false); - } - //in case we didn't go through EmuScreen::boot g_Config.loadGameConfig(id, g_paramSFO.GetValueString("TITLE")); System_PostUIMessage(UIMessage::CONFIG_LOADED); @@ -375,17 +365,10 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) { homebrewName = homebrewName.substr(lslash + 1); if (rslash != homebrewName.npos) homebrewName = homebrewName.substr(rslash + 1); - std::string homebrewTitle = g_paramSFO.GetValueString("TITLE"); - if (homebrewTitle.empty()) - homebrewTitle = homebrewName; std::string discID = g_paramSFO.GetDiscID(); std::string discVersion = g_paramSFO.GetValueString("DISC_VERSION"); std::string madeUpID = g_paramSFO.GenerateFakeID(Path()); - std::string title = StringFromFormat("%s : %s", discID.c_str(), homebrewTitle.c_str()); - INFO_LOG(Log::Loader, "%s", title.c_str()); - System_SetWindowTitle(title); - // Migrate old save states from old versions of fake game IDs. // Ugh, this might actually be slow on Android. const Path savestateDir = GetSysDirectory(DIRECTORY_SAVESTATE); diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index 8727fa8bb3..8a0c5fee24 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -381,7 +381,7 @@ namespace Reporting void UpdateConfig() { currentSupported = IsSupported(); - if (!currentSupported && PSP_IsInited()) + if (!currentSupported && PSP_GetBootState() == BootState::Complete) everUnsupported = true; } @@ -438,7 +438,7 @@ namespace Reporting void AddGameplayInfo(UrlEncoder &postdata) { // Just to get an idea of how long they played. - if (PSP_IsInited()) + if (PSP_GetBootState() == BootState::Complete) postdata.Add("ticks", (const uint64_t)CoreTiming::GetTicks()); float vps, fps; @@ -536,7 +536,7 @@ namespace Reporting // Don't report from games without a version ID (i.e. random hashed homebrew IDs.) // The problem is, these aren't useful because the hashes end up different for different people. // TODO: Should really hash the ELF instead of the path, but then that affects savestates/cheats. - if (PSP_IsInited() && g_paramSFO.GetValueString("DISC_VERSION").empty()) + if (PSP_GetBootState() == BootState::Complete && g_paramSFO.GetValueString("DISC_VERSION").empty()) return false; // Some users run the exe from a zip or something, and don't have fonts. @@ -555,7 +555,7 @@ namespace Reporting bool IsEnabled() { - if (g_Config.sReportHost.empty() || (!currentSupported && PSP_IsInited())) + if (g_Config.sReportHost.empty() || (!currentSupported && PSP_GetBootState() == BootState::Complete)) return false; // Disabled by default for now. if (g_Config.sReportHost.compare("default") == 0) diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 7f46ef9456..f553a59813 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -1147,15 +1147,10 @@ double g_lastSaveTime = -1.0; } void Cleanup() { + // TODO: Handle this better. if (needsRestart) { - PSP_Shutdown(); - std::string resetError; - if (!PSP_Init(PSP_CoreParameter(), &resetError)) { - ERROR_LOG(Log::Boot, "Error resetting: %s", resetError.c_str()); - // TODO: This probably doesn't clean up well enough. - Core_Stop(); - return; - } + std::string error_string; + PSP_Reboot(&error_string); System_Notify(SystemNotification::BOOT_DONE); System_Notify(SystemNotification::DISASSEMBLY); needsRestart = false; diff --git a/Core/System.cpp b/Core/System.cpp index 0bc36fd7f0..12a392b37e 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -71,6 +71,7 @@ #include "GPU/GPUCommon.h" #include "GPU/Debugger/Playback.h" #include "GPU/Debugger/RecordFormat.h" +#include "UI/DiscordIntegration.h" enum CPUThreadState { CPU_THREAD_NOT_RUNNING, @@ -94,11 +95,11 @@ static volatile CPUThreadState cpuThreadState = CPU_THREAD_NOT_RUNNING; static GPUBackend gpuBackend; static std::string gpuBackendDevice; -// Ugly! -static volatile bool pspIsInited = false; -static volatile bool pspIsIniting = false; -static volatile bool pspIsQuitting = false; -static volatile bool pspIsRebooting = false; +static BootState g_bootState = BootState::Off; + +BootState PSP_GetBootState() { + return g_bootState; +} void ResetUIState() { globalUIState = UISTATE_MENU; @@ -131,21 +132,7 @@ std::string GetGPUBackendDevice() { return gpuBackendDevice; } -bool CPU_IsReady() { - if (coreState == CORE_POWERUP) - return false; - return cpuThreadState == CPU_THREAD_RUNNING || cpuThreadState == CPU_THREAD_NOT_RUNNING; -} - -bool CPU_IsShutdown() { - return cpuThreadState == CPU_THREAD_NOT_RUNNING; -} - -bool CPU_HasPendingAction() { - return cpuThreadState != CPU_THREAD_RUNNING; -} - -void CPU_Shutdown(); +void CPU_Shutdown(bool success); static Path SymbolMapFilename(const Path ¤tFilename, const char *ext) { File::FileInfo info{}; @@ -249,6 +236,24 @@ static void GetBootError(IdentifiedFileType type, std::string *errorString) { } } +static void ShowCompatWarnings(const Compatibility &compat) { + // UI changes are best done after PSP_InitStart. + if (compat.flags().RequireBufferedRendering && g_Config.bSkipBufferEffects && !g_Config.bSoftwareRendering) { + auto gr = GetI18NCategory(I18NCat::GRAPHICS); + g_OSD.Show(OSDType::MESSAGE_WARNING, gr->T("BufferedRenderingRequired", "Warning: This game requires Rendering Mode to be set to Buffered."), 10.0f); + } + + if (compat.flags().RequireBlockTransfer && g_Config.iSkipGPUReadbackMode != (int)SkipGPUReadbackMode::NO_SKIP && !PSP_CoreParameter().compat.flags().ForceEnableGPUReadback) { + auto gr = GetI18NCategory(I18NCat::GRAPHICS); + g_OSD.Show(OSDType::MESSAGE_WARNING, gr->T("BlockTransferRequired", "Warning: This game requires Skip GPU Readbacks be set to No."), 10.0f); + } + + if (compat.flags().RequireDefaultCPUClock && g_Config.iLockedCPUSpeed != 0) { + auto gr = GetI18NCategory(I18NCat::GRAPHICS); + g_OSD.Show(OSDType::MESSAGE_WARNING, gr->T("DefaultCPUClockRequired", "Warning: This game requires the CPU clock to be set to default."), 10.0f); + } +} + // NOTE: The loader has already been fully resolved (ResolveFileLoaderTarget) and identified here. static bool CPU_Init(FileLoader *fileLoader, IdentifiedFileType type, std::string *errorString) { // Default memory settings @@ -263,6 +268,8 @@ static bool CPU_Init(FileLoader *fileLoader, IdentifiedFileType type, std::strin std::string geDumpDiscID; + std::string gameTitle = "Unidentified PSP title"; + switch (type) { case IdentifiedFileType::PSP_ISO: case IdentifiedFileType::PSP_ISO_NP: @@ -294,6 +301,7 @@ static bool CPU_Init(FileLoader *fileLoader, IdentifiedFileType type, std::strin if (DiscIDFromGEDumpPath(g_CoreParameter.fileToStart, fileLoader, &geDumpDiscID)) { // Store in SFO, otherwise it'll generate a fake disc ID. g_paramSFO.SetValue("DISC_ID", geDumpDiscID, 16); + gameTitle = g_CoreParameter.fileToStart.GetFilename(); } break; default: @@ -306,6 +314,15 @@ static bool CPU_Init(FileLoader *fileLoader, IdentifiedFileType type, std::strin } } + // OK, pretty confident we have a PSP game. + if (g_paramSFO.IsValid()) { + gameTitle = SanitizeString(g_paramSFO.GetValueString("TITLE"), StringRestriction::NoLineBreaksOrSpecials); + } + + std::string title = StringFromFormat("%s : %s", g_paramSFO.GetValueString("DISC_ID").c_str(), gameTitle.c_str()); + INFO_LOG(Log::Loader, "%s", title.c_str()); + System_SetWindowTitle(title); + currentMIPS = &mipsr4k; g_symbolMap = new SymbolMap(); @@ -319,6 +336,7 @@ static bool CPU_Init(FileLoader *fileLoader, IdentifiedFileType type, std::strin // Homebrew usually has an empty discID, and even if they do have a disc id, it's not // likely to collide with any commercial ones. g_CoreParameter.compat.Load(g_paramSFO.GetDiscID()); + ShowCompatWarnings(g_CoreParameter.compat); // Compat settings can override the software renderer, take care of that here. if (g_Config.bSoftwareRendering || PSP_CoreParameter().compat.flags().ForceSoftwareRenderer) { @@ -329,7 +347,6 @@ static bool CPU_Init(FileLoader *fileLoader, IdentifiedFileType type, std::strin if (!Memory::Init()) { // We're screwed. *errorString = "Memory init failed"; - CPU_Shutdown(); return false; } @@ -370,7 +387,10 @@ static bool CPU_Init(FileLoader *fileLoader, IdentifiedFileType type, std::strin dir = ResolvePBPDirectory(Path(dir)).ToString(); pspFileSystem.SetStartingDirectory("ms0:/" + dir.substr(pos)); } - return Load_PSP_ELF_PBP(fileLoader, errorString); + if (!Load_PSP_ELF_PBP(fileLoader, errorString)) { + return false; + } + break; } // Looks like a wrong fall through but is not, both paths are handled above. @@ -378,17 +398,26 @@ static bool CPU_Init(FileLoader *fileLoader, IdentifiedFileType type, std::strin case IdentifiedFileType::PSP_ELF: { INFO_LOG(Log::Loader, "File is an ELF or loose PBP! %s", fileLoader->GetPath().c_str()); - return Load_PSP_ELF_PBP(fileLoader, errorString); + if (!Load_PSP_ELF_PBP(fileLoader, errorString)) { + return false; + } + break; } case IdentifiedFileType::PSP_ISO: case IdentifiedFileType::PSP_ISO_NP: case IdentifiedFileType::PSP_DISC_DIRECTORY: // behaves the same as the mounting is already done by now pspFileSystem.SetStartingDirectory("disc0:/PSP_GAME/USRDIR"); - return Load_PSP_ISO(fileLoader, errorString); + if (!Load_PSP_ISO(fileLoader, errorString)) { + return false; + } + break; case IdentifiedFileType::PPSSPP_GE_DUMP: - return Load_PSP_GE_Dump(fileLoader, errorString); + if (!Load_PSP_GE_Dump(fileLoader, errorString)) { + return false; + } + break; default: GetBootError(type, errorString); @@ -405,20 +434,12 @@ static bool CPU_Init(FileLoader *fileLoader, IdentifiedFileType type, std::strin return true; } -PSP_LoadingLock::PSP_LoadingLock() { - loadingLock.lock(); -} - -PSP_LoadingLock::~PSP_LoadingLock() { - loadingLock.unlock(); -} - -void CPU_Shutdown() { +void CPU_Shutdown(bool success) { UninstallExceptionHandler(); GPURecord::Replay_Unload(); - if (g_Config.bAutoSaveSymbolMap) { + if (g_Config.bAutoSaveSymbolMap && success) { SaveSymbolMapIfSupported(); } @@ -473,30 +494,32 @@ void PSP_ForceDebugStats(bool enable) { } bool PSP_InitStart(const CoreParameter &coreParam) { - if (pspIsIniting || pspIsQuitting) { - ERROR_LOG(Log::System, "Can't start loader thread - initing or quitting"); + if (g_bootState != BootState::Off) { + ERROR_LOG(Log::System, "Can't start loader thread - already on."); return false; } + _dbg_assert_(coreState != CORE_POWERUP); + coreState = CORE_POWERUP; + g_bootState = BootState::Booting; + GraphicsContext *temp = g_CoreParameter.graphicsContext; g_CoreParameter = coreParam; if (g_CoreParameter.graphicsContext == nullptr) { g_CoreParameter.graphicsContext = temp; } g_CoreParameter.errorString.clear(); - pspIsIniting = true; std::string *error_string = &g_CoreParameter.errorString; INFO_LOG(Log::System, "Starting loader thread..."); + _dbg_assert_(!g_loadingThread.joinable()); + g_loadingThread = std::thread([error_string]() { SetCurrentThreadName("ExecLoader"); - PSP_LoadingLock guard; - if (coreState != CORE_POWERUP) - return; AndroidJNIThreadContext jniContext; @@ -532,14 +555,14 @@ bool PSP_InitStart(const CoreParameter &coreParam) { // TODO: The reason we pass in g_CoreParameter.errorString here is that it's persistent - // it gets written to from the loader thread that gets spawned. if (!CPU_Init(loadedFile, type, &g_CoreParameter.errorString)) { - CPU_Shutdown(); + CPU_Shutdown(false); coreState = CORE_BOOT_ERROR; g_CoreParameter.fileToStart.clear(); *error_string = g_CoreParameter.errorString; if (error_string->empty()) { *error_string = "Failed initializing CPU/Memory"; } - pspIsIniting = false; + g_bootState = BootState::Failed; return; } @@ -549,101 +572,84 @@ bool PSP_InitStart(const CoreParameter &coreParam) { } else { coreState = CORE_RUNNING_CPU; } + + g_bootState = BootState::Complete; }); return true; } -bool PSP_InitUpdate(std::string *error_string) { - if (pspIsInited || !pspIsIniting) { - return true; +BootState PSP_InitUpdate(std::string *error_string) { + if (g_bootState == BootState::Booting || g_bootState == BootState::Off) { + // We're done already. + return g_bootState; } - if (!CPU_IsReady()) { - return false; - } - - bool success = !g_CoreParameter.fileToStart.empty(); - if (!g_CoreParameter.errorString.empty()) { - *error_string = g_CoreParameter.errorString; - } + _dbg_assert_(g_bootState == BootState::Complete || g_bootState == BootState::Failed); // Since we load on a background thread, wait for startup to complete. _dbg_assert_(g_loadingThread.joinable()); g_loadingThread.join(); - if (success && gpu == nullptr) { + if (g_bootState == BootState::Failed) { + // Failed! (Note: PSP_Shutdown was already called on the loader thread). + Core_NotifyLifecycle(CoreLifecycle::START_COMPLETE); + *error_string = g_CoreParameter.errorString; + return g_bootState; + } + + // Ok, async boot completed, let's finish up things on the main thread. + + if (!gpu) { // should be! INFO_LOG(Log::System, "Starting graphics..."); Draw::DrawContext *draw = g_CoreParameter.graphicsContext ? g_CoreParameter.graphicsContext->GetDrawContext() : nullptr; - success = GPU_Init(g_CoreParameter.graphicsContext, draw); + bool success = GPU_Init(g_CoreParameter.graphicsContext, draw); if (!success) { *error_string = "Unable to initialize rendering engine."; + PSP_Shutdown(false); + g_bootState = BootState::Failed; + return g_bootState; } } - if (!success) { - pspIsRebooting = false; - PSP_Shutdown(); - return true; + + // TODO: This should all be checked during GPU_Init. + if (!GPU_IsStarted()) { + *error_string = "Unable to initialize rendering engine."; + PSP_Shutdown(false); + g_bootState = BootState::Failed; } - pspIsInited = GPU_IsReady(); - pspIsIniting = !pspIsInited; - if (pspIsInited) { - Core_NotifyLifecycle(CoreLifecycle::START_COMPLETE); - pspIsRebooting = false; - - // If GPU init failed during IsReady checks, bail. - if (!GPU_IsStarted()) { - *error_string = "Unable to initialize rendering engine."; - pspIsRebooting = false; - PSP_Shutdown(); - return true; - } - } - return pspIsInited; + Core_NotifyLifecycle(CoreLifecycle::START_COMPLETE); + return g_bootState; } // Most platforms should not use this one, they should call PSP_InitStart and then do their thing // while repeatedly calling PSP_InitUpdate. This is basically just for libretro convenience. -bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) { +BootState PSP_Init(const CoreParameter &coreParam, std::string *error_string) { // InitStart doesn't really fail anymore. if (!PSP_InitStart(coreParam)) - return false; + return BootState::Failed; - while (!PSP_InitUpdate(error_string)) - sleep_ms(10, "psp-init-poll"); - return pspIsInited; + while (true) { + BootState state = PSP_InitUpdate(error_string); + if (state != BootState::Booting) { + return state; + } + sleep_ms(5, "psp-init-poll"); + } } -bool PSP_IsIniting() { - return pspIsIniting; -} - -bool PSP_IsInited() { - return pspIsInited && !pspIsQuitting && !pspIsRebooting; -} - -bool PSP_IsRebooting() { - return pspIsRebooting; -} - -bool PSP_IsQuitting() { - return pspIsQuitting; -} - -void PSP_Shutdown() { +void PSP_Shutdown(bool success) { // Reduce the risk for weird races with the Windows GE debugger. gpuDebug = nullptr; Achievements::UnloadGame(); // Do nothing if we never inited. - if (!pspIsInited && !pspIsIniting && !pspIsQuitting) { + if (g_bootState == BootState::Off) { return; } - // Make sure things know right away that PSP memory, etc. is going away. - pspIsQuitting = !pspIsRebooting; if (coreState == CORE_RUNNING_CPU) Core_Stop(); @@ -651,29 +657,42 @@ void PSP_Shutdown() { MIPSAnalyst::StoreHashMap(); } - if (pspIsIniting) + if (g_bootState == BootState::Booting) { + // This should only happen during failures. Core_NotifyLifecycle(CoreLifecycle::START_COMPLETE); + } Core_NotifyLifecycle(CoreLifecycle::STOPPING); - CPU_Shutdown(); + + CPU_Shutdown(success); GPU_Shutdown(); g_paramSFO.Clear(); System_SetWindowTitle(""); - currentMIPS = 0; - pspIsInited = false; - pspIsIniting = false; - pspIsQuitting = false; + + currentMIPS = nullptr; + g_Config.unloadGameConfig(); + Core_NotifyLifecycle(CoreLifecycle::STOPPED); + + if (success) { + g_bootState = BootState::Off; + } } -bool PSP_Reboot(std::string *error_string) { - if (!pspIsInited || pspIsQuitting) - return false; +// Call this after handling BootState::Failed. +void PSP_CancelBoot() { + _dbg_assert_(g_bootState == BootState::Failed); + g_bootState = BootState::Off; +} + +BootState PSP_Reboot(std::string *error_string) { + if (g_bootState != BootState::Complete) { + return g_bootState; + } - pspIsRebooting = true; Core_Stop(); Core_WaitInactive(); - PSP_Shutdown(); + PSP_Shutdown(true); std::string resetError; return PSP_Init(PSP_CoreParameter(), error_string); } diff --git a/Core/System.h b/Core/System.h index b5b451f23e..3ca344ee86 100644 --- a/Core/System.h +++ b/Core/System.h @@ -71,27 +71,41 @@ void SetGPUBackend(GPUBackend type, const std::string &device = ""); GPUBackend GetGPUBackend(); std::string GetGPUBackendDevice(); -bool PSP_Init(const CoreParameter &coreParam, std::string *error_string); +enum class BootState { + Off, + Booting, + Complete, + Failed, +}; + +BootState PSP_GetBootState(); +inline bool PSP_IsInited() { + return PSP_GetBootState() == BootState::Complete; +} + +// Call this once, then call PSP_InitUpdate repeatedly to monitor progress. bool PSP_InitStart(const CoreParameter &coreParam); -bool PSP_InitUpdate(std::string *error_string); -bool PSP_IsIniting(); -bool PSP_IsInited(); -bool PSP_IsRebooting(); -bool PSP_IsQuitting(); -void PSP_Shutdown(); -bool PSP_Reboot(std::string *error_string); + +// Check the return value of this - if Booting, keep calling. +// If Complete or Failed, handle as appropriate, and stop calling. +BootState PSP_InitUpdate(std::string *error_string); + +// Blocking wrapper around the two above functions, used for convenience in a couple of places. +// Should be avoided/removed eventually. +// Returns either BootState::Complete or BootState::Failed. +BootState PSP_Init(const CoreParameter &coreParam, std::string *error_string); +// Call this after handling BootState::Failed from PSP_Init. +void PSP_CancelBoot(); + +void PSP_Shutdown(bool success); +BootState PSP_Reboot(std::string *error_string); + void PSP_BeginHostFrame(); void PSP_EndHostFrame(); void PSP_RunLoopWhileState(); void PSP_RunLoopFor(int cycles); -// Used to wait for background loading thread. -struct PSP_LoadingLock { - PSP_LoadingLock(); - ~PSP_LoadingLock(); -}; - // Call before PSP_BeginHostFrame() in order to not miss any GPU stats. void PSP_UpdateDebugStats(bool collectStats); // Increments or decrements an internal counter. Intended to be used by debuggers. diff --git a/GPU/Debugger/State.cpp b/GPU/Debugger/State.cpp index 90f6b7d269..72f206446f 100644 --- a/GPU/Debugger/State.cpp +++ b/GPU/Debugger/State.cpp @@ -563,7 +563,7 @@ static void FormatVertColRawType(char *dest, size_t destSize, const void *data, static void FormatVertColRawColor(char *dest, size_t destSize, const void *data, int type); void FormatVertColRaw(VertexDecoder *decoder, char *dest, size_t destSize, int row, int col) { - if (!PSP_IsInited()) { + if (PSP_GetBootState() != BootState::Complete) { truncate_cpy(dest, destSize, "Invalid"); return; } diff --git a/GPU/GPU.cpp b/GPU/GPU.cpp index 742d3705bf..7dfc759ebe 100644 --- a/GPU/GPU.cpp +++ b/GPU/GPU.cpp @@ -53,10 +53,6 @@ static void SetGPU(T *obj) { #undef new #endif -bool GPU_IsReady() { - return gpu != nullptr; -} - bool GPU_IsStarted() { if (gpu) return gpu->IsStarted(); diff --git a/GPU/GPU.h b/GPU/GPU.h index 506f0d9c38..442586f24f 100644 --- a/GPU/GPU.h +++ b/GPU/GPU.h @@ -182,7 +182,6 @@ namespace Draw { } bool GPU_Init(GraphicsContext *ctx, Draw::DrawContext *draw); -bool GPU_IsReady(); bool GPU_IsStarted(); void GPU_Shutdown(); diff --git a/UI/DiscordIntegration.cpp b/UI/DiscordIntegration.cpp index a72caa782e..542fa1047c 100644 --- a/UI/DiscordIntegration.cpp +++ b/UI/DiscordIntegration.cpp @@ -5,7 +5,7 @@ #include "ppsspp_config.h" #include "Common/Log.h" #include "Core/Config.h" -#include "DiscordIntegration.h" +#include "UI/DiscordIntegration.h" #include "Common/Data/Text/I18n.h" #if (PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(LINUX)) && !PPSSPP_PLATFORM(ANDROID) && !PPSSPP_PLATFORM(UWP) diff --git a/UI/DisplayLayoutScreen.cpp b/UI/DisplayLayoutScreen.cpp index b7ed910e71..c3f03a9c87 100644 --- a/UI/DisplayLayoutScreen.cpp +++ b/UI/DisplayLayoutScreen.cpp @@ -120,7 +120,7 @@ private: DisplayLayoutScreen::DisplayLayoutScreen(const Path &filename) : UIDialogScreenWithGameBackground(filename) {} void DisplayLayoutScreen::DrawBackground(UIContext &dc) { - if (PSP_IsInited() && !g_Config.bSkipBufferEffects) { + if (PSP_GetBootState() == BootState::Complete && !g_Config.bSkipBufferEffects) { // We normally rely on the PSP screen showing through. } else { // But if it's not present (we're not in game, or skip buffer effects is used), diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 2d8e8874d1..bd3123fe72 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -229,7 +229,6 @@ bool EmuScreen::bootAllowStorage(const Path &filename) { return false; case PERMISSION_STATUS_DENIED: - stopRender_ = true; screenManager()->switchScreen(new MainScreen()); return false; @@ -251,37 +250,42 @@ void EmuScreen::bootGame(const Path &filename) { return; } - if (PSP_IsRebooting()) + std::string error_string = "(unknown error)"; + BootState state = PSP_InitUpdate(&error_string); + + switch (state) { + case BootState::Booting: + // Keep trying. return; - if (PSP_IsInited()) { + case BootState::Failed: + // Failure. + PSP_CancelBoot(); + _dbg_assert_(!error_string.empty()); + g_BackgroundAudio.SetGame(Path()); bootPending_ = false; + errorMessage_ = error_string; + ERROR_LOG(Log::Boot, "Boot failed: %s", errorMessage_.c_str()); + return; + case BootState::Complete: + // Done booting! + g_BackgroundAudio.SetGame(Path()); + bootPending_ = false; + errorMessage_.clear(); bootComplete(); + // Reset views in case controls are in a different place. + RecreateViews(); return; + case BootState::Off: + // Gotta start the boot process! Continue below. + break; } - if (PSP_IsIniting()) { - std::string error_string = "(unknown error)"; - - bootPending_ = !PSP_InitUpdate(&error_string); - - if (!bootPending_) { - if (!PSP_IsInited()) { - errorMessage_ = error_string; - ERROR_LOG(Log::Boot, "isIniting bootGame error: %s", errorMessage_.c_str()); - return; - } - bootComplete(); - } - return; - } - - g_BackgroundAudio.SetGame(Path()); - // Check permission status first, in case we came from a shortcut. if (!bootAllowStorage(filename)) return; // We don't want to boot with the wrong game specific config, so wait until info is ready. + // TODO: Actually, we read this info again during bootup, so this is not really necessary. std::shared_ptr info = g_gameInfoCache->GetInfo(nullptr, filename, GameInfoFlags::PARAM_SFO); if (!info->Ready(GameInfoFlags::PARAM_SFO)) { return; @@ -303,10 +307,6 @@ void EmuScreen::bootGame(const Path &filename) { SetAssertCancelCallback(&AssertCancelCallback, this); if (!info->id.empty()) { - g_Config.loadGameConfig(info->id, info->GetTitle()); - // Reset views in case controls are in a different place. - RecreateViews(); - g_Discord.SetPresenceGame(info->GetTitle()); } else { g_Discord.SetPresenceGame(sc->T("Untitled PSP game")); @@ -359,21 +359,7 @@ void EmuScreen::bootGame(const Path &filename) { if (!PSP_InitStart(coreParam)) { bootPending_ = false; ERROR_LOG(Log::Boot, "InitStart bootGame error: %s", errorMessage_.c_str()); - } - - if (PSP_CoreParameter().compat.flags().RequireBufferedRendering && g_Config.bSkipBufferEffects && !g_Config.bSoftwareRendering) { - auto gr = GetI18NCategory(I18NCat::GRAPHICS); - g_OSD.Show(OSDType::MESSAGE_WARNING, gr->T("BufferedRenderingRequired", "Warning: This game requires Rendering Mode to be set to Buffered."), 10.0f); - } - - if (PSP_CoreParameter().compat.flags().RequireBlockTransfer && g_Config.iSkipGPUReadbackMode != (int)SkipGPUReadbackMode::NO_SKIP && !PSP_CoreParameter().compat.flags().ForceEnableGPUReadback) { - auto gr = GetI18NCategory(I18NCat::GRAPHICS); - g_OSD.Show(OSDType::MESSAGE_WARNING, gr->T("BlockTransferRequired", "Warning: This game requires Skip GPU Readbacks be set to No."), 10.0f); - } - - if (PSP_CoreParameter().compat.flags().RequireDefaultCPUClock && g_Config.iLockedCPUSpeed != 0) { - auto gr = GetI18NCategory(I18NCat::GRAPHICS); - g_OSD.Show(OSDType::MESSAGE_WARNING, gr->T("DefaultCPUClockRequired", "Warning: This game requires the CPU clock to be set to default."), 10.0f); + return; } loadingViewColor_->Divert(0xFFFFFFFF, 0.75f); @@ -386,6 +372,7 @@ void EmuScreen::bootGame(const Path &filename) { } } +// Only call this on successful boot. void EmuScreen::bootComplete() { UpdateUIState(UISTATE_INGAME); System_Notify(SystemNotification::BOOT_DONE); @@ -456,9 +443,8 @@ EmuScreen::~EmuScreen() { std::string gameID = g_paramSFO.GetValueString("DISC_ID"); g_Config.TimeTracker().Stop(gameID); - // If we were invalid, it would already be shutdown. if (!bootPending_) { - PSP_Shutdown(); + PSP_Shutdown(true); } System_PostUIMessage(UIMessage::GAME_SELECTED, ""); @@ -543,17 +529,15 @@ void EmuScreen::sendMessage(UIMessage message, const char *value) { screenManager()->push(new GamePauseScreen(gamePath_)); } else if (message == UIMessage::REQUEST_GAME_STOP) { // We will push MainScreen in update(). - PSP_Shutdown(); + PSP_Shutdown(true); bootPending_ = false; - stopRender_ = true; System_Notify(SystemNotification::DISASSEMBLY); } else if (message == UIMessage::REQUEST_GAME_RESET) { - PSP_Shutdown(); + PSP_Shutdown(true); bootPending_ = true; System_Notify(SystemNotification::DISASSEMBLY); if (!PSP_InitStart(PSP_CoreParameter())) { ERROR_LOG(Log::Loader, "Error resetting"); - stopRender_ = true; screenManager()->switchScreen(new MainScreen()); return; } @@ -567,7 +551,7 @@ void EmuScreen::sendMessage(UIMessage message, const char *value) { if (ext != nullptr && !strcmp(ext, ".ppst")) { SaveState::Load(Path(value), -1, &AfterStateBoot); } else { - PSP_Shutdown(); + PSP_Shutdown(true); bootPending_ = true; gamePath_ = Path(value); // Don't leave it on CORE_POWERDOWN, we'll sometimes aggressively bail. @@ -1433,14 +1417,11 @@ void EmuScreen::update() { } bool EmuScreen::checkPowerDown() { - if (PSP_IsRebooting()) { - bootPending_ = true; - } - - if (coreState == CORE_POWERDOWN && !PSP_IsIniting() && !PSP_IsRebooting()) { + // This is for handling things like sceKernelExitGame(). + if (coreState == CORE_POWERDOWN && PSP_GetBootState() == BootState::Complete) { bool shutdown = false; if (PSP_IsInited()) { - PSP_Shutdown(); + PSP_Shutdown(true); shutdown = true; } INFO_LOG(Log::System, "SELF-POWERDOWN!"); diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 0e47051942..24a8ea6e1b 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -101,7 +101,6 @@ private: Path gamePath_; bool quit_ = false; - bool stopRender_ = false; std::string errorMessage_; // If set, pauses at the end of the frame. diff --git a/UI/ImDebugger/ImDisasmView.cpp b/UI/ImDebugger/ImDisasmView.cpp index d05a3d6582..85736b79ee 100644 --- a/UI/ImDebugger/ImDisasmView.cpp +++ b/UI/ImDebugger/ImDisasmView.cpp @@ -50,7 +50,7 @@ static ImColor scaleColor(ImColor color, float factor) { } bool ImDisasmView::getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData) { - if (!PSP_IsInited()) + if (PSP_GetBootState() != BootState::Complete) return false; return GetDisasmAddressText(address, dest, abbreviateLabels, showData, displaySymbols_); diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index bc2f7a4200..609f332d34 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -483,8 +483,7 @@ void GamePauseScreen::CreateViews() { rightColumnItems->Add(new Spacer(20.0)); - std::string gameId = g_paramSFO.GetDiscID(); - if (g_Config.hasGameConfig(gameId)) { + if (g_paramSFO.IsValid() && g_Config.hasGameConfig(g_paramSFO.GetDiscID())) { rightColumnItems->Add(new Choice(pa->T("Game Settings")))->OnClick.Handle(this, &GamePauseScreen::OnGameSettings); rightColumnItems->Add(new Choice(pa->T("Delete Game Config")))->OnClick.Handle(this, &GamePauseScreen::OnDeleteConfig); } else { diff --git a/android/jni/TestRunner.cpp b/android/jni/TestRunner.cpp index cce6e5b745..ed0d9a7037 100644 --- a/android/jni/TestRunner.cpp +++ b/android/jni/TestRunner.cpp @@ -120,7 +120,7 @@ bool RunTests() { INFO_LOG(Log::System, "Preparing to execute '%s'", testName.c_str()); std::string error_string; output.clear(); - if (!PSP_Init(coreParam, &error_string)) { + if (BootState::Complete != PSP_Init(coreParam, &error_string)) { ERROR_LOG(Log::System, "Failed to init unittest %s : %s", testsToRun[i], error_string.c_str()); PSP_CoreParameter().pixelWidth = g_display.pixel_xres; PSP_CoreParameter().pixelHeight = g_display.pixel_yres; @@ -177,7 +177,7 @@ bool RunTests() { break; } } - PSP_Shutdown(); + PSP_Shutdown(true); } PSP_CoreParameter().pixelWidth = g_display.pixel_xres; PSP_CoreParameter().pixelHeight = g_display.pixel_yres; diff --git a/headless/Headless.cpp b/headless/Headless.cpp index e525f768a9..6320a057c4 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -199,7 +199,7 @@ bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, const headlessHost->SetComparisonScreenshot(ExpectedScreenshotFromFilename(coreParameter.fileToStart), opt.maxScreenshotError); std::string error_string; - while (!PSP_InitUpdate(&error_string)) + while (PSP_InitUpdate(&error_string) == BootState::Booting) sleep_ms(1, "auto-test"); if (!PSP_IsInited()) { @@ -265,7 +265,7 @@ bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, const draw->EndFrame(); } - PSP_Shutdown(); + PSP_Shutdown(true); if (!opt.bench) headlessHost->FlushDebugOutput();