Improved launching of Steam games by keeping ES-DE running in the background.

This commit is contained in:
Leon Styhre 2021-03-24 20:13:33 +01:00
parent 5248ece0c2
commit 083e0a12e9
5 changed files with 58 additions and 44 deletions

View file

@ -954,9 +954,16 @@ void FileData::launchGame(Window* window)
LOG(LogInfo) << command;
#if defined(_WIN64)
returnValue = launchEmulatorWindows(Utils::String::stringToWideString(command));
if (mSystem->hasPlatformId(PlatformIds::VALVE_STEAM) ||
Settings::getInstance()->getBool("RunInBackground"))
returnValue = launchGameWindows(Utils::String::stringToWideString(command), true);
else
returnValue = launchGameWindows(Utils::String::stringToWideString(command), false);
#else
returnValue = launchEmulatorUnix(command);
if (mSystem->hasPlatformId(PlatformIds::VALVE_STEAM))
returnValue = launchGameUnix(command, true);
else
returnValue = launchGameUnix(command, false);
#endif
// Notify the user in case of a failed game launch using a popup window.
@ -972,16 +979,21 @@ void FileData::launchGame(Window* window)
// Stop showing the game launch notification.
window->stopInfoPopup();
#if defined(_WIN64)
// This code is only needed for Windows, where we may need to keep ES running while
// the game/emulator is in use. It's basically used to pause any playing game video
// and to keep the screensaver from activating.
if (Settings::getInstance()->getBool("RunInBackground"))
// If starting a Steam game or if the "RunInBackground" setting has been enabled,
// then keep ES-DE running while the game is launched. This pauses any video and keeps
// the screensaver from getting activated.
if (mSystem->hasPlatformId(PlatformIds::VALVE_STEAM) ||
Settings::getInstance()->getBool("RunInBackground"))
window->setLaunchedGame();
else
// Normalize deltaTime so that the screensaver does not start immediately
// when returning from the game.
window->normalizeNextUpdate();
#else
// If starting a Steam game, then keep ES-DE running while the game is launched.
// This pauses any video and keeps the screensaver from getting activated.
if (mSystem->hasPlatformId(PlatformIds::VALVE_STEAM))
window->setLaunchedGame();
// Normalize deltaTime so that the screensaver does not start immediately
// when returning from the game.
window->normalizeNextUpdate();

View file

@ -762,18 +762,13 @@ bool ViewController::input(InputConfig* config, Input input)
if (mLockInput)
return true;
#if defined(_WIN64)
// This code is only needed for Windows, where we may need to keep ES running while
// the game/emulator is in use. It's basically used to pause any playing game video
// and to keep the screensaver from activating.
if (Settings::getInstance()->getBool("RunInBackground")) {
// If we have previously launched a game and there is now input registered, it means
// the user is back in ES, so unset the flag to indicate that a game has been launched
// and update all the GUI components to reflect this.
// For Steam games or if enabling the "RunInBackground" setting on Windows, ES-DE will
// run in the background while a game is launched. If we're in this state and then
// register some input, it means that the user is back in ES-DE. Therefore unset the game
// launch flag and update all the GUI components. This will re-enable the video player
// and let the screensaver start on schedule again.
if (mWindow->getGameLaunchedState())
mWindow->unsetLaunchedGame();
}
#endif
// Open the main menu.
if (!(UIModeController::getInstance()->isUIModeKid() &&
@ -930,16 +925,12 @@ void ViewController::reloadGameListView(IGameListView* view, bool reloadTheme)
}
}
#if defined(_WIN64)
// This code is only needed for Windows, where we may need to keep ES running while
// the game/emulator is in use. It's basically used to pause any playing game video
// and to keep the screensaver from activating.
if (Settings::getInstance()->getBool("RunInBackground")) {
// If a game has been launched, then update all the GUI components to reflect this.
// For Steam games or if enabling the "RunInBackground" setting on Windows, ES-DE will
// run in the background while a game is launched. If this flag has been set, then update
// all the GUI components. This will disable the video player and prevent the screensaver
// from starting on schedule.
if (mWindow->getGameLaunchedState())
mWindow->setLaunchedGame();
}
#endif
// Redisplay the current view.
if (mCurrentView)

View file

