diff options
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 6 | ||||
| -rw-r--r-- | src/core/hle/result.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.cpp | 51 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.h | 6 | ||||
| -rw-r--r-- | src/core/hle/service/fs/fs_user.cpp | 42 |
6 files changed, 95 insertions, 13 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 929422b36..6a690e915 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -14,6 +14,7 @@ namespace Kernel { | |||
| 14 | 14 | ||
| 15 | Handle g_main_thread = 0; | 15 | Handle g_main_thread = 0; |
| 16 | ObjectPool g_object_pool; | 16 | ObjectPool g_object_pool; |
| 17 | u64 g_program_id = 0; | ||
| 17 | 18 | ||
| 18 | ObjectPool::ObjectPool() { | 19 | ObjectPool::ObjectPool() { |
| 19 | next_id = INITIAL_NEXT_ID; | 20 | next_id = INITIAL_NEXT_ID; |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 7e0f15c84..7123485be 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -151,6 +151,12 @@ private: | |||
| 151 | extern ObjectPool g_object_pool; | 151 | extern ObjectPool g_object_pool; |
| 152 | extern Handle g_main_thread; | 152 | extern Handle g_main_thread; |
| 153 | 153 | ||
| 154 | /// The ID code of the currently running game | ||
| 155 | /// TODO(Subv): This variable should not be here, | ||
| 156 | /// we need a way to store information about the currently loaded application | ||
| 157 | /// for later query during runtime, maybe using the LDR service? | ||
| 158 | extern u64 g_program_id; | ||
| 159 | |||
| 154 | /// Initialize the kernel | 160 | /// Initialize the kernel |
| 155 | void Init(); | 161 | void Init(); |
| 156 | 162 | ||
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 15c4a2677..14d2be4a2 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | /// Detailed description of the error. This listing is likely incomplete. | 17 | /// Detailed description of the error. This listing is likely incomplete. |
| 18 | enum class ErrorDescription : u32 { | 18 | enum class ErrorDescription : u32 { |
| 19 | Success = 0, | 19 | Success = 0, |
| 20 | FS_NotFound = 100, | ||
| 21 | FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive | ||
| 20 | InvalidSection = 1000, | 22 | InvalidSection = 1000, |
| 21 | TooLarge = 1001, | 23 | TooLarge = 1001, |
| 22 | NotAuthorized = 1002, | 24 | NotAuthorized = 1002, |
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index caf82d556..9c3834733 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/file_util.h" | 9 | #include "common/file_util.h" |
| 10 | #include "common/math_util.h" | 10 | #include "common/math_util.h" |
| 11 | 11 | ||
| 12 | #include "core/file_sys/archive_savedata.h" | ||
| 12 | #include "core/file_sys/archive_backend.h" | 13 | #include "core/file_sys/archive_backend.h" |
| 13 | #include "core/file_sys/archive_sdmc.h" | 14 | #include "core/file_sys/archive_sdmc.h" |
| 14 | #include "core/file_sys/directory_backend.h" | 15 | #include "core/file_sys/directory_backend.h" |
| @@ -135,6 +136,13 @@ public: | |||
| 135 | break; | 136 | break; |
| 136 | } | 137 | } |
| 137 | 138 | ||
| 139 | case FileCommand::Flush: | ||
| 140 | { | ||
| 141 | LOG_TRACE(Service_FS, "Flush"); | ||
| 142 | backend->Flush(); | ||
| 143 | break; | ||
| 144 | } | ||
| 145 | |||
| 138 | // Unknown command... | 146 | // Unknown command... |
| 139 | default: | 147 | default: |
| 140 | LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); | 148 | LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); |
| @@ -220,9 +228,18 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code) { | |||
| 220 | 228 | ||
| 221 | auto itr = id_code_map.find(id_code); | 229 | auto itr = id_code_map.find(id_code); |
| 222 | if (itr == id_code_map.end()) { | 230 | if (itr == id_code_map.end()) { |
| 231 | if (id_code == ArchiveIdCode::SaveData) { | ||
| 232 | // When a SaveData archive is created for the first time, it is not yet formatted | ||
| 233 | // and the save file/directory structure expected by the game has not yet been initialized. | ||
| 234 | // Returning the NotFormatted error code will signal the game to provision the SaveData archive | ||
| 235 | // with the files and folders that it expects. | ||
| 236 | // The FormatSaveData service call will create the SaveData archive when it is called. | ||
| 237 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, | ||
| 238 | ErrorSummary::InvalidState, ErrorLevel::Status); | ||
| 239 | } | ||
| 223 | // TODO: Verify error against hardware | 240 | // TODO: Verify error against hardware |
| 224 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, | 241 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |
| 225 | ErrorSummary::NotFound, ErrorLevel::Permanent); | 242 | ErrorSummary::NotFound, ErrorLevel::Permanent); |
| 226 | } | 243 | } |
| 227 | 244 | ||
| 228 | // This should never even happen in the first place with 64-bit handles, | 245 | // This should never even happen in the first place with 64-bit handles, |
| @@ -260,8 +277,8 @@ ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSy | |||
| 260 | 277 | ||
| 261 | std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode); | 278 | std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode); |
| 262 | if (backend == nullptr) { | 279 | if (backend == nullptr) { |
| 263 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, | 280 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, |
| 264 | ErrorSummary::NotFound, ErrorLevel::Permanent); | 281 | ErrorSummary::NotFound, ErrorLevel::Status); |
| 265 | } | 282 | } |
| 266 | 283 | ||
| 267 | auto file = std::make_unique<File>(std::move(backend), path); | 284 | auto file = std::make_unique<File>(std::move(backend), path); |
| @@ -366,6 +383,28 @@ ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const F | |||
| 366 | return MakeResult<Handle>(handle); | 383 | return MakeResult<Handle>(handle); |
| 367 | } | 384 | } |
| 368 | 385 | ||
| 386 | ResultCode FormatSaveData() { | ||
| 387 | // TODO(Subv): Actually wipe the savedata folder after creating or opening it | ||
| 388 | |||
| 389 | // Do not create the archive again if it already exists | ||
| 390 | if (id_code_map.find(ArchiveIdCode::SaveData) != id_code_map.end()) | ||
| 391 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the correct error code | ||
| 392 | |||
| 393 | // Create the SaveData archive | ||
| 394 | std::string savedata_directory = FileUtil::GetUserPath(D_SAVEDATA_IDX); | ||
| 395 | auto savedata_archive = std::make_unique<FileSys::Archive_SaveData>(savedata_directory, | ||
| 396 | Kernel::g_program_id); | ||
| 397 | |||
| 398 | if (savedata_archive->Initialize()) { | ||
| 399 | CreateArchive(std::move(savedata_archive), ArchiveIdCode::SaveData); | ||
| 400 | return RESULT_SUCCESS; | ||
| 401 | } else { | ||
| 402 | LOG_ERROR(Service_FS, "Can't instantiate SaveData archive with path %s", | ||
| 403 | savedata_archive->GetMountPoint().c_str()); | ||
| 404 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the proper error code | ||
| 405 | } | ||
| 406 | } | ||
| 407 | |||
| 369 | /// Initialize archives | 408 | /// Initialize archives |
| 370 | void ArchiveInit() { | 409 | void ArchiveInit() { |
| 371 | next_handle = 1; | 410 | next_handle = 1; |
| @@ -375,9 +414,9 @@ void ArchiveInit() { | |||
| 375 | // archive type is SDMC, so it is the only one getting exposed. | 414 | // archive type is SDMC, so it is the only one getting exposed. |
| 376 | 415 | ||
| 377 | std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); | 416 | std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); |
| 378 | auto archive = std::make_unique<FileSys::Archive_SDMC>(sdmc_directory); | 417 | auto sdmc_archive = std::make_unique<FileSys::Archive_SDMC>(sdmc_directory); |
| 379 | if (archive->Initialize()) | 418 | if (sdmc_archive->Initialize()) |
| 380 | CreateArchive(std::move(archive), ArchiveIdCode::SDMC); | 419 | CreateArchive(std::move(sdmc_archive), ArchiveIdCode::SDMC); |
| 381 | else | 420 | else |
| 382 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); | 421 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); |
| 383 | } | 422 | } |
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index a38de92e3..a128276b6 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h | |||
| @@ -109,6 +109,12 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons | |||
| 109 | */ | 109 | */ |
| 110 | ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); | 110 | ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); |
| 111 | 111 | ||
| 112 | /** | ||
| 113 | * Creates a blank SaveData archive. | ||
| 114 | * @return ResultCode 0 on success or the corresponding code on error | ||
| 115 | */ | ||
| 116 | ResultCode FormatSaveData(); | ||
| 117 | |||
| 112 | /// Initialize archives | 118 | /// Initialize archives |
| 113 | void ArchiveInit(); | 119 | void ArchiveInit(); |
| 114 | 120 | ||
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 0f75d5e3a..f99d84b2f 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp | |||
| @@ -3,11 +3,11 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/common.h" | 5 | #include "common/common.h" |
| 6 | #include "common/file_util.h" | ||
| 6 | #include "common/scope_exit.h" | 7 | #include "common/scope_exit.h" |
| 7 | |||
| 8 | #include "common/string_util.h" | 8 | #include "common/string_util.h" |
| 9 | #include "core/hle/service/fs/archive.h" | ||
| 10 | #include "core/hle/result.h" | 9 | #include "core/hle/result.h" |
| 10 | #include "core/hle/service/fs/archive.h" | ||
| 11 | #include "core/hle/service/fs/fs_user.h" | 11 | #include "core/hle/service/fs/fs_user.h" |
| 12 | #include "core/settings.h" | 12 | #include "core/settings.h" |
| 13 | 13 | ||
| @@ -50,9 +50,7 @@ static void Initialize(Service::Interface* self) { | |||
| 50 | static void OpenFile(Service::Interface* self) { | 50 | static void OpenFile(Service::Interface* self) { |
| 51 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 51 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 52 | 52 | ||
| 53 | // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to | 53 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); |
| 54 | // 3dmoo's or ctrulib's implementations. Triple check if it's really the case. | ||
| 55 | Handle archive_handle = static_cast<Handle>(cmd_buff[3]); | ||
| 56 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | 54 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |
| 57 | u32 filename_size = cmd_buff[5]; | 55 | u32 filename_size = cmd_buff[5]; |
| 58 | FileSys::Mode mode; mode.hex = cmd_buff[6]; | 56 | FileSys::Mode mode; mode.hex = cmd_buff[6]; |
| @@ -398,6 +396,36 @@ static void IsSdmcDetected(Service::Interface* self) { | |||
| 398 | LOG_DEBUG(Service_FS, "called"); | 396 | LOG_DEBUG(Service_FS, "called"); |
| 399 | } | 397 | } |
| 400 | 398 | ||
| 399 | /** | ||
| 400 | * FS_User::FormatSaveData service function | ||
| 401 | * Inputs: | ||
| 402 | * Outputs: | ||
| 403 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 404 | */ | ||
| 405 | static void FormatSaveData(Service::Interface* self) { | ||
| 406 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 407 | LOG_DEBUG(Service_FS, "(STUBBED)"); | ||
| 408 | |||
| 409 | // TODO(Subv): Find out what the inputs and outputs of this function are | ||
| 410 | |||
| 411 | cmd_buff[1] = FormatSaveData().raw; | ||
| 412 | } | ||
| 413 | |||
| 414 | /** | ||
| 415 | * FS_User::FormatThisUserSaveData service function | ||
| 416 | * Inputs: | ||
| 417 | * Outputs: | ||
| 418 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 419 | */ | ||
| 420 | static void FormatThisUserSaveData(Service::Interface* self) { | ||
| 421 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 422 | LOG_DEBUG(Service_FS, "(STUBBED)"); | ||
| 423 | |||
| 424 | // TODO(Subv): Find out what the inputs and outputs of this function are | ||
| 425 | |||
| 426 | cmd_buff[1] = FormatSaveData().raw; | ||
| 427 | } | ||
| 428 | |||
| 401 | const FSUserInterface::FunctionInfo FunctionTable[] = { | 429 | const FSUserInterface::FunctionInfo FunctionTable[] = { |
| 402 | {0x000100C6, nullptr, "Dummy1"}, | 430 | {0x000100C6, nullptr, "Dummy1"}, |
| 403 | {0x040100C4, nullptr, "Control"}, | 431 | {0x040100C4, nullptr, "Control"}, |
| @@ -415,7 +443,7 @@ const FSUserInterface::FunctionInfo FunctionTable[] = { | |||
| 415 | {0x080C00C2, OpenArchive, "OpenArchive"}, | 443 | {0x080C00C2, OpenArchive, "OpenArchive"}, |
| 416 | {0x080D0144, nullptr, "ControlArchive"}, | 444 | {0x080D0144, nullptr, "ControlArchive"}, |
| 417 | {0x080E0080, CloseArchive, "CloseArchive"}, | 445 | {0x080E0080, CloseArchive, "CloseArchive"}, |
| 418 | {0x080F0180, nullptr, "FormatThisUserSaveData"}, | 446 | {0x080F0180, FormatThisUserSaveData,"FormatThisUserSaveData"}, |
| 419 | {0x08100200, nullptr, "CreateSystemSaveData"}, | 447 | {0x08100200, nullptr, "CreateSystemSaveData"}, |
| 420 | {0x08110040, nullptr, "DeleteSystemSaveData"}, | 448 | {0x08110040, nullptr, "DeleteSystemSaveData"}, |
| 421 | {0x08120080, nullptr, "GetFreeBytes"}, | 449 | {0x08120080, nullptr, "GetFreeBytes"}, |
| @@ -476,7 +504,7 @@ const FSUserInterface::FunctionInfo FunctionTable[] = { | |||
| 476 | {0x08490040, nullptr, "GetArchiveResource"}, | 504 | {0x08490040, nullptr, "GetArchiveResource"}, |
| 477 | {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"}, | 505 | {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"}, |
| 478 | {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"}, | 506 | {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"}, |
| 479 | {0x084C0242, nullptr, "FormatSaveData"}, | 507 | {0x084C0242, FormatSaveData, "FormatSaveData"}, |
| 480 | {0x084D0102, nullptr, "GetLegacySubBannerData"}, | 508 | {0x084D0102, nullptr, "GetLegacySubBannerData"}, |
| 481 | {0x084E0342, nullptr, "UpdateSha256Context"}, | 509 | {0x084E0342, nullptr, "UpdateSha256Context"}, |
| 482 | {0x084F0102, nullptr, "ReadSpecialFile"}, | 510 | {0x084F0102, nullptr, "ReadSpecialFile"}, |