Added support for a %STARTDIR% es_systems.xml variable.

This commit is contained in:
Leon Styhre 2022-04-30 20:43:29 +02:00
parent de48b69760
commit 6caf4d193b
3 changed files with 142 additions and 24 deletions

View file

@ -994,10 +994,9 @@ void FileData::launchGame()
}
else {
#if defined(_WIN64)
LOG(LogDebug) << "FileData::launchGame(): Found emulator binary \""
LOG(LogDebug) << "FileData::launchGame(): Found emulator binary "
<< Utils::String::replace(
Utils::String::replace(binaryPath, "%ESPATH%", esPath), "/", "\\")
<< "\"";
Utils::String::replace(binaryPath, "%ESPATH%", esPath), "/", "\\");
#else
LOG(LogDebug) << "FileData::launchGame(): Found emulator binary \""
<< Utils::String::replace(binaryPath, "%ESPATH%", esPath) << "\"";
@ -1165,15 +1164,116 @@ void FileData::launchGame()
return;
}
std::string startDirectory;
size_t startDirPos {command.find("%STARTDIR%")};
if (startDirPos != std::string::npos) {
bool invalidEntry {false};
if (startDirPos + 12 >= command.size())
invalidEntry = true;
else if (command[startDirPos + 10] != '=')
invalidEntry = true;
if (!invalidEntry && command[startDirPos + 11] == '\"') {
size_t closingQuotation {command.find("\"", startDirPos + 12)};
if (closingQuotation != std::string::npos) {
startDirectory =
command.substr(startDirPos + 12, closingQuotation - startDirPos - 12);
command = command.replace(startDirPos, closingQuotation - startDirPos + 2, "");
}
else {
invalidEntry = true;
}
}
else if (!invalidEntry) {
size_t spacePos {command.find(" ", startDirPos)};
if (spacePos != std::string::npos) {
startDirectory = command.substr(startDirPos + 11, spacePos - startDirPos - 11);
command = command.replace(startDirPos, spacePos - startDirPos + 1, "");
}
else {
startDirectory = command.substr(startDirPos + 11, command.size() - startDirPos);
command = command.replace(startDirPos, command.size() - startDirPos, "");
}
}
if (invalidEntry) {
LOG(LogError) << "Couldn't launch game, invalid %STARTDIR% entry";
LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw;
window->queueInfoPopup("ERROR: INVALID %STARTDIR% VARIABLE ENTRY", 6000);
window->setAllowTextScrolling(true);
window->setAllowFileAnimation(true);
return;
}
if (startDirectory != "") {
startDirectory = Utils::FileSystem::expandHomePath(startDirectory);
#if defined(_WIN64)
startDirectory = Utils::String::replace(
startDirectory, "%EMUDIR%",
Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\"", "")));
#else
startDirectory = Utils::String::replace(
startDirectory, "%EMUDIR%",
Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\\", "")));
#endif
if (!Utils::FileSystem::isDirectory(startDirectory)) {
Utils::FileSystem::createDirectory(startDirectory);
if (!Utils::FileSystem::isDirectory(startDirectory)) {
LOG(LogError)
<< "Couldn't launch game, directory defined by %STARTDIR% could not be "
"created, permission problems?";
LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw;
window->queueInfoPopup("ERROR: DIRECTORY DEFINED BY %STARTDIR% COULD NOT BE "
"CREATED, PERMISSION PROBLEMS?",
6000);
window->setAllowTextScrolling(true);
window->setAllowFileAnimation(true);
return;
}
}
#if defined(_WIN64)
startDirectory = Utils::String::replace(startDirectory, "/", "\\");
#else
startDirectory = Utils::FileSystem::getEscapedPath(startDirectory);
#endif
LOG(LogDebug) << "FileData::launchGame(): Setting start directory to \""
<< startDirectory << "\"";
}
}
// Replace the remaining variables with their actual values.
command = Utils::String::replace(command, "%ROM%", romPath);
command = Utils::String::replace(command, "%BASENAME%", baseName);
command = Utils::String::replace(command, "%ROMRAW%", romRaw);
command = Utils::String::replace(command, "%ROMPATH%", getROMDirectory());
command = Utils::String::replace(command, "%ROMPATH%",
Utils::FileSystem::getEscapedPath(getROMDirectory()));
#if defined(_WIN64)
command = Utils::String::replace(command, "%EMUDIR%",
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
Utils::String::replace(binaryPath, "\"", ""))));
#else
command = Utils::String::replace(command, "%EMUDIR%",
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
Utils::String::replace(binaryPath, "\\", ""))));
#endif
// Trim any leading and trailing whitespace characters as they could cause launch issues.
command = Utils::String::trim(command);
#if defined(_WIN64)
// Hack to be able to surround paths with quotation marks when using the %ROMPATH% and
// %EMUDIR% variables.
command = Utils::String::replace(command, "\"\"", "");
#endif
// swapBuffers() is called here to turn the screen black to eliminate some potential
// flickering and to avoid showing the game launch message briefly when returning
// from the game.
@ -1198,10 +1298,11 @@ void FileData::launchGame()
// Possibly keep ES-DE running in the background while the game is launched.
#if defined(_WIN64)
returnValue = Utils::Platform::launchGameWindows(Utils::String::stringToWideString(command),
runInBackground, hideWindow);
returnValue = Utils::Platform::launchGameWindows(
Utils::String::stringToWideString(command),
Utils::String::stringToWideString(startDirectory), runInBackground, hideWindow);
#else
returnValue = Utils::Platform::launchGameUnix(command, runInBackground);
returnValue = Utils::Platform::launchGameUnix(command, startDirectory, runInBackground);
#endif
// Notify the user in case of a failed game launch using a popup window.
if (returnValue != 0) {
@ -1495,6 +1596,7 @@ const std::string FileData::findEmulatorPath(std::string& command)
}
if (Utils::FileSystem::isRegularFile(path) || Utils::FileSystem::isSymlink(path)) {
path = Utils::FileSystem::getEscapedPath(path);
command.replace(startPos, endPos - startPos + 1, path);
return path;
}
@ -1540,10 +1642,11 @@ const std::string FileData::findEmulatorPath(std::string& command)
#else
if (Utils::FileSystem::isRegularFile(emuExecutable) ||
Utils::FileSystem::isSymlink(emuExecutable)) {
exePath = emuExecutable;
exePath = Utils::FileSystem::getEscapedPath(emuExecutable);
}
else {
exePath = Utils::FileSystem::getPathToBinary(emuExecutable);
exePath =
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getPathToBinary(emuExecutable));
if (exePath != "")
exePath += "/" + emuExecutable;
}

