Browse Source

[hle] adjust GetApplicationControlData to FW20+ to make on FW20.0.0 - FW20.5.0 icons work

pull/3153/head
Maufeat 4 weeks ago
parent
commit
531266c2ee
  1. 52
      src/core/hle/service/ns/application_manager_interface.cpp
  2. 7
      src/core/hle/service/ns/application_manager_interface.h
  3. 84
      src/core/hle/service/ns/ns_types.h
  4. 79
      src/core/hle/service/ns/read_only_application_control_data_interface.cpp
  5. 11
      src/core/hle/service/ns/read_only_application_control_data_interface.h

52
src/core/hle/service/ns/application_manager_interface.cpp

@ -13,6 +13,7 @@
#include "core/hle/service/ns/content_management_interface.h"
#include "core/hle/service/ns/read_only_application_control_data_interface.h"
#include "core/file_sys/patch_manager.h"
#include "frontend_common/firmware_manager.h"
namespace Service::NS {
@ -429,13 +430,13 @@ Result IApplicationManagerInterface::IsAnyApplicationEntityInstalled(
}
Result IApplicationManagerInterface::GetApplicationViewDeprecated(
OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
OutArray<ApplicationViewV19, BufferAttr_HipcMapAlias> out_application_views,
InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
const auto size = (std::min)(out_application_views.size(), application_ids.size());
LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size());
for (size_t i = 0; i < size; i++) {
ApplicationView view{};
ApplicationViewV19 view{};
view.application_id = application_ids[i];
view.version = 0x70000;
view.flags = 0x401f17;
@ -447,34 +448,53 @@ Result IApplicationManagerInterface::GetApplicationViewDeprecated(
}
Result IApplicationManagerInterface::GetApplicationViewWithPromotionInfo(
OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views,
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
Out<u32> out_count,
InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
const auto size = (std::min)(out_application_views.size(), application_ids.size());
LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size());
for (size_t i = 0; i < size; i++) {
ApplicationViewWithPromotionInfo view{};
view.view.application_id = application_ids[i];
view.view.version = 0x70000;
view.view.flags = 0x401f17;
view.promotion = {};
out_application_views[i] = view;
const auto requested = application_ids.size();
LOG_WARNING(Service_NS, "(STUBBED) called, size={}", requested);
const auto fw_pair = FirmwareManager::GetFirmwareVersion(system);
const bool is_fw20 = fw_pair.first.major >= 20;
const size_t per_entry_size = is_fw20 ? (sizeof(ApplicationViewV20) + sizeof(PromotionInfo))
: (sizeof(ApplicationViewV19) + sizeof(PromotionInfo));
const size_t capacity_entries = out_buffer.size() / per_entry_size;
const size_t to_write_entries = (std::min)(requested, capacity_entries);
u8* dst = out_buffer.data();
for (size_t i = 0; i < to_write_entries; ++i) {
ApplicationViewWithPromotionData data{};
data.view.application_id = application_ids[i];
data.view.version = 0x70000;
data.view.unk = 0;
data.view.flags = 0x401f17;
data.view.download_state = {};
data.view.download_progress = {};
data.promotion = {};
const size_t written = WriteApplicationViewWithPromotion(dst, out_buffer.size() - (dst - out_buffer.data()), data, is_fw20);
if (written == 0) {
break;
}
dst += written;
}
*out_count = static_cast<u32>(dst - out_buffer.data()) / static_cast<u32>(per_entry_size);
R_SUCCEED();
}
Result IApplicationManagerInterface::GetApplicationView(
OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
OutArray<ApplicationViewV20, BufferAttr_HipcMapAlias> out_application_views,
InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
const auto size = (std::min)(out_application_views.size(), application_ids.size());
LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size());
for (size_t i = 0; i < size; i++) {
ApplicationView view{};
ApplicationViewV20 view{};
view.application_id = application_ids[i];
view.version = 0x70000;
view.unk = 0;
view.flags = 0x401f17;
out_application_views[i] = view;

7
src/core/hle/service/ns/application_manager_interface.h

@ -36,13 +36,14 @@ public:
Result IsGameCardApplicationRunning(Out<bool> out_is_running);
Result IsAnyApplicationEntityInstalled(Out<bool> out_is_any_application_entity_installed);
Result GetApplicationViewDeprecated(
OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
OutArray<ApplicationViewV19, BufferAttr_HipcMapAlias> out_application_views,
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
Result GetApplicationViewWithPromotionInfo(
OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views,
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
Out<u32> out_count,
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
Result GetApplicationView(
OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
OutArray<ApplicationViewV20, BufferAttr_HipcMapAlias> out_application_views,
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
Result GetApplicationRightsOnClient(
OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count,

84
src/core/hle/service/ns/ns_types.h

@ -55,16 +55,6 @@ struct ApplicationDownloadState {
static_assert(sizeof(ApplicationDownloadState) == 0x20,
"ApplicationDownloadState has incorrect size.");
/// ApplicationView
struct ApplicationView {
u64 application_id; ///< ApplicationId.
u32 version; ///< Application Version(?)
u32 flags; ///< Flags.
ApplicationDownloadState download_state; ///< \ref ApplicationDownloadState
ApplicationDownloadState download_progress; ///< \ref ApplicationDownloadState
};
static_assert(sizeof(ApplicationView) == 0x50, "ApplicationView has incorrect size.");
struct ApplicationRightsOnClient {
u64 application_id;
Common::UUID uid;
@ -88,14 +78,74 @@ struct PromotionInfo {
};
static_assert(sizeof(PromotionInfo) == 0x20, "PromotionInfo has incorrect size.");
// TODO(Maufeat): NsApplicationViewWithPromotionInfo is on SDK20+ 0x78 bytes
/// NsApplicationViewWithPromotionInfo
struct ApplicationViewWithPromotionInfo {
ApplicationView view; ///< \ref NsApplicationView
PromotionInfo promotion; ///< \ref NsPromotionInfo
struct ApplicationViewV19 {
u64 application_id;
u32 version;
u32 flags;
ApplicationDownloadState download_state;
ApplicationDownloadState download_progress;
};
static_assert(sizeof(ApplicationViewV19) == 0x50, "ApplicationViewV19 has incorrect size.");
struct ApplicationViewV20 {
u64 application_id;
u32 version;
u32 unk;
u32 flags;
ApplicationDownloadState download_state;
ApplicationDownloadState download_progress;
};
static_assert(sizeof(ApplicationViewV20) == 0x58, "ApplicationViewV20 has incorrect size.");
struct ApplicationViewData {
u64 application_id{};
u32 version{};
u32 unk{};
u32 flags{};
ApplicationDownloadState download_state{};
ApplicationDownloadState download_progress{};
};
static_assert(sizeof(ApplicationViewWithPromotionInfo) == 0x70,
"ApplicationViewWithPromotionInfo has incorrect size.");
inline size_t WriteApplicationView(void* dst, size_t dst_size, const ApplicationViewData& data,
bool is_fw20) {
if (is_fw20) {
if (dst_size < sizeof(ApplicationViewV20)) return 0;
auto* out = reinterpret_cast<ApplicationViewV20*>(dst);
out->application_id = data.application_id;
out->version = data.version;
out->unk = data.unk;
out->flags = data.flags;
out->download_state = data.download_state;
out->download_progress = data.download_progress;
return sizeof(ApplicationViewV20);
} else {
if (dst_size < sizeof(ApplicationViewV19)) return 0;
auto* out = reinterpret_cast<ApplicationViewV19*>(dst);
out->application_id = data.application_id;
out->version = data.version;
out->flags = data.flags;
out->download_state = data.download_state;
out->download_progress = data.download_progress;
return sizeof(ApplicationViewV19);
}
}
struct ApplicationViewWithPromotionData {
ApplicationViewData view;
PromotionInfo promotion;
};
inline size_t WriteApplicationViewWithPromotion(void* dst, size_t dst_size,
const ApplicationViewWithPromotionData& data,
bool sdk20_plus) {
const size_t view_written = WriteApplicationView(dst, dst_size, data.view, sdk20_plus);
if (view_written == 0) return 0;
const size_t remaining = dst_size - view_written;
if (remaining < sizeof(PromotionInfo)) return 0;
auto* promo_dst = reinterpret_cast<u8*>(dst) + view_written;
std::memcpy(promo_dst, &data.promotion, sizeof(PromotionInfo));
return view_written + sizeof(PromotionInfo);
}
struct ApplicationOccupiedSizeEntity {
FileSys::StorageId storage_id;

79
src/core/hle/service/ns/read_only_application_control_data_interface.cpp

@ -27,8 +27,8 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa
{2, D<&IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"},
{3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
{4, nullptr, "SelectApplicationDesiredLanguage"},
{5, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlDataWithoutIcon>, "GetApplicationControlDataWithoutIcon"},
{19, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlDataWithoutIcon>, "GetApplicationControlDataWithoutIcon"},
{5, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData2>, "GetApplicationControlDataWithoutIcon"},
{19, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData3>, "GetApplicationControlDataWithoutIcon3"},
};
// clang-format on
@ -125,11 +125,68 @@ Result IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLan
R_SUCCEED();
}
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlDataWithoutIcon(
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData2(
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u64> out_total_size,
ApplicationControlSource application_control_source, u64 application_id) {
LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
application_control_source, application_id);
ApplicationControlSource application_control_source, u8 flag1, u8 flag2, u64 application_id) {
LOG_INFO(Service_NS, "called with control_source={}, flags=({:02X},{:02X}), application_id={:016X}",
application_control_source, flag1, flag2, application_id);
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(),
system.GetContentProvider()};
const auto control = pm.GetControlMetadata();
const auto size = out_buffer.size();
const auto nacp_size = sizeof(FileSys::RawNACP);
if (size < nacp_size) {
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min={:08X})",
size, nacp_size);
R_THROW(ResultUnknown);
}
if (control.first != nullptr) {
const auto bytes = control.first->GetRawBytes();
const auto copy_len = (std::min)(static_cast<size_t>(bytes.size()), static_cast<size_t>(nacp_size));
std::memcpy(out_buffer.data(), bytes.data(), copy_len);
if (copy_len < nacp_size) {
std::memset(out_buffer.data() + copy_len, 0, nacp_size - copy_len);
}
} else {
LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}", application_id);
std::memset(out_buffer.data(), 0, nacp_size);
}
const auto icon_area_size = size - nacp_size;
size_t available_icon_bytes = 0;
if (control.second != nullptr) {
available_icon_bytes = control.second->GetSize();
}
if (icon_area_size > 0) {
if (control.second != nullptr) {
const size_t to_copy = std::min(available_icon_bytes, icon_area_size);
if (to_copy > 0) {
std::vector<u8> tmp(to_copy);
control.second->Read(tmp.data(), to_copy);
std::memcpy(out_buffer.data() + nacp_size, tmp.data(), to_copy);
}
if (to_copy < icon_area_size) {
std::memset(out_buffer.data() + nacp_size + to_copy, 0, icon_area_size - to_copy);
}
} else {
std::memset(out_buffer.data() + nacp_size, 0, icon_area_size);
}
}
const u32 total_available = static_cast<u32>(nacp_size + available_icon_bytes);
*out_total_size = (static_cast<u64>(total_available) << 32);
R_SUCCEED();
}
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData3(
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u64> out_total_size,
ApplicationControlSource application_control_source, u8 flag1, u8 flag2, u64 application_id) {
LOG_INFO(Service_NS, "called with control_source={}, flags=({:02X},{:02X}), application_id={:016X}",
application_control_source, flag1, flag2, application_id);
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(),
system.GetContentProvider()};
@ -158,10 +215,13 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlDataWithou
}
const auto icon_area_size = size - nacp_size;
size_t available_icon_bytes = 0;
if (control.second != nullptr) {
available_icon_bytes = control.second->GetSize();
}
if (icon_area_size > 0) {
if (control.second != nullptr) {
const auto icon_size = control.second->GetSize();
const auto to_copy = static_cast<size_t>((std::min)(icon_size, icon_area_size));
const auto to_copy = static_cast<size_t>((std::min)(available_icon_bytes, icon_area_size));
control.second->Read(out_buffer.data() + nacp_size, to_copy);
if (to_copy < icon_area_size) {
std::memset(out_buffer.data() + nacp_size + to_copy, 0, icon_area_size - to_copy);
@ -173,7 +233,8 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlDataWithou
}
}
*out_total_size = static_cast<u64>(size);
const u32 actual_total_size = static_cast<u32>(nacp_size + available_icon_bytes);
*out_total_size = static_cast<u64>(actual_total_size) << 32;
R_SUCCEED();
}

11
src/core/hle/service/ns/read_only_application_control_data_interface.h

@ -27,10 +27,19 @@ public:
u32 supported_languages);
Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code,
ApplicationLanguage application_language);
Result GetApplicationControlDataWithoutIcon(
Result GetApplicationControlData2(
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
Out<u64> out_total_size,
ApplicationControlSource application_control_source,
u8 flag1,
u8 flag2,
u64 application_id);
Result GetApplicationControlData3(
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
Out<u64> out_total_size,
ApplicationControlSource application_control_source,
u8 flag1,
u8 flag2,
u64 application_id);
};

Loading…
Cancel
Save