mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-01-18 15:15:37 +00:00
(Android) Added find rules logic and launch command configuration logic
Also did some general refactoring of the emulator launch code
This commit is contained in:
parent
d48872af6c
commit
310fb6e809
|
@ -947,6 +947,12 @@ void FileData::launchGame()
|
|||
bool foundCoreFile {false};
|
||||
std::vector<std::string> emulatorCorePaths;
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
std::string androidPackage;
|
||||
std::string androidComponent;
|
||||
std::vector<std::pair<std::string, std::string>> androidExtras;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64)
|
||||
bool hideWindow {false};
|
||||
|
||||
|
@ -997,30 +1003,27 @@ void FileData::launchGame()
|
|||
// Expand home path if ~ is used.
|
||||
command = Utils::FileSystem::expandHomePath(command);
|
||||
|
||||
std::string preCommandPath;
|
||||
|
||||
// Check for any pre-command entry, and if it exists then expand it using the find rules.
|
||||
if (command.find("%PRECOMMAND_") != std::string::npos) {
|
||||
preCommandPath = findEmulatorPath(command, true);
|
||||
const std::pair<std::string, FileData::findEmulatorResult> preCommand {
|
||||
findEmulator(command, true)};
|
||||
// Show an error message if there was no matching emulator entry in es_find_rules.xml.
|
||||
if (preCommandPath.substr(0, 18) == "NO EMULATOR RULE: ") {
|
||||
const std::string& preCommandEntry {
|
||||
preCommandPath.substr(18, preCommandPath.size() - 18)};
|
||||
if (preCommand.second == FileData::findEmulatorResult::NO_RULES) {
|
||||
LOG(LogError)
|
||||
<< "Couldn't launch game, either there is no emulator entry for pre-command \""
|
||||
<< preCommandEntry << "\" in es_find_rules.xml or there are no rules defined";
|
||||
<< preCommand.first << "\" in es_find_rules.xml or there are no rules defined";
|
||||
LOG(LogError) << "Raw emulator launch command:";
|
||||
LOG(LogError) << commandRaw;
|
||||
|
||||
window->queueInfoPopup("ERROR: MISSING PRE-COMMAND FIND RULES CONFIGURATION FOR '" +
|
||||
preCommandEntry + "'",
|
||||
preCommand.first + "'",
|
||||
6000);
|
||||
window->setAllowTextScrolling(true);
|
||||
window->setAllowFileAnimation(true);
|
||||
return;
|
||||
}
|
||||
else if (preCommandPath.empty()) {
|
||||
LOG(LogError) << "Couldn't launch game, pre-command binary not found";
|
||||
else if (preCommand.first.empty()) {
|
||||
LOG(LogError) << "Couldn't launch game, pre-command not found";
|
||||
LOG(LogError) << "Raw emulator launch command:";
|
||||
LOG(LogError) << commandRaw;
|
||||
|
||||
|
@ -1047,30 +1050,30 @@ void FileData::launchGame()
|
|||
return;
|
||||
}
|
||||
else {
|
||||
LOG(LogDebug) << "FileData::launchGame(): Pre-command binary set to \""
|
||||
<< preCommandPath << "\"";
|
||||
LOG(LogDebug) << "FileData::launchGame(): Pre-command set to \"" << preCommand.first
|
||||
<< "\"";
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the emulator binary actually exists, and if so, get its path.
|
||||
const std::string& binaryPath {findEmulatorPath(command, false)};
|
||||
// Check that the emulator actually exists, and if so, get its path.
|
||||
const std::pair<std::string, FileData::findEmulatorResult> emulator {
|
||||
findEmulator(command, false)};
|
||||
|
||||
// Show an error message if there was no matching emulator entry in es_find_rules.xml.
|
||||
if (binaryPath.substr(0, 18) == "NO EMULATOR RULE: ") {
|
||||
const std::string& emulatorEntry {binaryPath.substr(18, binaryPath.size() - 18)};
|
||||
if (emulator.second == FileData::findEmulatorResult::NO_RULES) {
|
||||
LOG(LogError) << "Couldn't launch game, either there is no emulator entry for \""
|
||||
<< emulatorEntry << "\" in es_find_rules.xml or there are no rules defined";
|
||||
<< emulator.first << "\" in es_find_rules.xml or there are no rules defined";
|
||||
LOG(LogError) << "Raw emulator launch command:";
|
||||
LOG(LogError) << commandRaw;
|
||||
|
||||
window->queueInfoPopup(
|
||||
"ERROR: MISSING EMULATOR FIND RULES CONFIGURATION FOR '" + emulatorEntry + "'", 6000);
|
||||
"ERROR: MISSING EMULATOR FIND RULES CONFIGURATION FOR '" + emulator.first + "'", 6000);
|
||||
window->setAllowTextScrolling(true);
|
||||
window->setAllowFileAnimation(true);
|
||||
return;
|
||||
}
|
||||
else if (binaryPath.empty()) {
|
||||
LOG(LogError) << "Couldn't launch game, emulator binary not found";
|
||||
else if (emulator.second == FileData::findEmulatorResult::NOT_FOUND) {
|
||||
LOG(LogError) << "Couldn't launch game, emulator not found";
|
||||
LOG(LogError) << "Raw emulator launch command:";
|
||||
LOG(LogError) << commandRaw;
|
||||
|
||||
|
@ -1098,15 +1101,27 @@ void FileData::launchGame()
|
|||
}
|
||||
#if defined(_WIN64)
|
||||
else {
|
||||
std::string binaryLogPath {Utils::String::replace(
|
||||
Utils::String::replace(binaryPath, "%ESPATH%", esPath), "/", "\\")};
|
||||
if (binaryLogPath.front() != '\"' && binaryLogPath.back() != '\"')
|
||||
binaryLogPath = "\"" + binaryLogPath + "\"";
|
||||
LOG(LogDebug) << "FileData::launchGame(): Emulator binary set to " << binaryLogPath;
|
||||
std::string emulatorLogPath {Utils::String::replace(
|
||||
Utils::String::replace(emulator.first, "%ESPATH%", esPath), "/", "\\")};
|
||||
if (emulatorLogPath.front() != '\"' && emulatorLogPath.back() != '\"')
|
||||
emulatorLogPath = "\"" + emulatorLogPath + "\"";
|
||||
LOG(LogDebug) << "FileData::launchGame(): Emulator set to " << emulatorLogPath;
|
||||
#else
|
||||
#if defined(__ANDROID__)
|
||||
else if (emulator.second == FileData::findEmulatorResult::FOUND_ANDROID_PACKAGE) {
|
||||
androidPackage = emulator.first;
|
||||
const size_t pipePos {androidPackage.find('|')};
|
||||
if (pipePos != std::string::npos) {
|
||||
androidComponent = androidPackage.substr(pipePos + 1);
|
||||
androidPackage = androidPackage.substr(0, pipePos);
|
||||
}
|
||||
LOG(LogDebug) << "FileData::launchGame(): Found Android emulator package \""
|
||||
<< androidPackage << "\"";
|
||||
}
|
||||
#endif
|
||||
else if (!isShortcut) {
|
||||
LOG(LogDebug) << "FileData::launchGame(): Emulator binary set to \""
|
||||
<< Utils::String::replace(binaryPath, "%ESPATH%", esPath) << "\"";
|
||||
LOG(LogDebug) << "FileData::launchGame(): Emulator set to \""
|
||||
<< Utils::String::replace(emulator.first, "%ESPATH%", esPath) << "\"";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1127,11 +1142,12 @@ void FileData::launchGame()
|
|||
if (spacePos != std::string::npos) {
|
||||
coreRaw = command.substr(emuPathPos, spacePos - emuPathPos);
|
||||
#if defined(_WIN64)
|
||||
coreFile = Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\"", "")) +
|
||||
command.substr(emuPathPos + 9, spacePos - emuPathPos - 9);
|
||||
coreFile =
|
||||
Utils::FileSystem::getParent(Utils::String::replace(emulator.first, "\"", "")) +
|
||||
command.substr(emuPathPos + 9, spacePos - emuPathPos - 9);
|
||||
coreFile = Utils::String::replace(coreFile, "/", "\\");
|
||||
#else
|
||||
coreFile = Utils::FileSystem::getParent(binaryPath) +
|
||||
coreFile = Utils::FileSystem::getParent(emulator.first) +
|
||||
command.substr(emuPathPos + 9, spacePos - emuPathPos - 9);
|
||||
#endif
|
||||
if (hasQuotationMark) {
|
||||
|
@ -1192,7 +1208,7 @@ void FileData::launchGame()
|
|||
// the emulator core using the rules defined in es_find_rules.xml.
|
||||
for (std::string& path : emulatorCorePaths) {
|
||||
// The position of the %CORE_ variable could have changed as there may have been an
|
||||
// %EMULATOR_ variable that was substituted for the actual emulator binary.
|
||||
// %EMULATOR_ variable that was substituted for the actual emulator.
|
||||
coreEntryPos = command.find("%CORE_");
|
||||
coreFilePos = command.find("%", coreEntryPos + 6);
|
||||
|
||||
|
@ -1218,10 +1234,11 @@ void FileData::launchGame()
|
|||
#if defined(_WIN64)
|
||||
coreFile = coreFile.replace(
|
||||
stringPos, 9,
|
||||
Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\"", "")));
|
||||
Utils::FileSystem::getParent(Utils::String::replace(emulator.first, "\"", "")));
|
||||
coreFile = Utils::String::replace(coreFile, "/", "\\");
|
||||
#else
|
||||
coreFile = coreFile.replace(stringPos, 9, Utils::FileSystem::getParent(binaryPath));
|
||||
coreFile =
|
||||
coreFile.replace(stringPos, 9, Utils::FileSystem::getParent(emulator.first));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1325,7 +1342,7 @@ void FileData::launchGame()
|
|||
#if defined(_WIN64)
|
||||
startDirectory = Utils::String::replace(
|
||||
startDirectory, "%EMUDIR%",
|
||||
Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\"", "")));
|
||||
Utils::FileSystem::getParent(Utils::String::replace(emulator.first, "\"", "")));
|
||||
|
||||
startDirectory = Utils::String::replace(
|
||||
startDirectory, "%GAMEDIR%",
|
||||
|
@ -1336,7 +1353,7 @@ void FileData::launchGame()
|
|||
#else
|
||||
startDirectory = Utils::String::replace(
|
||||
startDirectory, "%EMUDIR%",
|
||||
Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\\", "")));
|
||||
Utils::FileSystem::getParent(Utils::String::replace(emulator.first, "\\", "")));
|
||||
|
||||
startDirectory = Utils::String::replace(
|
||||
startDirectory, "%GAMEDIR%",
|
||||
|
@ -1500,7 +1517,7 @@ void FileData::launchGame()
|
|||
if (Utils::FileSystem::exists(Utils::String::replace(romPath, "\\", ""))) {
|
||||
LOG(LogInfo) << "Opening app or alias file \""
|
||||
<< Utils::String::replace(romPath, "\\", "") << "\"";
|
||||
command = Utils::String::replace(command, binaryPath, "open -W -a");
|
||||
command = Utils::String::replace(command, emulator.first, "open -W -a");
|
||||
}
|
||||
else {
|
||||
LOG(LogError) << "App or alias file \"" << romPath
|
||||
|
@ -1551,7 +1568,7 @@ void FileData::launchGame()
|
|||
}
|
||||
romPath = Utils::String::replace(romPath, "%%", "%");
|
||||
romPath = Utils::String::trim(romPath);
|
||||
command = Utils::String::replace(command, binaryPath, "");
|
||||
command = Utils::String::replace(command, emulator.first, "");
|
||||
execEntry = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1583,12 +1600,71 @@ void FileData::launchGame()
|
|||
command = Utils::String::replace(command, "%ROMRAW%", romRaw);
|
||||
command = Utils::String::replace(command, "%ROMPATH%",
|
||||
Utils::FileSystem::getEscapedPath(getROMDirectory()));
|
||||
#if defined(__ANDROID__)
|
||||
command = Utils::String::replace(command, "%ANDROIDPACKAGE%", androidPackage);
|
||||
size_t extraPos {command.find("%EXTRA_")};
|
||||
|
||||
while (extraPos != std::string::npos) {
|
||||
if (extraPos != std::string::npos) {
|
||||
bool invalidEntry {false};
|
||||
bool isQuoted {false};
|
||||
std::string extraName;
|
||||
std::string extraValue;
|
||||
|
||||
size_t equalPos {command.find("=", extraPos)};
|
||||
if (equalPos == std::string::npos)
|
||||
invalidEntry = true;
|
||||
|
||||
if (!invalidEntry && extraPos + 8 >= command.size())
|
||||
invalidEntry = true;
|
||||
|
||||
if (!invalidEntry) {
|
||||
if (command.length() > equalPos && command[equalPos + 1] == '\"')
|
||||
isQuoted = true;
|
||||
|
||||
extraName = command.substr(extraPos + 7, equalPos - (extraPos + 8));
|
||||
|
||||
if (isQuoted) {
|
||||
const size_t closeQuotePos {command.find("\"", equalPos + 2)};
|
||||
if (closeQuotePos != std::string::npos)
|
||||
extraValue = command.substr(equalPos + 2, closeQuotePos - (equalPos + 2));
|
||||
else
|
||||
invalidEntry = true;
|
||||
}
|
||||
else {
|
||||
const size_t spacePos {command.find(" ", extraPos)};
|
||||
if (spacePos != std::string::npos)
|
||||
extraValue = command.substr(equalPos + 1, spacePos - (equalPos + 1));
|
||||
else
|
||||
extraValue = command.substr(equalPos + 1, command.size() - equalPos);
|
||||
}
|
||||
|
||||
if (invalidEntry) {
|
||||
LOG(LogError) << "Invalid entry in systems configuration file es_systems.xml";
|
||||
LOG(LogError) << "Raw emulator launch command:";
|
||||
LOG(LogError) << commandRaw;
|
||||
|
||||
window->queueInfoPopup("ERROR: INVALID ENTRY IN SYSTEMS CONFIGURATION FILE",
|
||||
6000);
|
||||
window->setAllowTextScrolling(true);
|
||||
window->setAllowFileAnimation(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (extraName != "" && extraValue != "")
|
||||
androidExtras.emplace_back(make_pair(extraName, extraValue));
|
||||
}
|
||||
}
|
||||
extraPos = command.find("%EXTRA_", extraPos + 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64)
|
||||
command = Utils::String::replace(
|
||||
command, "%ESPATH%", Utils::String::replace(Utils::FileSystem::getExePath(), "/", "\\"));
|
||||
command = Utils::String::replace(command, "%EMUDIR%",
|
||||
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
|
||||
Utils::String::replace(binaryPath, "\"", ""))));
|
||||
Utils::String::replace(emulator.first, "\"", ""))));
|
||||
command = Utils::String::replace(command, "%GAMEDIR%",
|
||||
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
|
||||
Utils::String::replace(romPath, "\"", ""))));
|
||||
|
@ -1600,7 +1676,7 @@ void FileData::launchGame()
|
|||
command = Utils::String::replace(command, "%ESPATH%", Utils::FileSystem::getExePath());
|
||||
command = Utils::String::replace(command, "%EMUDIR%",
|
||||
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
|
||||
Utils::String::replace(binaryPath, "\\", ""))));
|
||||
Utils::String::replace(emulator.first, "\\", ""))));
|
||||
command = Utils::String::replace(command, "%GAMEDIR%",
|
||||
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
|
||||
Utils::String::replace(romPath, "\\", ""))));
|
||||
|
@ -1625,8 +1701,19 @@ void FileData::launchGame()
|
|||
|
||||
LOG(LogDebug) << "Raw emulator launch command:";
|
||||
LOG(LogDebug) << commandRaw;
|
||||
#if defined(__ANDROID__)
|
||||
LOG(LogInfo) << "Expanded emulator launch parameters:";
|
||||
LOG(LogInfo) << "Package: " << androidPackage;
|
||||
LOG(LogInfo) << "Component: "
|
||||
<< (androidComponent == "" ? "<package default>" : androidComponent);
|
||||
for (auto& extra : androidExtras) {
|
||||
LOG(LogInfo) << "Extra name: " << extra.first;
|
||||
LOG(LogInfo) << "Extra value: " << extra.second;
|
||||
}
|
||||
#else
|
||||
LOG(LogInfo) << "Expanded emulator launch command:";
|
||||
LOG(LogInfo) << command;
|
||||
#endif
|
||||
|
||||
#if defined(FLATPAK_BUILD)
|
||||
// Break out of the sandbox.
|
||||
|
@ -1645,8 +1732,11 @@ void FileData::launchGame()
|
|||
returnValue = Utils::Platform::launchGameWindows(
|
||||
Utils::String::stringToWideString(command),
|
||||
Utils::String::stringToWideString(startDirectory), runInBackground, hideWindow);
|
||||
#elif defined(__ANDROID__)
|
||||
returnValue =
|
||||
Utils::Platform::Android::launchGame(androidPackage, androidComponent, androidExtras);
|
||||
#else
|
||||
returnValue = Utils::Platform::launchGameUnix(command, startDirectory, 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) {
|
||||
|
@ -1737,23 +1827,27 @@ void FileData::launchGame()
|
|||
gameToUpdate->mSystem->onMetaDataSavePoint();
|
||||
}
|
||||
|
||||
const std::string FileData::findEmulatorPath(std::string& command, const bool preCommand)
|
||||
const std::pair<std::string, FileData::findEmulatorResult> FileData::findEmulator(
|
||||
std::string& command, const bool preCommand)
|
||||
{
|
||||
// Extract the emulator executable from the launch command string. There are two ways
|
||||
// that the emulator can be defined in es_systems.xml, either using the find rules in
|
||||
// es_find_rules.xml or via the explicit emulator binary name. In the former case, we
|
||||
// es_find_rules.xml or via the explicit emulator name. In the former case, we
|
||||
// need to process any configured systempath and staticpath rules (and for Windows also
|
||||
// winregistrypath and winregistryvalue rules), and in the latter case we simply search
|
||||
// for the emulator binary in the system path.
|
||||
// for the emulator in the system path.
|
||||
|
||||
std::string emuExecutable;
|
||||
std::string exePath;
|
||||
|
||||
// Method 1, emulator binary is defined using find rules:
|
||||
// Method 1, emulator is defined using find rules:
|
||||
|
||||
#if defined(_WIN64)
|
||||
std::vector<std::string> emulatorWinRegistryPaths;
|
||||
std::vector<std::string> emulatorWinRegistryValues;
|
||||
#endif
|
||||
#if defined(__ANDROID__)
|
||||
std::vector<std::string> emulatorAndroidPackages;
|
||||
#endif
|
||||
std::vector<std::string> emulatorSystemPaths;
|
||||
std::vector<std::string> emulatorStaticPaths;
|
||||
|
@ -1782,6 +1876,10 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
|
|||
SystemData::sFindRules.get()->mEmulators[emulatorEntry].winRegistryPaths;
|
||||
emulatorWinRegistryValues =
|
||||
SystemData::sFindRules.get()->mEmulators[emulatorEntry].winRegistryValues;
|
||||
#endif
|
||||
#if defined(__ANDROID__)
|
||||
emulatorAndroidPackages =
|
||||
SystemData::sFindRules.get()->mEmulators[emulatorEntry].androidPackages;
|
||||
#endif
|
||||
emulatorSystemPaths = SystemData::sFindRules.get()->mEmulators[emulatorEntry].systemPaths;
|
||||
|
||||
|
@ -1793,10 +1891,13 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
|
|||
if (emulatorEntry != "" && emulatorWinRegistryPaths.empty() &&
|
||||
emulatorWinRegistryValues.empty() && emulatorSystemPaths.empty() &&
|
||||
emulatorStaticPaths.empty())
|
||||
#elif defined(__ANDROID__)
|
||||
if (emulatorEntry != "" && emulatorAndroidPackages.empty() && emulatorSystemPaths.empty() &&
|
||||
emulatorStaticPaths.empty())
|
||||
#else
|
||||
if (emulatorEntry != "" && emulatorSystemPaths.empty() && emulatorStaticPaths.empty())
|
||||
#endif
|
||||
return "NO EMULATOR RULE: " + emulatorEntry;
|
||||
return std::make_pair(emulatorEntry, FileData::findEmulatorResult::NO_RULES);
|
||||
|
||||
#if defined(_WIN64)
|
||||
for (std::string& path : emulatorWinRegistryPaths) {
|
||||
|
@ -1834,19 +1935,19 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
|
|||
continue;
|
||||
}
|
||||
|
||||
// That a value was found does not guarantee that the emulator binary actually exists,
|
||||
// so check for that as well.
|
||||
// That a value was found does not guarantee that the emulator actually exists, so
|
||||
// check for that as well.
|
||||
if (pathStatus == ERROR_SUCCESS) {
|
||||
if (Utils::FileSystem::isRegularFile(Utils::String::wideStringToString(registryPath)) ||
|
||||
Utils::FileSystem::isSymlink(Utils::String::wideStringToString(registryPath))) {
|
||||
LOG(LogDebug) << "FileData::findEmulatorPath(): "
|
||||
<< (preCommand ? "Pre-command binary" : "Emulator binary")
|
||||
LOG(LogDebug) << "FileData::findEmulator(): "
|
||||
<< (preCommand ? "Pre-command" : "Emulator")
|
||||
<< " found via winregistrypath rule";
|
||||
exePath = Utils::FileSystem::getEscapedPath(
|
||||
Utils::String::wideStringToString(registryPath));
|
||||
command.replace(startPos, endPos - startPos + 1, exePath);
|
||||
RegCloseKey(registryKey);
|
||||
return exePath;
|
||||
return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
|
||||
}
|
||||
}
|
||||
RegCloseKey(registryKey);
|
||||
|
@ -1906,25 +2007,45 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
|
|||
if (!appendString.empty())
|
||||
path.append(Utils::String::stringToWideString(appendString));
|
||||
|
||||
// That a value was found does not guarantee that the emulator binary actually exists,
|
||||
// That a value was found does not guarantee that the emulator actually exists,
|
||||
// so check for that as well.
|
||||
if (pathStatus == ERROR_SUCCESS) {
|
||||
if (Utils::FileSystem::isRegularFile(Utils::String::wideStringToString(path)) ||
|
||||
Utils::FileSystem::isSymlink(Utils::String::wideStringToString(path))) {
|
||||
LOG(LogDebug) << "FileData::findEmulatorPath(): "
|
||||
<< (preCommand ? "Pre-command binary" : "Emulator binary")
|
||||
LOG(LogDebug) << "FileData::findEmulator(): "
|
||||
<< (preCommand ? "Pre-command" : "Emulator")
|
||||
<< " found via winregistryvalue rule";
|
||||
exePath =
|
||||
Utils::FileSystem::getEscapedPath(Utils::String::wideStringToString(path));
|
||||
command.replace(startPos, endPos - startPos + 1, exePath);
|
||||
RegCloseKey(registryKey);
|
||||
return exePath;
|
||||
return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
|
||||
}
|
||||
}
|
||||
RegCloseKey(registryKey);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
for (std::string& androidpackage : emulatorAndroidPackages) {
|
||||
// If a pipe character is present in the androidpackage entry it means an explicit Intent
|
||||
// component should be used rather than the default one. The checkEmulatorInstalled()
|
||||
// Java function will check for the component as well and if it's not found it flags
|
||||
// the overall emulator entry as not found.
|
||||
std::string packageName {androidpackage};
|
||||
std::string component;
|
||||
const size_t pipePos {packageName.find('|')};
|
||||
if (pipePos != std::string::npos) {
|
||||
component = packageName.substr(pipePos + 1);
|
||||
packageName = packageName.substr(0, pipePos);
|
||||
}
|
||||
if (Utils::Platform::Android::checkEmulatorInstalled(packageName, component)) {
|
||||
return std::make_pair(androidpackage,
|
||||
FileData::findEmulatorResult::FOUND_ANDROID_PACKAGE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (std::string& path : emulatorSystemPaths) {
|
||||
#if defined(_WIN64)
|
||||
std::wstring pathWide {Utils::String::stringToWideString(path)};
|
||||
|
@ -1945,30 +2066,30 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
|
|||
}
|
||||
}
|
||||
if (exePath != "") {
|
||||
LOG(LogDebug) << "FileData::findEmulatorPath(): "
|
||||
<< (preCommand ? "Pre-command binary" : "Emulator binary")
|
||||
LOG(LogDebug) << "FileData::findEmulator(): "
|
||||
<< (preCommand ? "Pre-command" : "Emulator")
|
||||
<< " found via systempath rule";
|
||||
exePath += "\\" + path;
|
||||
exePath = Utils::FileSystem::getEscapedPath(exePath);
|
||||
command.replace(startPos, endPos - startPos + 1, exePath);
|
||||
return exePath;
|
||||
return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
|
||||
}
|
||||
#else
|
||||
exePath = Utils::FileSystem::getPathToBinary(path);
|
||||
if (exePath != "") {
|
||||
LOG(LogDebug) << "FileData::findEmulatorPath(): "
|
||||
<< (preCommand ? "Pre-command binary" : "Emulator binary")
|
||||
LOG(LogDebug) << "FileData::findEmulator(): "
|
||||
<< (preCommand ? "Pre-command" : "Emulator")
|
||||
<< " found via systempath rule";
|
||||
exePath += "/" + path;
|
||||
command.replace(startPos, endPos - startPos + 1, exePath);
|
||||
return exePath;
|
||||
return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for (std::string& path : emulatorStaticPaths) {
|
||||
// If a pipe character is present in the staticpath entry it means we should substitute
|
||||
// the emulator binary with whatever is defined after the pipe character.
|
||||
// the emulator with whatever is defined after the pipe character.
|
||||
std::string replaceCommand;
|
||||
const size_t pipePos {path.find('|')};
|
||||
|
||||
|
@ -1998,23 +2119,23 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
|
|||
}
|
||||
|
||||
if (Utils::FileSystem::isRegularFile(path) || Utils::FileSystem::isSymlink(path)) {
|
||||
LOG(LogDebug) << "FileData::findEmulatorPath(): "
|
||||
<< (preCommand ? "Pre-command binary" : "Emulator binary")
|
||||
LOG(LogDebug) << "FileData::findEmulator(): "
|
||||
<< (preCommand ? "Pre-command" : "Emulator")
|
||||
<< " found via staticpath rule";
|
||||
if (replaceCommand == "") {
|
||||
exePath = Utils::FileSystem::getEscapedPath(path);
|
||||
}
|
||||
else {
|
||||
LOG(LogDebug) << "FileData::findEmulatorPath(): Replacing emulator binary in "
|
||||
LOG(LogDebug) << "FileData::findEmulator(): Replacing emulator in "
|
||||
"staticpath rule with explicitly defined command";
|
||||
exePath = replaceCommand;
|
||||
}
|
||||
command.replace(startPos, endPos - startPos + 1, exePath);
|
||||
return exePath;
|
||||
return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
// Method 2, exact emulator binary name:
|
||||
// Method 2, exact emulator name:
|
||||
|
||||
// If %ESPATH% is used, then expand it to the binary directory of ES-DE.
|
||||
command = Utils::String::replace(command, "%ESPATH%", Utils::FileSystem::getExePath());
|
||||
|
@ -2052,7 +2173,7 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
|
|||
|
||||
exePath = Utils::String::wideStringToString(pathBuffer.data());
|
||||
}
|
||||
#else
|
||||
#elif !defined(__ANDROID__)
|
||||
if (Utils::FileSystem::isRegularFile(emuExecutable) ||
|
||||
Utils::FileSystem::isSymlink(emuExecutable)) {
|
||||
exePath = Utils::FileSystem::getEscapedPath(emuExecutable);
|
||||
|
@ -2065,7 +2186,7 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
|
|||
}
|
||||
#endif
|
||||
|
||||
return exePath;
|
||||
return std::make_pair(exePath, FileData::findEmulatorResult::NOT_FOUND);
|
||||
}
|
||||
|
||||
CollectionFileData::CollectionFileData(FileData* file, SystemData* system)
|
||||
|
|
|
@ -123,8 +123,16 @@ public:
|
|||
virtual FileData* getSourceFileData() { return this; }
|
||||
const std::string& getSystemName() const { return mSystemName; }
|
||||
|
||||
enum class findEmulatorResult {
|
||||
FOUND_FILE,
|
||||
FOUND_ANDROID_PACKAGE,
|
||||
NOT_FOUND,
|
||||
NO_RULES
|
||||
};
|
||||
|
||||
void launchGame();
|
||||
const std::string findEmulatorPath(std::string& command, const bool preCommand);
|
||||
const std::pair<std::string, FileData::findEmulatorResult> findEmulator(std::string& command,
|
||||
const bool preCommand);
|
||||
|
||||
using ComparisonFunction = bool(const FileData* a, const FileData* b);
|
||||
struct SortType {
|
||||
|
|
|
@ -56,6 +56,9 @@ void FindRules::loadFindRules()
|
|||
#elif defined(__APPLE__)
|
||||
filePath =
|
||||
ResourceManager::getInstance().getResourcePath(":/systems/macos/es_find_rules.xml", false);
|
||||
#elif defined(__ANDROID__)
|
||||
filePath = ResourceManager::getInstance().getResourcePath(":/systems/android/es_find_rules.xml",
|
||||
false);
|
||||
#else
|
||||
filePath =
|
||||
ResourceManager::getInstance().getResourcePath(":/systems/unix/es_find_rules.xml", false);
|
||||
|
@ -84,7 +87,6 @@ void FindRules::loadFindRules()
|
|||
#else
|
||||
const pugi::xml_parse_result& res {doc.load_file(path.c_str())};
|
||||
#endif
|
||||
|
||||
if (!res) {
|
||||
LOG(LogError) << "Couldn't parse es_find_rules.xml: " << res.description();
|
||||
continue;
|
||||
|
@ -126,6 +128,9 @@ void FindRules::loadFindRules()
|
|||
#if defined(_WIN64)
|
||||
if (ruleType != "winregistrypath" && ruleType != "winregistryvalue" &&
|
||||
ruleType != "systempath" && ruleType != "staticpath") {
|
||||
#elif defined(__ANDROID__)
|
||||
if (ruleType != "androidpackage" && ruleType != "systempath" &&
|
||||
ruleType != "staticpath") {
|
||||
#else
|
||||
if (ruleType != "systempath" && ruleType != "staticpath") {
|
||||
#endif
|
||||
|
@ -145,6 +150,9 @@ void FindRules::loadFindRules()
|
|||
emulatorRules.winRegistryPaths.emplace_back(entryValue);
|
||||
else if (ruleType == "winregistryvalue")
|
||||
emulatorRules.winRegistryValues.emplace_back(entryValue);
|
||||
#elif defined(__ANDROID__)
|
||||
else if (ruleType == "androidpackage")
|
||||
emulatorRules.androidPackages.emplace_back(entryValue);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -154,6 +162,8 @@ void FindRules::loadFindRules()
|
|||
#if defined(_WIN64)
|
||||
emulatorRules.winRegistryPaths.clear();
|
||||
emulatorRules.winRegistryValues.clear();
|
||||
#elif defined(__ANDROID__)
|
||||
emulatorRules.androidPackages.clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -969,6 +979,8 @@ std::vector<std::string> SystemData::getConfigPath()
|
|||
path = ResourceManager::getInstance().getResourcePath(":/systems/windows/es_systems.xml", true);
|
||||
#elif defined(__APPLE__)
|
||||
path = ResourceManager::getInstance().getResourcePath(":/systems/macos/es_systems.xml", true);
|
||||
#elif defined(__ANDROID__)
|
||||
path = ResourceManager::getInstance().getResourcePath(":/systems/android/es_systems.xml", true);
|
||||
#else
|
||||
path = ResourceManager::getInstance().getResourcePath(":/systems/unix/es_systems.xml", true);
|
||||
#endif
|
||||
|
|
|
@ -44,6 +44,8 @@ private:
|
|||
#if defined(_WIN64)
|
||||
std::vector<std::string> winRegistryPaths;
|
||||
std::vector<std::string> winRegistryValues;
|
||||
#elif defined(__ANDROID__)
|
||||
std::vector<std::string> androidPackages;
|
||||
#endif
|
||||
std::vector<std::string> systemPaths;
|
||||
std::vector<std::string> staticPaths;
|
||||
|
|
|
@ -379,13 +379,60 @@ namespace Utils
|
|||
// TODO: Wait for interface to close and check actual outcome.
|
||||
JNIEnv* jniEnv {reinterpret_cast<JNIEnv*>(SDL_AndroidGetJNIEnv())};
|
||||
jclass jniClass {jniEnv->FindClass("org/esde/esde/esde")};
|
||||
jmethodID funcID {
|
||||
jmethodID methodID {
|
||||
jniEnv->GetStaticMethodID(jniClass, "requestStoragePermissions", "()Z")};
|
||||
const bool result {
|
||||
static_cast<bool>(jniEnv->CallStaticBooleanMethod(jniClass, funcID))};
|
||||
static_cast<bool>(jniEnv->CallStaticBooleanMethod(jniClass, methodID))};
|
||||
// jniEnv->DeleteLocalRef(jniClass);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool checkEmulatorInstalled(const std::string& packageName,
|
||||
const std::string& component)
|
||||
{
|
||||
JNIEnv* jniEnv {reinterpret_cast<JNIEnv*>(SDL_AndroidGetJNIEnv())};
|
||||
jclass jniClass {jniEnv->FindClass("org/esde/esde/esde")};
|
||||
jmethodID methodID {jniEnv->GetStaticMethodID(
|
||||
jniClass, "checkEmulatorInstalled", "(Ljava/lang/String;Ljava/lang/String;)Z")};
|
||||
bool returnValue {static_cast<bool>(jniEnv->CallStaticBooleanMethod(
|
||||
jniClass, methodID, jniEnv->NewStringUTF(packageName.c_str()),
|
||||
jniEnv->NewStringUTF(component.c_str())))};
|
||||
// jniEnv->DeleteLocalRef(jniClass);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
int launchGame(const std::string& packageName,
|
||||
const std::string& component,
|
||||
std::vector<std::pair<std::string, std::string>>& extras)
|
||||
{
|
||||
JNIEnv* jniEnv {reinterpret_cast<JNIEnv*>(SDL_AndroidGetJNIEnv())};
|
||||
jclass jniClass {jniEnv->FindClass("org/esde/esde/esde")};
|
||||
jmethodID methodID {jniEnv->GetStaticMethodID(
|
||||
jniClass, "launchGame",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/util/Vector;Ljava/util/Vector;)Z")};
|
||||
jclass vectorClass {jniEnv->FindClass("java/util/Vector")};
|
||||
jmethodID vectorMID {jniEnv->GetMethodID(vectorClass, "<init>", "()V")};
|
||||
jmethodID addMethodID {
|
||||
jniEnv->GetMethodID(vectorClass, "add", "(Ljava/lang/Object;)Z")};
|
||||
jobject extrasNames {jniEnv->NewObject(vectorClass, vectorMID)};
|
||||
jobject extrasValues {jniEnv->NewObject(vectorClass, vectorMID)};
|
||||
for (auto& extra : extras) {
|
||||
jniEnv->CallBooleanMethod(extrasNames, addMethodID,
|
||||
jniEnv->NewStringUTF(extra.first.c_str()));
|
||||
jniEnv->CallBooleanMethod(extrasValues, addMethodID,
|
||||
jniEnv->NewStringUTF(extra.second.c_str()));
|
||||
}
|
||||
const bool returnValue {static_cast<bool>(jniEnv->CallStaticBooleanMethod(
|
||||
jniClass, methodID, jniEnv->NewStringUTF(packageName.c_str()),
|
||||
jniEnv->NewStringUTF(component.c_str()), extrasNames, extrasValues))};
|
||||
// jniEnv->DeleteLocalRef(vectorClass);
|
||||
// jniEnv->DeleteLocalRef(jniClass);
|
||||
if (returnValue)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Android
|
||||
#endif
|
||||
} // namespace Platform
|
||||
|
|
|
@ -60,7 +60,12 @@ namespace Utils
|
|||
namespace Android
|
||||
{
|
||||
bool requestStoragePermission();
|
||||
}; // namespace Android
|
||||
bool checkEmulatorInstalled(const std::string& packageName,
|
||||
const std::string& component);
|
||||
int launchGame(const std::string& packageName,
|
||||
const std::string& component,
|
||||
std::vector<std::pair<std::string, std::string>>& extras);
|
||||
} // namespace Android
|
||||
#endif
|
||||
|
||||
static QuitMode sQuitMode = QuitMode::QUIT;
|
||||
|
|
Loading…
Reference in a new issue