View file

@ -74,7 +74,9 @@ namespace Utils
#endif
}
int launchGameUnix(const std::string& cmd_utf8, bool runInBackground)
int launchGameUnix(const std::string& cmd_utf8,
const std::string& startDirectory,
bool runInBackground)
{
#if defined(__unix__) || defined(__APPLE__)
std::string command = std::string(cmd_utf8) + " 2>&1 &";
@ -94,6 +96,9 @@ namespace Utils
std::string commandOutput;
int returnValue;
if (startDirectory != "")
command = "cd " + startDirectory + " && " + command;
if (!(commandPipe = reinterpret_cast<FILE*>(popen(command.c_str(), "r")))) {
LOG(LogError) << "Couldn't open pipe to command.";
return -1;
@ -141,7 +146,10 @@ namespace Utils
#endif
}
int launchGameWindows(const std::wstring& cmd_utf16, bool runInBackground, bool hideWindow)
int launchGameWindows(const std::wstring& cmd_utf16,
std::wstring& startDirectory,
bool runInBackground,
bool hideWindow)
{
#if defined(_WIN64)
STARTUPINFOW si {};
@ -157,18 +165,20 @@ namespace Utils
bool processReturnValue = true;
DWORD errorCode = 0;
wchar_t* startDir {startDirectory == L"" ? nullptr : &startDirectory[0]};
// clang-format off
processReturnValue = CreateProcessW(
nullptr, // No application name (use command line).
const_cast<wchar_t*>(cmd_utf16.c_str()), // Command line.
nullptr, // Process attributes.
nullptr, // Thread attributes.
FALSE, // Handles inheritance.
0, // Creation flags.
nullptr, // Use parent's environment block.
nullptr, // Use parent's starting directory.
&si, // Pointer to the STARTUPINFOW structure.
&pi); // Pointer to the PROCESS_INFORMATION structure.
processReturnValue = CreateProcessW(
nullptr, // No application name (use command line).
const_cast<wchar_t*>(cmd_utf16.c_str()), // Command line.
nullptr, // Process attributes.
nullptr, // Thread attributes.
FALSE, // Handles inheritance.
0, // Creation flags.
nullptr, // Use parent's environment block.
startDir, // Starting directory, possibly the same as parent.
&si, // Pointer to the STARTUPINFOW structure.
&pi); // Pointer to the PROCESS_INFORMATION structure.
// clang-format on
if (!runInBackground) {

View file

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