diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index 11e31c8f57..4ae1cb234c 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -137,6 +137,7 @@
     <ClCompile Include="src\arm\arminit.cpp" />
     <ClCompile Include="src\arm\disassembler\arm_disasm.cpp" />
     <ClCompile Include="src\core.cpp" />
+    <ClCompile Include="src\file_sys\file_sys_directory.cpp" />
     <ClCompile Include="src\loader.cpp" />
     <ClCompile Include="src\mem_map.cpp" />
     <ClCompile Include="src\mem_map_funcs.cpp" />
@@ -156,6 +157,8 @@
     <ClInclude Include="src\arm\mmu\wb.h" />
     <ClInclude Include="src\arm\skyeye_defs.h" />
     <ClInclude Include="src\core.h" />
+    <ClInclude Include="src\file_sys\file_sys.h" />
+    <ClInclude Include="src\file_sys\file_sys_directory.h" />
     <ClInclude Include="src\loader.h" />
     <ClInclude Include="src\mem_map.h" />
   </ItemGroup>
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 51aa17d76a..8fbb1d4e3b 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -14,6 +14,9 @@
     </ClCompile>
     <ClCompile Include="src\mem_map_funcs.cpp" />
     <ClCompile Include="src\loader.cpp" />
+    <ClCompile Include="src\file_sys\file_sys_directory.cpp">
+      <Filter>file_sys</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <Filter Include="arm">
@@ -25,6 +28,9 @@
     <Filter Include="arm\mmu">
       <UniqueIdentifier>{a64d3c8a-747a-491b-b782-6e2622bedf24}</UniqueIdentifier>
     </Filter>
+    <Filter Include="file_sys">
+      <UniqueIdentifier>{d19a3be3-56c3-4b0b-877c-c68388904bb2}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\arm\disassembler\arm_disasm.h">
@@ -69,6 +75,12 @@
       <Filter>arm\mmu</Filter>
     </ClInclude>
     <ClInclude Include="src\loader.h" />
+    <ClInclude Include="src\file_sys\file_sys.h">
+      <Filter>file_sys</Filter>
+    </ClInclude>
+    <ClInclude Include="src\file_sys\file_sys_directory.h">
+      <Filter>file_sys</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="CMakeLists.txt" />
diff --git a/src/core/src/file_sys/file_sys_directory.cpp b/src/core/src/file_sys/file_sys_directory.cpp
index 255369cb6d..cf21d74cb0 100644
--- a/src/core/src/file_sys/file_sys_directory.cpp
+++ b/src/core/src/file_sys/file_sys_directory.cpp
@@ -21,9 +21,9 @@
 //#include "ISOFileSystem.h"
 //#include "Core/HLE/sceKernel.h"
 //#include "file/zip_read.h"
-//#include "util/text/utf8.h"
+#include "utf8.h"
 
-#ifdef _WIN32
+#if EMU_PLATFORM == PLATFORM_WINDOWS
 //#include "Common/CommonWindows.h"
 #include <sys/stat.h>
 #else
@@ -33,6 +33,106 @@
 #include <ctype.h>
 #endif
 