@ -71,10 +71,19 @@ int runSystemCommand(const std::wstring& cmd_utf16)
#endif
}
int launchEmulatorUnix(const std::string& cmd_utf8)
int launchGameUnix(const std::string& cmd_utf8, bool runInBackground)
{
#if defined(__unix__) || defined (__APPLE__)
std::string command = std::string(cmd_utf8) + " 2>&1";
std::string command = std::string(cmd_utf8) + " 2>&1 &";
// Launching games while keeping ES-DE running in the background is very crude as for
// instance no output from the command is captured and no real error handling is
// implemented. It should therefore only be used when absolutely necessary.
if (runInBackground) {
LOG(LogDebug) << "Platform::launchGameUnix(): Launching game while keeping ES-DE "
"running in the background, no command output will be written to the log file";
return system(command.c_str());
}
FILE* commandPipe;
std::array<char, 128> buffer;
@ -101,15 +110,15 @@ int launchEmulatorUnix(const std::string& cmd_utf8)
}
if (returnValue) {
LOG(LogError) << "launchEmulatorUnix - return value " <<
LOG(LogError) << "launchGameUnix - return value " <<
std::to_string(returnValue) + ":";
if (commandOutput.size())
LOG(LogError) << commandOutput;
else
LOG(LogError) << "No error output provided by emulator.";
LOG(LogError) << "No error output provided by game or emulator";
}
else if (commandOutput.size()) {
LOG(LogDebug) << "Platform::launchEmulatorUnix():";
LOG(LogDebug) << "Platform::launchGameUnix():";
LOG(LogDebug) << "Output from launched game:\n" << commandOutput;
}
@ -120,7 +129,7 @@ int launchEmulatorUnix(const std::string& cmd_utf8)
#endif
}
int launchEmulatorWindows(const std::wstring& cmd_utf16)
int launchGameWindows(const std::wstring& cmd_utf16, bool runInBackground)
{
#if defined(_WIN64)
STARTUPINFOW si {};
@ -142,12 +151,14 @@ int launchEmulatorWindows(const std::wstring& cmd_utf16)
&si, // Pointer to the STARTUPINFOW structure.
&pi); // Pointer to the PROCESS_INFORMATION structure.
// Unfortunately suspending ES and resuming when the emulator process has exited
// doesn't work reliably on Windows, so we may need to keep ES running in the
// background while the game is launched. I'm not sure if there is a workaround
// for this, but on some Windows installations it seems to work fine so we'll let
// the user choose via a menu option.
if (!Settings::getInstance()->getBool("RunInBackground")) {
// Unfortunately suspending ES-DE and resuming when the game/emulator process has exited
// doesn't work reliably on Windows, so we may need to keep ES-DE running in the background
// while the game is launched. I'm not sure if there is a workaround for this, but on most
// Windows installations it seems to work fine so we'll let the user choose via a menu option.
// Possibly the issue is specific to Windows 8.
// Running in the background is also required for Steam games as ES-DE would otherwise
// wait forever for Steam to exit unless it was already running when the game was launched.
if (!runInBackground) {
// Wait for the child process to exit.
WaitForSingleObject(pi.hThread, INFINITE);
WaitForSingleObject(pi.hProcess, INFINITE);
@ -174,7 +185,7 @@ int launchEmulatorWindows(const std::wstring& cmd_utf16)
}
}
LOG(LogError) << "launchEmulatorWindows - system error code " <<
LOG(LogError) << "launchGameWindows - system error code " <<
errorCode << ": " << errorMessage;
}

View file

@ -26,8 +26,8 @@ int runSystemCommand(const std::string& cmd_utf8);
// Windows specific UTF-16/wstring function. (FOR FUTURE USE)
int runSystemCommand(const std::wstring& cmd_utf16);
int launchEmulatorUnix(const std::string& cmd_utf8);
int launchEmulatorWindows(const std::wstring& cmd_utf16);
int launchGameUnix(const std::string& cmd_utf8, bool runInBackground);
int launchGameWindows(const std::wstring& cmd_utf16, bool runInBackground);
unsigned int getTaskbarState();
void hideTaskbar();

View file

@ -648,7 +648,7 @@ void Window::setLaunchedGame()
void Window::unsetLaunchedGame()
{
// Tell the GUI components that the user is back in ES again.
// Tell the GUI components that the user is back in ES-DE again.
for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++)
(*it)->onGameLaunchedDeactivate();