diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 767faf167..c4ed0d42c 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -289,6 +289,16 @@ ResultCode ArchiveManager::CreateSystemSaveData(u32 high, u32 low) { return RESULT_SUCCESS; } +ResultVal ArchiveManager::GetArchiveResource(MediaType media_type) const { + // TODO(Subv): Implement querying the actual size information for these storages. + ArchiveResource resource{}; + resource.sector_size_in_bytes = 512; + resource.cluster_size_in_bytes = 16384; + resource.partition_capacity_in_clusters = 0x80000; // 8GiB capacity + resource.free_space_in_clusters = 0x80000; // 8GiB free + return MakeResult(resource); +} + void ArchiveManager::RegisterArchiveTypes() { // TODO(Subv): Add the other archive types (see here for the known types: // http://3dbrew.org/wiki/FS:OpenArchive#Archive_idcodes). diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index aba06ac6f..97696e4bb 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -50,6 +50,14 @@ enum class MediaType : u32 { NAND = 0, SDMC = 1, GameCard = 2 }; typedef u64 ArchiveHandle; +struct ArchiveResource { + u32 sector_size_in_bytes; + u32 cluster_size_in_bytes; + u32 partition_capacity_in_clusters; + u32 free_space_in_clusters; +}; +static_assert(sizeof(ArchiveResource) == 0x10, "ArchiveResource has incorrect size"); + using FileSys::ArchiveBackend; using FileSys::ArchiveFactory; @@ -231,6 +239,13 @@ public: */ ResultCode CreateSystemSaveData(u32 high, u32 low); + /** + * Returns capacity and free space information about the given media type. + * @param media_type The media type to obtain the information about. + * @return The capacity information of the media type, or an error code if failed. + */ + ResultVal GetArchiveResource(MediaType media_type) const; + /// Registers a new NCCH file with the SelfNCCH archive factory void RegisterSelfNCCH(Loader::AppLoader& app_loader); diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 010600ee2..8fea8a3eb 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -444,6 +444,41 @@ void FS_USER::GetFreeBytes(Kernel::HLERequestContext& ctx) { } } +void FS_USER::GetSdmcArchiveResource(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x814, 0, 0); + + LOG_WARNING(Service_FS, "(STUBBED) called"); + + auto resource = archives.GetArchiveResource(MediaType::SDMC); + + if (resource.Failed()) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(resource.Code()); + return; + } + + IPC::RequestBuilder rb = rp.MakeBuilder(5, 0); + rb.Push(RESULT_SUCCESS); + rb.PushRaw(*resource); +} + +void FS_USER::GetNandArchiveResource(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x815, 0, 0); + + LOG_WARNING(Service_FS, "(STUBBED) called"); + + auto resource = archives.GetArchiveResource(MediaType::NAND); + if (resource.Failed()) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(resource.Code()); + return; + } + + IPC::RequestBuilder rb = rp.MakeBuilder(5, 0); + rb.Push(RESULT_SUCCESS); + rb.PushRaw(*resource); +} + void FS_USER::CreateExtSaveData(Kernel::HLERequestContext& ctx) { // TODO(Subv): Figure out the other parameters. IPC::RequestParser rp(ctx, 0x0851, 9, 2); @@ -596,16 +631,20 @@ void FS_USER::GetPriority(Kernel::HLERequestContext& ctx) { void FS_USER::GetArchiveResource(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x849, 1, 0); - u32 system_media_type = rp.Pop(); + auto media_type = rp.PopEnum(); - LOG_WARNING(Service_FS, "(STUBBED) called Media type=0x{:08X}", system_media_type); + LOG_WARNING(Service_FS, "(STUBBED) called Media type=0x{:08X}", static_cast(media_type)); + + auto resource = archives.GetArchiveResource(media_type); + if (resource.Failed()) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(resource.Code()); + return; + } IPC::RequestBuilder rb = rp.MakeBuilder(5, 0); rb.Push(RESULT_SUCCESS); - rb.Push(512); - rb.Push(16384); - rb.Push(0x80000); // 8GiB capacity - rb.Push(0x80000); // 8GiB free + rb.PushRaw(*resource); } void FS_USER::GetFormatInfo(Kernel::HLERequestContext& ctx) { @@ -793,8 +832,8 @@ FS_USER::FS_USER(Core::System& system) {0x08110040, nullptr, "DeleteSystemSaveData"}, {0x08120080, &FS_USER::GetFreeBytes, "GetFreeBytes"}, {0x08130000, nullptr, "GetCardType"}, - {0x08140000, nullptr, "GetSdmcArchiveResource"}, - {0x08150000, nullptr, "GetNandArchiveResource"}, + {0x08140000, &FS_USER::GetSdmcArchiveResource, "GetSdmcArchiveResource"}, + {0x08150000, &FS_USER::GetNandArchiveResource, "GetNandArchiveResource"}, {0x08160000, nullptr, "GetSdmcFatfsError"}, {0x08170000, &FS_USER::IsSdmcDetected, "IsSdmcDetected"}, {0x08180000, &FS_USER::IsSdmcWriteable, "IsSdmcWritable"}, diff --git a/src/core/hle/service/fs/fs_user.h b/src/core/hle/service/fs/fs_user.h index e972d0dae..243b8f858 100644 --- a/src/core/hle/service/fs/fs_user.h +++ b/src/core/hle/service/fs/fs_user.h @@ -301,6 +301,32 @@ private: */ void GetFreeBytes(Kernel::HLERequestContext& ctx); + /** + * FS_User::GetSdmcArchiveResource service function. + * Inputs: + * 0 : 0x08140000 + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Sector byte-size + * 3 : Cluster byte-size + * 4 : Partition capacity in clusters + * 5 : Available free space in clusters + */ + void GetSdmcArchiveResource(Kernel::HLERequestContext& ctx); + + /** + * FS_User::GetNandArchiveResource service function. + * Inputs: + * 0 : 0x08150000 + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Sector byte-size + * 3 : Cluster byte-size + * 4 : Partition capacity in clusters + * 5 : Available free space in clusters + */ + void GetNandArchiveResource(Kernel::HLERequestContext& ctx); + /** * FS_User::CreateExtSaveData service function * Inputs: