diff --git a/CMakeLists.txt b/CMakeLists.txt
index ed2c331..de68bf3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -168,6 +168,20 @@ set(MAIN_SOURCE
 
 source_group("MKXP Source" FILES ${MAIN_SOURCE} ${MAIN_HEADERS})
 
+## Platform source ##
+
+if(LINUX)
+	set(PLATFORM_SOURCE
+		src/platform_linux.cpp
+	)
+elseif(APPLE)
+	set(PLATFORM_SOURCE
+		src/platform_osx.mm
+	)
+else()
+	message(FATAL_ERROR "No platform source for this platform")
+endif()
+
 ## Setup embedded source ##
 
 set(EMBEDDED_INPUT
@@ -340,6 +354,7 @@ add_executable(${PROJECT_NAME} MACOSX_BUNDLE
 	${BINDING_HEADERS}
 	${BINDING_SOURCE}
 	${EMBEDDED_SOURCE}
+	${PLATFORM_SOURCE}
 )
 
 target_compile_definitions(${PROJECT_NAME} PRIVATE
diff --git a/src/config.cpp b/src/config.cpp
index 7e3091f..e2eb338 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -50,7 +50,9 @@ Config::Config()
       anyAltToggleFS(false),
       allowSymlinks(false),
       pathCache(true)
-{}
+{
+	setupPaths();
+}
 
 void Config::read(int argc, char *argv[])
 {
diff --git a/src/config.h b/src/config.h
index 411ce51..ec956e5 100644
--- a/src/config.h
+++ b/src/config.h
@@ -50,6 +50,8 @@ struct Config
 	bool pathCache;
 
 	std::string iconPath;
+	
+	std::string desktopPath;
 
 	std::string customScript;
 	std::vector<std::string> rtps;
@@ -64,6 +66,8 @@ struct Config
 
 	void read(int argc, char *argv[]);
 	void readGameINI();
+private:
+	void setupPaths();
 };
 
 #endif // CONFIG_H
diff --git a/src/graphics.cpp b/src/graphics.cpp
index 22236ff..9394539 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -544,7 +544,8 @@ struct GraphicsPrivate
 		snprintf(filename, sizeof(filename), "%d%02d%02d-%02d%02d%02d.png",
 		         tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
 
-		writeScreenshot(filename);
+		std::string path = threadData->config.desktopPath + filename;
+		writeScreenshot(path.c_str());
 	}
 };
 
diff --git a/src/platform_linux.cpp b/src/platform_linux.cpp
new file mode 100644
index 0000000..fb4ba82
--- /dev/null
+++ b/src/platform_linux.cpp
@@ -0,0 +1,91 @@
+#include "config.h"
+
+#include <stdlib.h>
+#include <fstream>
+#include <string>
+#include <unistd.h>
+#include <boost/algorithm/string.hpp>
+
+inline void ensure_trailing_slash(std::string& path)
+{
+	if (path.size() && path[path.size()-1] != '/') {
+		path += "/";
+	}
+}
+
+static std::string find_xdg_config_dir()
+{
+	std::string path;
+	const char* env = getenv("XDG_CONFIG_HOME");
+	if (env) {
+		path = env;
+		ensure_trailing_slash(path);
+	} else {
+		env = getenv("HOME");
+		if (!env) {
+			return "";
+		}
+		path = env;
+		ensure_trailing_slash(path);
+		path += ".config/";
+	}
+	return path;
+}
+
+static std::string get_desktop_dir()
+{
+	std::string desktopPath;
+
+	std::string cfg_dir = find_xdg_config_dir();
+	if (!cfg_dir.empty()) {
+		std::string cfg_file = cfg_dir + "user-dirs.dirs";
+		if (access(cfg_file.c_str(), F_OK) == 0) {
+			std::ifstream fin(cfg_file.c_str());
+			std::string line;
+			while (std::getline(fin, line)) {
+				/* skip blank and comment lines */
+				if (line.empty() || line[0] == '#') continue;
+
+				std::vector<std::string> parts;
+				boost::split(parts, line, boost::is_any_of("="));
+				if (parts.size() == 2) {
+					std::string key = boost::trim_copy(parts[0]);
+					if (key == "XDG_DESKTOP_DIR") {
+						std::string val = boost::trim_copy_if(parts[1], boost::is_any_of(" \n\r\t\""));
+						desktopPath = val;
+						break;
+					}
+				}
+			}
+		}
+	}
+	const char* home = getenv("HOME");
+	if (home) {
+		size_t pos = desktopPath.find("$HOME");
+		if (pos != desktopPath.npos) {
+			desktopPath.replace(pos, pos + 5, home);
+		}
+		pos = desktopPath.find("${HOME}");
+		if (pos != desktopPath.npos) {
+			desktopPath.replace(pos, pos + 7, home);
+		}
+	}
+	if (desktopPath.empty() || access(desktopPath.c_str(), F_OK) != 0) {
+		if (home) {
+			desktopPath = home;
+			ensure_trailing_slash(desktopPath);
+			if (access((desktopPath + "Desktop").c_str(), F_OK) == 0) {
+				desktopPath += "Desktop/";
+			}
+		} else {
+			desktopPath = "";
+		}
+	}
+	ensure_trailing_slash(desktopPath);
+	return desktopPath;
+}
+
+void Config::setupPaths()
+{
+	desktopPath = get_desktop_dir();
+}
\ No newline at end of file
diff --git a/src/platform_osx.mm b/src/platform_osx.mm
new file mode 100644
index 0000000..e84f022
--- /dev/null
+++ b/src/platform_osx.mm
@@ -0,0 +1,35 @@
+#include "config.h"
+
+#include <string>
+
+#import <Foundation/Foundation.h>
+
+static void ensure_trailing_slash(std::string& path)
+{
+	if (path.size() && path[path.size()-1] != '/') {
+		path += "/";
+	}
+}
+
+static std::string get_desktop_dir()
+{
+	std::string ret;
+	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES);
+	NSString *path = [paths objectAtIndex: 0];
+
+	ret = [path fileSystemRepresentation];
+
+	[pool drain];
+
+	ensure_trailing_slash(ret);
+	return ret;
+}
+
+
+void Config::setupPaths()
+{
+	desktopPath = get_desktop_dir();
+}
+