Core: Add a Directory object, with both a stub and a passthrough implementations.
This commit is contained in:
		| @@ -26,6 +26,8 @@ set(SRCS | ||||
|             file_sys/archive_sdmc.cpp | ||||
|             file_sys/file_romfs.cpp | ||||
|             file_sys/file_sdmc.cpp | ||||
|             file_sys/directory_romfs.cpp | ||||
|             file_sys/directory_sdmc.cpp | ||||
|             hle/kernel/address_arbiter.cpp | ||||
|             hle/kernel/archive.cpp | ||||
|             hle/kernel/event.cpp | ||||
| @@ -84,6 +86,9 @@ set(HEADERS | ||||
|             file_sys/file.h | ||||
|             file_sys/file_romfs.h | ||||
|             file_sys/file_sdmc.h | ||||
|             file_sys/directory.h | ||||
|             file_sys/directory_romfs.h | ||||
|             file_sys/directory_sdmc.h | ||||
|             hle/kernel/address_arbiter.h | ||||
|             hle/kernel/archive.h | ||||
|             hle/kernel/event.h | ||||
|   | ||||
							
								
								
									
										53
									
								
								src/core/file_sys/directory.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/core/file_sys/directory.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| // Copyright 2014 Citra Emulator Project | ||||
| // Licensed under GPLv2 | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "common/common_types.h" | ||||
|  | ||||
| #include "core/hle/kernel/kernel.h" | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // FileSys namespace | ||||
|  | ||||
| namespace FileSys { | ||||
|  | ||||
| // Structure of a directory entry, from http://3dbrew.org/wiki/FSDir:Read#Entry_format | ||||
| const size_t FILENAME_LENGTH = 0x20C / 2; | ||||
| struct Entry { | ||||
|     char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) | ||||
|     char short_name[8]; // 8.3 file name ('longfilename' -> 'LONGFI~1') | ||||
|     char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) | ||||
|     char extension[3]; // 8.3 file extension (set to spaces for directories) | ||||
|     char unknown2; // unknown (always 0x01) | ||||
|     char unknown3; // unknown (0x00 or 0x08) | ||||
|     char is_directory; // directory flag | ||||
|     char is_hidden; // hidden flag | ||||
|     char is_archive; // archive flag | ||||
|     char is_read_only; // read-only flag | ||||
|     u64 file_size; // file size (for files only) | ||||
| }; | ||||
| static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); | ||||
|  | ||||
| class Directory : NonCopyable { | ||||
| public: | ||||
|     Directory() { } | ||||
|     virtual ~Directory() { } | ||||
|  | ||||
|     /** | ||||
|      * List files contained in the directory | ||||
|      * @param count Number of entries to return at once in entries | ||||
|      * @param entries Buffer to read data into | ||||
|      * @return Number of entries listed | ||||
|      */ | ||||
|     virtual u32 Read(const u32 count, Entry* entries) = 0; | ||||
|  | ||||
|     /** | ||||
|      * Close the directory | ||||
|      * @return true if the directory closed correctly | ||||
|      */ | ||||
|     virtual bool Close() const = 0; | ||||
| }; | ||||
|  | ||||
| } // namespace FileSys | ||||
							
								
								
									
										38
									
								
								src/core/file_sys/directory_romfs.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/core/file_sys/directory_romfs.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| // Copyright 2014 Citra Emulator Project | ||||
