diff --git a/src/b_game.cpp b/src/b_game.cpp
index 4300e0ada..661d09c6e 100644
--- a/src/b_game.cpp
+++ b/src/b_game.cpp
@@ -534,7 +534,7 @@ bool FCajunMaster::LoadBots ()
 	}
 	if (!sc.OpenFile(tmp))
 	{
-		Printf("Unable to open %s. So no bots\n");
+		Printf("Unable to open %s. So no bots\n", tmp.GetChars());
 		return false;
 	}
 
@@ -665,4 +665,4 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, RemoveAllBots)
 	PARAM_BOOL(fromlist);
 	bglobal.RemoveAllBots(fromlist);
 	return 0;
-}
\ No newline at end of file
+}
diff --git a/src/cmdlib.cpp b/src/cmdlib.cpp
index bccb4afcd..e58b3569f 100644
--- a/src/cmdlib.cpp
+++ b/src/cmdlib.cpp
@@ -544,18 +544,13 @@ void CreatePath(const char *fn)
 		{
 			*p = '\0';
 		}
-		struct stat info;
-		if (DirEntryExists(copy))
+		if (!DirEntryExists(copy) && mkdir(copy, 0755) == -1)
 		{
-			if (info.st_mode & S_IFDIR)
-				goto exists;
-		}
-		if (mkdir(copy, 0755) == -1)
-		{ // failed
+			// failed
 			free(copy);
 			return;
 		}
-exists:	if (p != NULL)
+		if (p != NULL)
 		{
 			*p = '/';
 		}
diff --git a/src/g_game.cpp b/src/g_game.cpp
index f56bdac8e..0adfa2fc9 100644
--- a/src/g_game.cpp
+++ b/src/g_game.cpp
@@ -2978,7 +2978,7 @@ bool G_CheckDemoStatus (void)
 		bool saved = false;
 		if (fw != nullptr)
 		{
-			auto size = long(demo_p - demobuffer);
+			const size_t size = demo_p - demobuffer;
 			saved = fw->Write(demobuffer, size) == size;
 			delete fw;
 			if (!saved) remove(demoname);
diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp
index 329ac6484..af03af86e 100644
--- a/src/gl/scene/gl_scene.cpp
+++ b/src/gl/scene/gl_scene.cpp
@@ -800,8 +800,8 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f
 	GLRenderer->mAngles.Roll.Degrees = r_viewpoint.Angles.Roll.Degrees;
 
 	// Scroll the sky
-	GLRenderer->mSky1Pos = (double)fmod(screen->FrameTime * level.skyspeed1, 1024.f) * 90./256.;
-	GLRenderer->mSky2Pos = (double)fmod(screen->FrameTime * level.skyspeed2, 1024.f) * 90./256.;
+	GLRenderer->mSky1Pos = (double)fmod((double)screen->FrameTime * (double)level.skyspeed1, 1024.f) * 90./256.;
+	GLRenderer->mSky2Pos = (double)fmod((double)screen->FrameTime * (double)level.skyspeed2, 1024.f) * 90./256.;
 
 
 
diff --git a/src/m_misc.h b/src/m_misc.h
index 8f375b930..f3773659d 100644
--- a/src/m_misc.h
+++ b/src/m_misc.h
@@ -60,5 +60,6 @@ FString M_GetCajunPath(const char *filename);
 FString M_GetConfigPath(bool for_reading);
 FString M_GetScreenshotsPath();
 FString M_GetSavegamesPath();
+FString M_GetDocumentsPath();
 
 #endif
diff --git a/src/posix/osx/i_specialpaths.mm b/src/posix/osx/i_specialpaths.mm
index fbb32cec6..540aaf4b0 100644
--- a/src/posix/osx/i_specialpaths.mm
+++ b/src/posix/osx/i_specialpaths.mm
@@ -215,3 +215,24 @@ FString M_GetSavegamesPath()
 	return path;
 }
 
+//===========================================================================
+//
+// M_GetDocumentsPath												Unix
+//
+// Returns the path to the default documents directory.
+//
+//===========================================================================
+
+FString M_GetDocumentsPath()
+{
+	FString path;
+	char cpath[PATH_MAX];
+	FSRef folder;
+
+	if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) &&
+		noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
+	{
+		path << cpath << "/" GAME_DIR "/";
+	}
+	return path;
+}
diff --git a/src/posix/unix/i_specialpaths.cpp b/src/posix/unix/i_specialpaths.cpp
index 581fda5d5..01320548d 100644
--- a/src/posix/unix/i_specialpaths.cpp
+++ b/src/posix/unix/i_specialpaths.cpp
@@ -218,3 +218,16 @@ FString M_GetSavegamesPath()
 {
 	return NicePath("~/" GAME_DIR);
 }
+
+//===========================================================================
+//
+// M_GetDocumentsPath												Unix
+//
+// Returns the path to the default documents directory.
+//
+//===========================================================================
+
+FString M_GetDocumentsPath()
+{
+	return NicePath("~/" GAME_DIR);
+}
\ No newline at end of file
diff --git a/src/r_data/models/models_md3.cpp b/src/r_data/models/models_md3.cpp
index e504b252a..8a649f713 100644
--- a/src/r_data/models/models_md3.cpp
+++ b/src/r_data/models/models_md3.cpp
@@ -166,6 +166,8 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le
 		for (int i = 0; i < s->numSkins; i++)
 		{
 			// [BB] According to the MD3 spec, Name is supposed to include the full path.
+			// ... and since some tools seem to output backslashes, these need to be replaced with forward slashes to work.
+			FixPathSeperator(shader[i].Name);
 			s->skins[i] = LoadSkin("", shader[i].Name);
 			// [BB] Fall back and check if Name is relative.
 			if (!s->skins[i].isValid())
diff --git a/src/resourcefiles/file_directory.cpp b/src/resourcefiles/file_directory.cpp
index 02c70a21e..2e5630169 100644
--- a/src/resourcefiles/file_directory.cpp
+++ b/src/resourcefiles/file_directory.cpp
@@ -35,27 +35,13 @@
 
 
 #include <sys/stat.h>
-#include <sys/types.h>
 #ifdef _WIN32
 #include <io.h>
-#define stat _stat
 #else
-#include <dirent.h>
-#ifndef __sun
 #include <fts.h>
 #endif
-#endif
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <time.h>
 
-#include "doomtype.h"
-#include "tarray.h"
 #include "resourcefile.h"
-#include "zstring.h"
 #include "cmdlib.h"
 #include "doomerrors.h"
 
@@ -185,43 +171,6 @@ int FDirectory::AddDirectory(const char *dirpath)
 	return count;
 }
 
