mirror of
https://github.com/libretro/ppsspp.git
synced 2024-12-12 02:44:00 +00:00
Merge pull request #4136 from unknownbrackets/ui-tweaks
Improve some shutdown problems on Windows
This commit is contained in:
commit
7a4029fd65
153
Core/Core.cpp
153
Core/Core.cpp
@ -51,61 +51,54 @@ InputState input_state;
|
||||
extern InputState input_state;
|
||||
#endif
|
||||
|
||||
void Core_ListenShutdown(Core_ShutdownFunc func)
|
||||
{
|
||||
void Core_ListenShutdown(Core_ShutdownFunc func) {
|
||||
shutdownFuncs.insert(func);
|
||||
}
|
||||
|
||||
void Core_NotifyShutdown()
|
||||
{
|
||||
for (auto it = shutdownFuncs.begin(); it != shutdownFuncs.end(); ++it)
|
||||
void Core_NotifyShutdown() {
|
||||
for (auto it = shutdownFuncs.begin(); it != shutdownFuncs.end(); ++it) {
|
||||
(*it)();
|
||||
}
|
||||
}
|
||||
|
||||
void Core_ErrorPause()
|
||||
{
|
||||
void Core_ErrorPause() {
|
||||
Core_UpdateState(CORE_ERROR);
|
||||
}
|
||||
|
||||
void Core_Halt(const char *msg)
|
||||
{
|
||||
void Core_Halt(const char *msg) {
|
||||
Core_EnableStepping(true);
|
||||
ERROR_LOG(CPU, "CPU HALTED : %s",msg);
|
||||
_dbg_update_();
|
||||
}
|
||||
|
||||
void Core_Stop()
|
||||
{
|
||||
void Core_Stop() {
|
||||
Core_UpdateState(CORE_POWERDOWN);
|
||||
Core_NotifyShutdown();
|
||||
m_hStepEvent.notify_one();
|
||||
}
|
||||
|
||||
bool Core_IsStepping()
|
||||
{
|
||||
bool Core_IsStepping() {
|
||||
return coreState == CORE_STEPPING || coreState == CORE_POWERDOWN;
|
||||
}
|
||||
|
||||
bool Core_IsActive()
|
||||
{
|
||||
bool Core_IsActive() {
|
||||
return coreState == CORE_RUNNING || coreState == CORE_NEXTFRAME || coreStatePending;
|
||||
}
|
||||
|
||||
bool Core_IsInactive()
|
||||
{
|
||||
bool Core_IsInactive() {
|
||||
return coreState != CORE_RUNNING && coreState != CORE_NEXTFRAME && !coreStatePending;
|
||||
}
|
||||
|
||||
void Core_WaitInactive()
|
||||
{
|
||||
while (Core_IsActive())
|
||||
void Core_WaitInactive() {
|
||||
while (Core_IsActive()) {
|
||||
m_hInactiveEvent.wait(m_hInactiveMutex);
|
||||
}
|
||||
}
|
||||
|
||||
void Core_WaitInactive(int milliseconds)
|
||||
{
|
||||
if (Core_IsActive())
|
||||
void Core_WaitInactive(int milliseconds) {
|
||||
if (Core_IsActive()) {
|
||||
m_hInactiveEvent.wait_for(m_hInactiveMutex, milliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateScreenScale() {
|
||||
@ -127,61 +120,78 @@ void UpdateScreenScale() {
|
||||
pixel_in_dps = (float)pixel_xres / dp_xres;
|
||||
}
|
||||
|
||||
static inline void UpdateRunLoop() {
|
||||
UpdateScreenScale();
|
||||
{
|
||||
{
|
||||
#ifdef _WIN32
|
||||
lock_guard guard(input_state.lock);
|
||||
input_state.pad_buttons = 0;
|
||||
input_state.pad_lstick_x = 0;
|
||||
input_state.pad_lstick_y = 0;
|
||||
input_state.pad_rstick_x = 0;
|
||||
input_state.pad_rstick_y = 0;
|
||||
host->PollControllers(input_state);
|
||||
UpdateInputState(&input_state);
|
||||
#endif
|
||||
}
|
||||
NativeUpdate(input_state);
|
||||
EndInputState(&input_state);
|
||||
}
|
||||
NativeRender();
|
||||
}
|
||||
|
||||
void Core_RunLoop()
|
||||
{
|
||||
while (globalUIState != UISTATE_INGAME && globalUIState != UISTATE_EXIT) {
|
||||
time_update();
|
||||
|
||||
#ifdef _WIN32
|
||||
double startTime = time_now_d();
|
||||
UpdateRunLoop();
|
||||
|
||||
// Simple throttling to not burn the GPU in the menu.
|
||||
time_update();
|
||||
double diffTime = time_now_d() - startTime;
|
||||
int sleepTime = (int) (1000000.0 / 60.0) - (int) (diffTime * 1000000.0);
|
||||
if (sleepTime > 0)
|
||||
Sleep(sleepTime / 1000);
|
||||
GL_SwapBuffers();
|
||||
#else
|
||||
UpdateRunLoop();
|
||||
#endif
|
||||
}
|
||||
|
||||
while (!coreState) {
|
||||
time_update();
|
||||
double startTime = time_now_d();
|
||||
UpdateScreenScale();
|
||||
{
|
||||
{
|
||||
UpdateRunLoop();
|
||||
#ifdef _WIN32
|
||||
lock_guard guard(input_state.lock);
|
||||
input_state.pad_buttons = 0;
|
||||
input_state.pad_lstick_x = 0;
|
||||
input_state.pad_lstick_y = 0;
|
||||
input_state.pad_rstick_x = 0;
|
||||
input_state.pad_rstick_y = 0;
|
||||
host->PollControllers(input_state);
|
||||
UpdateInputState(&input_state);
|
||||
#endif
|
||||
}
|
||||
NativeUpdate(input_state);
|
||||
EndInputState(&input_state);
|
||||
}
|
||||
NativeRender();
|
||||
time_update();
|
||||
// Simple throttling to not burn the GPU in the menu.
|
||||
#ifdef _WIN32
|
||||
if (globalUIState != UISTATE_INGAME) {
|
||||
double diffTime = time_now_d() - startTime;
|
||||
int sleepTime = (int) (1000000.0 / 60.0) - (int) (diffTime * 1000000.0);
|
||||
if (sleepTime > 0)
|
||||
Sleep(sleepTime / 1000);
|
||||
GL_SwapBuffers();
|
||||
} else if (!Core_IsStepping()) {
|
||||
if (!Core_IsStepping()) {
|
||||
GL_SwapBuffers();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Core_DoSingleStep()
|
||||
{
|
||||
void Core_DoSingleStep() {
|
||||
singleStepPending = true;
|
||||
m_hStepEvent.notify_one();
|
||||
}
|
||||
|
||||
void Core_UpdateSingleStep()
|
||||
{
|
||||
void Core_UpdateSingleStep() {
|
||||
m_hStepEvent.notify_one();
|
||||
}
|
||||
|
||||
void Core_SingleStep()
|
||||
{
|
||||
void Core_SingleStep() {
|
||||
currentMIPS->SingleStep();
|
||||
}
|
||||
|
||||
static inline void CoreStateProcessed() {
|
||||
if (coreStatePending) {
|
||||
coreStatePending = false;
|
||||
m_hInactiveEvent.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
// Some platforms, like Android, do not call this function but handle things on their own.
|
||||
void Core_Run()
|
||||
@ -194,6 +204,15 @@ void Core_Run()
|
||||
#endif
|
||||
{
|
||||
reswitch:
|
||||
if (globalUIState != UISTATE_INGAME) {
|
||||
CoreStateProcessed();
|
||||
if (globalUIState == UISTATE_EXIT) {
|
||||
return;
|
||||
}
|
||||
Core_RunLoop();
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (coreState)
|
||||
{
|
||||
case CORE_RUNNING:
|
||||
@ -204,10 +223,7 @@ reswitch:
|
||||
// We should never get here on Android.
|
||||
case CORE_STEPPING:
|
||||
singleStepPending = false;
|
||||
if (coreStatePending) {
|
||||
coreStatePending = false;
|
||||
m_hInactiveEvent.notify_one();
|
||||
}
|
||||
CoreStateProcessed();
|
||||
|
||||
// Check if there's any pending savestate actions.
|
||||
SaveState::Process();
|
||||
@ -251,10 +267,7 @@ reswitch:
|
||||
case CORE_POWERDOWN:
|
||||
case CORE_ERROR:
|
||||
// Exit loop!!
|
||||
if (coreStatePending) {
|
||||
coreStatePending = false;
|
||||
m_hInactiveEvent.notify_one();
|
||||
}
|
||||
CoreStateProcessed();
|
||||
|
||||
return;
|
||||
|
||||
@ -266,19 +279,15 @@ reswitch:
|
||||
}
|
||||
|
||||
|
||||
void Core_EnableStepping(bool step)
|
||||
{
|
||||
if (step)
|
||||
{
|
||||
void Core_EnableStepping(bool step) {
|
||||
if (step) {
|
||||
sleep_ms(1);
|
||||
#if defined(_DEBUG)
|
||||
host->SetDebugMode(true);
|
||||
#endif
|
||||
m_hStepEvent.reset();
|
||||
Core_UpdateState(CORE_STEPPING);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
#if defined(_DEBUG)
|
||||
host->SetDebugMode(false);
|
||||
#endif
|
||||
|
@ -126,7 +126,7 @@ unsigned int MIPSDebugInterface::readMemory(unsigned int address)
|
||||
|
||||
bool MIPSDebugInterface::isAlive()
|
||||
{
|
||||
return PSP_IsInited();
|
||||
return PSP_IsInited() && coreState != CORE_ERROR && coreState != CORE_POWERDOWN;
|
||||
}
|
||||
|
||||
bool MIPSDebugInterface::isBreakpoint(unsigned int address)
|
||||
|
@ -67,6 +67,7 @@ static PSPMixer *mixer;
|
||||
static std::thread *cpuThread = NULL;
|
||||
static recursive_mutex cpuThreadLock;
|
||||
static condition_variable cpuThreadCond;
|
||||
static condition_variable cpuThreadReplyCond;
|
||||
static u64 cpuThreadUntil;
|
||||
|
||||
// This can be read and written from ANYWHERE.
|
||||
@ -95,9 +96,11 @@ bool IsOnSeparateCPUThread() {
|
||||
}
|
||||
|
||||
bool CPU_NextState(CPUThreadState from, CPUThreadState to) {
|
||||
lock_guard guard(cpuThreadLock);
|
||||
if (cpuThreadState == from) {
|
||||
cpuThreadState = to;
|
||||
cpuThreadCond.notify_one();
|
||||
cpuThreadReplyCond.notify_one();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -105,8 +108,10 @@ bool CPU_NextState(CPUThreadState from, CPUThreadState to) {
|
||||
}
|
||||
|
||||
void CPU_SetState(CPUThreadState to) {
|
||||
lock_guard guard(cpuThreadLock);
|
||||
cpuThreadState = to;
|
||||
cpuThreadCond.notify_one();
|
||||
cpuThreadReplyCond.notify_one();
|
||||
}
|
||||
|
||||
bool CPU_IsReady() {
|
||||
@ -121,11 +126,11 @@ bool CPU_HasPendingAction() {
|
||||
return cpuThreadState != CPU_THREAD_RUNNING;
|
||||
}
|
||||
|
||||
void CPU_WaitStatus(bool (*pred)()) {
|
||||
cpuThreadLock.lock();
|
||||
while (!pred())
|
||||
cpuThreadCond.wait(cpuThreadLock);
|
||||
cpuThreadLock.unlock();
|
||||
void CPU_WaitStatus(condition_variable &cond, bool (*pred)()) {
|
||||
lock_guard guard(cpuThreadLock);
|
||||
while (!pred()) {
|
||||
cond.wait(cpuThreadLock);
|
||||
}
|
||||
}
|
||||
|
||||
void CPU_Shutdown();
|
||||
@ -219,7 +224,7 @@ void CPU_RunLoop() {
|
||||
|
||||
while (cpuThreadState != CPU_THREAD_SHUTDOWN)
|
||||
{
|
||||
CPU_WaitStatus(&CPU_HasPendingAction);
|
||||
CPU_WaitStatus(cpuThreadCond, &CPU_HasPendingAction);
|
||||
switch (cpuThreadState) {
|
||||
case CPU_THREAD_EXECUTE:
|
||||
mipsr4k.RunLoopUntil(cpuThreadUntil);
|
||||
@ -271,7 +276,7 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) {
|
||||
Core_ListenShutdown(System_Wake);
|
||||
CPU_SetState(CPU_THREAD_PENDING);
|
||||
cpuThread = new std::thread(&CPU_RunLoop);
|
||||
CPU_WaitStatus(&CPU_IsReady);
|
||||
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady);
|
||||
} else {
|
||||
CPU_Init();
|
||||
}
|
||||
@ -298,7 +303,7 @@ void PSP_Shutdown() {
|
||||
Core_NotifyShutdown();
|
||||
if (cpuThread != NULL) {
|
||||
CPU_SetState(CPU_THREAD_SHUTDOWN);
|
||||
CPU_WaitStatus(&CPU_IsShutdown);
|
||||
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsShutdown);
|
||||
delete cpuThread;
|
||||
cpuThread = 0;
|
||||
} else {
|
||||
|
@ -40,7 +40,8 @@ enum GlobalUIState {
|
||||
extern GlobalUIState globalUIState;
|
||||
|
||||
inline static void UpdateUIState(GlobalUIState newState) {
|
||||
if (globalUIState != newState) {
|
||||
// Never leave the EXIT state.
|
||||
if (globalUIState != newState && globalUIState != UISTATE_EXIT) {
|
||||
globalUIState = newState;
|
||||
host->UpdateDisassembly();
|
||||
}
|
||||
|
@ -487,6 +487,7 @@ ShaderManager::~ShaderManager() {
|
||||
}
|
||||
|
||||
void ShaderManager::Clear() {
|
||||
DirtyLastShader();
|
||||
for (auto iter = linkedShaderCache_.begin(); iter != linkedShaderCache_.end(); ++iter) {
|
||||
delete iter->ls;
|
||||
}
|
||||
|
@ -147,7 +147,8 @@ void EmuScreen::sendMessage(const char *message, const char *value) {
|
||||
if (!strcmp(message, "pause")) {
|
||||
screenManager()->push(new GamePauseScreen(gamePath_));
|
||||
} else if (!strcmp(message, "stop")) {
|
||||
screenManager()->switchScreen(new MainScreen());
|
||||
// We will push MainScreen in update().
|
||||
PSP_Shutdown();
|
||||
} else if (!strcmp(message, "reset")) {
|
||||
PSP_Shutdown();
|
||||
std::string resetError;
|
||||
@ -497,6 +498,7 @@ void EmuScreen::render() {
|
||||
} else if (coreState == CORE_POWERDOWN) {
|
||||
ILOG("SELF-POWERDOWN!");
|
||||
screenManager()->switchScreen(new MainScreen());
|
||||
invalid_ = true;
|
||||
}
|
||||
|
||||
if (invalid_)
|
||||
|
@ -130,11 +130,12 @@ unsigned int WINAPI TheThread(void *)
|
||||
|
||||
while (globalUIState != UISTATE_EXIT)
|
||||
{
|
||||
Core_Run();
|
||||
|
||||
// We're here again, so the game quit. Restart Core_Run() which controls the UI.
|
||||
// This way they can load a new game.
|
||||
Core_UpdateState(CORE_RUNNING);
|
||||
if (!Core_IsActive())
|
||||
UpdateUIState(UISTATE_MENU);
|
||||
|
||||
Core_Run();
|
||||
}
|
||||
|
||||
shutdown:
|
||||
|
@ -782,19 +782,6 @@ namespace MainWindow
|
||||
DialogManager::AddDlg(memoryWindow[0]);
|
||||
}
|
||||
|
||||
void WaitForCore() {
|
||||
if (Core_IsStepping()) {
|
||||
// If the current PC is on a breakpoint, disabling stepping doesn't work without
|
||||
// explicitly skipping it
|
||||
CBreakPoints::SetSkipFirst(currentMIPS->pc);
|
||||
Core_EnableStepping(false);
|
||||
}
|
||||
|
||||
Core_EnableStepping(true);
|
||||
Core_WaitInactive();
|
||||
Core_EnableStepping(false);
|
||||
}
|
||||
|
||||
void BrowseAndBoot(std::string defaultPath, bool browseDirectory) {
|
||||
std::string fn;
|
||||
std::string filter = "PSP ROMs (*.iso *.cso *.pbp *.elf)|*.pbp;*.elf;*.iso;*.cso;*.prx|All files (*.*)|*.*||";
|
||||
@ -1140,21 +1127,22 @@ namespace MainWindow
|
||||
break;
|
||||
|
||||
case ID_EMULATION_STOP:
|
||||
WaitForCore();
|
||||
Core_Stop();
|
||||
NativeMessageReceived("stop", "");
|
||||
Core_WaitInactive();
|
||||
Update();
|
||||
break;
|
||||
|
||||
case ID_EMULATION_RESET:
|
||||
WaitForCore();
|
||||
NativeMessageReceived("reset", "");
|
||||
Core_EnableStepping(false);
|
||||
break;
|
||||
|
||||
case ID_EMULATION_CHEATS:
|
||||
g_Config.bEnableCheats = !g_Config.bEnableCheats;
|
||||
osm.ShowOnOff(g->T("Cheats"), g_Config.bEnableCheats);
|
||||
WaitForCore();
|
||||
NativeMessageReceived("reset", "");
|
||||
Core_EnableStepping(false);
|
||||
break;
|
||||
|
||||
case ID_FILE_LOADSTATEFILE:
|
||||
|
Loading…
Reference in New Issue
Block a user