diff options
Diffstat (limited to 'src')
28 files changed, 1298 insertions, 59 deletions
diff --git a/src/common/chunk_file.h b/src/common/chunk_file.h index 2b0f120e6..7a3b537c7 100644 --- a/src/common/chunk_file.h +++ b/src/common/chunk_file.h | |||
| @@ -671,7 +671,7 @@ public: | |||
| 671 | _failureReason->clear(); | 671 | _failureReason->clear(); |
| 672 | _failureReason->append("LoadStateWrongVersion"); | 672 | _failureReason->append("LoadStateWrongVersion"); |
| 673 | 673 | ||
| 674 | if (!File::Exists(_rFilename)) { | 674 | if (!FileUtil::Exists(_rFilename)) { |
| 675 | _failureReason->clear(); | 675 | _failureReason->clear(); |
| 676 | _failureReason->append("LoadStateDoesntExist"); | 676 | _failureReason->append("LoadStateDoesntExist"); |
| 677 | ERROR_LOG(COMMON, "ChunkReader: File doesn't exist"); | 677 | ERROR_LOG(COMMON, "ChunkReader: File doesn't exist"); |
| @@ -679,7 +679,7 @@ public: | |||
| 679 | } | 679 | } |
| 680 | 680 | ||
| 681 | // Check file size | 681 | // Check file size |
| 682 | const u64 fileSize = File::GetSize(_rFilename); | 682 | const u64 fileSize = FileUtil::GetSize(_rFilename); |
| 683 | static const u64 headerSize = sizeof(SChunkHeader); | 683 | static const u64 headerSize = sizeof(SChunkHeader); |
| 684 | if (fileSize < headerSize) | 684 | if (fileSize < headerSize) |
| 685 | { | 685 | { |
| @@ -687,7 +687,7 @@ public: | |||
| 687 | return ERROR_BAD_FILE; | 687 | return ERROR_BAD_FILE; |
| 688 | } | 688 | } |
| 689 | 689 | ||
| 690 | File::IOFile pFile(_rFilename, "rb"); | 690 | FileUtil::IOFile pFile(_rFilename, "rb"); |
| 691 | if (!pFile) | 691 | if (!pFile) |
| 692 | { | 692 | { |
| 693 | ERROR_LOG(COMMON,"ChunkReader: Can't open file for reading"); | 693 | ERROR_LOG(COMMON,"ChunkReader: Can't open file for reading"); |
| @@ -765,7 +765,7 @@ public: | |||
| 765 | { | 765 | { |
| 766 | INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str()); | 766 | INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str()); |
| 767 | 767 | ||
| 768 | File::IOFile pFile(_rFilename, "wb"); | 768 | FileUtil::IOFile pFile(_rFilename, "wb"); |
| 769 | if (!pFile) | 769 | if (!pFile) |
| 770 | { | 770 | { |
| 771 | ERROR_LOG(COMMON,"ChunkReader: Error opening file for write"); | 771 | ERROR_LOG(COMMON,"ChunkReader: Error opening file for write"); |
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 970041007..ecfccbd66 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | // This namespace has various generic functions related to files and paths. | 39 | // This namespace has various generic functions related to files and paths. |
| 40 | // The code still needs a ton of cleanup. | 40 | // The code still needs a ton of cleanup. |
| 41 | // REMEMBER: strdup considered harmful! | 41 | // REMEMBER: strdup considered harmful! |
| 42 | namespace File | 42 | namespace FileUtil |
| 43 | { | 43 | { |
| 44 | 44 | ||
| 45 | // Remove any ending forward slashes from directory paths | 45 | // Remove any ending forward slashes from directory paths |
| @@ -172,7 +172,7 @@ bool CreateFullPath(const std::string &fullPath) | |||
| 172 | int panicCounter = 100; | 172 | int panicCounter = 100; |
| 173 | INFO_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str()); | 173 | INFO_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str()); |
| 174 | 174 | ||
| 175 | if (File::Exists(fullPath)) | 175 | if (FileUtil::Exists(fullPath)) |
| 176 | { | 176 | { |
| 177 | INFO_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str()); | 177 | INFO_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str()); |
| 178 | return true; | 178 | return true; |
| @@ -190,8 +190,8 @@ bool CreateFullPath(const std::string &fullPath) | |||
| 190 | 190 | ||
| 191 | // Include the '/' so the first call is CreateDir("/") rather than CreateDir("") | 191 | // Include the '/' so the first call is CreateDir("/") rather than CreateDir("") |
| 192 | std::string const subPath(fullPath.substr(0, position + 1)); | 192 | std::string const subPath(fullPath.substr(0, position + 1)); |
| 193 | if (!File::IsDirectory(subPath)) | 193 | if (!FileUtil::IsDirectory(subPath)) |
| 194 | File::CreateDir(subPath); | 194 | FileUtil::CreateDir(subPath); |
| 195 | 195 | ||
| 196 | // A safety check | 196 | // A safety check |
| 197 | panicCounter--; | 197 | panicCounter--; |
| @@ -211,7 +211,7 @@ bool DeleteDir(const std::string &filename) | |||
| 211 | INFO_LOG(COMMON, "DeleteDir: directory %s", filename.c_str()); | 211 | INFO_LOG(COMMON, "DeleteDir: directory %s", filename.c_str()); |
| 212 | 212 | ||
| 213 | // check if a directory | 213 | // check if a directory |
| 214 | if (!File::IsDirectory(filename)) | 214 | if (!FileUtil::IsDirectory(filename)) |
| 215 | { | 215 | { |
| 216 | ERROR_LOG(COMMON, "DeleteDir: Not a directory %s", filename.c_str()); | 216 | ERROR_LOG(COMMON, "DeleteDir: Not a directory %s", filename.c_str()); |
| 217 | return false; | 217 | return false; |
| @@ -386,7 +386,7 @@ bool CreateEmptyFile(const std::string &filename) | |||
| 386 | { | 386 | { |
| 387 | INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str()); | 387 | INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str()); |
| 388 | 388 | ||
| 389 | if (!File::IOFile(filename, "wb")) | 389 | if (!FileUtil::IOFile(filename, "wb")) |
| 390 | { | 390 | { |
| 391 | ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s", | 391 | ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s", |
| 392 | filename.c_str(), GetLastErrorMsg()); | 392 | filename.c_str(), GetLastErrorMsg()); |
| @@ -519,7 +519,7 @@ bool DeleteDirRecursively(const std::string &directory) | |||
| 519 | } | 519 | } |
| 520 | else | 520 | else |
| 521 | { | 521 | { |
| 522 | if (!File::Delete(newPath)) | 522 | if (!FileUtil::Delete(newPath)) |
| 523 | { | 523 | { |
| 524 | #ifndef _WIN32 | 524 | #ifndef _WIN32 |
| 525 | closedir(dirp); | 525 | closedir(dirp); |
| @@ -536,7 +536,7 @@ bool DeleteDirRecursively(const std::string &directory) | |||
| 536 | } | 536 | } |
| 537 | closedir(dirp); | 537 | closedir(dirp); |
| 538 | #endif | 538 | #endif |
| 539 | File::DeleteDir(directory); | 539 | FileUtil::DeleteDir(directory); |
| 540 | 540 | ||
| 541 | return true; | 541 | return true; |
| 542 | } | 542 | } |
| @@ -546,8 +546,8 @@ void CopyDir(const std::string &source_path, const std::string &dest_path) | |||
| 546 | { | 546 | { |
| 547 | #ifndef _WIN32 | 547 | #ifndef _WIN32 |
| 548 | if (source_path == dest_path) return; | 548 | if (source_path == dest_path) return; |
| 549 | if (!File::Exists(source_path)) return; | 549 | if (!FileUtil::Exists(source_path)) return; |
| 550 | if (!File::Exists(dest_path)) File::CreateFullPath(dest_path); | 550 | if (!FileUtil::Exists(dest_path)) FileUtil::CreateFullPath(dest_path); |
| 551 | 551 | ||
| 552 | struct dirent dirent, *result = NULL; | 552 | struct dirent dirent, *result = NULL; |
| 553 | DIR *dirp = opendir(source_path.c_str()); | 553 | DIR *dirp = opendir(source_path.c_str()); |
| @@ -569,10 +569,10 @@ void CopyDir(const std::string &source_path, const std::string &dest_path) | |||
| 569 | { | 569 | { |
| 570 | source += '/'; | 570 | source += '/'; |
| 571 | dest += '/'; | 571 | dest += '/'; |
| 572 | if (!File::Exists(dest)) File::CreateFullPath(dest); | 572 | if (!FileUtil::Exists(dest)) FileUtil::CreateFullPath(dest); |
| 573 | CopyDir(source, dest); | 573 | CopyDir(source, dest); |
| 574 | } | 574 | } |
| 575 | else if (!File::Exists(dest)) File::Copy(source, dest); | 575 | else if (!FileUtil::Exists(dest)) FileUtil::Copy(source, dest); |
| 576 | } | 576 | } |
| 577 | closedir(dirp); | 577 | closedir(dirp); |
| 578 | #endif | 578 | #endif |
| @@ -660,7 +660,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new | |||
| 660 | #ifdef _WIN32 | 660 | #ifdef _WIN32 |
| 661 | paths[D_USER_IDX] = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP; | 661 | paths[D_USER_IDX] = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP; |
| 662 | #else | 662 | #else |
| 663 | if (File::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) | 663 | if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) |
| 664 | paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; | 664 | paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; |
| 665 | else | 665 | else |
| 666 | paths[D_USER_IDX] = std::string(getenv("HOME") ? | 666 | paths[D_USER_IDX] = std::string(getenv("HOME") ? |
| @@ -688,7 +688,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new | |||
| 688 | 688 | ||
| 689 | if (!newPath.empty()) | 689 | if (!newPath.empty()) |
| 690 | { | 690 | { |
| 691 | if (!File::IsDirectory(newPath)) | 691 | if (!FileUtil::IsDirectory(newPath)) |
| 692 | { | 692 | { |
| 693 | WARN_LOG(COMMON, "Invalid path specified %s", newPath.c_str()); | 693 | WARN_LOG(COMMON, "Invalid path specified %s", newPath.c_str()); |
| 694 | return paths[DirIDX]; | 694 | return paths[DirIDX]; |
| @@ -750,11 +750,11 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new | |||
| 750 | 750 | ||
| 751 | //std::string GetThemeDir(const std::string& theme_name) | 751 | //std::string GetThemeDir(const std::string& theme_name) |
| 752 | //{ | 752 | //{ |
| 753 | // std::string dir = File::GetUserPath(D_THEMES_IDX) + theme_name + "/"; | 753 | // std::string dir = FileUtil::GetUserPath(D_THEMES_IDX) + theme_name + "/"; |
| 754 | // | 754 | // |
| 755 | //#if !defined(_WIN32) | 755 | //#if !defined(_WIN32) |
| 756 | // // If theme does not exist in user's dir load from shared directory | 756 | // // If theme does not exist in user's dir load from shared directory |
| 757 | // if (!File::Exists(dir)) | 757 | // if (!FileUtil::Exists(dir)) |
| 758 | // dir = SHARED_USER_DIR THEMES_DIR "/" + theme_name + "/"; | 758 | // dir = SHARED_USER_DIR THEMES_DIR "/" + theme_name + "/"; |
| 759 | //#endif | 759 | //#endif |
| 760 | // | 760 | // |
| @@ -763,12 +763,12 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new | |||
| 763 | 763 | ||
| 764 | bool WriteStringToFile(bool text_file, const std::string &str, const char *filename) | 764 | bool WriteStringToFile(bool text_file, const std::string &str, const char *filename) |
| 765 | { | 765 | { |
| 766 | return File::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size()); | 766 | return FileUtil::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size()); |
| 767 | } | 767 | } |
| 768 | 768 | ||
| 769 | bool ReadFileToString(bool text_file, const char *filename, std::string &str) | 769 | bool ReadFileToString(bool text_file, const char *filename, std::string &str) |
| 770 | { | 770 | { |
| 771 | File::IOFile file(filename, text_file ? "r" : "rb"); | 771 | FileUtil::IOFile file(filename, text_file ? "r" : "rb"); |
| 772 | auto const f = file.GetHandle(); | 772 | auto const f = file.GetHandle(); |
| 773 | 773 | ||
| 774 | if (!f) | 774 | if (!f) |
| @@ -854,7 +854,7 @@ void IOFile::SetHandle(std::FILE* file) | |||
| 854 | u64 IOFile::GetSize() | 854 | u64 IOFile::GetSize() |
| 855 | { | 855 | { |
| 856 | if (IsOpen()) | 856 | if (IsOpen()) |
| 857 | return File::GetSize(m_file); | 857 | return FileUtil::GetSize(m_file); |
| 858 | else | 858 | else |
| 859 | return 0; | 859 | return 0; |
| 860 | } | 860 | } |
diff --git a/src/common/file_util.h b/src/common/file_util.h index fdae5c9c8..897cbd77e 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h | |||
| @@ -43,7 +43,7 @@ enum { | |||
| 43 | NUM_PATH_INDICES | 43 | NUM_PATH_INDICES |
| 44 | }; | 44 | }; |
| 45 | 45 | ||
| 46 | namespace File | 46 | namespace FileUtil |
| 47 | { | 47 | { |
| 48 | 48 | ||
| 49 | // FileSystem tree node/ | 49 | // FileSystem tree node/ |
| @@ -151,29 +151,41 @@ public: | |||
| 151 | bool Close(); | 151 | bool Close(); |
| 152 | 152 | ||
| 153 | template <typename T> | 153 | template <typename T> |
| 154 | bool ReadArray(T* data, size_t length) | 154 | size_t ReadArray(T* data, size_t length) |
| 155 | { | 155 | { |
| 156 | if (!IsOpen() || length != std::fread(data, sizeof(T), length, m_file)) | 156 | if (!IsOpen()) { |
| 157 | m_good = false; | 157 | m_good = false; |
| 158 | return -1; | ||
| 159 | } | ||
| 158 | 160 | ||
| 159 | return m_good; | 161 | size_t items_read = std::fread(data, sizeof(T), length, m_file); |
| 162 | if (items_read != length) | ||
| 163 | m_good = false; | ||
| 164 | |||
| 165 | return items_read; | ||
| 160 | } | 166 | } |
| 161 | 167 | ||
| 162 | template <typename T> | 168 | template <typename T> |
| 163 | bool WriteArray(const T* data, size_t length) | 169 | size_t WriteArray(const T* data, size_t length) |
| 164 | { | 170 | { |
| 165 | if (!IsOpen() || length != std::fwrite(data, sizeof(T), length, m_file)) | 171 | if (!IsOpen()) { |
| 172 | m_good = false; | ||
| 173 | return -1; | ||
| 174 | } | ||
| 175 | |||
| 176 | size_t items_written = std::fwrite(data, sizeof(T), length, m_file); | ||
| 177 | if (items_written != length) | ||
| 166 | m_good = false; | 178 | m_good = false; |
| 167 | 179 | ||
| 168 | return m_good; | 180 | return items_written; |
| 169 | } | 181 | } |
| 170 | 182 | ||
| 171 | bool ReadBytes(void* data, size_t length) | 183 | size_t ReadBytes(void* data, size_t length) |
| 172 | { | 184 | { |
| 173 | return ReadArray(reinterpret_cast<char*>(data), length); | 185 | return ReadArray(reinterpret_cast<char*>(data), length); |
| 174 | } | 186 | } |
| 175 | 187 | ||
| 176 | bool WriteBytes(const void* data, size_t length) | 188 | size_t WriteBytes(const void* data, size_t length) |
| 177 | { | 189 | { |
| 178 | return WriteArray(reinterpret_cast<const char*>(data), length); | 190 | return WriteArray(reinterpret_cast<const char*>(data), length); |
| 179 | } | 191 | } |
diff --git a/src/common/log_manager.cpp b/src/common/log_manager.cpp index 43346f279..28b72fa20 100644 --- a/src/common/log_manager.cpp +++ b/src/common/log_manager.cpp | |||
| @@ -75,7 +75,7 @@ LogManager::LogManager() | |||
| 75 | m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager"); | 75 | m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager"); |
| 76 | m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay"); | 76 | m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay"); |
| 77 | 77 | ||
| 78 | m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str()); | 78 | m_fileLog = new FileLogListener(FileUtil::GetUserPath(F_MAINLOG_IDX).c_str()); |
| 79 | m_consoleLog = new ConsoleListener(); | 79 | m_consoleLog = new ConsoleListener(); |
| 80 | m_debuggerLog = new DebuggerLogListener(); | 80 | m_debuggerLog = new DebuggerLogListener(); |
| 81 | 81 | ||
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 1f358ec8d..2b26292fd 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -23,6 +23,11 @@ set(SRCS | |||
| 23 | arm/interpreter/armvirt.cpp | 23 | arm/interpreter/armvirt.cpp |
| 24 | arm/interpreter/thumbemu.cpp | 24 | arm/interpreter/thumbemu.cpp |
| 25 | file_sys/archive_romfs.cpp | 25 | file_sys/archive_romfs.cpp |
| 26 | file_sys/archive_sdmc.cpp | ||
| 27 | file_sys/file_romfs.cpp | ||
| 28 | file_sys/file_sdmc.cpp | ||
| 29 | file_sys/directory_romfs.cpp | ||
| 30 | file_sys/directory_sdmc.cpp | ||
| 26 | hle/kernel/address_arbiter.cpp | 31 | hle/kernel/address_arbiter.cpp |
| 27 | hle/kernel/archive.cpp | 32 | hle/kernel/archive.cpp |
| 28 | hle/kernel/event.cpp | 33 | hle/kernel/event.cpp |
| @@ -77,6 +82,13 @@ set(HEADERS | |||
| 77 | arm/arm_interface.h | 82 | arm/arm_interface.h |
| 78 | file_sys/archive.h | 83 | file_sys/archive.h |
| 79 | file_sys/archive_romfs.h | 84 | file_sys/archive_romfs.h |
| 85 | file_sys/archive_sdmc.h | ||
| 86 | file_sys/file.h | ||
| 87 | file_sys/file_romfs.h | ||
| 88 | file_sys/file_sdmc.h | ||
| 89 | file_sys/directory.h | ||
| 90 | file_sys/directory_romfs.h | ||
| 91 | file_sys/directory_sdmc.h | ||
| 80 | hle/kernel/address_arbiter.h | 92 | hle/kernel/address_arbiter.h |
| 81 | hle/kernel/archive.h | 93 | hle/kernel/archive.h |
| 82 | hle/kernel/event.h | 94 | hle/kernel/event.h |
diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h index ac5630bea..560db6dea 100644 --- a/src/core/file_sys/archive.h +++ b/src/core/file_sys/archive.h | |||
| @@ -4,7 +4,13 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | ||
| 8 | |||
| 7 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/bit_field.h" | ||
| 11 | |||
| 12 | #include "core/file_sys/file.h" | ||
| 13 | #include "core/file_sys/directory.h" | ||
| 8 | 14 | ||
| 9 | #include "core/hle/kernel/kernel.h" | 15 | #include "core/hle/kernel/kernel.h" |
| 10 | 16 | ||
| @@ -13,6 +19,13 @@ | |||
| 13 | 19 | ||
| 14 | namespace FileSys { | 20 | namespace FileSys { |
| 15 | 21 | ||
| 22 | union Mode { | ||
| 23 | u32 hex; | ||
| 24 | BitField<0, 1, u32> read_flag; | ||
| 25 | BitField<1, 1, u32> write_flag; | ||
| 26 | BitField<2, 1, u32> create_flag; | ||
| 27 | }; | ||
| 28 | |||
| 16 | class Archive : NonCopyable { | 29 | class Archive : NonCopyable { |
| 17 | public: | 30 | public: |
| 18 | /// Supported archive types | 31 | /// Supported archive types |
| @@ -36,6 +49,21 @@ public: | |||
| 36 | virtual IdCode GetIdCode() const = 0; | 49 | virtual IdCode GetIdCode() const = 0; |
| 37 | 50 | ||
| 38 | /** | 51 | /** |
| 52 | * Open a file specified by its path, using the specified mode | ||
| 53 | * @param path Path relative to the archive | ||
| 54 | * @param mode Mode to open the file with | ||
| 55 | * @return Opened file, or nullptr | ||
| 56 | */ | ||
| 57 | virtual std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const = 0; | ||
| 58 | |||
| 59 | /** | ||
| 60 | * Open a directory specified by its path | ||
| 61 | * @param path Path relative to the archive | ||
| 62 | * @return Opened directory, or nullptr | ||
| 63 | */ | ||
| 64 | virtual std::unique_ptr<Directory> OpenDirectory(const std::string& path) const = 0; | ||
| 65 | |||
| 66 | /** | ||
| 39 | * Read data from the archive | 67 | * Read data from the archive |
| 40 | * @param offset Offset in bytes to start reading data from | 68 | * @param offset Offset in bytes to start reading data from |
| 41 | * @param length Length in bytes of data to read from archive | 69 | * @param length Length in bytes of data to read from archive |
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index dc3fb1807..9bab3471f 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| 6 | 6 | ||
| 7 | #include "core/file_sys/archive_romfs.h" | 7 | #include "core/file_sys/archive_romfs.h" |
| 8 | #include "core/file_sys/directory_romfs.h" | ||
| 9 | #include "core/file_sys/file_romfs.h" | ||
| 8 | 10 | ||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 10 | // FileSys namespace | 12 | // FileSys namespace |
| @@ -22,6 +24,25 @@ Archive_RomFS::~Archive_RomFS() { | |||
| 22 | } | 24 | } |
| 23 | 25 | ||
| 24 | /** | 26 | /** |
| 27 | * Open a file specified by its path, using the specified mode | ||
| 28 | * @param path Path relative to the archive | ||
| 29 | * @param mode Mode to open the file with | ||
| 30 | * @return Opened file, or nullptr | ||
| 31 | */ | ||
| 32 | std::unique_ptr<File> Archive_RomFS::OpenFile(const std::string& path, const Mode mode) const { | ||
| 33 | return std::unique_ptr<File>(new File_RomFS); | ||
| 34 | } | ||
| 35 | |||
| 36 | /** | ||
| 37 | * Open a directory specified by its path | ||
| 38 | * @param path Path relative to the archive | ||
| 39 | * @return Opened directory, or nullptr | ||
| 40 | */ | ||
| 41 | std::unique_ptr<Directory> Archive_RomFS::OpenDirectory(const std::string& path) const { | ||
| 42 | return std::unique_ptr<Directory>(new Directory_RomFS); | ||
| 43 | } | ||
| 44 | |||
| 45 | /** | ||
| 25 | * Read data from the archive | 46 | * Read data from the archive |
| 26 | * @param offset Offset in bytes to start reading data from | 47 | * @param offset Offset in bytes to start reading data from |
| 27 | * @param length Length in bytes of data to read from archive | 48 | * @param length Length in bytes of data to read from archive |
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h index e9ed6f77a..fcdefa95f 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h | |||
| @@ -29,6 +29,21 @@ public: | |||
| 29 | IdCode GetIdCode() const override { return IdCode::RomFS; }; | 29 | IdCode GetIdCode() const override { return IdCode::RomFS; }; |
| 30 | 30 | ||
| 31 | /** | 31 | /** |
| 32 | * Open a file specified by its path, using the specified mode | ||
| 33 | * @param path Path relative to the archive | ||
| 34 | * @param mode Mode to open the file with | ||
| 35 | * @return Opened file, or nullptr | ||
| 36 | */ | ||
| 37 | std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override; | ||
| 38 | |||
| 39 | /** | ||
| 40 | * Open a directory specified by its path | ||
| 41 | * @param path Path relative to the archive | ||
| 42 | * @return Opened directory, or nullptr | ||
| 43 | */ | ||
| 44 | std::unique_ptr<Directory> OpenDirectory(const std::string& path) const override; | ||
| 45 | |||
| 46 | /** | ||
| 32 | * Read data from the archive | 47 | * Read data from the archive |
| 33 | * @param offset Offset in bytes to start reading data from | 48 | * @param offset Offset in bytes to start reading data from |
| 34 | * @param length Length in bytes of data to read from archive | 49 | * @param length Length in bytes of data to read from archive |
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp new file mode 100644 index 000000000..30d33be5f --- /dev/null +++ b/src/core/file_sys/archive_sdmc.cpp | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <sys/stat.h> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/archive_sdmc.h" | ||
| 11 | #include "core/file_sys/directory_sdmc.h" | ||
| 12 | #include "core/file_sys/file_sdmc.h" | ||
| 13 | |||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 15 | // FileSys namespace | ||
| 16 | |||
| 17 | namespace FileSys { | ||
| 18 | |||
| 19 | Archive_SDMC::Archive_SDMC(const std::string& mount_point) { | ||
| 20 | this->mount_point = mount_point; | ||
| 21 | DEBUG_LOG(FILESYS, "Directory %s set as SDMC.", mount_point.c_str()); | ||
| 22 | } | ||
| 23 | |||
| 24 | Archive_SDMC::~Archive_SDMC() { | ||
| 25 | } | ||
| 26 | |||
| 27 | bool Archive_SDMC::Initialize() { | ||
| 28 | if (!FileUtil::IsDirectory(mount_point)) { | ||
| 29 | WARN_LOG(FILESYS, "Directory %s not found, disabling SDMC.", mount_point.c_str()); | ||
| 30 | return false; | ||
| 31 | } | ||
| 32 | |||
| 33 | return true; | ||
| 34 | } | ||
| 35 | |||
| 36 | /** | ||
| 37 | * Open a file specified by its path, using the specified mode | ||
| 38 | * @param path Path relative to the archive | ||
| 39 | * @param mode Mode to open the file with | ||
| 40 | * @return Opened file, or nullptr | ||
| 41 | */ | ||
| 42 | std::unique_ptr<File> Archive_SDMC::OpenFile(const std::string& path, const Mode mode) const { | ||
| 43 | DEBUG_LOG(FILESYS, "called path=%s mode=%d", path.c_str(), mode); | ||
| 44 | File_SDMC* file = new File_SDMC(this, path, mode); | ||
| 45 | return std::unique_ptr<File>(file); | ||
| 46 | } | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Open a directory specified by its path | ||
| 50 | * @param path Path relative to the archive | ||
| 51 | * @return Opened directory, or nullptr | ||
| 52 | */ | ||
| 53 | std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const std::string& path) const { | ||
| 54 | DEBUG_LOG(FILESYS, "called path=%s", path.c_str()); | ||
| 55 | Directory_SDMC* directory = new Directory_SDMC(this, path); | ||
| 56 | return std::unique_ptr<Directory>(directory); | ||
| 57 | } | ||
| 58 | |||
| 59 | /** | ||
| 60 | * Read data from the archive | ||
| 61 | * @param offset Offset in bytes to start reading archive from | ||
| 62 | * @param length Length in bytes to read data from archive | ||
| 63 | * @param buffer Buffer to read data into | ||
| 64 | * @return Number of bytes read | ||
| 65 | */ | ||
| 66 | size_t Archive_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const { | ||
| 67 | ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||
| 68 | return -1; | ||
| 69 | } | ||
| 70 | |||
| 71 | /** | ||
| 72 | * Write data to the archive | ||
| 73 | * @param offset Offset in bytes to start writing data to | ||
| 74 | * @param length Length in bytes of data to write to archive | ||
| 75 | * @param buffer Buffer to write data from | ||
| 76 | * @param flush The flush parameters (0 == do not flush) | ||
| 77 | * @return Number of bytes written | ||
| 78 | */ | ||
| 79 | size_t Archive_SDMC::Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) { | ||
| 80 | ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||
| 81 | return -1; | ||
| 82 | } | ||
| 83 | |||
| 84 | /** | ||
| 85 | * Get the size of the archive in bytes | ||
| 86 | * @return Size of the archive in bytes | ||
| 87 | */ | ||
| 88 | size_t Archive_SDMC::GetSize() const { | ||
| 89 | ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | /** | ||
| 94 | * Set the size of the archive in bytes | ||
| 95 | */ | ||
| 96 | void Archive_SDMC::SetSize(const u64 size) { | ||
| 97 | ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||
| 98 | } | ||
| 99 | |||
| 100 | /** | ||
| 101 | * Getter for the path used for this Archive | ||
| 102 | * @return Mount point of that passthrough archive | ||
| 103 | */ | ||
| 104 | std::string Archive_SDMC::GetMountPoint() const { | ||
| 105 | return mount_point; | ||
| 106 | } | ||
| 107 | |||
| 108 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h new file mode 100644 index 000000000..946f8b957 --- /dev/null +++ b/src/core/file_sys/archive_sdmc.h | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "core/file_sys/archive.h" | ||
| 10 | #include "core/loader/loader.h" | ||
| 11 | |||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 13 | // FileSys namespace | ||
| 14 | |||
| 15 | namespace FileSys { | ||
| 16 | |||
| 17 | /// File system interface to the SDMC archive | ||
| 18 | class Archive_SDMC final : public Archive { | ||
| 19 | public: | ||
| 20 | Archive_SDMC(const std::string& mount_point); | ||
| 21 | ~Archive_SDMC() override; | ||
| 22 | |||
| 23 | bool Initialize(); | ||
| 24 | |||
| 25 | /** | ||
| 26 | * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) | ||
| 27 | * @return IdCode of the archive | ||
| 28 | */ | ||
| 29 | IdCode GetIdCode() const override { return IdCode::SDMC; }; | ||
| 30 | |||
| 31 | /** | ||
| 32 | * Open a file specified by its path, using the specified mode | ||
| 33 | * @param path Path relative to the archive | ||
| 34 | * @param mode Mode to open the file with | ||
| 35 | * @return Opened file, or nullptr | ||
| 36 | */ | ||
| 37 | std::unique_ptr<File> OpenFile(const std::string& path, const Mode mode) const override; | ||
| 38 | |||
| 39 | /** | ||
| 40 | * Open a directory specified by its path | ||
| 41 | * @param path Path relative to the archive | ||
| 42 | * @return Opened directory, or nullptr | ||
| 43 | */ | ||
| 44 | std::unique_ptr<Directory> OpenDirectory(const std::string& path) const override; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Read data from the archive | ||
| 48 | * @param offset Offset in bytes to start reading archive from | ||
| 49 | * @param length Length in bytes to read data from archive | ||
| 50 | * @param buffer Buffer to read data into | ||
| 51 | * @return Number of bytes read | ||
| 52 | */ | ||
| 53 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||
| 54 | |||
| 55 | /** | ||
| 56 | * Write data to the archive | ||
| 57 | * @param offset Offset in bytes to start writing data to | ||
| 58 | * @param length Length in bytes of data to write to archive | ||
| 59 | * @param buffer Buffer to write data from | ||
| 60 | * @param flush The flush parameters (0 == do not flush) | ||
| 61 | * @return Number of bytes written | ||
| 62 | */ | ||
| 63 | size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) override; | ||
| 64 | |||
| 65 | /** | ||
| 66 | * Get the size of the archive in bytes | ||
| 67 | * @return Size of the archive in bytes | ||
| 68 | */ | ||
| 69 | size_t GetSize() const override; | ||
| 70 | |||
| 71 | /** | ||
| 72 | * Set the size of the archive in bytes | ||
| 73 | */ | ||
| 74 | void SetSize(const u64 size) override; | ||
| 75 | |||
| 76 | /** | ||
| 77 | * Getter for the path used for this Archive | ||
| 78 | * @return Mount point of that passthrough archive | ||
| 79 | */ | ||
| 80 | std::string GetMountPoint() const; | ||
| 81 | |||
| 82 | private: | ||
| 83 | std::string mount_point; | ||
| 84 | }; | ||
| 85 | |||
| 86 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory.h new file mode 100644 index 000000000..cf9a2010b --- /dev/null +++ b/src/core/file_sys/directory.h | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "core/hle/kernel/kernel.h" | ||
| 10 | |||
| 11 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 12 | // FileSys namespace | ||
| 13 | |||
| 14 | namespace FileSys { | ||
| 15 | |||
| 16 | // Structure of a directory entry, from http://3dbrew.org/wiki/FSDir:Read#Entry_format | ||
| 17 | const size_t FILENAME_LENGTH = 0x20C / 2; | ||
| 18 | struct Entry { | ||
| 19 | char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) | ||
| 20 | char short_name[8]; // 8.3 file name ('longfilename' -> 'LONGFI~1') | ||
| 21 | char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) | ||
| 22 | char extension[3]; // 8.3 file extension (set to spaces for directories) | ||
| 23 | char unknown2; // unknown (always 0x01) | ||
| 24 | char unknown3; // unknown (0x00 or 0x08) | ||
| 25 | char is_directory; // directory flag | ||
| 26 | char is_hidden; // hidden flag | ||
| 27 | char is_archive; // archive flag | ||
| 28 | char is_read_only; // read-only flag | ||
| 29 | u64 file_size; // file size (for files only) | ||
| 30 | }; | ||
| 31 | static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); | ||
| 32 | |||
| 33 | class Directory : NonCopyable { | ||
| 34 | public: | ||
| 35 | Directory() { } | ||
| 36 | virtual ~Directory() { } | ||
| 37 | |||
| 38 | /** | ||
| 39 | * List files contained in the directory | ||
| 40 | * @param count Number of entries to return at once in entries | ||
| 41 | * @param entries Buffer to read data into | ||
| 42 | * @return Number of entries listed | ||
| 43 | */ | ||
| 44 | virtual u32 Read(const u32 count, Entry* entries) = 0; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Close the directory | ||
| 48 | * @return true if the directory closed correctly | ||
| 49 | */ | ||
| 50 | virtual bool Close() const = 0; | ||
| 51 | }; | ||
| 52 | |||
| 53 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/directory_romfs.cpp b/src/core/file_sys/directory_romfs.cpp new file mode 100644 index 000000000..4e8f4c04d --- /dev/null +++ b/src/core/file_sys/directory_romfs.cpp | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/common_types.h" | ||
| 6 | |||
| 7 | #include "core/file_sys/directory_romfs.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // FileSys namespace | ||
| 11 | |||
| 12 | namespace FileSys { | ||
| 13 | |||
| 14 | Directory_RomFS::Directory_RomFS() { | ||
| 15 | } | ||
| 16 | |||
| 17 | Directory_RomFS::~Directory_RomFS() { | ||
| 18 | } | ||
| 19 | |||
| 20 | /** | ||
| 21 | * List files contained in the directory | ||
| 22 | * @param count Number of entries to return at once in entries | ||
| 23 | * @param entries Buffer to read data into | ||
| 24 | * @return Number of entries listed | ||
| 25 | */ | ||
| 26 | u32 Directory_RomFS::Read(const u32 count, Entry* entries) { | ||
| 27 | return 0; | ||
| 28 | } | ||
| 29 | |||
| 30 | /** | ||
| 31 | * Close the directory | ||
| 32 | * @return true if the directory closed correctly | ||
| 33 | */ | ||
| 34 | bool Directory_RomFS::Close() const { | ||
| 35 | return false; | ||
| 36 | } | ||
| 37 | |||
| 38 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/directory_romfs.h b/src/core/file_sys/directory_romfs.h new file mode 100644 index 000000000..4b71c4b13 --- /dev/null +++ b/src/core/file_sys/directory_romfs.h | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "core/file_sys/directory.h" | ||
| 10 | #include "core/loader/loader.h" | ||
| 11 | |||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 13 | // FileSys namespace | ||
| 14 | |||
| 15 | namespace FileSys { | ||
| 16 | |||
| 17 | class Directory_RomFS final : public Directory { | ||
| 18 | public: | ||
| 19 | Directory_RomFS(); | ||
| 20 | ~Directory_RomFS() override; | ||
| 21 | |||
| 22 | /** | ||
| 23 | * List files contained in the directory | ||
| 24 | * @param count Number of entries to return at once in entries | ||
| 25 | * @param entries Buffer to read data into | ||
| 26 | * @return Number of entries listed | ||
| 27 | */ | ||
| 28 | u32 Read(const u32 count, Entry* entries) override; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * Close the directory | ||
| 32 | * @return true if the directory closed correctly | ||
| 33 | */ | ||
| 34 | bool Close() const override; | ||
| 35 | }; | ||
| 36 | |||
| 37 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/directory_sdmc.cpp b/src/core/file_sys/directory_sdmc.cpp new file mode 100644 index 000000000..11e867857 --- /dev/null +++ b/src/core/file_sys/directory_sdmc.cpp | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <sys/stat.h> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/directory_sdmc.h" | ||
| 11 | #include "core/file_sys/archive_sdmc.h" | ||
| 12 | |||
| 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 14 | // FileSys namespace | ||
| 15 | |||
| 16 | namespace FileSys { | ||
| 17 | |||
| 18 | Directory_SDMC::Directory_SDMC(const Archive_SDMC* archive, const std::string& path) { | ||
| 19 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | ||
| 20 | // the root directory we set while opening the archive. | ||
| 21 | // For example, opening /../../usr/bin can give the emulated program your installed programs. | ||
| 22 | std::string absolute_path = archive->GetMountPoint() + path; | ||
| 23 | entry_count = FileUtil::ScanDirectoryTree(absolute_path, entry); | ||
| 24 | current_entry = 0; | ||
| 25 | } | ||
| 26 | |||
| 27 | Directory_SDMC::~Directory_SDMC() { | ||
| 28 | Close(); | ||
| 29 | } | ||
| 30 | |||
| 31 | /** | ||
| 32 | * List files contained in the directory | ||
| 33 | * @param count Number of entries to return at once in entries | ||
| 34 | * @param entries Buffer to read data into | ||
| 35 | * @return Number of entries listed | ||
| 36 | */ | ||
| 37 | u32 Directory_SDMC::Read(const u32 count, Entry* entries) { | ||
| 38 | u32 i; | ||
| 39 | for (i = 0; i < count && current_entry < entry_count; ++i) { | ||
| 40 | FileUtil::FSTEntry file = entry.children[current_entry]; | ||
| 41 | std::string filename = file.virtualName; | ||
| 42 | WARN_LOG(FILESYS, "File %s: size=%d dir=%d", filename.c_str(), file.size, file.isDirectory); | ||
| 43 | |||
| 44 | Entry* entry = &entries[i]; | ||
| 45 | |||
| 46 | // TODO(Link Mauve): use a proper conversion to UTF-16. | ||
| 47 | for (int j = 0; j < FILENAME_LENGTH; ++j) { | ||
| 48 | entry->filename[j] = filename[j]; | ||
| 49 | if (!filename[j]) | ||
| 50 | break; | ||
| 51 | } | ||
| 52 | |||
| 53 | // Split the filename into 8.3 format. | ||
| 54 | // TODO(Link Mauve): move that to common, I guess, and make it more robust to long filenames. | ||
| 55 | std::string::size_type n = filename.rfind('.'); | ||
| 56 | if (n == std::string::npos) { | ||
| 57 | strncpy(entry->short_name, filename.c_str(), 8); | ||
| 58 | memset(entry->extension, '\0', 3); | ||
| 59 | } else { | ||
| 60 | strncpy(entry->short_name, filename.substr(0, n).c_str(), 8); | ||
| 61 | strncpy(entry->extension, filename.substr(n + 1).c_str(), 8); | ||
| 62 | } | ||
| 63 | |||
| 64 | entry->is_directory = file.isDirectory; | ||
| 65 | entry->file_size = file.size; | ||
| 66 | |||
| 67 | // We emulate a SD card where the archive bit has never been cleared, as it would be on | ||
| 68 | // most user SD cards. | ||
| 69 | // Some homebrews (blargSNES for instance) are known to mistakenly use the archive bit as a | ||
| 70 | // file bit. | ||
| 71 | entry->is_archive = !file.isDirectory; | ||
| 72 | |||
| 73 | ++current_entry; | ||
| 74 | } | ||
| 75 | return i; | ||
| 76 | } | ||
| 77 | |||
| 78 | /** | ||
| 79 | * Close the directory | ||
| 80 | * @return true if the directory closed correctly | ||
| 81 | */ | ||
| 82 | bool Directory_SDMC::Close() const { | ||
| 83 | return true; | ||
| 84 | } | ||
| 85 | |||
| 86 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/directory_sdmc.h b/src/core/file_sys/directory_sdmc.h new file mode 100644 index 000000000..0bc6c9eff --- /dev/null +++ b/src/core/file_sys/directory_sdmc.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/directory.h" | ||
| 11 | #include "core/file_sys/archive_sdmc.h" | ||
| 12 | #include "core/loader/loader.h" | ||
| 13 | |||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 15 | // FileSys namespace | ||
| 16 | |||
| 17 | namespace FileSys { | ||
| 18 | |||
| 19 | class Directory_SDMC final : public Directory { | ||
| 20 | public: | ||
| 21 | Directory_SDMC(); | ||
| 22 | Directory_SDMC(const Archive_SDMC* archive, const std::string& path); | ||
| 23 | ~Directory_SDMC() override; | ||
| 24 | |||
| 25 | /** | ||
| 26 | * List files contained in the directory | ||
| 27 | * @param count Number of entries to return at once in entries | ||
| 28 | * @param entries Buffer to read data into | ||
| 29 | * @return Number of entries listed | ||
| 30 | */ | ||
| 31 | u32 Read(const u32 count, Entry* entries) override; | ||
| 32 | |||
| 33 | /** | ||
| 34 | * Close the directory | ||
| 35 | * @return true if the directory closed correctly | ||
| 36 | */ | ||
| 37 | bool Close() const override; | ||
| 38 | |||
| 39 | private: | ||
| 40 | u32 entry_count; | ||
| 41 | u32 current_entry; | ||
| 42 | FileUtil::FSTEntry entry; | ||
| 43 | }; | ||
| 44 | |||
| 45 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/file.h b/src/core/file_sys/file.h new file mode 100644 index 000000000..f7b009f5a --- /dev/null +++ b/src/core/file_sys/file.h | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "core/hle/kernel/kernel.h" | ||
| 10 | |||
| 11 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 12 | // FileSys namespace | ||
| 13 | |||
| 14 | namespace FileSys { | ||
| 15 | |||
| 16 | class File : NonCopyable { | ||
| 17 | public: | ||
| 18 | File() { } | ||
| 19 | virtual ~File() { } | ||
| 20 | |||
| 21 | /** | ||
| 22 | * Read data from the file | ||
| 23 | * @param offset Offset in bytes to start reading data from | ||
| 24 | * @param length Length in bytes of data to read from file | ||
| 25 | * @param buffer Buffer to read data into | ||
| 26 | * @return Number of bytes read | ||
| 27 | */ | ||
| 28 | virtual size_t Read(const u64 offset, const u32 length, u8* buffer) const = 0; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * Write data to the file | ||
| 32 | * @param offset Offset in bytes to start writing data to | ||
| 33 | * @param length Length in bytes of data to write to file | ||
| 34 | * @param buffer Buffer to write data from | ||
| 35 | * @param flush The flush parameters (0 == do not flush) | ||
| 36 | * @return Number of bytes written | ||
| 37 | */ | ||
| 38 | virtual size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const = 0; | ||
| 39 | |||
| 40 | /** | ||
| 41 | * Get the size of the file in bytes | ||
| 42 | * @return Size of the file in bytes | ||
| 43 | */ | ||
| 44 | virtual size_t GetSize() const = 0; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Close the file | ||
| 48 | * @return true if the file closed correctly | ||
| 49 | */ | ||
| 50 | virtual bool Close() const = 0; | ||
| 51 | }; | ||
| 52 | |||
| 53 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/file_romfs.cpp b/src/core/file_sys/file_romfs.cpp new file mode 100644 index 000000000..00f3c2ea8 --- /dev/null +++ b/src/core/file_sys/file_romfs.cpp | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/common_types.h" | ||
| 6 | |||
| 7 | #include "core/file_sys/file_romfs.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // FileSys namespace | ||
| 11 | |||
| 12 | namespace FileSys { | ||
| 13 | |||
| 14 | File_RomFS::File_RomFS() { | ||
| 15 | } | ||
| 16 | |||
| 17 | File_RomFS::~File_RomFS() { | ||
| 18 | } | ||
| 19 | |||
| 20 | /** | ||
| 21 | * Read data from the file | ||
| 22 | * @param offset Offset in bytes to start reading data from | ||
| 23 | * @param length Length in bytes of data to read from file | ||
| 24 | * @param buffer Buffer to read data into | ||
| 25 | * @return Number of bytes read | ||
| 26 | */ | ||
| 27 | size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { | ||
| 28 | return -1; | ||
| 29 | } | ||
| 30 | |||
| 31 | /** | ||
| 32 | * Write data to the file | ||
| 33 | * @param offset Offset in bytes to start writing data to | ||
| 34 | * @param length Length in bytes of data to write to file | ||
| 35 | * @param buffer Buffer to write data from | ||
| 36 | * @param flush The flush parameters (0 == do not flush) | ||
| 37 | * @return Number of bytes written | ||
| 38 | */ | ||
| 39 | size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | ||
| 40 | return -1; | ||
| 41 | } | ||
| 42 | |||
| 43 | /** | ||
| 44 | * Get the size of the file in bytes | ||
| 45 | * @return Size of the file in bytes | ||
| 46 | */ | ||
| 47 | size_t File_RomFS::GetSize() const { | ||
| 48 | return -1; | ||
| 49 | } | ||
| 50 | |||
| 51 | /** | ||
| 52 | * Close the file | ||
| 53 | * @return true if the file closed correctly | ||
| 54 | */ | ||
| 55 | bool File_RomFS::Close() const { | ||
| 56 | return false; | ||
| 57 | } | ||
| 58 | |||
| 59 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/file_romfs.h b/src/core/file_sys/file_romfs.h new file mode 100644 index 000000000..5db43d4a0 --- /dev/null +++ b/src/core/file_sys/file_romfs.h | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "core/file_sys/file.h" | ||
| 10 | #include "core/loader/loader.h" | ||
| 11 | |||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 13 | // FileSys namespace | ||
| 14 | |||
| 15 | namespace FileSys { | ||
| 16 | |||
| 17 | class File_RomFS final : public File { | ||
| 18 | public: | ||
| 19 | File_RomFS(); | ||
| 20 | ~File_RomFS() override; | ||
| 21 | |||
| 22 | /** | ||
| 23 | * Read data from the file | ||
| 24 | * @param offset Offset in bytes to start reading data from | ||
| 25 | * @param length Length in bytes of data to read from file | ||
| 26 | * @param buffer Buffer to read data into | ||
| 27 | * @return Number of bytes read | ||
| 28 | */ | ||
| 29 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||
| 30 | |||
| 31 | /** | ||
| 32 | * Write data to the file | ||
| 33 | * @param offset Offset in bytes to start writing data to | ||
| 34 | * @param length Length in bytes of data to write to file | ||
| 35 | * @param buffer Buffer to write data from | ||
| 36 | * @param flush The flush parameters (0 == do not flush) | ||
| 37 | * @return Number of bytes written | ||
| 38 | */ | ||
| 39 | size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; | ||
| 40 | |||
| 41 | /** | ||
| 42 | * Get the size of the file in bytes | ||
| 43 | * @return Size of the file in bytes | ||
| 44 | */ | ||
| 45 | size_t GetSize() const override; | ||
| 46 | |||
| 47 | /** | ||
| 48 | * Close the file | ||
| 49 | * @return true if the file closed correctly | ||
| 50 | */ | ||
| 51 | bool Close() const override; | ||
| 52 | }; | ||
| 53 | |||
| 54 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/file_sdmc.cpp b/src/core/file_sys/file_sdmc.cpp new file mode 100644 index 000000000..76adc6403 --- /dev/null +++ b/src/core/file_sys/file_sdmc.cpp | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <sys/stat.h> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/file_sdmc.h" | ||
| 11 | #include "core/file_sys/archive_sdmc.h" | ||
| 12 | |||
| 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 14 | // FileSys namespace | ||
| 15 | |||
| 16 | namespace FileSys { | ||
| 17 | |||
| 18 | File_SDMC::File_SDMC(const Archive_SDMC* archive, const std::string& path, const Mode mode) { | ||
| 19 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | ||
| 20 | // the root directory we set while opening the archive. | ||
| 21 | // For example, opening /../../etc/passwd can give the emulated program your users list. | ||
| 22 | std::string real_path = archive->GetMountPoint() + path; | ||
| 23 | |||
| 24 | if (!mode.create_flag && !FileUtil::Exists(real_path)) { | ||
| 25 | file = nullptr; | ||
| 26 | return; | ||
| 27 | } | ||
| 28 | |||
| 29 | std::string mode_string; | ||
| 30 | if (mode.read_flag) | ||
| 31 | mode_string += "r"; | ||
| 32 | if (mode.write_flag) | ||
| 33 | mode_string += "w"; | ||
| 34 | |||
| 35 | file = new FileUtil::IOFile(real_path, mode_string.c_str()); | ||
| 36 | } | ||
| 37 | |||
| 38 | File_SDMC::~File_SDMC() { | ||
| 39 | Close(); | ||
| 40 | } | ||
| 41 | |||
| 42 | size_t File_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const { | ||
| 43 | file->Seek(offset, SEEK_SET); | ||
| 44 | return file->ReadBytes(buffer, length); | ||
| 45 | } | ||
| 46 | |||
| 47 | size_t File_SDMC::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | ||
| 48 | file->Seek(offset, SEEK_SET); | ||
| 49 | size_t written = file->WriteBytes(buffer, length); | ||
| 50 | if (flush) | ||
| 51 | file->Flush(); | ||
| 52 | return written; | ||
| 53 | } | ||
| 54 | |||
| 55 | size_t File_SDMC::GetSize() const { | ||
| 56 | return file->GetSize(); | ||
| 57 | } | ||
| 58 | |||
| 59 | bool File_SDMC::Close() const { | ||
| 60 | return file->Close(); | ||
| 61 | } | ||
| 62 | |||
| 63 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/file_sdmc.h b/src/core/file_sys/file_sdmc.h new file mode 100644 index 000000000..b2e46f449 --- /dev/null +++ b/src/core/file_sys/file_sdmc.h | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/file.h" | ||
| 11 | #include "core/file_sys/archive_sdmc.h" | ||
| 12 | #include "core/loader/loader.h" | ||
| 13 | |||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 15 | // FileSys namespace | ||
| 16 | |||
| 17 | namespace FileSys { | ||
| 18 | |||
| 19 | class File_SDMC final : public File { | ||
| 20 | public: | ||
| 21 | File_SDMC(); | ||
| 22 | File_SDMC(const Archive_SDMC* archive, const std::string& path, const Mode mode); | ||
| 23 | ~File_SDMC() override; | ||
| 24 | |||
| 25 | /** | ||
| 26 | * Read data from the file | ||
| 27 | * @param offset Offset in bytes to start reading data from | ||
| 28 | * @param length Length in bytes of data to read from file | ||
| 29 | * @param buffer Buffer to read data into | ||
| 30 | * @return Number of bytes read | ||
| 31 | */ | ||
| 32 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||
| 33 | |||
| 34 | /** | ||
| 35 | * Write data to the file | ||
| 36 | * @param offset Offset in bytes to start writing data to | ||
| 37 | * @param length Length in bytes of data to write to file | ||
| 38 | * @param buffer Buffer to write data from | ||
| 39 | * @param flush The flush parameters (0 == do not flush) | ||
| 40 | * @return Number of bytes written | ||
| 41 | */ | ||
| 42 | size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; | ||
| 43 | |||
| 44 | /** | ||
| 45 | * Get the size of the file in bytes | ||
| 46 | * @return Size of the file in bytes | ||
| 47 | */ | ||
| 48 | size_t GetSize() const override; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * Close the file | ||
| 52 | * @return true if the file closed correctly | ||
| 53 | */ | ||
| 54 | bool Close() const override; | ||
| 55 | |||
| 56 | private: | ||
| 57 | FileUtil::IOFile* file; | ||
| 58 | }; | ||
| 59 | |||
| 60 | } // namespace FileSys | ||
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp index 20536f40f..a7fa661d6 100644 --- a/src/core/hle/kernel/archive.cpp +++ b/src/core/hle/kernel/archive.cpp | |||
| @@ -3,9 +3,12 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| 6 | #include "common/file_util.h" | ||
| 6 | #include "common/math_util.h" | 7 | #include "common/math_util.h" |
| 7 | 8 | ||
| 8 | #include "core/file_sys/archive.h" | 9 | #include "core/file_sys/archive.h" |
| 10 | #include "core/file_sys/archive_sdmc.h" | ||
| 11 | #include "core/file_sys/directory.h" | ||
| 9 | #include "core/hle/service/service.h" | 12 | #include "core/hle/service/service.h" |
| 10 | #include "core/hle/kernel/archive.h" | 13 | #include "core/hle/kernel/archive.h" |
| 11 | 14 | ||
| @@ -29,6 +32,14 @@ enum class FileCommand : u32 { | |||
| 29 | Flush = 0x08090000, | 32 | Flush = 0x08090000, |
| 30 | }; | 33 | }; |
| 31 | 34 | ||
| 35 | // Command to access directory | ||
| 36 | enum class DirectoryCommand : u32 { | ||
| 37 | Dummy1 = 0x000100C6, | ||
| 38 | Control = 0x040100C4, | ||
| 39 | Read = 0x08010042, | ||
| 40 | Close = 0x08020000, | ||
| 41 | }; | ||
| 42 | |||
| 32 | class Archive : public Object { | 43 | class Archive : public Object { |
| 33 | public: | 44 | public: |
| 34 | std::string GetTypeName() const { return "Archive"; } | 45 | std::string GetTypeName() const { return "Archive"; } |
| @@ -85,6 +96,13 @@ public: | |||
| 85 | backend->SetSize(cmd_buff[1] | ((u64)cmd_buff[2] << 32)); | 96 | backend->SetSize(cmd_buff[1] | ((u64)cmd_buff[2] << 32)); |
| 86 | break; | 97 | break; |
| 87 | } | 98 | } |
| 99 | case FileCommand::Close: | ||
| 100 | { | ||
| 101 | DEBUG_LOG(KERNEL, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); | ||
| 102 | Kernel::g_object_pool.Destroy<Archive>(GetHandle()); | ||
| 103 | CloseArchive(backend->GetIdCode()); | ||
| 104 | break; | ||
| 105 | } | ||
| 88 | // Unknown command... | 106 | // Unknown command... |
| 89 | default: | 107 | default: |
| 90 | { | 108 | { |
| @@ -108,6 +126,153 @@ public: | |||
| 108 | } | 126 | } |
| 109 | }; | 127 | }; |
| 110 | 128 | ||
| 129 | class File : public Object { | ||
| 130 | public: | ||
| 131 | std::string GetTypeName() const { return "File"; } | ||
| 132 | std::string GetName() const { return path; } | ||
| 133 | |||
| 134 | static Kernel::HandleType GetStaticHandleType() { return HandleType::File; } | ||
| 135 | Kernel::HandleType GetHandleType() const { return HandleType::File; } | ||
| 136 | |||
| 137 | std::string path; ///< Path of the file | ||
| 138 | std::unique_ptr<FileSys::File> backend; ///< File backend interface | ||
| 139 | |||
| 140 | /** | ||
| 141 | * Synchronize kernel object | ||
| 142 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 143 | * @return Result of operation, 0 on success, otherwise error code | ||
| 144 | */ | ||
| 145 | Result SyncRequest(bool* wait) { | ||
| 146 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 147 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | ||
| 148 | switch (cmd) { | ||
| 149 | |||
| 150 | // Read from file... | ||
| 151 | case FileCommand::Read: | ||
| 152 | { | ||
| 153 | u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32; | ||
| 154 | u32 length = cmd_buff[3]; | ||
| 155 | u32 address = cmd_buff[5]; | ||
| 156 | DEBUG_LOG(KERNEL, "Read %s %s: offset=0x%x length=%d address=0x%x", | ||
| 157 | GetTypeName().c_str(), GetName().c_str(), offset, length, address); | ||
| 158 | cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address)); | ||
| 159 | break; | ||
| 160 | } | ||
| 161 | |||
| 162 | // Write to file... | ||
| 163 | case FileCommand::Write: | ||
| 164 | { | ||
| 165 | u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32; | ||
| 166 | u32 length = cmd_buff[3]; | ||
| 167 | u32 flush = cmd_buff[4]; | ||
| 168 | u32 address = cmd_buff[6]; | ||
| 169 | DEBUG_LOG(KERNEL, "Write %s %s: offset=0x%x length=%d address=0x%x, flush=0x%x", | ||
| 170 | GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); | ||
| 171 | cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address)); | ||
| 172 | break; | ||
| 173 | } | ||
| 174 | |||
| 175 | case FileCommand::GetSize: | ||
| 176 | { | ||
| 177 | DEBUG_LOG(KERNEL, "GetSize %s %s", GetTypeName().c_str(), GetName().c_str()); | ||
| 178 | u64 size = backend->GetSize(); | ||
| 179 | cmd_buff[2] = (u32)size; | ||
| 180 | cmd_buff[3] = size >> 32; | ||
| 181 | break; | ||
| 182 | } | ||
| 183 | |||
| 184 | case FileCommand::Close: | ||
| 185 | { | ||
| 186 | DEBUG_LOG(KERNEL, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); | ||
| 187 | Kernel::g_object_pool.Destroy<File>(GetHandle()); | ||
| 188 | break; | ||
| 189 | } | ||
| 190 | |||
| 191 | // Unknown command... | ||
| 192 | default: | ||
| 193 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); | ||
| 194 | cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. | ||
| 195 | return -1; | ||
| 196 | } | ||
| 197 | cmd_buff[1] = 0; // No error | ||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | /** | ||
| 202 | * Wait for kernel object to synchronize | ||
| 203 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 204 | * @return Result of operation, 0 on success, otherwise error code | ||
| 205 | */ | ||
| 206 | Result WaitSynchronization(bool* wait) { | ||
| 207 | // TODO(bunnei): ImplementMe | ||
| 208 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | ||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | }; | ||
| 212 | |||
| 213 | class Directory : public Object { | ||
| 214 | public: | ||
| 215 | std::string GetTypeName() const { return "Directory"; } | ||
| 216 | std::string GetName() const { return path; } | ||
| 217 | |||
| 218 | static Kernel::HandleType GetStaticHandleType() { return HandleType::Directory; } | ||
| 219 | Kernel::HandleType GetHandleType() const { return HandleType::Directory; } | ||
| 220 | |||
| 221 | std::string path; ///< Path of the directory | ||
| 222 | std::unique_ptr<FileSys::Directory> backend; ///< File backend interface | ||
| 223 | |||
| 224 | /** | ||
| 225 | * Synchronize kernel object | ||
| 226 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 227 | * @return Result of operation, 0 on success, otherwise error code | ||
| 228 | */ | ||
| 229 | Result SyncRequest(bool* wait) { | ||
| 230 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 231 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); | ||
| 232 | switch (cmd) { | ||
| 233 | |||
| 234 | // Read from directory... | ||
| 235 | case DirectoryCommand::Read: | ||
| 236 | { | ||
| 237 | u32 count = cmd_buff[1]; | ||
| 238 | u32 address = cmd_buff[3]; | ||
| 239 | FileSys::Entry* entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); | ||
| 240 | DEBUG_LOG(KERNEL, "Read %s %s: count=%d", GetTypeName().c_str(), GetName().c_str(), count); | ||
| 241 | |||
| 242 | // Number of entries actually read | ||
| 243 | cmd_buff[2] = backend->Read(count, entries); | ||
| 244 | break; | ||
| 245 | } | ||
| 246 | |||
| 247 | case DirectoryCommand::Close: | ||
| 248 | { | ||
| 249 | DEBUG_LOG(KERNEL, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); | ||
| 250 | Kernel::g_object_pool.Destroy<Directory>(GetHandle()); | ||
| 251 | break; | ||
| 252 | } | ||
| 253 | |||
| 254 | // Unknown command... | ||
| 255 | default: | ||
| 256 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); | ||
| 257 | cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. | ||
| 258 | return -1; | ||
| 259 | } | ||
| 260 | cmd_buff[1] = 0; // No error | ||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | /** | ||
| 265 | * Wait for kernel object to synchronize | ||
| 266 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 267 | * @return Result of operation, 0 on success, otherwise error code | ||
| 268 | */ | ||
| 269 | Result WaitSynchronization(bool* wait) { | ||
| 270 | // TODO(bunnei): ImplementMe | ||
| 271 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | ||
| 272 | return 0; | ||
| 273 | } | ||
| 274 | }; | ||
| 275 | |||
| 111 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 276 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 112 | 277 | ||
| 113 | std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode | 278 | std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode |
| @@ -126,6 +291,21 @@ Handle OpenArchive(FileSys::Archive::IdCode id_code) { | |||
| 126 | } | 291 | } |
| 127 | 292 | ||
| 128 | /** | 293 | /** |
| 294 | * Closes an archive | ||
| 295 | * @param id_code IdCode of the archive to open | ||
| 296 | * @return Result of operation, 0 on success, otherwise error code | ||
| 297 | */ | ||
| 298 | Result CloseArchive(FileSys::Archive::IdCode id_code) { | ||
| 299 | if (1 != g_archive_map.erase(id_code)) { | ||
| 300 | ERROR_LOG(KERNEL, "Cannot close archive %d", (int) id_code); | ||
| 301 | return -1; | ||
| 302 | } | ||
| 303 | |||
| 304 | INFO_LOG(KERNEL, "Closed archive %d", (int) id_code); | ||
| 305 | return 0; | ||
| 306 | } | ||
| 307 | |||
| 308 | /** | ||
| 129 | * Mounts an archive | 309 | * Mounts an archive |
| 130 | * @param archive Pointer to the archive to mount | 310 | * @param archive Pointer to the archive to mount |
| 131 | * @return Result of operation, 0 on success, otherwise error code | 311 | * @return Result of operation, 0 on success, otherwise error code |
| @@ -171,9 +351,56 @@ Handle CreateArchive(FileSys::Archive* backend, const std::string& name) { | |||
| 171 | return handle; | 351 | return handle; |
| 172 | } | 352 | } |
| 173 | 353 | ||
| 354 | /** | ||
| 355 | * Open a File from an Archive | ||
| 356 | * @param archive_handle Handle to an open Archive object | ||
| 357 | * @param path Path to the File inside of the Archive | ||
| 358 | * @param mode Mode under which to open the File | ||
| 359 | * @return Opened File object | ||
| 360 | */ | ||
| 361 | Handle OpenFileFromArchive(Handle archive_handle, const std::string& path, const FileSys::Mode mode) { | ||
| 362 | File* file = new File; | ||
| 363 | Handle handle = Kernel::g_object_pool.Create(file); | ||
| 364 | |||
| 365 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | ||
| 366 | file->path = path; | ||
| 367 | file->backend = archive->backend->OpenFile(path, mode); | ||
| 368 | |||
| 369 | return handle; | ||
| 370 | } | ||
| 371 | |||
| 372 | /** | ||
| 373 | * Open a Directory from an Archive | ||
| 374 | * @param archive_handle Handle to an open Archive object | ||
| 375 | * @param path Path to the Directory inside of the Archive | ||
| 376 | * @return Opened Directory object | ||
| 377 | */ | ||
| 378 | Handle OpenDirectoryFromArchive(Handle archive_handle, const std::string& path) { | ||
| 379 | Directory* directory = new Directory; | ||
| 380 | Handle handle = Kernel::g_object_pool.Create(directory); | ||
| 381 | |||
| 382 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | ||
| 383 | directory->path = path; | ||
| 384 | directory->backend = archive->backend->OpenDirectory(path); | ||
| 385 | |||
| 386 | return handle; | ||
| 387 | } | ||
| 388 | |||
| 174 | /// Initialize archives | 389 | /// Initialize archives |
| 175 | void ArchiveInit() { | 390 | void ArchiveInit() { |
| 176 | g_archive_map.clear(); | 391 | g_archive_map.clear(); |
| 392 | |||
| 393 | // TODO(Link Mauve): Add the other archive types (see here for the known types: | ||
| 394 | // http://3dbrew.org/wiki/FS:OpenArchive#Archive_idcodes). Currently the only half-finished | ||
| 395 | // archive type is SDMC, so it is the only one getting exposed. | ||
| 396 | |||
| 397 | // TODO(Link Mauve): don't assume the path separator is '/'. | ||
| 398 | std::string sdmc_directory = FileUtil::GetCurrentDir() + "/userdata/sdmc"; | ||
| 399 | auto archive = new FileSys::Archive_SDMC(sdmc_directory); | ||
| 400 | if (archive->Initialize()) | ||
| 401 | CreateArchive(archive, "SDMC"); | ||
| 402 | else | ||
| 403 | ERROR_LOG(KERNEL, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); | ||
| 177 | } | 404 | } |
| 178 | 405 | ||
| 179 | /// Shutdown archives | 406 | /// Shutdown archives |
diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h index 3758e7061..593861f8e 100644 --- a/src/core/hle/kernel/archive.h +++ b/src/core/hle/kernel/archive.h | |||
| @@ -22,6 +22,13 @@ namespace Kernel { | |||
| 22 | Handle OpenArchive(FileSys::Archive::IdCode id_code); | 22 | Handle OpenArchive(FileSys::Archive::IdCode id_code); |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
| 25 | * Closes an archive | ||
| 26 | * @param id_code IdCode of the archive to open | ||
| 27 | * @return true if it worked fine | ||
| 28 | */ | ||
| 29 | Result CloseArchive(FileSys::Archive::IdCode id_code); | ||
| 30 | |||
| 31 | /** | ||
| 25 | * Creates an Archive | 32 | * Creates an Archive |
| 26 | * @param backend File system backend interface to the archive | 33 | * @param backend File system backend interface to the archive |
| 27 | * @param name Optional name of Archive | 34 | * @param name Optional name of Archive |
| @@ -29,6 +36,23 @@ Handle OpenArchive(FileSys::Archive::IdCode id_code); | |||
| 29 | */ | 36 | */ |
| 30 | Handle CreateArchive(FileSys::Archive* backend, const std::string& name); | 37 | Handle CreateArchive(FileSys::Archive* backend, const std::string& name); |
| 31 | 38 | ||
| 39 | /** | ||
| 40 | * Open a File from an Archive | ||
| 41 | * @param archive_handle Handle to an open Archive object | ||
| 42 | * @param path Path to the File inside of the Archive | ||
| 43 | * @param mode Mode under which to open the File | ||
| 44 | * @return Opened File object | ||
| 45 | */ | ||
| 46 | Handle OpenFileFromArchive(Handle handle, const std::string& name, const FileSys::Mode mode); | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Open a Directory from an Archive | ||
| 50 | * @param archive_handle Handle to an open Archive object | ||
| 51 | * @param path Path to the Directory inside of the Archive | ||
| 52 | * @return Opened Directory object | ||
| 53 | */ | ||
| 54 | Handle OpenDirectoryFromArchive(Handle handle, const std::string& name); | ||
| 55 | |||
| 32 | /// Initialize archives | 56 | /// Initialize archives |
| 33 | void ArchiveInit(); | 57 | void ArchiveInit(); |
| 34 | 58 | ||
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 0e7e5ff68..867d1b89c 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -32,6 +32,7 @@ enum class HandleType : u32 { | |||
| 32 | File = 10, | 32 | File = 10, |
| 33 | Semaphore = 11, | 33 | Semaphore = 11, |
| 34 | Archive = 12, | 34 | Archive = 12, |
| 35 | Directory = 13, | ||
| 35 | }; | 36 | }; |
| 36 | 37 | ||
| 37 | enum { | 38 | enum { |
diff --git a/src/core/hle/service/fs.cpp b/src/core/hle/service/fs.cpp index 9e1998b0f..8469d9840 100644 --- a/src/core/hle/service/fs.cpp +++ b/src/core/hle/service/fs.cpp | |||
| @@ -12,35 +12,192 @@ | |||
| 12 | 12 | ||
| 13 | namespace FS_User { | 13 | namespace FS_User { |
| 14 | 14 | ||
| 15 | // Command to access archive file | ||
| 16 | enum class LowPathType : u32 { | ||
| 17 | Invalid = 0, | ||
| 18 | Empty = 1, | ||
| 19 | Binary = 2, | ||
| 20 | Char = 3, | ||
| 21 | Wchar = 4 | ||
| 22 | }; | ||
| 23 | |||
| 24 | std::string GetStringFromCmdBuff(const u32 pointer, const u32 size) { | ||
| 25 | auto data = reinterpret_cast<const char*>(Memory::GetPointer(pointer)); | ||
| 26 | return std::string(data, size - 1); | ||
| 27 | } | ||
| 28 | |||
| 29 | // We currently return 0 for success and -1 for failure in cmd_buff[1]. -1 was chosen because it | ||
| 30 | // puts all the sections of the http://3dbrew.org/wiki/Error_codes to something non-zero, to make | ||
| 31 | // sure we don't mislead the application into thinking something worked. | ||
| 32 | |||
| 15 | void Initialize(Service::Interface* self) { | 33 | void Initialize(Service::Interface* self) { |
| 16 | u32* cmd_buff = Service::GetCommandBuffer(); | 34 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 17 | cmd_buff[1] = 0; // No error | 35 | |
| 36 | // TODO(Link Mauve): check the behavior when cmd_buff[1] isn't 32, as per | ||
| 37 | // http://3dbrew.org/wiki/FS:Initialize#Request | ||
| 38 | cmd_buff[1] = 0; | ||
| 39 | |||
| 40 | DEBUG_LOG(KERNEL, "called"); | ||
| 41 | } | ||
| 42 | |||
| 43 | void OpenFile(Service::Interface* self) { | ||
| 44 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 45 | |||
| 46 | u32 transaction = cmd_buff[1]; | ||
| 47 | // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to | ||
| 48 | // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. | ||
| 49 | Handle archive_handle = static_cast<Handle>(cmd_buff[3]); | ||
| 50 | LowPathType type = static_cast<LowPathType>(cmd_buff[4]); | ||
| 51 | u32 size = cmd_buff[5]; | ||
| 52 | FileSys::Mode mode; mode.hex = cmd_buff[6]; | ||
| 53 | u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes. | ||
| 54 | u32 pointer = cmd_buff[9]; | ||
| 55 | |||
| 56 | if (type != LowPathType::Char) { | ||
| 57 | ERROR_LOG(KERNEL, "file LowPath type other than char is currently unsupported"); | ||
| 58 | cmd_buff[1] = -1; | ||
| 59 | return; | ||
| 60 | } | ||
| 61 | |||
| 62 | std::string file_name = GetStringFromCmdBuff(pointer, size); | ||
| 63 | |||
| 64 | DEBUG_LOG(KERNEL, "type=%d size=%d mode=%d attrs=%d data=%s", type, size, mode, attributes, file_name.c_str()); | ||
| 65 | |||
| 66 | Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_name, mode); | ||
| 67 | if (handle) { | ||
| 68 | cmd_buff[1] = 0; | ||
| 69 | cmd_buff[3] = handle; | ||
| 70 | } else { | ||
| 71 | ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_name.c_str()); | ||
| 72 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 73 | cmd_buff[1] = -1; | ||
| 74 | } | ||
| 75 | |||
| 18 | DEBUG_LOG(KERNEL, "called"); | 76 | DEBUG_LOG(KERNEL, "called"); |
| 19 | } | 77 | } |
| 20 | 78 | ||
| 21 | void OpenFileDirectly(Service::Interface* self) { | 79 | void OpenFileDirectly(Service::Interface* self) { |
| 22 | u32* cmd_buff = Service::GetCommandBuffer(); | 80 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 23 | 81 | ||
| 24 | FileSys::Archive::IdCode arch_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]); | 82 | u32 transaction = cmd_buff[1]; |
| 25 | 83 | auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]); | |
| 26 | // TODO(bunnei): Properly implement use of these... | 84 | LowPathType archive_type = static_cast<LowPathType>(cmd_buff[3]); |
| 27 | //u32 transaction = cmd_buff[1]; | 85 | u32 archive_size = cmd_buff[4]; |
| 28 | //u32 arch_lowpath_type = cmd_buff[3]; | 86 | LowPathType type = static_cast<LowPathType>(cmd_buff[5]); |
| 29 | //u32 arch_lowpath_sz = cmd_buff[4]; | 87 | u32 size = cmd_buff[6]; |
| 30 | //u32 file_lowpath_type = cmd_buff[5]; | 88 | FileSys::Mode mode; mode.hex = cmd_buff[7]; |
| 31 | //u32 file_lowpath_sz = cmd_buff[6]; | 89 | u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes. |
| 32 | //u32 flags = cmd_buff[7]; | 90 | u32 archive_pointer = cmd_buff[10]; |
| 33 | //u32 attr = cmd_buff[8]; | 91 | u32 pointer = cmd_buff[12]; |
| 34 | //u32 arch_lowpath_desc = cmd_buff[9]; | 92 | |
| 35 | //u32 arch_lowpath_ptr = cmd_buff[10]; | 93 | if (archive_type != LowPathType::Empty) { |
| 36 | //u32 file_lowpath_desc = cmd_buff[11]; | 94 | ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported"); |
| 37 | //u32 file_lowpath_ptr = cmd_buff[12]; | 95 | cmd_buff[1] = -1; |
| 96 | return; | ||
| 97 | } | ||
| 98 | |||
| 99 | if (type != LowPathType::Char) { | ||
| 100 | ERROR_LOG(KERNEL, "file LowPath type other than char is currently unsupported"); | ||
| 101 | cmd_buff[1] = -1; | ||
| 102 | return; | ||
| 103 | } | ||
| 104 | |||
| 105 | std::string archive_name = GetStringFromCmdBuff(archive_pointer, archive_size); | ||
| 106 | std::string file_name = GetStringFromCmdBuff(pointer, size); | ||
| 107 | |||
| 108 | DEBUG_LOG(KERNEL, "archive_type=%d archive_size=%d archive_data=%s" | ||
| 109 | "file_type=%d file_size=%d file_mode=%d file_attrs=%d file_data=%s", | ||
| 110 | archive_type, archive_size, archive_name.c_str(), | ||
| 111 | type, size, mode, attributes, file_name.c_str()); | ||
| 112 | |||
| 113 | // TODO(Link Mauve): check if we should even get a handle for the archive, and don't leak it. | ||
| 114 | Handle archive_handle = Kernel::OpenArchive(archive_id); | ||
| 115 | if (archive_handle) { | ||
| 116 | cmd_buff[1] = 0; | ||
| 117 | // cmd_buff[2] isn't used according to 3dmoo's implementation. | ||
| 118 | cmd_buff[3] = archive_handle; | ||
| 119 | } else { | ||
| 120 | ERROR_LOG(KERNEL, "failed to get a handle for archive %s", archive_name.c_str()); | ||
| 121 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 122 | cmd_buff[1] = -1; | ||
| 123 | return; | ||
| 124 | } | ||
| 125 | |||
| 126 | Handle handle = Kernel::OpenFileFromArchive(archive_handle, file_name, mode); | ||
| 127 | if (handle) { | ||
| 128 | cmd_buff[1] = 0; | ||
| 129 | cmd_buff[3] = handle; | ||
| 130 | } else { | ||
| 131 | ERROR_LOG(KERNEL, "failed to get a handle for file %s", file_name.c_str()); | ||
| 132 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 133 | cmd_buff[1] = -1; | ||
| 134 | } | ||
| 135 | |||
| 136 | DEBUG_LOG(KERNEL, "called"); | ||
| 137 | } | ||
| 138 | |||
| 139 | void OpenDirectory(Service::Interface* self) { | ||
| 140 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 141 | |||
| 142 | // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to | ||
| 143 | // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. | ||
| 144 | Handle archive_handle = static_cast<Handle>(cmd_buff[2]); | ||
| 145 | LowPathType type = static_cast<LowPathType>(cmd_buff[3]); | ||
| 146 | u32 size = cmd_buff[4]; | ||
| 147 | u32 pointer = cmd_buff[6]; | ||
| 148 | |||
| 149 | if (type != LowPathType::Char) { | ||
| 150 | ERROR_LOG(KERNEL, "directory LowPath type other than char is currently unsupported"); | ||
| 151 | cmd_buff[1] = -1; | ||
| 152 | return; | ||
| 153 | } | ||
| 154 | |||
| 155 | std::string dir_name = GetStringFromCmdBuff(pointer, size); | ||
| 156 | |||
| 157 | DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", type, size, dir_name.c_str()); | ||
| 158 | |||
| 159 | Handle handle = Kernel::OpenDirectoryFromArchive(archive_handle, dir_name); | ||
| 160 | if (handle) { | ||
| 161 | cmd_buff[1] = 0; | ||
| 162 | cmd_buff[3] = handle; | ||
| 163 | } else { | ||
| 164 | ERROR_LOG(KERNEL, "failed to get a handle for directory %s", dir_name.c_str()); | ||
| 165 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 166 | cmd_buff[1] = -1; | ||
| 167 | } | ||
| 168 | |||
| 169 | DEBUG_LOG(KERNEL, "called"); | ||
| 170 | } | ||
| 171 | |||
| 172 | void OpenArchive(Service::Interface* self) { | ||
| 173 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 174 | |||
| 175 | auto arch_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]); | ||
| 176 | LowPathType type = static_cast<LowPathType>(cmd_buff[2]); | ||
| 177 | u32 size = cmd_buff[3]; | ||
| 178 | u32 pointer = cmd_buff[5]; | ||
| 179 | |||
| 180 | if (type != LowPathType::Empty) { | ||
| 181 | ERROR_LOG(KERNEL, "archive LowPath type other than empty is currently unsupported"); | ||
| 182 | cmd_buff[1] = -1; | ||
| 183 | return; | ||
| 184 | } | ||
| 185 | |||
| 186 | std::string archive_name = GetStringFromCmdBuff(pointer, size); | ||
| 187 | |||
| 188 | DEBUG_LOG(KERNEL, "type=%d size=%d data=%s", type, size, archive_name.c_str()); | ||
| 38 | 189 | ||
| 39 | Handle handle = Kernel::OpenArchive(arch_id); | 190 | Handle handle = Kernel::OpenArchive(arch_id); |
| 40 | if (0 != handle) { | 191 | if (handle) { |
| 41 | cmd_buff[1] = 0; // No error | 192 | cmd_buff[1] = 0; |
| 193 | // cmd_buff[2] isn't used according to 3dmoo's implementation. | ||
| 42 | cmd_buff[3] = handle; | 194 | cmd_buff[3] = handle; |
| 195 | } else { | ||
| 196 | ERROR_LOG(KERNEL, "failed to get a handle for archive %s", archive_name.c_str()); | ||
| 197 | // TODO(Link Mauve): check for the actual error values, this one was just chosen arbitrarily. | ||
| 198 | cmd_buff[1] = -1; | ||
| 43 | } | 199 | } |
| 200 | |||
| 44 | DEBUG_LOG(KERNEL, "called"); | 201 | DEBUG_LOG(KERNEL, "called"); |
| 45 | } | 202 | } |
| 46 | 203 | ||
| @@ -48,7 +205,7 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 48 | {0x000100C6, nullptr, "Dummy1"}, | 205 | {0x000100C6, nullptr, "Dummy1"}, |
| 49 | {0x040100C4, nullptr, "Control"}, | 206 | {0x040100C4, nullptr, "Control"}, |
| 50 | {0x08010002, Initialize, "Initialize"}, | 207 | {0x08010002, Initialize, "Initialize"}, |
| 51 | {0x080201C2, nullptr, "OpenFile"}, | 208 | {0x080201C2, OpenFile, "OpenFile"}, |
| 52 | {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, | 209 | {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, |
| 53 | {0x08040142, nullptr, "DeleteFile"}, | 210 | {0x08040142, nullptr, "DeleteFile"}, |
| 54 | {0x08050244, nullptr, "RenameFile"}, | 211 | {0x08050244, nullptr, "RenameFile"}, |
| @@ -57,8 +214,8 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 57 | {0x08080202, nullptr, "CreateFile"}, | 214 | {0x08080202, nullptr, "CreateFile"}, |
| 58 | {0x08090182, nullptr, "CreateDirectory"}, | 215 | {0x08090182, nullptr, "CreateDirectory"}, |
| 59 | {0x080A0244, nullptr, "RenameDirectory"}, | 216 | {0x080A0244, nullptr, "RenameDirectory"}, |
| 60 | {0x080B0102, nullptr, "OpenDirectory"}, | 217 | {0x080B0102, OpenDirectory, "OpenDirectory"}, |
| 61 | {0x080C00C2, nullptr, "OpenArchive"}, | 218 | {0x080C00C2, OpenArchive, "OpenArchive"}, |
| 62 | {0x080D0144, nullptr, "ControlArchive"}, | 219 | {0x080D0144, nullptr, "ControlArchive"}, |
| 63 | {0x080E0080, nullptr, "CloseArchive"}, | 220 | {0x080E0080, nullptr, "CloseArchive"}, |
| 64 | {0x080F0180, nullptr, "FormatThisUserSaveData"}, | 221 | {0x080F0180, nullptr, "FormatThisUserSaveData"}, |
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 76c9d6d54..389d5a8c9 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp | |||
| @@ -351,7 +351,7 @@ ResultStatus AppLoader_ELF::Load() { | |||
| 351 | if (is_loaded) | 351 | if (is_loaded) |
| 352 | return ResultStatus::ErrorAlreadyLoaded; | 352 | return ResultStatus::ErrorAlreadyLoaded; |
| 353 | 353 | ||
| 354 | File::IOFile file(filename, "rb"); | 354 | FileUtil::IOFile file(filename, "rb"); |
| 355 | 355 | ||
| 356 | if (file.IsOpen()) { | 356 | if (file.IsOpen()) { |
| 357 | u32 size = (u32)file.GetSize(); | 357 | u32 size = (u32)file.GetSize(); |
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 577a2297a..a268e021a 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp | |||
| @@ -78,7 +78,7 @@ ResultStatus LoadFile(const std::string& filename) { | |||
| 78 | { | 78 | { |
| 79 | INFO_LOG(LOADER, "Loading BIN file %s...", filename.c_str()); | 79 | INFO_LOG(LOADER, "Loading BIN file %s...", filename.c_str()); |
| 80 | 80 | ||
| 81 | File::IOFile file(filename, "rb"); | 81 | FileUtil::IOFile file(filename, "rb"); |
| 82 | 82 | ||
| 83 | if (file.IsOpen()) { | 83 | if (file.IsOpen()) { |
| 84 | file.ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), (size_t)file.GetSize()); | 84 | file.ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), (size_t)file.GetSize()); |
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 9af59e419..1e5501e6d 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp | |||
| @@ -138,7 +138,7 @@ ResultStatus AppLoader_NCCH::LoadExec() const { | |||
| 138 | */ | 138 | */ |
| 139 | ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>& buffer) const { | 139 | ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>& buffer) const { |
| 140 | // Iterate through the ExeFs archive until we find the .code file... | 140 | // Iterate through the ExeFs archive until we find the .code file... |
| 141 | File::IOFile file(filename, "rb"); | 141 | FileUtil::IOFile file(filename, "rb"); |
| 142 | if (file.IsOpen()) { | 142 | if (file.IsOpen()) { |
| 143 | for (int i = 0; i < kMaxSections; i++) { | 143 | for (int i = 0; i < kMaxSections; i++) { |
| 144 | // Load the specified section... | 144 | // Load the specified section... |
| @@ -199,7 +199,7 @@ ResultStatus AppLoader_NCCH::Load() { | |||
| 199 | if (is_loaded) | 199 | if (is_loaded) |
| 200 | return ResultStatus::ErrorAlreadyLoaded; | 200 | return ResultStatus::ErrorAlreadyLoaded; |
| 201 | 201 | ||
| 202 | File::IOFile file(filename, "rb"); | 202 | FileUtil::IOFile file(filename, "rb"); |
| 203 | if (file.IsOpen()) { | 203 | if (file.IsOpen()) { |
| 204 | file.ReadBytes(&ncch_header, sizeof(NCCH_Header)); | 204 | file.ReadBytes(&ncch_header, sizeof(NCCH_Header)); |
| 205 | 205 | ||
| @@ -290,7 +290,7 @@ ResultStatus AppLoader_NCCH::ReadLogo(std::vector<u8>& buffer) const { | |||
| 290 | * @return ResultStatus result of function | 290 | * @return ResultStatus result of function |
| 291 | */ | 291 | */ |
| 292 | ResultStatus AppLoader_NCCH::ReadRomFS(std::vector<u8>& buffer) const { | 292 | ResultStatus AppLoader_NCCH::ReadRomFS(std::vector<u8>& buffer) const { |
| 293 | File::IOFile file(filename, "rb"); | 293 | FileUtil::IOFile file(filename, "rb"); |
| 294 | if (file.IsOpen()) { | 294 | if (file.IsOpen()) { |
| 295 | // Check if the NCCH has a RomFS... | 295 | // Check if the NCCH has a RomFS... |
| 296 | if (ncch_header.romfs_offset != 0 && ncch_header.romfs_size != 0) { | 296 | if (ncch_header.romfs_offset != 0 && ncch_header.romfs_size != 0) { |
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp index 48e6dd182..8f4aa0ad0 100644 --- a/src/video_core/debug_utils/debug_utils.cpp +++ b/src/video_core/debug_utils/debug_utils.cpp | |||
| @@ -336,7 +336,7 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { | |||
| 336 | png_infop info_ptr = nullptr; | 336 | png_infop info_ptr = nullptr; |
| 337 | 337 | ||
| 338 | // Open file for writing (binary mode) | 338 | // Open file for writing (binary mode) |
| 339 | File::IOFile fp(filename, "wb"); | 339 | FileUtil::IOFile fp(filename, "wb"); |
| 340 | 340 | ||
| 341 | // Initialize write structure | 341 | // Initialize write structure |
| 342 | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); | 342 | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); |