diff options
| author | 2018-11-13 18:51:08 -0800 | |
|---|---|---|
| committer | 2018-11-13 18:51:08 -0800 | |
| commit | 9b1262374382a32c4aec5e14d67eed6cd09249bb (patch) | |
| tree | 357554bcbd7eb477a90e0451868e2afd8536ccd7 /src/core | |
| parent | Merge pull request #1628 from greggameplayer/Texture2DArray (diff) | |
| parent | ns: Implement command 400: GetApplicationControlData (diff) | |
| download | yuzu-9b1262374382a32c4aec5e14d67eed6cd09249bb.tar.gz yuzu-9b1262374382a32c4aec5e14d67eed6cd09249bb.tar.xz yuzu-9b1262374382a32c4aec5e14d67eed6cd09249bb.zip | |
Merge pull request #1608 from DarkLordZach/save-data-reader
[ns|fsp_srv]: Implement various functions to boot Checkpoint
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/file_sys/control_metadata.cpp | 6 | ||||
| -rw-r--r-- | src/core/file_sys/control_metadata.h | 1 | ||||
| -rw-r--r-- | src/core/file_sys/savedata_factory.cpp | 32 | ||||
| -rw-r--r-- | src/core/file_sys/savedata_factory.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/filesystem.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/filesystem.h | 1 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.cpp | 153 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.h | 1 | ||||
| -rw-r--r-- | src/core/hle/service/ns/ns.cpp | 64 | ||||
| -rw-r--r-- | src/core/loader/nro.cpp | 5 |
10 files changed, 260 insertions, 16 deletions
diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp index a012c2be9..c8fa912bf 100644 --- a/src/core/file_sys/control_metadata.cpp +++ b/src/core/file_sys/control_metadata.cpp | |||
| @@ -66,4 +66,10 @@ std::string NACP::GetVersionString() const { | |||
| 66 | return Common::StringFromFixedZeroTerminatedBuffer(raw->version_string.data(), | 66 | return Common::StringFromFixedZeroTerminatedBuffer(raw->version_string.data(), |
| 67 | raw->version_string.size()); | 67 | raw->version_string.size()); |
| 68 | } | 68 | } |
| 69 | |||
| 70 | std::vector<u8> NACP::GetRawBytes() const { | ||
| 71 | std::vector<u8> out(sizeof(RawNACP)); | ||
| 72 | std::memcpy(out.data(), raw.get(), sizeof(RawNACP)); | ||
| 73 | return out; | ||
| 74 | } | ||
| 69 | } // namespace FileSys | 75 | } // namespace FileSys |
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h index 141f7e056..bfaad46b4 100644 --- a/src/core/file_sys/control_metadata.h +++ b/src/core/file_sys/control_metadata.h | |||
| @@ -81,6 +81,7 @@ public: | |||
| 81 | u64 GetTitleId() const; | 81 | u64 GetTitleId() const; |
| 82 | u64 GetDLCBaseTitleId() const; | 82 | u64 GetDLCBaseTitleId() const; |
| 83 | std::string GetVersionString() const; | 83 | std::string GetVersionString() const; |
| 84 | std::vector<u8> GetRawBytes() const; | ||
| 84 | 85 | ||
| 85 | private: | 86 | private: |
| 86 | std::unique_ptr<RawNACP> raw; | 87 | std::unique_ptr<RawNACP> raw; |
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index ef1aaebbb..5434f2149 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp | |||
| @@ -83,28 +83,32 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, SaveDataDescr | |||
| 83 | return MakeResult<VirtualDir>(std::move(out)); | 83 | return MakeResult<VirtualDir>(std::move(out)); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, | 86 | VirtualDir SaveDataFactory::GetSaveDataSpaceDirectory(SaveDataSpaceId space) const { |
| 87 | u128 user_id, u64 save_id) { | 87 | return dir->GetDirectoryRelative(GetSaveDataSpaceIdPath(space)); |
| 88 | // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should | 88 | } |
| 89 | // be interpreted as the title id of the current process. | ||
| 90 | if (type == SaveDataType::SaveData && title_id == 0) | ||
| 91 | title_id = Core::CurrentProcess()->GetTitleID(); | ||
| 92 | |||
| 93 | std::string out; | ||
| 94 | 89 | ||
| 90 | std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) { | ||
| 95 | switch (space) { | 91 | switch (space) { |
| 96 | case SaveDataSpaceId::NandSystem: | 92 | case SaveDataSpaceId::NandSystem: |
| 97 | out = "/system/"; | 93 | return "/system/"; |
| 98 | break; | ||
| 99 | case SaveDataSpaceId::NandUser: | 94 | case SaveDataSpaceId::NandUser: |
| 100 | out = "/user/"; | 95 | return "/user/"; |
| 101 | break; | ||
| 102 | case SaveDataSpaceId::TemporaryStorage: | 96 | case SaveDataSpaceId::TemporaryStorage: |
| 103 | out = "/temp/"; | 97 | return "/temp/"; |
| 104 | break; | ||
| 105 | default: | 98 | default: |
| 106 | ASSERT_MSG(false, "Unrecognized SaveDataSpaceId: {:02X}", static_cast<u8>(space)); | 99 | ASSERT_MSG(false, "Unrecognized SaveDataSpaceId: {:02X}", static_cast<u8>(space)); |
| 100 | return "/unrecognized/"; ///< To prevent corruption when ignoring asserts. | ||
| 107 | } | 101 | } |
| 102 | } | ||
| 103 | |||
| 104 | std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, | ||
| 105 | u128 user_id, u64 save_id) { | ||
| 106 | // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should | ||
| 107 | // be interpreted as the title id of the current process. | ||
| 108 | if (type == SaveDataType::SaveData && title_id == 0) | ||
| 109 | title_id = Core::CurrentProcess()->GetTitleID(); | ||
| 110 | |||
| 111 | std::string out = GetSaveDataSpaceIdPath(space); | ||
| 108 | 112 | ||
| 109 | switch (type) { | 113 | switch (type) { |
| 110 | case SaveDataType::SystemSaveData: | 114 | case SaveDataType::SystemSaveData: |
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h index d69ef6741..2a0088040 100644 --- a/src/core/file_sys/savedata_factory.h +++ b/src/core/file_sys/savedata_factory.h | |||
| @@ -52,6 +52,9 @@ public: | |||
| 52 | 52 | ||
| 53 | ResultVal<VirtualDir> Open(SaveDataSpaceId space, SaveDataDescriptor meta); | 53 | ResultVal<VirtualDir> Open(SaveDataSpaceId space, SaveDataDescriptor meta); |
| 54 | 54 | ||
| 55 | VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; | ||
| 56 | |||
| 57 | static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space); | ||
| 55 | static std::string GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, | 58 | static std::string GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, |
| 56 | u128 user_id, u64 save_id); | 59 | u128 user_id, u64 save_id); |
| 57 | 60 | ||
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index e32a7c48e..ea8fd965a 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -309,6 +309,16 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space, | |||
| 309 | return save_data_factory->Open(space, save_struct); | 309 | return save_data_factory->Open(space, save_struct); |
| 310 | } | 310 | } |
| 311 | 311 | ||
| 312 | ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) { | ||
| 313 | LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", static_cast<u8>(space)); | ||
| 314 | |||
| 315 | if (save_data_factory == nullptr) { | ||
| 316 | return ResultCode(ErrorModule::FS, FileSys::ErrCodes::TitleNotFound); | ||
| 317 | } | ||
| 318 | |||
| 319 | return MakeResult(save_data_factory->GetSaveDataSpaceDirectory(space)); | ||
| 320 | } | ||
| 321 | |||
| 312 | ResultVal<FileSys::VirtualDir> OpenSDMC() { | 322 | ResultVal<FileSys::VirtualDir> OpenSDMC() { |
| 313 | LOG_TRACE(Service_FS, "Opening SDMC"); | 323 | LOG_TRACE(Service_FS, "Opening SDMC"); |
| 314 | 324 | ||
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 6ca5c5636..2cbb70c87 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h | |||
| @@ -45,6 +45,7 @@ ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId stora | |||
| 45 | FileSys::ContentRecordType type); | 45 | FileSys::ContentRecordType type); |
| 46 | ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space, | 46 | ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space, |
| 47 | FileSys::SaveDataDescriptor save_struct); | 47 | FileSys::SaveDataDescriptor save_struct); |
| 48 | ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space); | ||
| 48 | ResultVal<FileSys::VirtualDir> OpenSDMC(); | 49 | ResultVal<FileSys::VirtualDir> OpenSDMC(); |
| 49 | 50 | ||
| 50 | std::unique_ptr<FileSys::RegisteredCacheUnion> GetUnionContents(); | 51 | std::unique_ptr<FileSys::RegisteredCacheUnion> GetUnionContents(); |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index c1c83a11d..b9a1d5105 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "common/hex_util.h" | ||
| 14 | #include "common/logging/log.h" | 15 | #include "common/logging/log.h" |
| 15 | #include "common/string_util.h" | 16 | #include "common/string_util.h" |
| 16 | #include "core/file_sys/directory.h" | 17 | #include "core/file_sys/directory.h" |
| @@ -451,7 +452,147 @@ private: | |||
| 451 | VfsDirectoryServiceWrapper backend; | 452 | VfsDirectoryServiceWrapper backend; |
| 452 | }; | 453 | }; |
| 453 | 454 | ||
| 455 | class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> { | ||
| 456 | public: | ||
| 457 | explicit ISaveDataInfoReader(FileSys::SaveDataSpaceId space) | ||
| 458 | : ServiceFramework("ISaveDataInfoReader") { | ||
| 459 | static const FunctionInfo functions[] = { | ||
| 460 | {0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"}, | ||
| 461 | }; | ||
| 462 | RegisterHandlers(functions); | ||
| 463 | |||
| 464 | FindAllSaves(space); | ||
| 465 | } | ||
| 466 | |||
| 467 | void ReadSaveDataInfo(Kernel::HLERequestContext& ctx) { | ||
| 468 | // Calculate how many entries we can fit in the output buffer | ||
| 469 | const u64 count_entries = ctx.GetWriteBufferSize() / sizeof(SaveDataInfo); | ||
| 470 | |||
| 471 | // Cap at total number of entries. | ||
| 472 | const u64 actual_entries = std::min(count_entries, info.size() - next_entry_index); | ||
| 473 | |||
| 474 | // Determine data start and end | ||
| 475 | const auto* begin = reinterpret_cast<u8*>(info.data() + next_entry_index); | ||
| 476 | const auto* end = reinterpret_cast<u8*>(info.data() + next_entry_index + actual_entries); | ||
| 477 | const auto range_size = static_cast<std::size_t>(std::distance(begin, end)); | ||
| 478 | |||
| 479 | next_entry_index += actual_entries; | ||
| 480 | |||
| 481 | // Write the data to memory | ||
| 482 | ctx.WriteBuffer(begin, range_size); | ||
| 483 | |||
| 484 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 485 | rb.Push(RESULT_SUCCESS); | ||
| 486 | rb.Push<u32>(static_cast<u32>(actual_entries)); | ||
| 487 | } | ||
| 488 | |||
| 489 | private: | ||
| 490 | static u64 stoull_be(std::string_view str) { | ||
| 491 | if (str.size() != 16) | ||
| 492 | return 0; | ||
| 493 | |||
| 494 | const auto bytes = Common::HexStringToArray<0x8>(str); | ||
| 495 | u64 out{}; | ||
| 496 | std::memcpy(&out, bytes.data(), sizeof(u64)); | ||
| 497 | |||
| 498 | return Common::swap64(out); | ||
| 499 | } | ||
| 500 | |||
| 501 | void FindAllSaves(FileSys::SaveDataSpaceId space) { | ||
| 502 | const auto save_root = OpenSaveDataSpace(space); | ||
| 503 | ASSERT(save_root.Succeeded()); | ||
| 504 | |||
| 505 | for (const auto& type : (*save_root)->GetSubdirectories()) { | ||
| 506 | if (type->GetName() == "save") { | ||
| 507 | for (const auto& save_id : type->GetSubdirectories()) { | ||
| 508 | for (const auto& user_id : save_id->GetSubdirectories()) { | ||
| 509 | const auto save_id_numeric = stoull_be(save_id->GetName()); | ||
| 510 | auto user_id_numeric = Common::HexStringToArray<0x10>(user_id->GetName()); | ||
| 511 | std::reverse(user_id_numeric.begin(), user_id_numeric.end()); | ||
| 512 | |||
| 513 | if (save_id_numeric != 0) { | ||
| 514 | // System Save Data | ||
| 515 | info.emplace_back(SaveDataInfo{ | ||
| 516 | 0, | ||
| 517 | space, | ||
| 518 | FileSys::SaveDataType::SystemSaveData, | ||
| 519 | {}, | ||
| 520 | user_id_numeric, | ||
| 521 | save_id_numeric, | ||
| 522 | 0, | ||
| 523 | user_id->GetSize(), | ||
| 524 | {}, | ||
| 525 | }); | ||
| 526 | |||
| 527 | continue; | ||
| 528 | } | ||
| 529 | |||
| 530 | for (const auto& title_id : user_id->GetSubdirectories()) { | ||
| 531 | const auto device = | ||
| 532 | std::all_of(user_id_numeric.begin(), user_id_numeric.end(), | ||
| 533 | [](u8 val) { return val == 0; }); | ||
| 534 | info.emplace_back(SaveDataInfo{ | ||
| 535 | 0, | ||
| 536 | space, | ||
| 537 | device ? FileSys::SaveDataType::DeviceSaveData | ||
| 538 | : FileSys::SaveDataType::SaveData, | ||
| 539 | {}, | ||
| 540 | user_id_numeric, | ||
| 541 | save_id_numeric, | ||
| 542 | stoull_be(title_id->GetName()), | ||
| 543 | title_id->GetSize(), | ||
| 544 | {}, | ||
| 545 | }); | ||
| 546 | } | ||
| 547 | } | ||
| 548 | } | ||
| 549 | } else if (space == FileSys::SaveDataSpaceId::TemporaryStorage) { | ||
| 550 | // Temporary Storage | ||
| 551 | for (const auto& user_id : type->GetSubdirectories()) { | ||
| 552 | for (const auto& title_id : user_id->GetSubdirectories()) { | ||
| 553 | if (!title_id->GetFiles().empty() || | ||
| 554 | !title_id->GetSubdirectories().empty()) { | ||
| 555 | auto user_id_numeric = | ||
| 556 | Common::HexStringToArray<0x10>(user_id->GetName()); | ||
| 557 | std::reverse(user_id_numeric.begin(), user_id_numeric.end()); | ||
| 558 | |||
| 559 | info.emplace_back(SaveDataInfo{ | ||
| 560 | 0, | ||
| 561 | space, | ||
| 562 | FileSys::SaveDataType::TemporaryStorage, | ||
| 563 | {}, | ||
| 564 | user_id_numeric, | ||
| 565 | stoull_be(type->GetName()), | ||
| 566 | stoull_be(title_id->GetName()), | ||
| 567 | title_id->GetSize(), | ||
| 568 | {}, | ||
| 569 | }); | ||
| 570 | } | ||
| 571 | } | ||
| 572 | } | ||
| 573 | } | ||
| 574 | } | ||
| 575 | } | ||
| 576 | |||
| 577 | struct SaveDataInfo { | ||
| 578 | u64_le save_id_unknown; | ||
| 579 | FileSys::SaveDataSpaceId space; | ||
| 580 | FileSys::SaveDataType type; | ||
| 581 | INSERT_PADDING_BYTES(0x6); | ||
| 582 | std::array<u8, 0x10> user_id; | ||
| 583 | u64_le save_id; | ||
| 584 | u64_le title_id; | ||
| 585 | u64_le save_image_size; | ||
| 586 | INSERT_PADDING_BYTES(0x28); | ||
| 587 | }; | ||
| 588 | static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size."); | ||
| 589 | |||
| 590 | std::vector<SaveDataInfo> info; | ||
| 591 | u64 next_entry_index = 0; | ||
| 592 | }; | ||
| 593 | |||
| 454 | FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { | 594 | FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { |
| 595 | // clang-format off | ||
| 455 | static const FunctionInfo functions[] = { | 596 | static const FunctionInfo functions[] = { |
| 456 | {0, nullptr, "MountContent"}, | 597 | {0, nullptr, "MountContent"}, |
| 457 | {1, &FSP_SRV::Initialize, "Initialize"}, | 598 | {1, &FSP_SRV::Initialize, "Initialize"}, |
| @@ -485,7 +626,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { | |||
| 485 | {58, nullptr, "ReadSaveDataFileSystemExtraData"}, | 626 | {58, nullptr, "ReadSaveDataFileSystemExtraData"}, |
| 486 | {59, nullptr, "WriteSaveDataFileSystemExtraData"}, | 627 | {59, nullptr, "WriteSaveDataFileSystemExtraData"}, |
| 487 | {60, nullptr, "OpenSaveDataInfoReader"}, | 628 | {60, nullptr, "OpenSaveDataInfoReader"}, |
| 488 | {61, nullptr, "OpenSaveDataInfoReaderBySaveDataSpaceId"}, | 629 | {61, &FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId, "OpenSaveDataInfoReaderBySaveDataSpaceId"}, |
| 489 | {62, nullptr, "OpenCacheStorageList"}, | 630 | {62, nullptr, "OpenCacheStorageList"}, |
| 490 | {64, nullptr, "OpenSaveDataInternalStorageFileSystem"}, | 631 | {64, nullptr, "OpenSaveDataInternalStorageFileSystem"}, |
| 491 | {65, nullptr, "UpdateSaveDataMacForDebug"}, | 632 | {65, nullptr, "UpdateSaveDataMacForDebug"}, |
| @@ -544,6 +685,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { | |||
| 544 | {1009, nullptr, "GetAndClearMemoryReportInfo"}, | 685 | {1009, nullptr, "GetAndClearMemoryReportInfo"}, |
| 545 | {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"}, | 686 | {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"}, |
| 546 | }; | 687 | }; |
| 688 | // clang-format on | ||
| 547 | RegisterHandlers(functions); | 689 | RegisterHandlers(functions); |
| 548 | } | 690 | } |
| 549 | 691 | ||
| @@ -618,6 +760,15 @@ void FSP_SRV::OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx) { | |||
| 618 | MountSaveData(ctx); | 760 | MountSaveData(ctx); |
| 619 | } | 761 | } |
| 620 | 762 | ||
| 763 | void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx) { | ||
| 764 | IPC::RequestParser rp{ctx}; | ||
| 765 | const auto space = rp.PopRaw<FileSys::SaveDataSpaceId>(); | ||
| 766 | |||
| 767 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 768 | rb.Push(RESULT_SUCCESS); | ||
| 769 | rb.PushIpcInterface<ISaveDataInfoReader>(std::make_shared<ISaveDataInfoReader>(space)); | ||
| 770 | } | ||
| 771 | |||
| 621 | void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { | 772 | void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { |
| 622 | LOG_WARNING(Service_FS, "(STUBBED) called"); | 773 | LOG_WARNING(Service_FS, "(STUBBED) called"); |
| 623 | 774 | ||
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index 4aa0358cb..e7abec0a3 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h | |||
| @@ -25,6 +25,7 @@ private: | |||
| 25 | void CreateSaveData(Kernel::HLERequestContext& ctx); | 25 | void CreateSaveData(Kernel::HLERequestContext& ctx); |
| 26 | void MountSaveData(Kernel::HLERequestContext& ctx); | 26 | void MountSaveData(Kernel::HLERequestContext& ctx); |
| 27 | void OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx); | 27 | void OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx); |
| 28 | void OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx); | ||
| 28 | void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); | 29 | void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); |
| 29 | void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); | 30 | void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); |
| 30 | void OpenDataStorageByDataId(Kernel::HLERequestContext& ctx); | 31 | void OpenDataStorageByDataId(Kernel::HLERequestContext& ctx); |
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 07c1381fe..1d2978f24 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp | |||
| @@ -2,6 +2,9 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | ||
| 6 | #include "core/file_sys/control_metadata.h" | ||
| 7 | #include "core/file_sys/patch_manager.h" | ||
| 5 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 6 | #include "core/hle/kernel/hle_ipc.h" | 9 | #include "core/hle/kernel/hle_ipc.h" |
| 7 | #include "core/hle/service/ns/ns.h" | 10 | #include "core/hle/service/ns/ns.h" |
| @@ -118,7 +121,7 @@ public: | |||
| 118 | {305, nullptr, "TerminateSystemApplet"}, | 121 | {305, nullptr, "TerminateSystemApplet"}, |
| 119 | {306, nullptr, "LaunchOverlayApplet"}, | 122 | {306, nullptr, "LaunchOverlayApplet"}, |
| 120 | {307, nullptr, "TerminateOverlayApplet"}, | 123 | {307, nullptr, "TerminateOverlayApplet"}, |
| 121 | {400, nullptr, "GetApplicationControlData"}, | 124 | {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"}, |
| 122 | {401, nullptr, "InvalidateAllApplicationControlCache"}, | 125 | {401, nullptr, "InvalidateAllApplicationControlCache"}, |
| 123 | {402, nullptr, "RequestDownloadApplicationControlData"}, | 126 | {402, nullptr, "RequestDownloadApplicationControlData"}, |
| 124 | {403, nullptr, "GetMaxApplicationControlCacheCount"}, | 127 | {403, nullptr, "GetMaxApplicationControlCacheCount"}, |
| @@ -243,6 +246,65 @@ public: | |||
| 243 | 246 | ||
| 244 | RegisterHandlers(functions); | 247 | RegisterHandlers(functions); |
| 245 | } | 248 | } |
| 249 | |||
| 250 | void GetApplicationControlData(Kernel::HLERequestContext& ctx) { | ||
| 251 | IPC::RequestParser rp{ctx}; | ||
| 252 | const auto flag = rp.PopRaw<u64>(); | ||
| 253 | LOG_DEBUG(Service_NS, "called with flag={:016X}", flag); | ||
| 254 | |||
| 255 | const auto title_id = rp.PopRaw<u64>(); | ||
| 256 | |||
| 257 | const auto size = ctx.GetWriteBufferSize(); | ||
| 258 | |||
| 259 | const FileSys::PatchManager pm{title_id}; | ||
| 260 | const auto control = pm.GetControlMetadata(); | ||
| 261 | |||
| 262 | std::vector<u8> out; | ||
| 263 | |||
| 264 | if (control.first != nullptr) { | ||
| 265 | if (size < 0x4000) { | ||
| 266 | LOG_ERROR(Service_NS, | ||
| 267 | "output buffer is too small! (actual={:016X}, expected_min=0x4000)", | ||
| 268 | size); | ||
| 269 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 270 | // TODO(DarkLordZach): Find a better error code for this. | ||
| 271 | rb.Push(ResultCode(-1)); | ||
| 272 | return; | ||
| 273 | } | ||
| 274 | |||
| 275 | out.resize(0x4000); | ||
| 276 | const auto bytes = control.first->GetRawBytes(); | ||
| 277 | std::memcpy(out.data(), bytes.data(), bytes.size()); | ||
| 278 | } else { | ||
| 279 | LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.", | ||
| 280 | title_id); | ||
| 281 | out.resize(std::min<u64>(0x4000, size)); | ||
| 282 | } | ||
| 283 | |||
| 284 | if (control.second != nullptr) { | ||
| 285 | if (size < 0x4000 + control.second->GetSize()) { | ||
| 286 | LOG_ERROR(Service_NS, | ||
| 287 | "output buffer is too small! (actual={:016X}, expected_min={:016X})", | ||
| 288 | size, 0x4000 + control.second->GetSize()); | ||
| 289 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 290 | // TODO(DarkLordZach): Find a better error code for this. | ||
| 291 | rb.Push(ResultCode(-1)); | ||
| 292 | return; | ||
| 293 | } | ||
| 294 | |||
| 295 | out.resize(0x4000 + control.second->GetSize()); | ||
| 296 | control.second->Read(out.data() + 0x4000, control.second->GetSize()); | ||
| 297 | } else { | ||
| 298 | LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.", | ||
| 299 | title_id); | ||
| 300 | } | ||
| 301 | |||
| 302 | ctx.WriteBuffer(out); | ||
| 303 | |||
| 304 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 305 | rb.Push(RESULT_SUCCESS); | ||
| 306 | rb.Push<u32>(static_cast<u32>(out.size())); | ||
| 307 | } | ||
| 246 | }; | 308 | }; |
| 247 | 309 | ||
| 248 | class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { | 310 | class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { |
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index bc8e402a8..c8e491fec 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -12,10 +12,12 @@ | |||
| 12 | #include "common/swap.h" | 12 | #include "common/swap.h" |
| 13 | #include "core/core.h" | 13 | #include "core/core.h" |
| 14 | #include "core/file_sys/control_metadata.h" | 14 | #include "core/file_sys/control_metadata.h" |
| 15 | #include "core/file_sys/romfs_factory.h" | ||
| 15 | #include "core/file_sys/vfs_offset.h" | 16 | #include "core/file_sys/vfs_offset.h" |
| 16 | #include "core/gdbstub/gdbstub.h" | 17 | #include "core/gdbstub/gdbstub.h" |
| 17 | #include "core/hle/kernel/process.h" | 18 | #include "core/hle/kernel/process.h" |
| 18 | #include "core/hle/kernel/vm_manager.h" | 19 | #include "core/hle/kernel/vm_manager.h" |
| 20 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 19 | #include "core/loader/nro.h" | 21 | #include "core/loader/nro.h" |
| 20 | #include "core/loader/nso.h" | 22 | #include "core/loader/nso.h" |
| 21 | #include "core/memory.h" | 23 | #include "core/memory.h" |
| @@ -208,6 +210,9 @@ ResultStatus AppLoader_NRO::Load(Kernel::Process& process) { | |||
| 208 | return ResultStatus::ErrorLoadingNRO; | 210 | return ResultStatus::ErrorLoadingNRO; |
| 209 | } | 211 | } |
| 210 | 212 | ||
| 213 | if (romfs != nullptr) | ||
| 214 | Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this)); | ||
| 215 | |||
| 211 | process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); | 216 | process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); |
| 212 | 217 | ||
| 213 | is_loaded = true; | 218 | is_loaded = true; |