mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 18:54:14 +01:00 
			
		
		
		
	added PPSSPP's file system directory module for game loading
This commit is contained in:
		
							parent
							
								
									3fe49a303d
								
							
						
					
					
						commit
						1af6ae2f48
					
				| @ -137,6 +137,7 @@ | |||||||
|     <ClCompile Include="src\arm\arminit.cpp" /> |     <ClCompile Include="src\arm\arminit.cpp" /> | ||||||
|     <ClCompile Include="src\arm\disassembler\arm_disasm.cpp" /> |     <ClCompile Include="src\arm\disassembler\arm_disasm.cpp" /> | ||||||
|     <ClCompile Include="src\core.cpp" /> |     <ClCompile Include="src\core.cpp" /> | ||||||
|  |     <ClCompile Include="src\file_sys\file_sys_directory.cpp" /> | ||||||
|     <ClCompile Include="src\loader.cpp" /> |     <ClCompile Include="src\loader.cpp" /> | ||||||
|     <ClCompile Include="src\mem_map.cpp" /> |     <ClCompile Include="src\mem_map.cpp" /> | ||||||
|     <ClCompile Include="src\mem_map_funcs.cpp" /> |     <ClCompile Include="src\mem_map_funcs.cpp" /> | ||||||
| @ -156,6 +157,8 @@ | |||||||
|     <ClInclude Include="src\arm\mmu\wb.h" /> |     <ClInclude Include="src\arm\mmu\wb.h" /> | ||||||
|     <ClInclude Include="src\arm\skyeye_defs.h" /> |     <ClInclude Include="src\arm\skyeye_defs.h" /> | ||||||
|     <ClInclude Include="src\core.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\loader.h" /> | ||||||
|     <ClInclude Include="src\mem_map.h" /> |     <ClInclude Include="src\mem_map.h" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  | |||||||
| @ -14,6 +14,9 @@ | |||||||
|     </ClCompile> |     </ClCompile> | ||||||
|     <ClCompile Include="src\mem_map_funcs.cpp" /> |     <ClCompile Include="src\mem_map_funcs.cpp" /> | ||||||
|     <ClCompile Include="src\loader.cpp" /> |     <ClCompile Include="src\loader.cpp" /> | ||||||
|  |     <ClCompile Include="src\file_sys\file_sys_directory.cpp"> | ||||||
|  |       <Filter>file_sys</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Filter Include="arm"> |     <Filter Include="arm"> | ||||||
| @ -25,6 +28,9 @@ | |||||||
|     <Filter Include="arm\mmu"> |     <Filter Include="arm\mmu"> | ||||||
|       <UniqueIdentifier>{a64d3c8a-747a-491b-b782-6e2622bedf24}</UniqueIdentifier> |       <UniqueIdentifier>{a64d3c8a-747a-491b-b782-6e2622bedf24}</UniqueIdentifier> | ||||||
|     </Filter> |     </Filter> | ||||||
|  |     <Filter Include="file_sys"> | ||||||
|  |       <UniqueIdentifier>{d19a3be3-56c3-4b0b-877c-c68388904bb2}</UniqueIdentifier> | ||||||
|  |     </Filter> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="src\arm\disassembler\arm_disasm.h"> |     <ClInclude Include="src\arm\disassembler\arm_disasm.h"> | ||||||
| @ -69,6 +75,12 @@ | |||||||
|       <Filter>arm\mmu</Filter> |       <Filter>arm\mmu</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|     <ClInclude Include="src\loader.h" /> |     <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> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="CMakeLists.txt" /> |     <None Include="CMakeLists.txt" /> | ||||||
|  | |||||||
| @ -21,9 +21,9 @@ | |||||||
| //#include "ISOFileSystem.h"
 | //#include "ISOFileSystem.h"
 | ||||||
| //#include "Core/HLE/sceKernel.h"
 | //#include "Core/HLE/sceKernel.h"
 | ||||||
| //#include "file/zip_read.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 "Common/CommonWindows.h"
 | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
| #else | #else | ||||||
| @ -33,6 +33,106 @@ | |||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
| #endif | #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) | std::string DirectoryFileHandle::GetLocalPath(std::string& basePath, std::string localpath) | ||||||
| { | { | ||||||
| 	if (localpath.empty()) | 	if (localpath.empty()) | ||||||
| @ -50,9 +150,20 @@ std::string DirectoryFileHandle::GetLocalPath(std::string& basePath, std::string | |||||||
| 	return basePath + localpath; | 	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); | 	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?
 | 	//TODO: tests, should append seek to end of file? seeking in a file opened for append?
 | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
| @ -74,7 +185,7 @@ bool DirectoryFileHandle::Open(std::string& basePath, std::string& fileName, Fil | |||||||
| 		openmode = OPEN_EXISTING; | 		openmode = OPEN_EXISTING; | ||||||
| 	} | 	} | ||||||
| 	//Let's do it!
 | 	//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; | 	bool success = hFile != INVALID_HANDLE_VALUE; | ||||||
| #else | #else | ||||||
| 	// Convert flags in access parameter to fopen access mode
 | 	// 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.
 | 	// At this point, we should check if the paths match and give an already exists error.
 | ||||||
| 	if (from == fullTo) | 	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); | 	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(); | 	const char * fullToC = fullTo.c_str(); | ||||||
| 
 | 
 | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
| 	bool retValue = (MoveFile(fullFrom.c_str(), fullToC) == TRUE); | 	bool retValue = (MoveFile(ConvertUTF8ToWString(fullFrom).c_str(), ConvertUTF8ToWString(fullToC).c_str()) == TRUE); | ||||||
| #else | #else | ||||||
| 	bool retValue = (0 == rename(fullFrom.c_str(), fullToC)); | 	bool retValue = (0 == rename(fullFrom.c_str(), fullToC)); | ||||||
| #endif | #endif | ||||||
| @ -305,7 +416,7 @@ int DirectoryFileSystem::RenameFile(const std::string &from, const std::string & | |||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	// TODO: Better error codes.
 | 	// 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) { | bool DirectoryFileSystem::RemoveFile(const std::string &filename) { | ||||||
| @ -439,7 +550,7 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) { | |||||||
| 	{ | 	{ | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
| 		struct _stat64i32 s; | 		struct _stat64i32 s; | ||||||
| 		_wstat64i32(fullName.c_str(), &s); | 		_wstat64i32(ConvertUTF8ToWString(fullName).c_str(), &s); | ||||||
| #else | #else | ||||||
| 		struct stat s; | 		struct stat s; | ||||||
| 		stat(fullName.c_str(), &s); | 		stat(fullName.c_str(), &s); | ||||||
| @ -559,7 +670,7 @@ void DirectoryFileSystem::DoState(PointerWrap &p) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | /*
 | ||||||
| 
 | 
 | ||||||
| VFSFileSystem::VFSFileSystem(IHandleAllocator *_hAlloc, std::string _basePath) : basePath(_basePath) { | VFSFileSystem::VFSFileSystem(IHandleAllocator *_hAlloc, std::string _basePath) : basePath(_basePath) { | ||||||
| 	INFO_LOG(FILESYS, "Creating VFS file system"); | 	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."); | 		ERROR_LOG(FILESYS, "FIXME: Open files during savestate, could go badly."); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | */ | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user