diff options
| author | 2013-09-23 21:50:41 -0400 | |
|---|---|---|
| committer | 2013-09-23 21:50:41 -0400 | |
| commit | 1af6ae2f4804eaa8f727f3603f685c13bb209d10 (patch) | |
| tree | b351e32ba4f7a473bb7464dce81dec056e561218 | |
| parent | added UNICODE preprocessor define (diff) | |
| download | yuzu-1af6ae2f4804eaa8f727f3603f685c13bb209d10.tar.gz yuzu-1af6ae2f4804eaa8f727f3603f685c13bb209d10.tar.xz yuzu-1af6ae2f4804eaa8f727f3603f685c13bb209d10.zip | |
added PPSSPP's file system directory module for game loading
| -rw-r--r-- | src/core/core.vcxproj | 3 | ||||
| -rw-r--r-- | src/core/core.vcxproj.filters | 12 | ||||
| -rw-r--r-- | src/core/src/file_sys/file_sys_directory.cpp | 133 |
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 | ||
| 37 | static 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 | |||
| 85 | bool 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 | |||
| 36 | std::string DirectoryFileHandle::GetLocalPath(std::string& basePath, std::string localpath) | 136 | std::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 | ||
| 53 | bool DirectoryFileHandle::Open(std::string& basePath, std::string& fileName, FileAccess access) { | 153 | bool 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 | ||
| 311 | bool DirectoryFileSystem::RemoveFile(const std::string &filename) { | 422 | bool 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 | ||
| 564 | VFSFileSystem::VFSFileSystem(IHandleAllocator *_hAlloc, std::string _basePath) : basePath(_basePath) { | 675 | VFSFileSystem::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 | */ | ||