diff --git a/README.md b/README.md index 9b9b5868f..47c63a4de 100644 --- a/README.md +++ b/README.md @@ -97,10 +97,12 @@ The COMMAND is the shell command ES will execute to start your emulator. As it i The following "tags" are replaced by ES in COMMANDs: -`%ROM%` - Replaced with absolute path to the selected ROM. +`%ROM%` - Replaced with absolute path to the selected ROM, with most Bash special characters escaped with a backslash. `%BASENAME%` - Replaced with the "base" name of the path to the selected ROM. For example, a path of "/foo/bar.rom", this tag would be "bar". This tag is useful for setting up AdvanceMAME. +`%ROM_RAW%` - Replaced with the unescaped absolute path to the selected ROM. If your emulator is picky about paths, you might want to use this instead of %ROM%, but enclosed in quotes. + gamelist.xml ============ diff --git a/src/AudioManager.cpp b/src/AudioManager.cpp index 081670e6c..c76e256b5 100644 --- a/src/AudioManager.cpp +++ b/src/AudioManager.cpp @@ -22,7 +22,7 @@ void AudioManager::mixAudio(void *unused, Uint8 *stream, int len) { //calculate rest length of current sample Uint32 restLength = (sound->getLength() - sound->getPosition()); - if (restLength > len) { + if (restLength > (Uint32)len) { //if stream length is smaller than smaple lenght, clip it restLength = len; } diff --git a/src/FolderData.cpp b/src/FolderData.cpp index 8d0d43596..2bc937cca 100644 --- a/src/FolderData.cpp +++ b/src/FolderData.cpp @@ -37,7 +37,9 @@ bool filesort(FileData* file1, FileData* file2) std::string name1 = file1->getName(); std::string name2 = file2->getName(); - for(unsigned int i = 0; i < name1.length(); i++) + //min of name1/name2 .length()s + unsigned int count = name1.length() > name2.length() ? name2.length() : name1.length(); + for(unsigned int i = 0; i < count; i++) { if(toupper(name1[i]) != toupper(name2[i])) { diff --git a/src/GameData.cpp b/src/GameData.cpp index b6d981fbd..bb656be01 100644 --- a/src/GameData.cpp +++ b/src/GameData.cpp @@ -22,6 +22,7 @@ std::string GameData::getBashPath() { //a quick and dirty way to insert a backslash before most characters that would mess up a bash path std::string path = mPath; + const char* invalidChars = " '\"\\!$^&*(){}[]?;<>"; for(unsigned int i = 0; i < path.length(); i++) { diff --git a/src/InputManager.cpp b/src/InputManager.cpp index 4f8f15394..5df74a951 100644 --- a/src/InputManager.cpp +++ b/src/InputManager.cpp @@ -72,7 +72,7 @@ std::vector InputManager::getInputDevices() const if (GetRawInputDeviceList(deviceList, &nrOfDevices, sizeof(RAWINPUTDEVICELIST)) != -1) { //loop through input devices - for (int i = 0; i < nrOfDevices; i++) + for (unsigned int i = 0; i < nrOfDevices; i++) { //get device name char * rawName = new char[2048]; diff --git a/src/SystemData.cpp b/src/SystemData.cpp index 9eb4e0866..e673041db 100644 --- a/src/SystemData.cpp +++ b/src/SystemData.cpp @@ -77,6 +77,7 @@ void SystemData::launchGame(Window* window, GameData* game) command = strreplace(command, "%ROM%", game->getBashPath()); command = strreplace(command, "%BASENAME%", game->getBaseName()); + command = strreplace(command, "%ROM_RAW%", game->getPath()); LOG(LogInfo) << " " << command; std::cout << "==============================================\n"; @@ -120,7 +121,37 @@ void SystemData::populateFolder(FolderData* folder) if(filePath.stem().string().empty()) continue; - if(fs::is_directory(filePath)) + //this is a little complicated because we allow a list of extensions to be defined (delimited with a space) + //we first get the extension of the file itself: + std::string extension = filePath.extension().string(); + std::string chkExt; + size_t extPos = 0; + + //folders *can* also match the extension and be added as games - this is mostly just to support higan + //see issue #75: https://github.com/Aloshi/EmulationStation/issues/75 + bool isGame = false; + do { + //now we loop through every extension in the list + size_t cpos = extPos; + extPos = mSearchExtension.find(" ", extPos); + chkExt = mSearchExtension.substr(cpos, ((extPos == std::string::npos) ? mSearchExtension.length() - cpos: extPos - cpos)); + + //if it matches, add it + if(chkExt == extension) + { + GameData* newGame = new GameData(this, filePath.string(), filePath.stem().string()); + folder->pushFileData(newGame); + isGame = true; + break; + }else if(extPos != std::string::npos) //if not, add one to the "next position" marker to skip the space when reading the next extension + { + extPos++; + } + + } while(extPos != std::string::npos && chkExt != "" && chkExt.find(".") != std::string::npos); + + //add directories that also do not match an extension as folders + if(!isGame && fs::is_directory(filePath)) { FolderData* newFolder = new FolderData(this, filePath.string(), filePath.stem().string()); populateFolder(newFolder); @@ -130,31 +161,6 @@ void SystemData::populateFolder(FolderData* folder) delete newFolder; else folder->pushFileData(newFolder); - }else{ - //this is a little complicated because we allow a list of extensions to be defined (delimited with a space) - //we first get the extension of the file itself: - std::string extension = filePath.extension().string(); - std::string chkExt; - size_t extPos = 0; - - do { - //now we loop through every extension in the list - size_t cpos = extPos; - extPos = mSearchExtension.find(" ", extPos); - chkExt = mSearchExtension.substr(cpos, ((extPos == std::string::npos) ? mSearchExtension.length() - cpos: extPos - cpos)); - - //if it matches, add it - if(chkExt == extension) - { - GameData* newGame = new GameData(this, filePath.string(), filePath.stem().string()); - folder->pushFileData(newGame); - break; - }else if(extPos != std::string::npos) //if not, add one to the "next position" marker to skip the space when reading the next extension - { - extPos++; - } - - } while(extPos != std::string::npos && chkExt != "" && chkExt.find(".") != std::string::npos); } } } diff --git a/src/components/GuiTheme.cpp b/src/components/GuiTheme.cpp index 71f9765b5..1c9cb3093 100644 --- a/src/components/GuiTheme.cpp +++ b/src/components/GuiTheme.cpp @@ -332,6 +332,9 @@ Gui* GuiTheme::createElement(pugi::xml_node data, Gui* parent) //expands a file path (./ becomes the directory of this theme file, ~/ becomes $HOME/) std::string GuiTheme::expandPath(std::string path) { + if(path.empty()) + return ""; + if(path[0] == '~') path = getHomePath() + path.substr(1, path.length() - 1); else if(path[0] == '.')