| // Licensed under GPLv2 | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include "common/common_types.h" | ||||
|  | ||||
| #include "core/file_sys/directory_romfs.h" | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // FileSys namespace | ||||
|  | ||||
| namespace FileSys { | ||||
|  | ||||
| Directory_RomFS::Directory_RomFS() { | ||||
| } | ||||
|  | ||||
| Directory_RomFS::~Directory_RomFS() { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * List files contained in the directory | ||||
|  * @param count Number of entries to return at once in entries | ||||
|  * @param entries Buffer to read data into | ||||
|  * @return Number of entries listed | ||||
|  */ | ||||
| u32 Directory_RomFS::Read(const u32 count, Entry* entries) { | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Close the directory | ||||
|  * @return true if the directory closed correctly | ||||
|  */ | ||||
| bool Directory_RomFS::Close() const { | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| } // namespace FileSys | ||||
							
								
								
									
										37
									
								
								src/core/file_sys/directory_romfs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/core/file_sys/directory_romfs.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| // Copyright 2014 Citra Emulator Project | ||||
| // Licensed under GPLv2 | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "common/common_types.h" | ||||
|  | ||||
| #include "core/file_sys/directory.h" | ||||
| #include "core/loader/loader.h" | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // FileSys namespace | ||||
|  | ||||
| namespace FileSys { | ||||
|  | ||||
| class Directory_RomFS final : public Directory { | ||||
| public: | ||||
|     Directory_RomFS(); | ||||
|     ~Directory_RomFS() override; | ||||
|  | ||||
|     /** | ||||
|      * List files contained in the directory | ||||
|      * @param count Number of entries to return at once in entries | ||||
|      * @param entries Buffer to read data into | ||||
|      * @return Number of entries listed | ||||
|      */ | ||||
|     u32 Read(const u32 count, Entry* entries) override; | ||||
|  | ||||
|     /** | ||||
|      * Close the directory | ||||
|      * @return true if the directory closed correctly | ||||
|      */ | ||||
|     bool Close() const override; | ||||
| }; | ||||
|  | ||||
| } // namespace FileSys | ||||
							
								
								
									
										86
									
								
								src/core/file_sys/directory_sdmc.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/core/file_sys/directory_sdmc.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| // Copyright 2014 Citra Emulator Project | ||||
| // Licensed under GPLv2 | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <sys/stat.h> | ||||
|  | ||||
| #include "common/common_types.h" | ||||
| #include "common/file_util.h" | ||||
|  | ||||
| #include "core/file_sys/directory_sdmc.h" | ||||
| #include "core/file_sys/archive_sdmc.h" | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // FileSys namespace | ||||
|  | ||||
| namespace FileSys { | ||||
|  | ||||
| Directory_SDMC::Directory_SDMC(const Archive_SDMC* archive, const std::string& path) { | ||||
|     // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | ||||
|     // the root directory we set while opening the archive. | ||||
|     // For example, opening /../../usr/bin can give the emulated program your installed programs. | ||||
|     std::string absolute_path = archive->GetMountPoint() + path; | ||||
|     entry_count = FileUtil::ScanDirectoryTree(absolute_path, entry); | ||||
|     current_entry = 0; | ||||
| } | ||||
|  | ||||
| Directory_SDMC::~Directory_SDMC() { | ||||
|     Close(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * List files contained in the directory | ||||
|  * @param count Number of entries to return at once in entries | ||||
|  * @param entries Buffer to read data into | ||||
|  * @return Number of entries listed | ||||
|  */ | ||||
| u32 Directory_SDMC::Read(const u32 count, Entry* entries) { | ||||
|     u32 i; | ||||
|     for (i = 0; i < count && current_entry < entry_count; ++i) { | ||||
|         FileUtil::FSTEntry file = entry.children[current_entry]; | ||||
|         std::string filename = file.virtualName; | ||||
|         WARN_LOG(FILESYS, "File %s: size=%d dir=%d", filename.c_str(), file.size, file.isDirectory); | ||||
|  | ||||
|         Entry* entry = &entries[i]; | ||||
|  | ||||
|         // TODO(Link Mauve): use a proper conversion to UTF-16. | ||||
|         for (int j = 0; j < FILENAME_LENGTH; ++j) { | ||||
|             entry->filename[j] = filename[j]; | ||||
|             if (!filename[j]) | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         // Split the filename into 8.3 format. | ||||
|         // TODO(Link Mauve): move that to common, I guess, and make it more robust to long filenames. | ||||
|         std::string::size_type n = filename.rfind('.'); | ||||
|         if (n == std::string::npos) { | ||||
|             strncpy(entry->short_name, filename.c_str(), 8); | ||||
|             memset(entry->extension, '\0', 3); | ||||
|         } else { | ||||
|             strncpy(entry->short_name, filename.substr(0, n).c_str(), 8); | ||||
|             strncpy(entry->extension, filename.substr(n + 1).c_str(), 8); | ||||
|         } | ||||
|  | ||||
|         entry->is_directory = file.isDirectory; | ||||
|         entry->file_size = file.size; | ||||
|  | ||||
|         // We emulate a SD card where the archive bit has never been cleared, as it would be on | ||||
|         // most user SD cards. | ||||
|         // Some homebrews (blargSNES for instance) are known to mistakenly use the archive bit as a | ||||
|         // file bit. | ||||
|         entry->is_archive = !file.isDirectory; | ||||
|  | ||||
|         ++current_entry; | ||||
|     } | ||||
|     return i; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Close the directory | ||||
|  * @return true if the directory closed correctly | ||||
|  */ | ||||
| bool Directory_SDMC::Close() const { | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| } // namespace FileSys | ||||
							
								
								
									
										45
									
								
								src/core/file_sys/directory_sdmc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/core/file_sys/directory_sdmc.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| // Copyright 2014 Citra Emulator Project | ||||
| // Licensed under GPLv2 | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "common/common_types.h" | ||||
| #include "common/file_util.h" | ||||
|  | ||||
| #include "core/file_sys/directory.h" | ||||
| #include "core/file_sys/archive_sdmc.h" | ||||
| #include "core/loader/loader.h" | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // FileSys namespace | ||||
|  | ||||
| namespace FileSys { | ||||
|  | ||||
| class Directory_SDMC final : public Directory { | ||||
| public: | ||||
|     Directory_SDMC(); | ||||
|     Directory_SDMC(const Archive_SDMC* archive, const std::string& path); | ||||
|     ~Directory_SDMC() override; | ||||
|  | ||||
|     /** | ||||
|      * List files contained in the directory | ||||
|      * @param count Number of entries to return at once in entries | ||||
|      * @param entries Buffer to read data into | ||||
|      * @return Number of entries listed | ||||
|      */ | ||||
|     u32 Read(const u32 count, Entry* entries) override; | ||||
|  | ||||
|     /** | ||||
|      * Close the directory | ||||
|      * @return true if the directory closed correctly | ||||
|      */ | ||||
|     bool Close() const override; | ||||
|  | ||||
| private: | ||||
|     u32 entry_count; | ||||
|     u32 current_entry; | ||||
|     FileUtil::FSTEntry entry; | ||||
| }; | ||||
|  | ||||
| } // namespace FileSys | ||||
		Reference in New Issue
	
	Block a user