diff --git a/README.md b/README.md
index 57695ee04..38c366234 100644
--- a/README.md
+++ b/README.md
@@ -193,7 +193,15 @@ An example gamelist.xml:
```
-The path element should be the *absolute path* of the ROM. Special characters SHOULD NOT be escaped. The image element is the path to an image to display above the description (like a screenshot or boxart). Most formats can be used (including png, jpg, gif, etc.). Not all elements need to be used.
+The path element should be either the absolute path of the ROM, or a path relative to the system games folder that starts with "./". For example:
+
+`/home/pi/ROMs/nes/mm2.nes`
+
+or
+
+`./mm2.nes`
+
+ES will attempt to encode paths as relative to the system's `path` setting whenever it writes a gamelist.xml. Special characters SHOULD NOT be escaped. The image element is the path to an image to display above the description (like a screenshot or boxart). Most popular image formats can be used (png, jpg, gif, etc.). Not all elements need to be used.
The switch `--gamelist-only` can be used to skip automatic searching, and only display games defined in the system's gamelist.xml.
The switch `--ignore-gamelist` can be used to ignore the gamelist and force ES to use the non-detailed view.
@@ -203,6 +211,10 @@ The switch `--ignore-gamelist` can be used to ignore the gamelist and force ES t
* **If you want to scrape multiple games:** press start to open the menu and choose the "SCRAPER" option. Adjust your settings and press "SCRAPE NOW".
* **If you just want to scrape one game:** find the game on the game list in ES and press select. Choose "EDIT THIS GAME'S METADATA" and then press the "SCRAPE" button at the bottom of the metadata editor.
+You can also edit metadata within ES by using the metadata editor - just find the game you wish to edit on the gamelist, press select, and choose "EDIT THIS GAME'S METADATA."
+
+If you're writing a tool to generate gamelist.xml files, you can see the complete list of possible elements at the top of `src/MetaData.cpp`.
+
A command-line version of the scraper is also provided - just run emulationstation with `--scrape` *(currently broken)*.
Themes
diff --git a/src/Gamelist.cpp b/src/Gamelist.cpp
index 8eb4d5488..c4c3eeba3 100644
--- a/src/Gamelist.cpp
+++ b/src/Gamelist.cpp
@@ -7,6 +7,21 @@
namespace fs = boost::filesystem;
+// expands "./my/path.sfc" to "[relativeTo]/my/path.sfc"
+fs::path resolvePath(const fs::path& path, const fs::path& relativeTo)
+{
+ if(path.begin() != path.end() && *path.begin() == fs::path("."))
+ {
+ fs::path ret = relativeTo;
+ for(auto it = ++path.begin(); it != path.end(); ++it)
+ ret /= *it;
+
+ return ret;
+ }
+
+ return path;
+}
+
// example: removeCommonPath("/home/pi/roms/nes/foo/bar.nes", "/home/pi/roms/nes/") returns "foo/bar.nes"
fs::path removeCommonPath(const fs::path& path, const fs::path& relativeTo, bool& contains)
{
@@ -150,7 +165,7 @@ void parseGamelist(SystemData* system)
FileType type = typeList[i];
for(pugi::xml_node fileNode = root.child(tag); fileNode; fileNode = fileNode.next_sibling(tag))
{
- boost::filesystem::path path = boost::filesystem::path(fileNode.child("path").text().get());
+ fs::path path = resolvePath(fileNode.child("path").text().get(), system->getStartPath());
if(!boost::filesystem::exists(path))
{
@@ -176,26 +191,6 @@ void parseGamelist(SystemData* system)
}
}
-void addGameDataNode(pugi::xml_node& parent, const FileData* game, SystemData* system)
-{
- //create game and add to parent node
- pugi::xml_node newGame = parent.append_child("game");
-
- //write metadata
- game->metadata.appendToXML(newGame, true);
-
- if(newGame.children().begin() == newGame.child("name") //first element is name
- && ++newGame.children().begin() == newGame.children().end() //theres only one element
- && newGame.child("name").text().get() == game->getCleanName()) //the name is the default
- {
- //if the only info is the default name, don't bother with this node
- parent.remove_child(newGame);
- }else{
- //there's something useful in there so we'll keep the node, add the path
- newGame.prepend_child("path").text().set(game->getPath().generic_string().c_str());
- }
-}
-
void addFileDataNode(pugi::xml_node& parent, const FileData* file, const char* tag, SystemData* system)
{
//create game and add to parent node
@@ -213,7 +208,19 @@ void addFileDataNode(pugi::xml_node& parent, const FileData* file, const char* t
parent.remove_child(newNode);
}else{
//there's something useful in there so we'll keep the node, add the path
- newNode.prepend_child("path").text().set(file->getPath().generic_string().c_str());
+
+ // try and make the path relative if we can so things still work if we change the rom folder location in the future
+ fs::path relPath = file->getPath();
+
+ bool contains = false;
+ relPath = removeCommonPath(relPath, system->getStartPath(), contains);
+ if(contains)
+ {
+ // it's in the start path (which we just stripped off), so add a "./"
+ relPath = "." / relPath;
+ }
+
+ newNode.prepend_child("path").text().set(relPath.generic_string().c_str());
}
}
@@ -277,7 +284,7 @@ void updateGamelist(SystemData* system)
continue;
}
- fs::path nodePath(pathNode.text().get());
+ fs::path nodePath = resolvePath(pathNode.text().get(), system->getStartPath());
fs::path gamePath((*fit)->getPath());
if(nodePath == gamePath || (fs::exists(nodePath) && fs::exists(gamePath) && fs::equivalent(nodePath, gamePath)))
{
diff --git a/src/MetaData.cpp b/src/MetaData.cpp
index f812b7be9..1d63808ad 100644
--- a/src/MetaData.cpp
+++ b/src/MetaData.cpp
@@ -8,7 +8,7 @@ MetaDataDecl gameDecls[] = {
{"desc", MD_MULTILINE_STRING, "", false, "description", "enter description"},
{"image", MD_IMAGE_PATH, "", false, "image", "enter path to image"},
{"thumbnail", MD_IMAGE_PATH, "", false, "thumbnail", "enter path to thumbnail"},
- {"rating", MD_RATING, "0", false, "rating", "enter rating"},
+ {"rating", MD_RATING, "0.000000", false, "rating", "enter rating"},
{"releasedate", MD_DATE, "not-a-date-time", false, "release date", "enter release date"},
{"developer", MD_STRING, "unknown", false, "developer", "enter game developer"},
{"publisher", MD_STRING, "unknown", false, "publisher", "enter game publisher"},