Added proper game launch function for Unix.

This commit is contained in:
Leon Styhre 2020-07-18 23:07:02 +02:00
parent 8fcb56cfb3
commit 6c79224eea
6 changed files with 83 additions and 15 deletions

View file

@ -466,7 +466,7 @@ void FileData::launchGame(Window* window)
#endif
Scripting::fireEvent("game-start", rom, basename);
int exitCode = 0;
int returnValue = 0;
if (command.find("%EMUPATH%") != std::string::npos) {
// Extract the emulator executable from the launch command string. This could either be
@ -530,24 +530,28 @@ void FileData::launchGame(Window* window)
#ifdef _WIN64
LOG(LogInfo) << Utils::String::wideStringToString(commandWide);
exitCode = launchEmulatorWindows(commandWide);
returnValue = launchEmulatorWindows(commandWide);
#else
LOG(LogInfo) << command;
exitCode = launchEmulatorUnix(command);
returnValue = launchEmulatorUnix(command);
#endif
// Notify the user in case of a failed game launch using a popup window.
if (exitCode != 0) {
LOG(LogWarning) << "...launch terminated with nonzero exit code " << exitCode << "!";
if (returnValue != 0) {
LOG(LogWarning) << "...launch terminated with nonzero return value " << returnValue << "!";
GuiInfoPopup* s = new GuiInfoPopup(window, "ERROR LAUNCHING GAME '" +
Utils::String::toUpper(metadata.get("name")) + "' (EXIT CODE " +
Utils::String::toUpper(std::to_string(exitCode) + ")"), 4000);
Utils::String::toUpper(metadata.get("name")) + "' (ERROR CODE " +
Utils::String::toUpper(std::to_string(returnValue) + ")"), 6000);
window->setInfoPopup(s);
}
// This code is only needed for Windows, where we need to keep ES running while
// the game/emulator is in use. It's basically used to pause any playing game video.
#ifdef _WIN64
else {
window->setLaunchedGame();
}
#endif
Scripting::fireEvent("game-end");

View file

@ -56,6 +56,8 @@ public:
void apply(float t) override
{
// TEMPORARY, disabled as it causes flicker when launching games.
return;
cameraOut = Transform4x4f::Identity();
float zoom = Math::lerp(1.0, 4.25f, t*t);

View file

@ -1,7 +1,7 @@
//
// MoveCameraAnimation.h
//
// Animation to play when moving the camera.
// Animation to play when moving the camera, used by the slide transition style.
//
#pragma once

View file

@ -408,12 +408,16 @@ bool ViewController::input(InputConfig* config, Input input)
if (mLockInput)
return true;
// This code is only needed for Windows, where we need to keep ES running while
// the game/emulator is in use. It's basically used to pause any playing game video.
#ifdef _WIN64
// 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.
if (mWindow->getGameLaunchedState()) {
mWindow->unsetLaunchedGame();
}
#endif
// Open menu.
if (!(UIModeController::getInstance()->isUIModeKid() &&
@ -539,9 +543,13 @@ void ViewController::reloadGameListView(IGameListView* view, bool reloadTheme)
}
}
// This code is only needed for Windows, where we need to keep ES running while
// the game/emulator is in use. It's basically used to pause any playing game video.
#ifdef _WIN64
// If a game has been launched, then update all the GUI components to reflect this.
if (mWindow->getGameLaunchedState())
mWindow->setLaunchedGame();
#endif
// Redisplay the current view.
if (mCurrentView)

View file

@ -68,10 +68,49 @@ int runSystemCommand(const std::wstring& cmd_utf16)
int launchEmulatorUnix(const std::string& cmd_utf8)
{
// TODO, replace with proper child process execution.
#ifdef __unix__
return system(cmd_utf8.c_str());
#else
std::string command = std::string(cmd_utf8) + " 2>&1";
FILE* commandPipe;
std::array<char, 128> buffer;
std::string commandOutput;
int returnValue;
if (!(commandPipe = (FILE*)popen(command.c_str(), "r"))) {
LOG(LogError) << "Error - couldn't open pipe to command.";
return -1;
}
while (fgets(buffer.data(), buffer.size(), commandPipe) != nullptr) {
commandOutput += buffer.data();
}
returnValue = pclose(commandPipe);
// We need to shift the return value as it contains some flags (which we don't need).
returnValue >>= 8;
// Remove any trailing newline from the command output.
if (commandOutput.size()) {
if (commandOutput.back() == '\n')
commandOutput.pop_back();
}
if (returnValue) {
LOG(LogError) << "Error - launchEmulatorUnix - return value " <<
std::to_string(returnValue) + ":";
if (commandOutput.size())
LOG(LogError) << commandOutput;
else
LOG(LogError) << "No error output provided by emulator.";
}
else if (commandOutput.size()) {
LOG(LogDebug) << "Platform::launchEmulatorUnix():";
LOG(LogDebug) << "Output from launched game:\n" << commandOutput;
}
return returnValue;
#else // __unix__
return 0;
#endif
}
@ -98,6 +137,15 @@ 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 need to keep ES running. Maybe there is
// some workaround for this. Possibly it's just SDL that is glitchy or it's actually
// something OS-specific. Keeping the code here just in case it could be reactivated.
// For sure it would simplify things, like not having to pause playing videos.
// // Wait for the child process to exit.
// WaitForSingleObject(pi.hThread, INFINITE);
// WaitForSingleObject(pi.hProcess, INFINITE);
// If the return value is false, then something failed.
if (!processReturnValue) {
LPWSTR pBuffer = nullptr;
@ -110,10 +158,14 @@ int launchEmulatorWindows(const std::wstring& cmd_utf16)
std::string errorMessage = Utils::String::wideStringToString(pBuffer);
// Remove trailing newline from the error message.
if (errorMessage.back() == '\n');
errorMessage.pop_back();
if (errorMessage.back() == '\r');
errorMessage.pop_back();
if (errorMessage.size()) {
if (errorMessage.back() == '\n')
errorMessage.pop_back();
if (errorMessage.size()) {
if (errorMessage.back() == '\r')
errorMessage.pop_back();
}
}
LOG(LogError) << "Error - launchEmulatorWindows - system error code " <<
errorCode << ": " << errorMessage;
@ -124,6 +176,7 @@ int launchEmulatorWindows(const std::wstring& cmd_utf16)
CloseHandle(pi.hThread);
return errorCode;
#else // _WIN64
return 0;
#endif

View file

@ -27,6 +27,7 @@ Window::Window()
mTimeSinceLastInput(0),
mScreenSaver(nullptr),
mRenderScreenSaver(false),
mGameLaunchedState(false),
mInfoPopup(nullptr)
{
mHelp = new HelpComponent(this);