Skip to content

Commit 8ae63d8

Browse files
author
N3xoX1
committed
OS: get System::AddGlueRegistrationForProcess added
1 parent e80c653 commit 8ae63d8

16 files changed

Lines changed: 292 additions & 12 deletions

File tree

src/nxemu-loader/system_loader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ bool Systemloader::Impl::LoadNRO(const char* nroFile)
138138
m_TitleID = Nacp->GetTitleId();
139139
m_fsController.RegisterProcess(processID, m_TitleID, std::make_unique<FileSys::RomFSFactory>(nullptr, false, *m_contentProvider, m_fsController));
140140
g_settings->SetString(NXCoreSetting::GameName, Nacp->GetApplicationName().c_str());
141-
operatingSystem.StartApplicationProcess(baseAddress, metaData.GetMainThreadPriority(), metaData.GetMainThreadStackSize());
141+
operatingSystem.StartApplicationProcess(metaData.GetMainThreadPriority(), metaData.GetMainThreadStackSize(), 0, StorageId::None, StorageId::None, nullptr, 0);
142142
return true;
143143
}
144144

src/nxemu-module-spec/operating_system.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ enum class PoolPartition : uint32_t
1818
SystemNonSecure = 3,
1919
};
2020

21+
enum class StorageId : uint8_t {
22+
None = 0,
23+
Host = 1,
24+
GameCard = 2,
25+
NandSystem = 3,
26+
NandUser = 4,
27+
SdCard = 5,
28+
};
29+
2130
__interface IProgramMetadata
2231
{
2332
bool Is64BitProgram() const = 0;
@@ -58,7 +67,7 @@ __interface IOperatingSystem
5867
{
5968
bool Initialize(void) = 0;
6069
bool CreateApplicationProcess(uint64_t codeSize, const IProgramMetadata & metaData, uint64_t & baseAddress, uint64_t & processID, bool is_hbl) = 0;
61-
void StartApplicationProcess(uint64_t baseAddress, int32_t priority, int64_t stackSize) = 0;
70+
void StartApplicationProcess(int32_t priority, int64_t stackSize, uint32_t version, StorageId baseGameStorageId, StorageId updateStorageId, uint8_t * nacpData, uint32_t nacpDataLen) = 0;
6271
bool LoadModule(const IModuleInfo & module, uint64_t baseAddress) = 0;
6372
IDeviceMemory & DeviceMemory(void) = 0;
6473
void KeyboardKeyPress(int modifier, int keyIndex, int keyCode) = 0;

src/nxemu-os/core/core.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "core/hle/service/am/frontend/applets.h"
2121
#include "core/hle/service/apm/apm_controller.h"
2222
#include "core/hle/service/filesystem/filesystem.h"
23+
#include "core/hle/service/glue/glue_manager.h"
2324
#include "core/hle/service/services.h"
2425
#include "core/perf_stats.h"
2526
#include "yuzu_hid_core/hid_core.h"
@@ -121,6 +122,7 @@ struct System::Impl {
121122

122123
kernel.Initialize();
123124
cpu_manager.Initialize();
125+
arp_manager.ResetAll();
124126

125127
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
126128
services =
@@ -186,6 +188,9 @@ struct System::Impl {
186188
/// APM (Performance) services
187189
Service::APM::Controller apm_controller{core_timing};
188190

191+
/// Service State
192+
Service::Glue::ARPManager arp_manager;
193+
189194
/// Service manager
190195
std::shared_ptr<Service::SM::ServiceManager> service_manager;
191196

@@ -353,6 +358,23 @@ u64 System::GetApplicationProcessProgramID() const {
353358
return impl->kernel.ApplicationProcess()->GetProgramId();
354359
}
355360

361+
void System::AddGlueRegistrationForProcess(Kernel::KProcess & process, uint32_t version, StorageId baseGameStorageId, StorageId updateStorageId, uint8_t * nacpData, uint32_t nacpDataLen) {
362+
std::vector<u8> nacp_data;
363+
if (nacpDataLen > 0)
364+
{
365+
nacp_data.resize(nacpDataLen);
366+
memcpy(nacp_data.data(), nacpData, nacpDataLen);
367+
}
368+
369+
Service::Glue::ApplicationLaunchProperty launch{};
370+
launch.title_id = process.GetProgramId();
371+
launch.version = version;
372+
launch.base_game_storage_id = baseGameStorageId;
373+
launch.update_storage_id = updateStorageId;
374+
375+
impl->arp_manager.Register(launch.title_id, launch, std::move(nacp_data));
376+
}
377+
356378
void System::SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set) {
357379
impl->frontend_applets.SetFrontendAppletSet(std::move(set));
358380
}
@@ -373,6 +395,14 @@ IFileSystemController & System::GetFileSystemController() {
373395
return impl->fs_controller;
374396
}
375397

398+
Service::Glue::ARPManager& System::GetARPManager() {
399+
return impl->arp_manager;
400+
}
401+
402+
const Service::Glue::ARPManager& System::GetARPManager() const {
403+
return impl->arp_manager;
404+
}
405+
376406
Service::APM::Controller& System::GetAPMController() {
377407
return impl->apm_controller;
378408
}

src/nxemu-os/core/core.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
#include "yuzu_common/common_types.h"
1616

17+
enum class StorageId : uint8_t;
18+
1719
__interface ISwitchSystem;
1820
__interface IVideo;
1921
__interface ISystemloader;
@@ -321,6 +323,8 @@ class System {
321323
[[nodiscard]] Service::SM::ServiceManager& ServiceManager();
322324
[[nodiscard]] const Service::SM::ServiceManager& ServiceManager() const;
323325

326+
void AddGlueRegistrationForProcess(Kernel::KProcess& process, uint32_t version, StorageId baseGameStorageId, StorageId updateStorageId, uint8_t* nacpData, uint32_t nacpDataLen);
327+
324328
void RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
325329
const std::array<u8, 0x20>& build_id, u64 main_region_begin,
326330
u64 main_region_size);

src/nxemu-os/core/hle/service/acc/acc.cpp

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "yuzu_common/fs/path_util.h"
1010
#include "yuzu_common/logging/log.h"
1111
#include "yuzu_common/polyfill_ranges.h"
12+
#include "yuzu_common/stb.h"
1213
#include "yuzu_common/string_util.h"
1314
#include "yuzu_common/swap.h"
1415
#include "core/constants.h"
@@ -42,6 +43,31 @@ static void JPGToMemory(void* context, void* data, int len) {
4243
jpg_image->insert(jpg_image->end(), jpg, jpg + len);
4344
}
4445

46+
static void SanitizeJPEGImageSize(std::vector<u8>& image) {
47+
constexpr std::size_t max_jpeg_image_size = 0x20000;
48+
constexpr int profile_dimensions = 256;
49+
int original_width, original_height, color_channels;
50+
51+
const auto plain_image =
52+
stbi_load_from_memory(image.data(), static_cast<int>(image.size()), &original_width,
53+
&original_height, &color_channels, STBI_rgb);
54+
55+
// Resize image to match 256*256
56+
if (original_width != profile_dimensions || original_height != profile_dimensions) {
57+
// Use vector instead of array to avoid overflowing the stack
58+
std::vector<u8> out_image(profile_dimensions * profile_dimensions * STBI_rgb);
59+
stbir_resize_uint8_srgb(plain_image, original_width, original_height, 0, out_image.data(),
60+
profile_dimensions, profile_dimensions, 0, STBI_rgb, 0,
61+
STBIR_FILTER_BOX);
62+
image.clear();
63+
if (!stbi_write_jpg_to_func(JPGToMemory, &image, profile_dimensions, profile_dimensions,
64+
STBI_rgb, out_image.data(), 0)) {
65+
LOG_ERROR(Service_ACC, "Failed to resize the user provided image.");
66+
}
67+
}
68+
69+
image.resize(std::min(image.size(), max_jpeg_image_size));
70+
}
4571

4672
class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> {
4773
public:
@@ -286,6 +312,8 @@ class IProfileCommon : public ServiceFramework<IProfileCommon> {
286312
static const FunctionInfo functions[] = {
287313
{0, &IProfileCommon::Get, "Get"},
288314
{1, &IProfileCommon::GetBase, "GetBase"},
315+
{10, &IProfileCommon::GetImageSize, "GetImageSize"},
316+
{11, &IProfileCommon::LoadImage, "LoadImage"},
289317
};
290318

291319
RegisterHandlers(functions);
@@ -332,6 +360,58 @@ class IProfileCommon : public ServiceFramework<IProfileCommon> {
332360
}
333361
}
334362

363+
void LoadImage(HLERequestContext& ctx) {
364+
LOG_DEBUG(Service_ACC, "called");
365+
366+
IPC::ResponseBuilder rb{ctx, 3};
367+
rb.Push(ResultSuccess);
368+
369+
const Common::FS::IOFile image(GetImagePath(user_id), Common::FS::FileAccessMode::Read,
370+
Common::FS::FileType::BinaryFile);
371+
if (!image.IsOpen()) {
372+
LOG_WARNING(Service_ACC,
373+
"Failed to load user provided image! Falling back to built-in backup...");
374+
ctx.WriteBuffer(Core::Constants::ACCOUNT_BACKUP_JPEG);
375+
rb.Push(static_cast<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size()));
376+
return;
377+
}
378+
379+
std::vector<u8> buffer(image.GetSize());
380+
381+
if (image.Read(buffer) != buffer.size()) {
382+
LOG_ERROR(Service_ACC, "Failed to read all the bytes in the user provided image.");
383+
}
384+
385+
SanitizeJPEGImageSize(buffer);
386+
387+
ctx.WriteBuffer(buffer);
388+
rb.Push(static_cast<u32>(buffer.size()));
389+
}
390+
391+
void GetImageSize(HLERequestContext& ctx) {
392+
LOG_DEBUG(Service_ACC, "called");
393+
IPC::ResponseBuilder rb{ctx, 3};
394+
rb.Push(ResultSuccess);
395+
396+
const Common::FS::IOFile image(GetImagePath(user_id), Common::FS::FileAccessMode::Read,
397+
Common::FS::FileType::BinaryFile);
398+
399+
if (!image.IsOpen()) {
400+
LOG_WARNING(Service_ACC,
401+
"Failed to load user provided image! Falling back to built-in backup...");
402+
rb.Push(static_cast<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size()));
403+
return;
404+
}
405+
406+
std::vector<u8> buffer(image.GetSize());
407+
408+
if (image.Read(buffer) != buffer.size()) {
409+
LOG_ERROR(Service_ACC, "Failed to read all the bytes in the user provided image.");
410+
}
411+
412+
SanitizeJPEGImageSize(buffer);
413+
rb.Push(static_cast<u32>(buffer.size()));
414+
}
335415

336416
void Store(HLERequestContext& ctx) {
337417
IPC::RequestParser rp{ctx};
@@ -708,13 +788,74 @@ void Module::Interface::IsUserRegistrationRequestPermitted(HLERequestContext& ct
708788
rb.Push(profile_manager->CanSystemRegisterUser());
709789
}
710790

791+
void Module::Interface::InitializeApplicationInfo(HLERequestContext& ctx) {
792+
LOG_DEBUG(Service_ACC, "called");
793+
IPC::ResponseBuilder rb{ctx, 2};
794+
rb.Push(InitializeApplicationInfoBase());
795+
}
796+
797+
void Module::Interface::InitializeApplicationInfoRestricted(HLERequestContext& ctx) {
798+
LOG_WARNING(Service_ACC, "(Partial implementation) called");
799+
800+
// TODO(ogniK): We require checking if the user actually owns the title and what not. As of
801+
// currently, we assume the user owns the title. InitializeApplicationInfoBase SHOULD be called
802+
// first then we do extra checks if the game is a digital copy.
803+
804+
IPC::ResponseBuilder rb{ctx, 2};
805+
rb.Push(InitializeApplicationInfoBase());
806+
}
807+
808+
Result Module::Interface::InitializeApplicationInfoBase() {
809+
if (application_info) {
810+
LOG_ERROR(Service_ACC, "Application already initialized");
811+
return Account::ResultApplicationInfoAlreadyInitialized;
812+
}
813+
814+
// TODO(ogniK): This should be changed to reflect the target process for when we have multiple
815+
// processes emulated. As we don't actually have pid support we should assume we're just using
816+
// our own process
817+
Glue::ApplicationLaunchProperty launch_property{};
818+
const auto result = system.GetARPManager().GetLaunchProperty(
819+
&launch_property, system.GetApplicationProcessProgramID());
820+
821+
if (result != ResultSuccess) {
822+
LOG_ERROR(Service_ACC, "Failed to get launch property");
823+
return Account::ResultInvalidApplication;
824+
}
825+
826+
switch (launch_property.base_game_storage_id) {
827+
case StorageId::GameCard:
828+
application_info.application_type = ApplicationType::GameCard;
829+
break;
830+
case StorageId::Host:
831+
case StorageId::NandUser:
832+
case StorageId::SdCard:
833+
case StorageId::None: // Yuzu specific, differs from hardware
834+
application_info.application_type = ApplicationType::Digital;
835+
break;
836+
default:
837+
LOG_ERROR(Service_ACC, "Invalid game storage ID! storage_id={}",
838+
launch_property.base_game_storage_id);
839+
return Account::ResultInvalidApplication;
840+
}
841+
842+
LOG_WARNING(Service_ACC, "ApplicationInfo init required");
843+
// TODO(ogniK): Actual initialization here
844+
return ResultSuccess;
845+
}
846+
711847
void Module::Interface::GetBaasAccountManagerForApplication(HLERequestContext& ctx) {
712848
LOG_DEBUG(Service_ACC, "called");
713849
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
714850
rb.Push(ResultSuccess);
715851
rb.PushIpcInterface<IManagerForApplication>(system, profile_manager);
716852
}
717853

854+
void Module::Interface::IsUserAccountSwitchLocked(HLERequestContext& ctx) {
855+
LOG_DEBUG(Service_ACC, "called");
856+
UNIMPLEMENTED();
857+
}
858+
718859
void Module::Interface::InitializeApplicationInfoV2(HLERequestContext& ctx) {
719860
LOG_WARNING(Service_ACC, "(STUBBED) called");
720861

src/nxemu-os/core/hle/service/acc/acc.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,12 @@ class Module final {
2626
void ListOpenUsers(HLERequestContext& ctx);
2727
void GetLastOpenedUser(HLERequestContext& ctx);
2828
void GetProfile(HLERequestContext& ctx);
29+
void InitializeApplicationInfo(HLERequestContext& ctx);
30+
void InitializeApplicationInfoRestricted(HLERequestContext& ctx);
2931
void GetBaasAccountManagerForApplication(HLERequestContext& ctx);
3032
void IsUserRegistrationRequestPermitted(HLERequestContext& ctx);
3133
void TrySelectUserWithoutInteraction(HLERequestContext& ctx);
34+
void IsUserAccountSwitchLocked(HLERequestContext& ctx);
3235
void InitializeApplicationInfoV2(HLERequestContext& ctx);
3336
void BeginUserRegistration(HLERequestContext& ctx);
3437
void CompleteUserRegistration(HLERequestContext& ctx);
@@ -40,6 +43,7 @@ class Module final {
4043
void StoreSaveDataThumbnailSystem(HLERequestContext& ctx);
4144

4245
private:
46+
Result InitializeApplicationInfoBase();
4347
void StoreSaveDataThumbnail(HLERequestContext& ctx, const Common::UUID& uuid,
4448
const u64 tid);
4549

@@ -49,6 +53,17 @@ class Module final {
4953
Unknown = 3,
5054
};
5155

56+
struct ApplicationInfo {
57+
Service::Glue::ApplicationLaunchProperty launch_property;
58+
ApplicationType application_type;
59+
60+
constexpr explicit operator bool() const {
61+
return launch_property.title_id != 0x0;
62+
}
63+
};
64+
65+
ApplicationInfo application_info{};
66+
5267
protected:
5368
std::shared_ptr<Module> module;
5469
std::shared_ptr<ProfileManager> profile_manager;

src/nxemu-os/core/hle/service/acc/acc_u0.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager>
2121
{51, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
2222
{60, &ACC_U0::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0
2323
{99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+
24+
{100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"},
2425
{101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"},
2526
{102, nullptr, "AuthenticateApplicationAsync"},
2627
{103, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+
@@ -29,7 +30,9 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager>
2930
{120, nullptr, "CreateGuestLoginRequest"},
3031
{130, nullptr, "LoadOpenContext"}, // 5.0.0+
3132
{131, &ACC_U0::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 6.0.0+
33+
{140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, // 6.0.0+
3234
{141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+
35+
{150, &ACC_U0::IsUserAccountSwitchLocked, "IsUserAccountSwitchLocked"}, // 6.0.0+
3336
{160, &ACC_U0::InitializeApplicationInfoV2, "InitializeApplicationInfoV2"},
3437
};
3538
// clang-format on

0 commit comments

Comments
 (0)