diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 96258ecf9..2feae2983 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -444,6 +444,10 @@ std::string GetTitlePath(Service::FS::MediaType media_type, u64 tid); */ std::string GetMediaTitlePath(Service::FS::MediaType media_type); +Result GetTitleInfoFromList(Core::System& system, std::span title_id_list, + Service::FS::MediaType media_type, + std::vector& title_info_out); + /** * Uninstalls the specified title. * @param media_type the storage medium the title is installed to diff --git a/src/core/hle/service/apt/applet_manager.cpp b/src/core/hle/service/apt/applet_manager.cpp index 535b970dc..1bc2c0266 100644 --- a/src/core/hle/service/apt/applet_manager.cpp +++ b/src/core/hle/service/apt/applet_manager.cpp @@ -105,7 +105,7 @@ static constexpr std::array applet_titleids = {{ // TODO(Subv): Fill in the rest of the titleids }}; -static u64 GetTitleIdForApplet(AppletId id, u32 region_value) { +u64 GetTitleIdForApplet(AppletId id, u32 region_value) { ASSERT_MSG(id != AppletId::None, "Invalid applet id"); auto itr = std::find_if(applet_titleids.begin(), applet_titleids.end(), diff --git a/src/core/hle/service/apt/applet_manager.h b/src/core/hle/service/apt/applet_manager.h index eea184b74..507841dd5 100644 --- a/src/core/hle/service/apt/applet_manager.h +++ b/src/core/hle/service/apt/applet_manager.h @@ -104,6 +104,8 @@ enum class AppletId : u32 { TypeMask = 0xF00, }; +u64 GetTitleIdForApplet(AppletId id, u32 region_value); + /// Application Old/New 3DS target platforms enum class TargetPlatform : u8 { Old3ds = 0, diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index c3dc315c4..2fbaeca65 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -1432,6 +1432,58 @@ void Module::APTInterface::Reboot(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void Module::APTInterface::GetAppletProgramInfo(Kernel::HLERequestContext& ctx) { + union { + u32 raw; + BitField<0, 1, u32> mediatype_nand; + BitField<1, 1, u32> mediatype_sdmc; + BitField<2, 1, u32> mediatype_gamecard; + BitField<4, 1, u32> is_appid; + BitField<5, 1, u32> not_appid_must_set; + BitField<8, 1, u32> is_system_app; + } flags; + + IPC::RequestParser rp(ctx); + u32 program_id = rp.Pop(); + flags.raw = rp.Pop(); + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + + u64 title_id; + if (flags.is_appid) { + auto cfg = Service::CFG::GetModule(apt->system); + title_id = + GetTitleIdForApplet(static_cast(program_id), cfg->GetRegionValue(true)); + } else { + if (!flags.not_appid_must_set) { + rb.Push(ResultUnknown); // TODO: Find proper error code + rb.Push(0); + return; + } else { + u32 tid_high = flags.is_system_app ? 0x00040010 : 0x00040000; + title_id = static_cast(tid_high) << 32 | program_id; + } + } + + std::vector info; + Result res = ResultUnknown; // TODO: Find proper error code + if (res.IsError() && flags.mediatype_nand) { + res = Service::AM::GetTitleInfoFromList(apt->system, std::span(&title_id, 1), + FS::MediaType::NAND, info); + } + if (res.IsError() && flags.mediatype_sdmc) { + res = Service::AM::GetTitleInfoFromList(apt->system, std::span(&title_id, 1), + FS::MediaType::SDMC, info); + } + if (res.IsError() && flags.mediatype_gamecard) { + res = Service::AM::GetTitleInfoFromList(apt->system, std::span(&title_id, 1), + FS::MediaType::GameCard, info); + } + + rb.Push(res); + rb.Push(res.IsSuccess() ? info[0].version : 0); +} + void Module::APTInterface::HardwareResetAsync(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx); diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 0bc4825ab..68c8fff05 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -1009,6 +1009,8 @@ public: */ void Reboot(Kernel::HLERequestContext& ctx); + void GetAppletProgramInfo(Kernel::HLERequestContext& ctx); + /** * APT::HardwareResetAsync service function. * Outputs: diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp index ab2314983..25a8b40ee 100644 --- a/src/core/hle/service/apt/apt_a.cpp +++ b/src/core/hle/service/apt/apt_a.cpp @@ -87,7 +87,7 @@ APT_A::APT_A(std::shared_ptr apt) {0x004A, &APT_A::GetCaptureInfo, "GetCaptureInfo"}, {0x004B, &APT_A::AppletUtility, "AppletUtility"}, {0x004C, nullptr, "SetFatalErrDispMode"}, - {0x004D, nullptr, "GetAppletProgramInfo"}, + {0x004D, &APT_A::GetAppletProgramInfo, "GetAppletProgramInfo"}, {0x004E, &APT_A::HardwareResetAsync, "HardwareResetAsync"}, {0x004F, &APT_A::SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, {0x0050, &APT_A::GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp index 1ffc074c4..3d83f296a 100644 --- a/src/core/hle/service/apt/apt_s.cpp +++ b/src/core/hle/service/apt/apt_s.cpp @@ -87,7 +87,7 @@ APT_S::APT_S(std::shared_ptr apt) {0x004A, &APT_S::GetCaptureInfo, "GetCaptureInfo"}, {0x004B, &APT_S::AppletUtility, "AppletUtility"}, {0x004C, nullptr, "SetFatalErrDispMode"}, - {0x004D, nullptr, "GetAppletProgramInfo"}, + {0x004D, &APT_S::GetAppletProgramInfo, "GetAppletProgramInfo"}, {0x004E, &APT_S::HardwareResetAsync, "HardwareResetAsync"}, {0x004F, &APT_S::SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, {0x0050, &APT_S::GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp index eb1cb5c98..0cc411c7a 100644 --- a/src/core/hle/service/apt/apt_u.cpp +++ b/src/core/hle/service/apt/apt_u.cpp @@ -87,7 +87,7 @@ APT_U::APT_U(std::shared_ptr apt) {0x004A, &APT_U::GetCaptureInfo, "GetCaptureInfo"}, {0x004B, &APT_U::AppletUtility, "AppletUtility"}, {0x004C, nullptr, "SetFatalErrDispMode"}, - {0x004D, nullptr, "GetAppletProgramInfo"}, + {0x004D, &APT_U::GetAppletProgramInfo, "GetAppletProgramInfo"}, {0x004E, &APT_U::HardwareResetAsync, "HardwareResetAsync"}, {0x004F, &APT_U::SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, {0x0050, &APT_U::GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},