+#if HOST_IS_CASE_SENSITIVE
+static bool FixFilenameCase(const std::string &path, std::string &filename)
+{
+	// Are we lucky?
+	if (File::Exists(path + filename))
+		return true;
+
+	size_t filenameSize = filename.size();  // size in bytes, not characters
+	for (size_t i = 0; i < filenameSize; i++)
+	{
+		filename[i] = tolower(filename[i]);
+	}
+
+	//TODO: lookup filename in cache for "path"
+
+	struct dirent_large { struct dirent entry; char padding[FILENAME_MAX+1]; } diren;
+	struct dirent_large;
+	struct dirent *result = NULL;
+
+	DIR *dirp = opendir(path.c_str());
+	if (!dirp)
+		return false;
+
+	bool retValue = false;
+
+	while (!readdir_r(dirp, (dirent*) &diren, &result) && result)
+	{
+		if (strlen(result->d_name) != filenameSize)
+			continue;
+
+		size_t i;
+		for (i = 0; i < filenameSize; i++)
+		{
+			if (filename[i] != tolower(result->d_name[i]))
+				break;
+		}
+
+		if (i < filenameSize)
+			continue;
+
+		filename = result->d_name;
+		retValue = true;
+	}
+
+	closedir(dirp);
+
+	return retValue;
+}
+
+bool FixPathCase(std::string& basePath, std::string &path, FixPathCaseBehavior behavior)
+{
+	size_t len = path.size();
+
+	if (len == 0)
+		return true;
+
+	if (path[len - 1] == '/')
+	{
+		len--;
+
+		if (len == 0)
+			return true;
+	}
+
+	std::string fullPath;
+	fullPath.reserve(basePath.size() + len + 1);
+	fullPath.append(basePath); 
+
+	size_t start = 0;
+	while (start < len)
+	{
+		size_t i = path.find('/', start);
+		if (i == std::string::npos)
+			i = len;
+
+		if (i > start)
+		{
+			std::string component = path.substr(start, i - start);
+
+			// Fix case and stop on nonexistant path component
+			if (FixFilenameCase(fullPath, component) == false) {
+				// Still counts as success if partial matches allowed or if this
+				// is the last component and only the ones before it are required
+				return (behavior == FPC_PARTIAL_ALLOWED || (behavior == FPC_PATH_MUST_EXIST && i >= len));
+			}
+
+			path.replace(start, i - start, component);
+
+			fullPath.append(component);
+			fullPath.append(1, '/');
+		}
+
+		start = i + 1;
+	}
+
+	return true;
+}
+
+#endif
+
 std::string DirectoryFileHandle::GetLocalPath(std::string& basePath, std::string localpath)
 {
 	if (localpath.empty())
@@ -50,9 +150,20 @@ std::string DirectoryFileHandle::GetLocalPath(std::string& basePath, std::string
 	return basePath + localpath;
 }
 
-bool DirectoryFileHandle::Open(std::string& basePath, std::string& fileName, FileAccess access) {
+bool DirectoryFileHandle::Open(std::string& basePath, std::string& fileName, FileAccess access)
+{
+#if HOST_IS_CASE_SENSITIVE
+	if (access & (FILEACCESS_APPEND|FILEACCESS_CREATE|FILEACCESS_WRITE))
+	{
+		DEBUG_LOG(FILESYS, "Checking case for path %s", fileName.c_str());
+		if ( ! FixPathCase(basePath, fileName, FPC_PATH_MUST_EXIST) )
+			return false;  // or go on and attempt (for a better error code than just 0?)
+	}
+	// else we try fopen first (in case we're lucky) before simulating case insensitivity
+#endif
+
 	std::string fullName = GetLocalPath(basePath,fileName);
-	INFO_LOG(FILESYS, "Actually opening %s", fullName.c_str());
+	INFO_LOG(FILESYS,"Actually opening %s", fullName.c_str());
 
 	//TODO: tests, should append seek to end of file? seeking in a file opened for append?
 #ifdef _WIN32
@@ -74,7 +185,7 @@ bool DirectoryFileHandle::Open(std::string& basePath, std::string& fileName, Fil
 		openmode = OPEN_EXISTING;
 	}
 	//Let's do it!
-	hFile = CreateFile(fullName.c_str(), desired, sharemode, 0, openmode, 0, 0);
+	hFile = CreateFile(ConvertUTF8ToWString(fullName).c_str(), desired, sharemode, 0, openmode, 0, 0);
 	bool success = hFile != INVALID_HANDLE_VALUE;
 #else
 	// Convert flags in access parameter to fopen access mode
@@ -268,7 +379,7 @@ int DirectoryFileSystem::RenameFile(const std::string &from, const std::string &
 
 	// At this point, we should check if the paths match and give an already exists error.
 	if (from == fullTo)
-		return SCE_KERNEL_ERROR_ERRNO_FILE_ALREADY_EXISTS;
+		return -1;//SCE_KERNEL_ERROR_ERRNO_FILE_ALREADY_EXISTS;
 
 	std::string fullFrom = GetLocalPath(from);
 
@@ -282,7 +393,7 @@ int DirectoryFileSystem::RenameFile(const std::string &from, const std::string &
 	const char * fullToC = fullTo.c_str();
 
 #ifdef _WIN32
-	bool retValue = (MoveFile(fullFrom.c_str(), fullToC) == TRUE);
+	bool retValue = (MoveFile(ConvertUTF8ToWString(fullFrom).c_str(), ConvertUTF8ToWString(fullToC).c_str()) == TRUE);
 #else
 	bool retValue = (0 == rename(fullFrom.c_str(), fullToC));
 #endif
@@ -305,7 +416,7 @@ int DirectoryFileSystem::RenameFile(const std::string &from, const std::string &
 #endif
 
 	// TODO: Better error codes.
-	return retValue ? 0 : SCE_KERNEL_ERROR_ERRNO_FILE_ALREADY_EXISTS;
+	return retValue ? 0 : -1;//SCE_KERNEL_ERROR_ERRNO_FILE_ALREADY_EXISTS;
 }
 
 bool DirectoryFileSystem::RemoveFile(const std::string &filename) {
@@ -439,7 +550,7 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) {
 	{
 #ifdef _WIN32
 		struct _stat64i32 s;
-		_wstat64i32(fullName.c_str(), &s);
+		_wstat64i32(ConvertUTF8ToWString(fullName).c_str(), &s);
 #else
 		struct stat s;
 		stat(fullName.c_str(), &s);
@@ -559,7 +670,7 @@ void DirectoryFileSystem::DoState(PointerWrap &p) {
 	}
 }
 
-
+/*
 
 VFSFileSystem::VFSFileSystem(IHandleAllocator *_hAlloc, std::string _basePath) : basePath(_basePath) {
 	INFO_LOG(FILESYS, "Creating VFS file system");
@@ -710,3 +821,5 @@ void VFSFileSystem::DoState(PointerWrap &p) {
 		ERROR_LOG(FILESYS, "FIXME: Open files during savestate, could go badly.");
 	}
 }
+
+*/