-#elif defined(__sun) || defined(__APPLE__)
-
-int FDirectory::AddDirectory(const char *dirpath)
-{
-	int count = 0;
-	TArray<FString> scanDirectories;
-	scanDirectories.Push(dirpath);
-	for(unsigned int i = 0;i < scanDirectories.Size();i++)
-	{
-		DIR* directory = opendir(scanDirectories[i].GetChars());
-		if (directory == NULL)
-		{
-			Printf("Could not read directory: %s\n", strerror(errno));
-			return 0;
-		}
-
-		struct dirent *file;
-		while((file = readdir(directory)) != NULL)
-		{
-			if(file->d_name[0] == '.') //File is hidden or ./.. directory so ignore it.
-				continue;
-
-			FString fullFileName = scanDirectories[i] + file->d_name;
-
-			if(DirExists(fullFileName.GetChars()))
-			{
-				scanDirectories.Push(scanDirectories[i] + file->d_name + "/");
-				continue;
-			}
-			AddEntry(scanDirectories[i] + file->d_name, fileStat.st_size);
-			count++;
-		}
-		closedir(directory);
-	}
-	return count;
-}
-
 #else
 
 //==========================================================================
@@ -246,6 +195,10 @@ int FDirectory::AddDirectory(const char *dirpath)
 		Printf("Failed to start directory traversal: %s\n", strerror(errno));
 		return 0;
 	}
+
+	const size_t namepos = strlen(Filename);
+	FString pathfix;
+
 	while ((ent = fts_read(fts)) != NULL)
 	{
 		if (ent->fts_info == FTS_D && ent->fts_name[0] == '.')
@@ -263,7 +216,22 @@ int FDirectory::AddDirectory(const char *dirpath)
 			// We're only interested in remembering files.
 			continue;
 		}
-		AddEntry(ent->fts_path, ent->fts_statp->st_size);
+
+		// Some implementations add an extra separator between
+		// root of the hierarchy and entity's path.
+		// It needs to be removed in order to resolve
+		// lumps' relative paths properly.
+		const char* path = ent->fts_path;
+
+		if ('/' == path[namepos])
+		{
+			pathfix = FString(path, namepos);
+			pathfix.AppendCStrPart(&path[namepos + 1], ent->fts_pathlen - namepos - 1);
+
+			path = pathfix.GetChars();
+		}
+
+		AddEntry(path, ent->fts_statp->st_size);
 		count++;
 	}
 	fts_close(fts);
diff --git a/src/tmpfileplus.cpp b/src/tmpfileplus.cpp
index bfe021dbb..2c14e1563 100644
--- a/src/tmpfileplus.cpp
+++ b/src/tmpfileplus.cpp
@@ -139,8 +139,8 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, FString *t
 	int oflag, pmode;
 
 /* In Windows, we use the _O_TEMPORARY flag with `open` to ensure the file is deleted when closed.
- * In Unix, we use the unlink function after opening the file. (This does not work in Windows,
- * which does not allow an open file to be unlinked.)
+ * In Unix, we use the remove function after opening the file. (This does not work in Windows,
+ * which does not allow an open file to be deleted.)
  */
 #ifdef _WIN32
 	/* MSVC flags */
@@ -175,7 +175,7 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, FString *t
 
 #ifndef _WIN32
 		/* [Unix only] And make sure the file will be deleted once closed */
-		if (!keep) remove(tmpname);
+		if (!keep) remove(tempname);
 #endif
 
 	}
diff --git a/src/win32/i_specialpaths.cpp b/src/win32/i_specialpaths.cpp
index 4a790798f..375f301dd 100644
--- a/src/win32/i_specialpaths.cpp
+++ b/src/win32/i_specialpaths.cpp
@@ -380,3 +380,41 @@ FString M_GetSavegamesPath()
 	}
 	return path;
 }
+
+//===========================================================================
+//
+// M_GetDocumentsPath												Windows
+//
+// Returns the path to the default documents directory.
+//
+//===========================================================================
+
+FString M_GetDocumentsPath()
+{
+	FString path;
+
+	// A portable INI means that this storage location should also be portable.
+	path.Format("%s" GAMENAME "_portable.ini", progdir.GetChars());
+	if (FileExists(path))
+	{
+		return progdir;
+	}
+
+	if (!UseKnownFolders())
+	{
+		return progdir;
+	}
+	// Try defacto My Documents/My Games folder
+	else if (GetKnownFolder(CSIDL_PERSONAL, FOLDERID_Documents, true, path))
+	{
+		// I assume since this isn't a standard folder, it doesn't have
+		// a localized name either.
+		path << "/My Games/" GAMENAME;
+		CreatePath(path);
+	}
+	else
+	{
+		path = progdir;
+	}
+	return path;
+}