diff options
| author | 2019-05-01 22:40:51 -0400 | |
|---|---|---|
| committer | 2019-09-30 17:27:23 -0400 | |
| commit | fe8c7e66e291b1fb3bef206e0d5809ad80441e9b (patch) | |
| tree | 710fde640e7c6785cdad860e154a59054ffbcd05 /src | |
| parent | configure_service: Allow Qt to open external links (diff) | |
| download | yuzu-fe8c7e66e291b1fb3bef206e0d5809ad80441e9b.tar.gz yuzu-fe8c7e66e291b1fb3bef206e0d5809ad80441e9b.tar.xz yuzu-fe8c7e66e291b1fb3bef206e0d5809ad80441e9b.zip | |
am: Unstub PopLaunchParameter and add bcat connection for app-specific data
Previously we were simply returning the account-preselect structure all times but if passed with a different mode the game expects application-specific data. This also adds a hook for BCAT into this allowing us to send the launch parameter through bcat,
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/am/am.cpp | 66 | ||||
| -rw-r--r-- | src/core/hle/service/am/am.h | 2 |
2 files changed, 52 insertions, 16 deletions
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 797c9a06f..79f9a393e 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include "core/hle/service/am/tcap.h" | 31 | #include "core/hle/service/am/tcap.h" |
| 32 | #include "core/hle/service/apm/controller.h" | 32 | #include "core/hle/service/apm/controller.h" |
| 33 | #include "core/hle/service/apm/interface.h" | 33 | #include "core/hle/service/apm/interface.h" |
| 34 | #include "core/hle/service/bcat/backend/backend.h" | ||
| 34 | #include "core/hle/service/filesystem/filesystem.h" | 35 | #include "core/hle/service/filesystem/filesystem.h" |
| 35 | #include "core/hle/service/ns/ns.h" | 36 | #include "core/hle/service/ns/ns.h" |
| 36 | #include "core/hle/service/nvflinger/nvflinger.h" | 37 | #include "core/hle/service/nvflinger/nvflinger.h" |
| @@ -46,15 +47,20 @@ constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 0x2}; | |||
| 46 | constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3}; | 47 | constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3}; |
| 47 | constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7}; | 48 | constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7}; |
| 48 | 49 | ||
| 49 | constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA; | 50 | enum class LaunchParameterKind : u32 { |
| 51 | ApplicationSpecific = 1, | ||
| 52 | AccountPreselectedUser = 2, | ||
| 53 | }; | ||
| 54 | |||
| 55 | constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA; | ||
| 50 | 56 | ||
| 51 | struct LaunchParameters { | 57 | struct LaunchParameterAccountPreselectedUser { |
| 52 | u32_le magic; | 58 | u32_le magic; |
| 53 | u32_le is_account_selected; | 59 | u32_le is_account_selected; |
| 54 | u128 current_user; | 60 | u128 current_user; |
| 55 | INSERT_PADDING_BYTES(0x70); | 61 | INSERT_PADDING_BYTES(0x70); |
| 56 | }; | 62 | }; |
| 57 | static_assert(sizeof(LaunchParameters) == 0x88); | 63 | static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88); |
| 58 | 64 | ||
| 59 | IWindowController::IWindowController(Core::System& system_) | 65 | IWindowController::IWindowController(Core::System& system_) |
| 60 | : ServiceFramework("IWindowController"), system{system_} { | 66 | : ServiceFramework("IWindowController"), system{system_} { |
| @@ -1128,26 +1134,54 @@ void IApplicationFunctions::EndBlockingHomeButton(Kernel::HLERequestContext& ctx | |||
| 1128 | } | 1134 | } |
| 1129 | 1135 | ||
| 1130 | void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { | 1136 | void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { |
| 1131 | LOG_DEBUG(Service_AM, "called"); | 1137 | IPC::RequestParser rp{ctx}; |
| 1138 | const auto kind = rp.PopEnum<LaunchParameterKind>(); | ||
| 1132 | 1139 | ||
| 1133 | LaunchParameters params{}; | 1140 | LOG_DEBUG(Service_AM, "called, kind={:08X}", static_cast<u8>(kind)); |
| 1134 | 1141 | ||
| 1135 | params.magic = POP_LAUNCH_PARAMETER_MAGIC; | 1142 | if (kind == LaunchParameterKind::ApplicationSpecific && !launch_popped_application_specific) { |
| 1136 | params.is_account_selected = 1; | 1143 | const auto backend = BCAT::CreateBackendFromSettings(&FileSystem::GetBCATDirectory); |
| 1144 | const auto build_id_full = Core::System::GetInstance().GetCurrentProcessBuildID(); | ||
| 1145 | u64 build_id{}; | ||
| 1146 | std::memcpy(&build_id, build_id_full.data(), sizeof(u64)); | ||
| 1137 | 1147 | ||
| 1138 | Account::ProfileManager profile_manager{}; | 1148 | const auto data = |
| 1139 | const auto uuid = profile_manager.GetUser(Settings::values.current_user); | 1149 | backend->GetLaunchParameter({Core::CurrentProcess()->GetTitleID(), build_id}); |
| 1140 | ASSERT(uuid); | ||
| 1141 | params.current_user = uuid->uuid; | ||
| 1142 | 1150 | ||
| 1143 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1151 | if (data.has_value()) { |
| 1152 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1153 | rb.Push(RESULT_SUCCESS); | ||
| 1154 | rb.PushIpcInterface<AM::IStorage>(*data); | ||
| 1155 | launch_popped_application_specific = true; | ||
| 1156 | return; | ||
| 1157 | } | ||
| 1158 | } else if (kind == LaunchParameterKind::AccountPreselectedUser && | ||
| 1159 | !launch_popped_account_preselect) { | ||
| 1160 | LaunchParameterAccountPreselectedUser params{}; | ||
| 1144 | 1161 | ||
| 1145 | rb.Push(RESULT_SUCCESS); | 1162 | params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC; |
| 1163 | params.is_account_selected = 1; | ||
| 1146 | 1164 | ||
| 1147 | std::vector<u8> buffer(sizeof(LaunchParameters)); | 1165 | Account::ProfileManager profile_manager{}; |
| 1148 | std::memcpy(buffer.data(), ¶ms, buffer.size()); | 1166 | const auto uuid = profile_manager.GetUser(Settings::values.current_user); |
| 1167 | ASSERT(uuid); | ||
| 1168 | params.current_user = uuid->uuid; | ||
| 1149 | 1169 | ||
| 1150 | rb.PushIpcInterface<AM::IStorage>(buffer); | 1170 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 1171 | |||
| 1172 | rb.Push(RESULT_SUCCESS); | ||
| 1173 | |||
| 1174 | std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser)); | ||
| 1175 | std::memcpy(buffer.data(), ¶ms, buffer.size()); | ||
| 1176 | |||
| 1177 | rb.PushIpcInterface<AM::IStorage>(buffer); | ||
| 1178 | launch_popped_account_preselect = true; | ||
| 1179 | return; | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!"); | ||
| 1183 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1184 | rb.Push(ERR_NO_DATA_IN_CHANNEL); | ||
| 1151 | } | 1185 | } |
| 1152 | 1186 | ||
| 1153 | void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest( | 1187 | void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest( |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index a3baeb673..9169eb2bd 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -255,6 +255,8 @@ private: | |||
| 255 | void EnableApplicationCrashReport(Kernel::HLERequestContext& ctx); | 255 | void EnableApplicationCrashReport(Kernel::HLERequestContext& ctx); |
| 256 | void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); | 256 | void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); |
| 257 | 257 | ||
| 258 | bool launch_popped_application_specific = false; | ||
| 259 | bool launch_popped_account_preselect = false; | ||
| 258 | Kernel::EventPair gpu_error_detected_event; | 260 | Kernel::EventPair gpu_error_detected_event; |
| 259 | Core::System& system; | 261 | Core::System& system; |
| 260 | }; | 262 | }; |