mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-02-28 09:15:37 +00:00
Expanded the usability of the %COREPATH% variable.
This commit is contained in:
parent
9f04f1419c
commit
267a47fdbd
es-app/src
|
@ -760,23 +760,53 @@ void FileData::launchGame(Window* window)
|
||||||
|
|
||||||
std::string commandRaw = command;
|
std::string commandRaw = command;
|
||||||
|
|
||||||
const std::string rom = Utils::FileSystem::getEscapedPath(getPath());
|
const std::string romPath = Utils::FileSystem::getEscapedPath(getPath());
|
||||||
const std::string basename = Utils::FileSystem::getStem(getPath());
|
const std::string baseName = Utils::FileSystem::getStem(getPath());
|
||||||
const std::string romraw = Utils::FileSystem::getPreferredPath(getPath());
|
const std::string romRaw = Utils::FileSystem::getPreferredPath(getPath());
|
||||||
const std::string emupath = Utils::FileSystem::getExePath();
|
const std::string esPath = Utils::FileSystem::getExePath();
|
||||||
const std::string emulatorCorePath = Settings::getInstance()->getString("EmulatorCorePath");
|
const std::string emulatorCorePath = Settings::getInstance()->getString("EmulatorCorePath");
|
||||||
|
|
||||||
command = Utils::String::replace(command, "%ROM%", rom);
|
command = Utils::String::replace(command, "%ROM%", romPath);
|
||||||
command = Utils::String::replace(command, "%BASENAME%", basename);
|
command = Utils::String::replace(command, "%BASENAME%", baseName);
|
||||||
command = Utils::String::replace(command, "%ROMRAW%", romraw);
|
command = Utils::String::replace(command, "%ROMRAW%", romRaw);
|
||||||
command = Utils::String::replace(command, "%ESPATH%", emupath);
|
command = Utils::String::replace(command, "%ESPATH%", esPath);
|
||||||
|
|
||||||
// Expand home path if ~ is used.
|
// Expand home path if ~ is used.
|
||||||
command = Utils::FileSystem::expandHomePath(command);
|
command = Utils::FileSystem::expandHomePath(command);
|
||||||
|
// If there's a quotation mark before the %COREPATH% variable, then remove it.
|
||||||
|
// The closing quotation mark will be removed later below.
|
||||||
|
command = Utils::String::replace(command, "\"%COREPATH%", "%COREPATH%");
|
||||||
|
|
||||||
|
// Get the emulator path, which will be used to check that this binary actually exists,
|
||||||
|
// and to expand the %EMUPATH% variable.
|
||||||
#if defined(_WIN64)
|
#if defined(_WIN64)
|
||||||
std::wstring commandWide = Utils::String::stringToWideString(command);
|
std::string commandTemp = Utils::String::replace(command, "/", "\\");
|
||||||
|
std::wstring commandWide = Utils::String::stringToWideString(commandTemp);
|
||||||
|
std::wstring emuPathWide = findEmulatorPath(commandWide);
|
||||||
|
if (!emuPathWide.empty()) {
|
||||||
|
auto stringPos = commandWide.find(L"%EMUPATH%");
|
||||||
|
if (stringPos != std::wstring::npos)
|
||||||
|
commandWide = commandWide.replace(stringPos, 9, emuPathWide);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#else
|
||||||
|
std::string emuPath = findEmulatorPath(command);
|
||||||
|
if (!emuPath.empty()) {
|
||||||
|
auto stringPos = command.find("%EMUPATH%");
|
||||||
|
if (stringPos != std::string::npos)
|
||||||
|
command = command.replace(stringPos, 9, emuPath);
|
||||||
|
}
|
||||||
|
else {
|
||||||
#endif
|
#endif
|
||||||
|
LOG(LogError) << "Couldn't launch game, emulator binary not found";
|
||||||
|
LOG(LogError) << "Raw emulator launch command:";
|
||||||
|
LOG(LogError) << commandRaw;
|
||||||
|
|
||||||
|
GuiInfoPopup* s = new GuiInfoPopup(window, "ERROR: COULDN'T FIND EMULATOR, HAS IT " \
|
||||||
|
"BEEN PROPERLY INSTALLED?", 6000);
|
||||||
|
window->setInfoPopup(s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If %COREPATH% is used in es_systems.cfg for this system, try to find the emulator
|
// If %COREPATH% is used in es_systems.cfg for this system, try to find the emulator
|
||||||
// core using the core paths defined in the setting EmulatorCorePath.
|
// core using the core paths defined in the setting EmulatorCorePath.
|
||||||
|
@ -800,23 +830,41 @@ void FileData::launchGame(Window* window)
|
||||||
if (spacePos != std::string::npos) {
|
if (spacePos != std::string::npos) {
|
||||||
coreName = command.substr(corePos + 10, spacePos - corePos - 10);
|
coreName = command.substr(corePos + 10, spacePos - corePos - 10);
|
||||||
for (auto path : corePaths) {
|
for (auto path : corePaths) {
|
||||||
bool pathHasSpaces = false;
|
|
||||||
if (path.find(" ") != std::string::npos)
|
|
||||||
pathHasSpaces = true;
|
|
||||||
std::string coreFile = Utils::FileSystem::expandHomePath(path + coreName);
|
std::string coreFile = Utils::FileSystem::expandHomePath(path + coreName);
|
||||||
|
// Expand %EMUPATH% if it has been used in the %COREPATH% variable.
|
||||||
|
auto stringPos = coreFile.find("%EMUPATH%");
|
||||||
|
if (stringPos != std::string::npos) {
|
||||||
|
#if defined (_WIN64)
|
||||||
|
coreFile = coreFile.replace(stringPos, 9,
|
||||||
|
Utils::String::wideStringToString(emuPathWide));
|
||||||
|
#else
|
||||||
|
coreFile = coreFile.replace(stringPos, 9, emuPath);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Expand %ESPATH% if it has been used in the %COREPATH% variable.
|
||||||
|
stringPos = coreFile.find("%ESPATH%");
|
||||||
|
if (stringPos != std::string::npos) {
|
||||||
|
coreFile = coreFile.replace(stringPos, 8, esPath);
|
||||||
|
#if defined(_WIN64)
|
||||||
|
coreFile = Utils::String::replace(coreFile, "/", "\\");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove any quotation mark as it will make the file functions fail.
|
||||||
|
if (coreFile.find(" ") != std::string::npos)
|
||||||
|
coreFile = Utils::String::replace(coreFile, "\"", "");
|
||||||
if (Utils::FileSystem::isRegularFile(coreFile) ||
|
if (Utils::FileSystem::isRegularFile(coreFile) ||
|
||||||
Utils::FileSystem::isSymlink(coreFile)) {
|
Utils::FileSystem::isSymlink(coreFile)) {
|
||||||
foundCoreFile = true;
|
foundCoreFile = true;
|
||||||
if (pathHasSpaces)
|
// Escape any blankspaces.
|
||||||
|
if (coreFile.find(" ") != std::string::npos)
|
||||||
|
coreFile = Utils::FileSystem::getEscapedPath(coreFile);
|
||||||
#if defined(_WIN64)
|
#if defined(_WIN64)
|
||||||
commandWide.replace(corePos, spacePos - corePos, L"\"" +
|
|
||||||
Utils::String::stringToWideString(coreFile) + L"\"");
|
|
||||||
else
|
|
||||||
commandWide.replace(corePos, spacePos - corePos,
|
commandWide.replace(corePos, spacePos - corePos,
|
||||||
Utils::String::stringToWideString(coreFile));
|
Utils::String::stringToWideString(coreFile));
|
||||||
#else
|
#else
|
||||||
command.replace(corePos, spacePos - corePos, "\"" + coreFile + "\"");
|
|
||||||
else
|
|
||||||
command.replace(corePos, spacePos - corePos, coreFile);
|
command.replace(corePos, spacePos - corePos, coreFile);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
@ -824,7 +872,7 @@ void FileData::launchGame(Window* window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG(LogError) << "Invalid entry in systems configuration file es_systems.cfg.";
|
LOG(LogError) << "Invalid entry in systems configuration file es_systems.cfg";
|
||||||
LOG(LogError) << "Raw emulator launch command:";
|
LOG(LogError) << "Raw emulator launch command:";
|
||||||
LOG(LogError) << commandRaw;
|
LOG(LogError) << commandRaw;
|
||||||
|
|
||||||
|
@ -834,10 +882,12 @@ void FileData::launchGame(Window* window)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!foundCoreFile && coreName.size() > 0) {
|
if (!foundCoreFile && coreName.size() > 0) {
|
||||||
LOG(LogError) << "Couldn't launch game, emulator core file '" <<
|
LOG(LogError) << "Couldn't launch game, emulator core file \"" <<
|
||||||
coreName.substr(1, coreName.size() - 1) << "' does not exist.";
|
coreName.substr(1, coreName.size() - 1) << "\" does not exist";
|
||||||
LOG(LogError) << "Raw emulator launch command:";
|
LOG(LogError) << "Raw emulator launch command:";
|
||||||
LOG(LogError) << commandRaw;
|
LOG(LogError) << commandRaw;
|
||||||
|
LOG(LogError) << "Configured core path:";
|
||||||
|
LOG(LogError) << emulatorCorePath;
|
||||||
|
|
||||||
GuiInfoPopup* s = new GuiInfoPopup(window, "ERROR: COULDN'T FIND EMULATOR CORE FILE '" +
|
GuiInfoPopup* s = new GuiInfoPopup(window, "ERROR: COULDN'T FIND EMULATOR CORE FILE '" +
|
||||||
Utils::String::toUpper(coreName.substr(1, coreName.size() - 1) + "'"), 6000);
|
Utils::String::toUpper(coreName.substr(1, coreName.size() - 1) + "'"), 6000);
|
||||||
|
@ -847,72 +897,16 @@ void FileData::launchGame(Window* window)
|
||||||
}
|
}
|
||||||
else if (corePos != std::string::npos) {
|
else if (corePos != std::string::npos) {
|
||||||
LOG(LogError) << "The variable %COREPATH% is used in es_systems.cfg but " \
|
LOG(LogError) << "The variable %COREPATH% is used in es_systems.cfg but " \
|
||||||
"no paths are defined in the setting EmulatorCorePath.";
|
"no paths are defined using the setting EmulatorCorePath";
|
||||||
GuiInfoPopup* s = new GuiInfoPopup(window, "ERROR: NO CORE PATHS CONFIGURED, " \
|
GuiInfoPopup* s = new GuiInfoPopup(window, "ERROR: NO CORE PATHS CONFIGURED, " \
|
||||||
"CAN'T LOCATE EMULATOR CORE", 6000);
|
"CAN'T LOCATE EMULATOR CORE", 6000);
|
||||||
window->setInfoPopup(s);
|
window->setInfoPopup(s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scripting::fireEvent("game-start", rom, getSourceFileData()->metadata.get("name"));
|
Scripting::fireEvent("game-start", romPath, getSourceFileData()->metadata.get("name"));
|
||||||
int returnValue = 0;
|
int returnValue = 0;
|
||||||
|
|
||||||
if (command.find("%EMUPATH%") != std::string::npos) {
|
|
||||||
// Extract the emulator executable from the launch command string. This could either be
|
|
||||||
// just the program name, assuming the binary is in the PATH variable of the operating
|
|
||||||
// system, or it could be an absolute path to the emulator. (In the latter case, if
|
|
||||||
// there is a space in the the path, it needs to be enclosed by quotation marks in
|
|
||||||
// es_systems.cfg.)
|
|
||||||
std::string emuExecutable;
|
|
||||||
|
|
||||||
// If the first character is a quotation mark, then we need to extract up to the
|
|
||||||
// next quotation mark, otherwise we'll extract up to the first space character.
|
|
||||||
if (command.front() == '\"') {
|
|
||||||
std::string emuTemp = command.substr(1, std::string::npos);
|
|
||||||
emuExecutable = emuTemp.substr(0, emuTemp.find('"'));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
emuExecutable = command.substr(0, command.find(' '));
|
|
||||||
}
|
|
||||||
|
|
||||||
// For Windows, we need to handle UTF-16 encoding.
|
|
||||||
#if defined(_WIN64)
|
|
||||||
std::wstring emuExecutableWide;
|
|
||||||
std::wstring emuPathWide;
|
|
||||||
|
|
||||||
emuExecutableWide = Utils::String::stringToWideString(emuExecutable);
|
|
||||||
|
|
||||||
// Search for the emulator using the PATH environmental variable.
|
|
||||||
DWORD size = SearchPathW(nullptr, emuExecutableWide.c_str(), L".exe", 0, nullptr, nullptr);
|
|
||||||
|
|
||||||
if (size) {
|
|
||||||
std::vector<wchar_t> pathBuffer(static_cast<size_t>(size) + 1 );
|
|
||||||
wchar_t* fileName = nullptr;
|
|
||||||
|
|
||||||
SearchPathW(nullptr, emuExecutableWide.c_str(), L".exe", size + 1 ,
|
|
||||||
pathBuffer.data(), &fileName);
|
|
||||||
std::wstring pathString = pathBuffer.data();
|
|
||||||
|
|
||||||
if (pathString.length()) {
|
|
||||||
emuPathWide = pathString.substr(0, pathString.size() -
|
|
||||||
std::wstring(fileName).size());
|
|
||||||
emuPathWide.pop_back();
|
|
||||||
auto stringPos = commandWide.find(L"%EMUPATH%");
|
|
||||||
commandWide = commandWide.replace(stringPos, 9, emuPathWide);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
std::string exePath;
|
|
||||||
if (Utils::FileSystem::isRegularFile(emuExecutable) ||
|
|
||||||
Utils::FileSystem::isSymlink(emuExecutable))
|
|
||||||
exePath = Utils::FileSystem::getParent(emuExecutable);
|
|
||||||
else
|
|
||||||
exePath = Utils::FileSystem::getPathToBinary(emuExecutable);
|
|
||||||
|
|
||||||
command = Utils::String::replace(command, "%EMUPATH%", exePath);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(LogDebug) << "Raw emulator launch command:";
|
LOG(LogDebug) << "Raw emulator launch command:";
|
||||||
LOG(LogDebug) << commandRaw;
|
LOG(LogDebug) << commandRaw;
|
||||||
LOG(LogInfo) << "Expanded emulator launch command:";
|
LOG(LogInfo) << "Expanded emulator launch command:";
|
||||||
|
@ -927,7 +921,7 @@ void FileData::launchGame(Window* window)
|
||||||
|
|
||||||
// Notify the user in case of a failed game launch using a popup window.
|
// Notify the user in case of a failed game launch using a popup window.
|
||||||
if (returnValue != 0) {
|
if (returnValue != 0) {
|
||||||
LOG(LogWarning) << "...launch terminated with nonzero return value " << returnValue << "!";
|
LOG(LogWarning) << "...launch terminated with nonzero return value " << returnValue;
|
||||||
|
|
||||||
GuiInfoPopup* s = new GuiInfoPopup(window, "ERROR LAUNCHING GAME '" +
|
GuiInfoPopup* s = new GuiInfoPopup(window, "ERROR LAUNCHING GAME '" +
|
||||||
Utils::String::toUpper(metadata.get("name")) + "' (ERROR CODE " +
|
Utils::String::toUpper(metadata.get("name")) + "' (ERROR CODE " +
|
||||||
|
@ -954,7 +948,7 @@ void FileData::launchGame(Window* window)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Scripting::fireEvent("game-end", rom, getSourceFileData()->metadata.get("name"));
|
Scripting::fireEvent("game-end", romPath, getSourceFileData()->metadata.get("name"));
|
||||||
|
|
||||||
// Re-enable the text scrolling that was disabled in ViewController on game launch.
|
// Re-enable the text scrolling that was disabled in ViewController on game launch.
|
||||||
window->setAllowTextScrolling(true);
|
window->setAllowTextScrolling(true);
|
||||||
|
@ -981,6 +975,76 @@ void FileData::launchGame(Window* window)
|
||||||
gameToUpdate->mSystem->onMetaDataSavePoint();
|
gameToUpdate->mSystem->onMetaDataSavePoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN64)
|
||||||
|
std::wstring FileData::findEmulatorPath(const std::wstring& command)
|
||||||
|
{
|
||||||
|
// Extract the emulator executable from the launch command string. This could either be
|
||||||
|
// just the program name, assuming the binary is in the PATH variable of the operating
|
||||||
|
// system, or it could be an absolute path to the emulator. (In the latter case, if
|
||||||
|
// there is a space in the the path, it needs to be enclosed by quotation marks in
|
||||||
|
// es_systems.cfg.)
|
||||||
|
std::wstring emuExecutable;
|
||||||
|
std::wstring exePath;
|
||||||
|
|
||||||
|
// If the first character is a quotation mark, then we need to extract up to the
|
||||||
|
// next quotation mark, otherwise we'll only extract up to the first space character.
|
||||||
|
if (command.front() == '\"') {
|
||||||
|
std::wstring emuTemp = command.substr(1, std::string::npos);
|
||||||
|
emuExecutable = emuTemp.substr(0, emuTemp.find('"'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
emuExecutable = command.substr(0, command.find(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for the emulator using the PATH environmental variable.
|
||||||
|
DWORD size = SearchPathW(nullptr, emuExecutable.c_str(), L".exe", 0, nullptr, nullptr);
|
||||||
|
|
||||||
|
if (size) {
|
||||||
|
std::vector<wchar_t> pathBuffer(static_cast<size_t>(size) + 1 );
|
||||||
|
wchar_t* fileName = nullptr;
|
||||||
|
|
||||||
|
SearchPathW(nullptr, emuExecutable.c_str(), L".exe", size + 1 ,
|
||||||
|
pathBuffer.data(), &fileName);
|
||||||
|
std::wstring pathString = pathBuffer.data();
|
||||||
|
|
||||||
|
if (pathString.length()) {
|
||||||
|
exePath = pathString.substr(0, pathString.size() -
|
||||||
|
std::wstring(fileName).size());
|
||||||
|
exePath.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exePath;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::string FileData::findEmulatorPath(const std::string& command)
|
||||||
|
{
|
||||||
|
// Extract the emulator executable from the launch command string. This could either be
|
||||||
|
// just the program name, assuming the binary is in the PATH variable of the operating
|
||||||
|
// system, or it could be an absolute path to the emulator. (In the latter case, if
|
||||||
|
// there is a space in the the path, it needs to be enclosed by quotation marks in
|
||||||
|
// es_systems.cfg.)
|
||||||
|
std::string emuExecutable;
|
||||||
|
std::string exePath;
|
||||||
|
|
||||||
|
// If the first character is a quotation mark, then we need to extract up to the
|
||||||
|
// next quotation mark, otherwise we'll only extract up to the first space character.
|
||||||
|
if (command.front() == '\"') {
|
||||||
|
std::string emuTemp = command.substr(1, std::string::npos);
|
||||||
|
emuExecutable = emuTemp.substr(0, emuTemp.find('"'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
emuExecutable = command.substr(0, command.find(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Utils::FileSystem::isRegularFile(emuExecutable) ||
|
||||||
|
Utils::FileSystem::isSymlink(emuExecutable))
|
||||||
|
exePath = Utils::FileSystem::getParent(emuExecutable);
|
||||||
|
else
|
||||||
|
exePath = Utils::FileSystem::getPathToBinary(emuExecutable);
|
||||||
|
return exePath;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CollectionFileData::CollectionFileData(FileData* file, SystemData* system)
|
CollectionFileData::CollectionFileData(FileData* file, SystemData* system)
|
||||||
: FileData(file->getSourceFileData()->getType(), file->getSourceFileData()->getPath(),
|
: FileData(file->getSourceFileData()->getType(), file->getSourceFileData()->getPath(),
|
||||||
file->getSourceFileData()->getSystemEnvData(), system)
|
file->getSourceFileData()->getSystemEnvData(), system)
|
||||||
|
|
|
@ -97,6 +97,11 @@ public:
|
||||||
std::string getCleanName() const;
|
std::string getCleanName() const;
|
||||||
|
|
||||||
void launchGame(Window* window);
|
void launchGame(Window* window);
|
||||||
|
#if defined(_WIN64)
|
||||||
|
std::wstring findEmulatorPath(const std::wstring& command);
|
||||||
|
#else
|
||||||
|
std::string findEmulatorPath(const std::string& command);
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef bool ComparisonFunction(const FileData* a, const FileData* b);
|
typedef bool ComparisonFunction(const FileData* a, const FileData* b);
|
||||||
struct SortType {
|
struct SortType {
|
||||||
|
|
Loading…
Reference in a new issue