diff options
| author | 2014-09-12 00:48:28 +0200 | |
|---|---|---|
| committer | 2014-09-17 14:35:46 +0000 | |
| commit | 99bfa4ae1fd76cbcc1b5245ea6962bd083d61268 (patch) | |
| tree | 74f185bcf33e2ff9a97b024a44e26319533e8f3b /src | |
| parent | Kernel: Add a Directory object and a getter for it from an Archive object. (diff) | |
| download | yuzu-99bfa4ae1fd76cbcc1b5245ea6962bd083d61268.tar.gz yuzu-99bfa4ae1fd76cbcc1b5245ea6962bd083d61268.tar.xz yuzu-99bfa4ae1fd76cbcc1b5245ea6962bd083d61268.zip | |
FS: Implement OpenArchive, OpenDirectory, OpenFile and OpenFileDirectly calls.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/fs.cpp | 197 |
1 files changed, 177 insertions, 20 deletions
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"}, |