summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ShizZy2013-09-23 21:50:41 -0400
committerGravatar ShizZy2013-09-23 21:50:41 -0400
commit1af6ae2f4804eaa8f727f3603f685c13bb209d10 (patch)
treeb351e32ba4f7a473bb7464dce81dec056e561218 /src
parentadded UNICODE preprocessor define (diff)
downloadyuzu-1af6ae2f4804eaa8f727f3603f685c13bb209d10.tar.gz
yuzu-1af6ae2f4804eaa8f727f3603f685c13bb209d10.tar.xz
yuzu-1af6ae2f4804eaa8f727f3603f685c13bb209d10.zip
added PPSSPP's file system directory module for game loading
Diffstat (limited to 'src')
-rw-r--r--src/core/core.vcxproj3
-rw-r--r--src/core/core.vcxproj.filters12
-rw-r--r--src/core/src/file_sys/file_sys_directory.cpp133
3 files changed, 138 insertions, 10 deletions
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index 11e31c8f5..4ae1cb234 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -137,6 +137,7 @@
137 <ClCompile Include="src\arm\arminit.cpp" /> 137 <ClCompile Include="src\arm\arminit.cpp" />
138 <ClCompile Include="src\arm\disassembler\arm_disasm.cpp" /> 138 <ClCompile Include="src\arm\disassembler\arm_disasm.cpp" />
139 <ClCompile Include="src\core.cpp" /> 139 <ClCompile Include="src\core.cpp" />
140 <ClCompile Include="src\file_sys\file_sys_directory.cpp" />
140 <ClCompile Include="src\loader.cpp" /> 141 <ClCompile Include="src\loader.cpp" />
141 <ClCompile Include="src\mem_map.cpp" /> 142 <ClCompile Include="src\mem_map.cpp" />
142 <ClCompile Include="src\mem_map_funcs.cpp" /> 143 <ClCompile Include="src\mem_map_funcs.cpp" />
@@ -156,6 +157,8 @@
156 <ClInclude Include="src\arm\mmu\wb.h" /> 157 <ClInclude Include="src\arm\mmu\wb.h" />
157 <ClInclude Include="src\arm\skyeye_defs.h" /> 158 <ClInclude Include="src\arm\skyeye_defs.h" />
158 <ClInclude Include="src\core.h" /> 159 <ClInclude Include="src\core.h" />
160 <ClInclude Include="src\file_sys\file_sys.h" />
161 <ClInclude Include="src\file_sys\file_sys_directory.h" />
159 <ClInclude Include="src\loader.h" /> 162 <ClInclude Include="src\loader.h" />
160 <ClInclude Include="src\mem_map.h" /> 163 <ClInclude Include="src\mem_map.h" />
161 </ItemGroup> 164 </ItemGroup>
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 51aa17d76..8fbb1d4e3 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -14,6 +14,9 @@
14 </ClCompile> 14 </ClCompile>
15 <ClCompile Include="src\mem_map_funcs.cpp" /> 15 <ClCompile Include="src\mem_map_funcs.cpp" />
16 <ClCompile Include="src\loader.cpp" /> 16 <ClCompile Include="src\loader.cpp" />
17 <ClCompile Include="src\file_sys\file_sys_directory.cpp">
18 <Filter>file_sys</Filter>
19 </ClCompile>
17 </ItemGroup> 20 </ItemGroup>
18 <ItemGroup> 21 <ItemGroup>
19 <Filter Include="arm"> 22 <Filter Include="arm">
@@ -25,6 +28,9 @@
25 <Filter Include="arm\mmu"> 28 <Filter Include="arm\mmu">
26 <UniqueIdentifier>{a64d3c8a-747a-491b-b782-6e2622bedf24}</UniqueIdentifier> 29 <UniqueIdentifier>{a64d3c8a-747a-491b-b782-6e2622bedf24}</UniqueIdentifier>
27 </Filter> 30 </Filter>
31 <Filter Include="file_sys">
32 <UniqueIdentifier>{d19a3be3-56c3-4b0b-877c-c68388904bb2}</UniqueIdentifier>
33 </Filter>
28 </ItemGroup> 34 </ItemGroup>
29 <ItemGroup> 35 <ItemGroup>
30 <ClInclude Include="src\arm\disassembler\arm_disasm.h"> 36 <ClInclude Include="src\arm\disassembler\arm_disasm.h">
@@ -69,6 +75,12 @@
69 <Filter>arm\mmu</Filter> 75 <Filter>arm\mmu</Filter>
70 </ClInclude> 76 </ClInclude>
71 <ClInclude Include="src\loader.h" /> 77 <ClInclude Include="src\loader.h" />
78 <ClInclude Include="src\file_sys\file_sys.h">
79 <Filter>file_sys</Filter>
80 </ClInclude>
81 <ClInclude Include="src\file_sys\file_sys_directory.h">
82 <Filter>file_sys</Filter>
83 </ClInclude>
72 </ItemGroup> 84 </ItemGroup>
73 <ItemGroup> 85 <ItemGroup>
74 <None Include="CMakeLists.txt" /> 86 <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 255369cb6..cf21d74cb 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 @@
21//#include "ISOFileSystem.h" 21//#include "ISOFileSystem.h"
22//#include "Core/HLE/sceKernel.h" 22//#include "Core/HLE/sceKernel.h"
23//#include "file/zip_read.h" 23//#include "file/zip_read.h"
24//#include "util/text/utf8.h" 24#include "utf8.h"
25 25
26#ifdef _WIN32 26#if EMU_PLATFORM == PLATFORM_WINDOWS
27//#include "Common/CommonWindows.h" 27//#include "Common/CommonWindows.h"
28#include <sys/stat.h> 28#include <sys/stat.h>
29#else 29#else
@@ -33,6 +33,106 @@
33#include <ctype.h> 33#include <ctype.h>
34#endif 34#endif
35 35
36#if HOST_IS_CASE_SENSITIVE
37static bool FixFilenameCase(const std::string &path, std::string &filename)
38{
39 // Are we lucky?
40 if (File::Exists(path + filename))
41 return true;
42
43 size_t filenameSize = filename.size(); // size in bytes, not characters
44 for (size_t i = 0; i < filenameSize; i++)
45 {
46 filename[i] = tolower(filename[i]);
47 }
48
49 //TODO: lookup filename in cache for "path"
50
51 struct dirent_large { struct dirent entry; char padding[FILENAME_MAX+1]; } diren;
52 struct dirent_large;
53 struct dirent *result = NULL;
54
55 DIR *dirp = opendir(path.c_str());
56 if (!dirp)
57 return false;
58
59 bool retValue = false;
60
61 while (!readdir_r(dirp, (dirent*) &diren, &result) && result)
62 {
63 if (strlen(result->d_name) != filenameSize)
64 continue;
65
66 size_t i;
67 for (i = 0; i < filenameSize; i++)
68 {
69 if (filename[i] != tolower(result->d_name[i]))
70 break;
71 }
72
73 if (i < filenameSize)
74 continue;
75
76 filename = result->d_name;
77 retValue = true;
78 }
79
80 closedir(dirp);
81
82 return retValue;
83}
84
85bool FixPathCase(std::string& basePath, std::string &path, FixPathCaseBehavior behavior)
86{
87 size_t len = path.size();
88
89 if (len == 0)
90 return true;
91
92 if (path[len - 1] == '/')
93 {
94 len--;
95
96 if (len == 0)
97 return true;
98 }
99
100 std::string fullPath;
101 fullPath.reserve(basePath.size() + len + 1);
102 fullPath.append(basePath);
103
104 size_t start = 0;
105 while (start < len)
106 {
107 size_t i = path.find('/', start);
108 if (i == std::string::npos)
109 i = len;
110
111 if (i > start)
112 {
113 std::string component = path.substr(start, i - start);
114
115 // Fix case and stop on nonexistant path component
116 if (FixFilenameCase(fullPath, component) == false) {
117 // Still counts as success if partial matches allowed or if this
118 // is the last component and only the ones before it are required
119 return (behavior == FPC_PARTIAL_ALLOWED || (behavior == FPC_PATH_MUST_EXIST && i >= len));
120 }
121
122 path.replace(start, i - start, component);
123
124 fullPath.append(component);
125 fullPath.append(1, '/');
126 }
127
128 start = i + 1;
129 }
130
131 return true;
132}
133
134#endif
135
36std::string DirectoryFileHandle::GetLocalPath(std::string& basePath, std::string localpath) 136std::string DirectoryFileHandle::GetLocalPath(std::string& basePath, std::string localpath)
37{ 137{
38 if (localpath.empty()) 138 if (localpath.empty())
@@ -50,9 +150,20 @@ std::string DirectoryFileHandle::GetLocalPath(std::string& basePath, std::string
50 return basePath + localpath; 150 return basePath + localpath;
51} 151}
52 152
53bool DirectoryFileHandle::Open(std::string& basePath, std::string& fileName, FileAccess access) { 153bool DirectoryFileHandle::Open(std::string& basePath, std::string& fileName, FileAccess access)
154{
155#if HOST_IS_CASE_SENSITIVE
156 if (access & (FILEACCESS_APPEND|FILEACCESS_CREATE|FILEACCESS_WRITE))
157 {
158 DEBUG_LOG(FILESYS, "Checking case for path %s", fileName.c_str());
159 if ( ! FixPathCase(basePath, fileName, FPC_PATH_MUST_EXIST) )
160 return false; // or go on and attempt (for a better error code than just 0?)
161 }
162 // else we try fopen first (in case we're lucky) before simulating case insensitivity
163#endif
164
54 std::string fullName = GetLocalPath(basePath,fileName); 165 std::string fullName = GetLocalPath(basePath,fileName);
55 INFO_LOG(FILESYS, "Actually opening %s", fullName.c_str()); 166 INFO_LOG(FILESYS,"Actually opening %s", fullName.c_str());
56 167
57 //TODO: tests, should append seek to end of file? seeking in a file opened for append? 168 //TODO: tests, should append seek to end of file? seeking in a file opened for append?
58#ifdef _WIN32 169#ifdef _WIN32
@@ -74,7 +185,7 @@ bool DirectoryFileHandle::Open(std::string& basePath, std::string& fileName, Fil
74 openmode = OPEN_EXISTING; 185 openmode = OPEN_EXISTING;
75 } 186 }
76 //Let's do it! 187 //Let's do it!
77 hFile = CreateFile(fullName.c_str(), desired, sharemode, 0, openmode, 0, 0); 188 hFile = CreateFile(ConvertUTF8ToWString(fullName).c_str(), desired, sharemode, 0, openmode, 0, 0);
78 bool success = hFile != INVALID_HANDLE_VALUE; 189 bool success = hFile != INVALID_HANDLE_VALUE;
79#else 190#else
80 // Convert flags in access parameter to fopen access mode 191 // Convert flags in access parameter to fopen access mode
@@ -268,7 +379,7 @@ int DirectoryFileSystem::RenameFile(const std::string &from, const std::string &
268 379
269 // At this point, we should check if the paths match and give an already exists error. 380 // At this point, we should check if the paths match and give an already exists error.
270 if (from == fullTo) 381 if (from == fullTo)
271 return SCE_KERNEL_ERROR_ERRNO_FILE_ALREADY_EXISTS; 382 return -1;//SCE_KERNEL_ERROR_ERRNO_FILE_ALREADY_EXISTS;
272 383
273 std::string fullFrom = GetLocalPath(from); 384 std::string fullFrom = GetLocalPath(from);
274 385
@@ -282,7 +393,7 @@ int DirectoryFileSystem::RenameFile(const std::string &from, const std::string &
282 const char * fullToC = fullTo.c_str(); 393 const char * fullToC = fullTo.c_str();
283 394
284#ifdef _WIN32 395#ifdef _WIN32
285 bool retValue = (MoveFile(fullFrom.c_str(), fullToC) == TRUE); 396 bool retValue = (MoveFile(ConvertUTF8ToWString(fullFrom).c_str(), ConvertUTF8ToWString(fullToC).c_str()) == TRUE);
286#else 397#else
287 bool retValue = (0 == rename(fullFrom.c_str(), fullToC)); 398 bool retValue = (0 == rename(fullFrom.c_str(), fullToC));
288#endif 399#endif
@@ -305,7 +416,7 @@ int DirectoryFileSystem::RenameFile(const std::string &from, const std::string &
305#endif 416#endif
306 417
307 // TODO: Better error codes. 418 // TODO: Better error codes.
308 return retValue ? 0 : SCE_KERNEL_ERROR_ERRNO_FILE_ALREADY_EXISTS; 419 return retValue ? 0 : -1;//SCE_KERNEL_ERROR_ERRNO_FILE_ALREADY_EXISTS;
309} 420}
310 421
311bool DirectoryFileSystem::RemoveFile(const std::string &filename) { 422bool DirectoryFileSystem::RemoveFile(const std::string &filename) {
@@ -439,7 +550,7 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) {
439 { 550 {
440#ifdef _WIN32 551#ifdef _WIN32
441 struct _stat64i32 s; 552 struct _stat64i32 s;
442 _wstat64i32(fullName.c_str(), &s); 553 _wstat64i32(ConvertUTF8ToWString(fullName).c_str(), &s);
443#else 554#else
444 struct stat s; 555 struct stat s;
445 stat(fullName.c_str(), &s); 556 stat(fullName.c_str(), &s);
@@ -559,7 +670,7 @@ void DirectoryFileSystem::DoState(PointerWrap &p) {
559 } 670 }
560} 671}
561 672
562 673/*
563 674
564VFSFileSystem::VFSFileSystem(IHandleAllocator *_hAlloc, std::string _basePath) : basePath(_basePath) { 675VFSFileSystem::VFSFileSystem(IHandleAllocator *_hAlloc, std::string _basePath) : basePath(_basePath) {
565 INFO_LOG(FILESYS, "Creating VFS file system"); 676 INFO_LOG(FILESYS, "Creating VFS file system");
@@ -710,3 +821,5 @@ void VFSFileSystem::DoState(PointerWrap &p) {
710 ERROR_LOG(FILESYS, "FIXME: Open files during savestate, could go badly."); 821 ERROR_LOG(FILESYS, "FIXME: Open files during savestate, could go badly.");
711 } 822 }
712} 823}
824
825*/