summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt4
-rw-r--r--src/android/app/src/main/jni/native.cpp37
-rw-r--r--src/android/app/src/main/jni/native.h5
-rw-r--r--src/core/core.cpp49
-rw-r--r--src/core/core.h9
-rw-r--r--src/yuzu/game_list.cpp12
-rw-r--r--src/yuzu/game_list.h3
-rw-r--r--src/yuzu/main.cpp72
-rw-r--r--src/yuzu/main.h23
-rw-r--r--src/yuzu_cmd/yuzu.cpp6
11 files changed, 143 insertions, 79 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
index 53137b2e2..6ebb46af7 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
@@ -261,7 +261,7 @@ object NativeLibrary {
261 /** 261 /**
262 * Begins emulation. 262 * Begins emulation.
263 */ 263 */
264 external fun run(path: String?, programIndex: Int = 0) 264 external fun run(path: String?, programIndex: Int, frontendInitiated: Boolean)
265 265
266 // Surface Handling 266 // Surface Handling
267 external fun surfaceChanged(surf: Surface?) 267 external fun surfaceChanged(surf: Surface?)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
index 1f591ced1..937b8faf1 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
@@ -927,7 +927,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
927 emulationThread.join() 927 emulationThread.join()
928 emulationThread = Thread({ 928 emulationThread = Thread({
929 Log.debug("[EmulationFragment] Starting emulation thread.") 929 Log.debug("[EmulationFragment] Starting emulation thread.")
930 NativeLibrary.run(gamePath, programIndex) 930 NativeLibrary.run(gamePath, programIndex, false)
931 }, "NativeEmulation") 931 }, "NativeEmulation")
932 emulationThread.start() 932 emulationThread.start()
933 } 933 }
@@ -981,7 +981,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
981 State.STOPPED -> { 981 State.STOPPED -> {
982 emulationThread = Thread({ 982 emulationThread = Thread({
983 Log.debug("[EmulationFragment] Starting emulation thread.") 983 Log.debug("[EmulationFragment] Starting emulation thread.")
984 NativeLibrary.run(gamePath, programIndex) 984 NativeLibrary.run(gamePath, programIndex, true)
985 }, "NativeEmulation") 985 }, "NativeEmulation")
986 emulationThread.start() 986 emulationThread.start()
987 } 987 }
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 1da510b7a..654510129 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -48,6 +48,7 @@
48#include "core/frontend/applets/software_keyboard.h" 48#include "core/frontend/applets/software_keyboard.h"
49#include "core/frontend/applets/web_browser.h" 49#include "core/frontend/applets/web_browser.h"
50#include "core/hle/service/am/applet_ae.h" 50#include "core/hle/service/am/applet_ae.h"
51#include "core/hle/service/am/applet_manager.h"
51#include "core/hle/service/am/applet_oe.h" 52#include "core/hle/service/am/applet_oe.h"
52#include "core/hle/service/am/frontend/applets.h" 53#include "core/hle/service/am/frontend/applets.h"
53#include "core/hle/service/filesystem/filesystem.h" 54#include "core/hle/service/filesystem/filesystem.h"
@@ -211,8 +212,15 @@ void EmulationSession::InitializeSystem(bool reload) {
211 m_system.GetFileSystemController().CreateFactories(*m_vfs); 212 m_system.GetFileSystemController().CreateFactories(*m_vfs);
212} 213}
213 214
215void EmulationSession::SetAppletId(int applet_id) {
216 m_applet_id = applet_id;
217 m_system.GetFrontendAppletHolder().SetCurrentAppletId(
218 static_cast<Service::AM::AppletId>(m_applet_id));
219}
220
214Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath, 221Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
215 const std::size_t program_index) { 222 const std::size_t program_index,
223 const bool frontend_initiated) {
216 std::scoped_lock lock(m_mutex); 224 std::scoped_lock lock(m_mutex);
217 225
218 // Create the render window. 226 // Create the render window.
@@ -242,8 +250,13 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
242 ConfigureFilesystemProvider(filepath); 250 ConfigureFilesystemProvider(filepath);
243 251
244 // Load the ROM. 252 // Load the ROM.
245 m_load_result = 253 Service::AM::FrontendAppletParameters params{
246 m_system.Load(EmulationSession::GetInstance().Window(), filepath, 0, program_index); 254 .applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
255 .launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated
256 : Service::AM::LaunchType::ApplicationInitiated,
257 .program_index = static_cast<s32>(program_index),
258 };
259 m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
247 if (m_load_result != Core::SystemResultStatus::Success) { 260 if (m_load_result != Core::SystemResultStatus::Success) {
248 return m_load_result; 261 return m_load_result;
249 } 262 }
@@ -339,6 +352,9 @@ void EmulationSession::RunEmulation() {
339 } 352 }
340 } 353 }
341 } 354 }
355
356 // Reset current applet ID.
357 m_applet_id = static_cast<int>(Service::AM::AppletId::Application);
342} 358}
343 359
344bool EmulationSession::IsHandheldOnly() { 360bool EmulationSession::IsHandheldOnly() {
@@ -434,7 +450,8 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
434} 450}
435 451
436static Core::SystemResultStatus RunEmulation(const std::string& filepath, 452static Core::SystemResultStatus RunEmulation(const std::string& filepath,
437 const size_t program_index = 0) { 453 const size_t program_index,
454 const bool frontend_initiated) {
438 MicroProfileOnThreadCreate("EmuThread"); 455 MicroProfileOnThreadCreate("EmuThread");
439 SCOPE_EXIT({ MicroProfileShutdown(); }); 456 SCOPE_EXIT({ MicroProfileShutdown(); });
440 457
@@ -447,7 +464,8 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath,
447 464
448 SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); }); 465 SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
449 466
450 jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index); 467 jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index,
468 frontend_initiated);
451 if (result != Core::SystemResultStatus::Success) { 469 if (result != Core::SystemResultStatus::Success) {
452 return result; 470 return result;
453 } 471 }
@@ -744,10 +762,12 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj
744} 762}
745 763
746void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path, 764void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
747 jint j_program_index) { 765 jint j_program_index,
766 jboolean j_frontend_initiated) {
748 const std::string path = GetJString(env, j_path); 767 const std::string path = GetJString(env, j_path);
749 768
750 const Core::SystemResultStatus result{RunEmulation(path, j_program_index)}; 769 const Core::SystemResultStatus result{
770 RunEmulation(path, j_program_index, j_frontend_initiated)};
751 if (result != Core::SystemResultStatus::Success) { 771 if (result != Core::SystemResultStatus::Success) {
752 env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), 772 env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
753 IDCache::GetExitEmulationActivity(), static_cast<int>(result)); 773 IDCache::GetExitEmulationActivity(), static_cast<int>(result));
@@ -809,8 +829,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getAppletLaunchPath(JNIEnv* env, j
809 829
810void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz, 830void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz,
811 jint jappletId) { 831 jint jappletId) {
812 EmulationSession::GetInstance().System().GetFrontendAppletHolder().SetCurrentAppletId( 832 EmulationSession::GetInstance().SetAppletId(jappletId);
813 static_cast<Service::AM::AppletId>(jappletId));
814} 833}
815 834
816void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz, 835void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz,
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h
index bfe3fccca..e49d4e015 100644
--- a/src/android/app/src/main/jni/native.h
+++ b/src/android/app/src/main/jni/native.h
@@ -45,8 +45,10 @@ public:
45 const Core::PerfStatsResults& PerfStats(); 45 const Core::PerfStatsResults& PerfStats();
46 void ConfigureFilesystemProvider(const std::string& filepath); 46 void ConfigureFilesystemProvider(const std::string& filepath);
47 void InitializeSystem(bool reload); 47 void InitializeSystem(bool reload);
48 void SetAppletId(int applet_id);
48 Core::SystemResultStatus InitializeEmulation(const std::string& filepath, 49 Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
49 const std::size_t program_index = 0); 50 const std::size_t program_index,
51 const bool frontend_initiated);
50 52
51 bool IsHandheldOnly(); 53 bool IsHandheldOnly();
52 void SetDeviceType([[maybe_unused]] int index, int type); 54 void SetDeviceType([[maybe_unused]] int index, int type);
@@ -79,6 +81,7 @@ private:
79 std::atomic<bool> m_is_paused = false; 81 std::atomic<bool> m_is_paused = false;
80 SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{}; 82 SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
81 std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider; 83 std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
84 int m_applet_id{1};
82 85
83 // GPU driver parameters 86 // GPU driver parameters
84 std::shared_ptr<Common::DynamicLibrary> m_vulkan_library; 87 std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 2bf377b24..8c04685a5 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -36,6 +36,7 @@
36#include "core/hle/kernel/kernel.h" 36#include "core/hle/kernel/kernel.h"
37#include "core/hle/kernel/physical_core.h" 37#include "core/hle/kernel/physical_core.h"
38#include "core/hle/service/acc/profile_manager.h" 38#include "core/hle/service/acc/profile_manager.h"
39#include "core/hle/service/am/applet_manager.h"
39#include "core/hle/service/am/frontend/applets.h" 40#include "core/hle/service/am/frontend/applets.h"
40#include "core/hle/service/apm/apm_controller.h" 41#include "core/hle/service/apm/apm_controller.h"
41#include "core/hle/service/filesystem/filesystem.h" 42#include "core/hle/service/filesystem/filesystem.h"
@@ -136,7 +137,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
136struct System::Impl { 137struct System::Impl {
137 explicit Impl(System& system) 138 explicit Impl(System& system)
138 : kernel{system}, fs_controller{system}, hid_core{}, room_network{}, cpu_manager{system}, 139 : kernel{system}, fs_controller{system}, hid_core{}, room_network{}, cpu_manager{system},
139 reporter{system}, frontend_applets{system}, profile_manager{} {} 140 reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {}
140 141
141 void Initialize(System& system) { 142 void Initialize(System& system) {
142 device_memory = std::make_unique<Core::DeviceMemory>(); 143 device_memory = std::make_unique<Core::DeviceMemory>();
@@ -330,16 +331,27 @@ struct System::Impl {
330 } 331 }
331 332
332 SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, 333 SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
333 const std::string& filepath, u64 program_id, 334 const std::string& filepath,
334 std::size_t program_index) { 335 Service::AM::FrontendAppletParameters& params) {
335 app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath), 336 app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath),
336 program_id, program_index); 337 params.program_id, params.program_index);
337 338
338 if (!app_loader) { 339 if (!app_loader) {
339 LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); 340 LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
340 return SystemResultStatus::ErrorGetLoader; 341 return SystemResultStatus::ErrorGetLoader;
341 } 342 }
342 343
344 if (app_loader->ReadProgramId(params.program_id) != Loader::ResultStatus::Success) {
345 LOG_ERROR(Core, "Failed to find title id for ROM!");
346 }
347
348 std::string name = "Unknown program";
349 if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) {
350 LOG_ERROR(Core, "Failed to read title for ROM!");
351 }
352
353 LOG_INFO(Core, "Loading {} ({})", name, params.program_id);
354
343 InitializeKernel(system); 355 InitializeKernel(system);
344 356
345 // Create the application process. 357 // Create the application process.
@@ -373,6 +385,10 @@ struct System::Impl {
373 cheat_engine->Initialize(); 385 cheat_engine->Initialize();
374 } 386 }
375 387
388 // Register with applet manager.
389 applet_manager.CreateAndInsertByFrontendAppletParameters(main_process->GetProcessId(),
390 params);
391
376 // All threads are started, begin main process execution, now that we're in the clear. 392 // All threads are started, begin main process execution, now that we're in the clear.
377 main_process->Run(load_parameters->main_thread_priority, 393 main_process->Run(load_parameters->main_thread_priority,
378 load_parameters->main_thread_stack_size); 394 load_parameters->main_thread_stack_size);
@@ -386,21 +402,13 @@ struct System::Impl {
386 } 402 }
387 } 403 }
388 404
389 if (app_loader->ReadProgramId(program_id) != Loader::ResultStatus::Success) { 405 perf_stats = std::make_unique<PerfStats>(params.program_id);
390 LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", load_result);
391 }
392 perf_stats = std::make_unique<PerfStats>(program_id);
393 // Reset counters and set time origin to current frame 406 // Reset counters and set time origin to current frame
394 GetAndResetPerfStats(); 407 GetAndResetPerfStats();
395 perf_stats->BeginSystemFrame(); 408 perf_stats->BeginSystemFrame();
396 409
397 std::string name = "Unknown Game";
398 if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) {
399 LOG_ERROR(Core, "Failed to read title for ROM (Error {})", load_result);
400 }
401
402 std::string title_version; 410 std::string title_version;
403 const FileSys::PatchManager pm(program_id, system.GetFileSystemController(), 411 const FileSys::PatchManager pm(params.program_id, system.GetFileSystemController(),
404 system.GetContentProvider()); 412 system.GetContentProvider());
405 const auto metadata = pm.GetControlMetadata(); 413 const auto metadata = pm.GetControlMetadata();
406 if (metadata.first != nullptr) { 414 if (metadata.first != nullptr) {
@@ -409,14 +417,15 @@ struct System::Impl {
409 if (auto room_member = room_network.GetRoomMember().lock()) { 417 if (auto room_member = room_network.GetRoomMember().lock()) {
410 Network::GameInfo game_info; 418 Network::GameInfo game_info;
411 game_info.name = name; 419 game_info.name = name;
412 game_info.id = program_id; 420 game_info.id = params.program_id;
413 game_info.version = title_version; 421 game_info.version = title_version;
414 room_member->SendGameInfo(game_info); 422 room_member->SendGameInfo(game_info);
415 } 423 }
416 424
417 // Workarounds: 425 // Workarounds:
418 // Activate this in Super Smash Brothers Ultimate, it only affects AMD cards using AMDVLK 426 // Activate this in Super Smash Brothers Ultimate, it only affects AMD cards using AMDVLK
419 Settings::values.renderer_amdvlk_depth_bias_workaround = program_id == 0x1006A800016E000ULL; 427 Settings::values.renderer_amdvlk_depth_bias_workaround =
428 params.program_id == 0x1006A800016E000ULL;
420 429
421 status = SystemResultStatus::Success; 430 status = SystemResultStatus::Success;
422 return status; 431 return status;
@@ -455,6 +464,7 @@ struct System::Impl {
455 } 464 }
456 kernel.CloseServices(); 465 kernel.CloseServices();
457 kernel.ShutdownCores(); 466 kernel.ShutdownCores();
467 applet_manager.Reset();
458 services.reset(); 468 services.reset();
459 service_manager.reset(); 469 service_manager.reset();
460 fs_controller.Reset(); 470 fs_controller.Reset();
@@ -566,7 +576,8 @@ struct System::Impl {
566 576
567 std::unique_ptr<Tools::RenderdocAPI> renderdoc_api; 577 std::unique_ptr<Tools::RenderdocAPI> renderdoc_api;
568 578
569 /// Frontend applets 579 /// Applets
580 Service::AM::AppletManager applet_manager;
570 Service::AM::Frontend::FrontendAppletHolder frontend_applets; 581 Service::AM::Frontend::FrontendAppletHolder frontend_applets;
571 582
572 /// APM (Performance) services 583 /// APM (Performance) services
@@ -680,8 +691,8 @@ void System::InitializeDebugger() {
680} 691}
681 692
682SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath, 693SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
683 u64 program_id, std::size_t program_index) { 694 Service::AM::FrontendAppletParameters& params) {
684 return impl->Load(*this, emu_window, filepath, program_id, program_index); 695 return impl->Load(*this, emu_window, filepath, params);
685} 696}
686 697
687bool System::IsPoweredOn() const { 698bool System::IsPoweredOn() const {
diff --git a/src/core/core.h b/src/core/core.h
index 800e69501..97e2d4b50 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -50,6 +50,11 @@ namespace Account {
50class ProfileManager; 50class ProfileManager;
51} // namespace Account 51} // namespace Account
52 52
53namespace AM {
54struct FrontendAppletParameters;
55class AppletManager;
56} // namespace AM
57
53namespace AM::Frontend { 58namespace AM::Frontend {
54struct FrontendAppletSet; 59struct FrontendAppletSet;
55class FrontendAppletHolder; 60class FrontendAppletHolder;
@@ -203,8 +208,8 @@ public:
203 * @returns SystemResultStatus code, indicating if the operation succeeded. 208 * @returns SystemResultStatus code, indicating if the operation succeeded.
204 */ 209 */
205 [[nodiscard]] SystemResultStatus Load(Frontend::EmuWindow& emu_window, 210 [[nodiscard]] SystemResultStatus Load(Frontend::EmuWindow& emu_window,
206 const std::string& filepath, u64 program_id = 0, 211 const std::string& filepath,
207 std::size_t program_index = 0); 212 Service::AM::FrontendAppletParameters& params);
208 213
209 /** 214 /**
210 * Indicates if the emulated system is powered on (all subsystems initialized and able to run an 215 * Indicates if the emulated system is powered on (all subsystems initialized and able to run an
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 59b317135..b40af957c 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -596,14 +596,10 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
596 connect(open_save_location, &QAction::triggered, [this, program_id, path]() { 596 connect(open_save_location, &QAction::triggered, [this, program_id, path]() {
597 emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path); 597 emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path);
598 }); 598 });
599 connect(start_game, &QAction::triggered, [this, path]() { 599 connect(start_game, &QAction::triggered,
600 emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Normal, 600 [this, path]() { emit BootGame(QString::fromStdString(path), StartGameType::Normal); });
601 AmLaunchType::UserInitiated); 601 connect(start_game_global, &QAction::triggered,
602 }); 602 [this, path]() { emit BootGame(QString::fromStdString(path), StartGameType::Global); });
603 connect(start_game_global, &QAction::triggered, [this, path]() {
604 emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Global,
605 AmLaunchType::UserInitiated);
606 });
607 connect(open_mod_location, &QAction::triggered, [this, program_id, path]() { 603 connect(open_mod_location, &QAction::triggered, [this, program_id, path]() {
608 emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path); 604 emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path);
609 }); 605 });
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index 563a3a35b..79f9c7ec0 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -106,8 +106,7 @@ public:
106 static const QStringList supported_file_extensions; 106 static const QStringList supported_file_extensions;
107 107
108signals: 108signals:
109 void BootGame(const QString& game_path, u64 program_id, std::size_t program_index, 109 void BootGame(const QString& game_path, StartGameType type);
110 StartGameType type, AmLaunchType launch_type);
111 void GameChosen(const QString& game_path, const u64 title_id = 0); 110 void GameChosen(const QString& game_path, const u64 title_id = 0);
112 void OpenFolderRequested(u64 program_id, GameListOpenTarget target, 111 void OpenFolderRequested(u64 program_id, GameListOpenTarget target,
113 const std::string& game_path); 112 const std::string& game_path);
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 90ddecbfc..02508b20d 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -8,6 +8,7 @@
8#include <iostream> 8#include <iostream>
9#include <memory> 9#include <memory>
10#include <thread> 10#include <thread>
11#include "core/hle/service/am/applet_manager.h"
11#include "core/loader/nca.h" 12#include "core/loader/nca.h"
12#include "core/tools/renderdoc.h" 13#include "core/tools/renderdoc.h"
13 14
@@ -569,7 +570,7 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
569 } 570 }
570 571
571 if (!game_path.isEmpty()) { 572 if (!game_path.isEmpty()) {
572 BootGame(game_path); 573 BootGame(game_path, ApplicationAppletParameters());
573 } 574 }
574} 575}
575 576
@@ -1474,7 +1475,7 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
1474} 1475}
1475 1476
1476void GMainWindow::ConnectWidgetEvents() { 1477void GMainWindow::ConnectWidgetEvents() {
1477 connect(game_list, &GameList::BootGame, this, &GMainWindow::BootGame); 1478 connect(game_list, &GameList::BootGame, this, &GMainWindow::BootGameFromList);
1478 connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile); 1479 connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile);
1479 connect(game_list, &GameList::OpenDirectory, this, &GMainWindow::OnGameListOpenDirectory); 1480 connect(game_list, &GameList::OpenDirectory, this, &GMainWindow::OnGameListOpenDirectory);
1480 connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder); 1481 connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder);
@@ -1762,8 +1763,7 @@ void GMainWindow::AllowOSSleep() {
1762#endif 1763#endif
1763} 1764}
1764 1765
1765bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index, 1766bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletParameters params) {
1766 AmLaunchType launch_type) {
1767 // Shutdown previous session if the emu thread is still active... 1767 // Shutdown previous session if the emu thread is still active...
1768 if (emu_thread != nullptr) { 1768 if (emu_thread != nullptr) {
1769 ShutdownGame(); 1769 ShutdownGame();
@@ -1775,7 +1775,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
1775 1775
1776 system->SetFilesystem(vfs); 1776 system->SetFilesystem(vfs);
1777 1777
1778 if (launch_type == AmLaunchType::UserInitiated) { 1778 if (params.launch_type == Service::AM::LaunchType::FrontendInitiated) {
1779 system->GetUserChannel().clear(); 1779 system->GetUserChannel().clear();
1780 } 1780 }
1781 1781
@@ -1794,7 +1794,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
1794 }); 1794 });
1795 1795
1796 const Core::SystemResultStatus result{ 1796 const Core::SystemResultStatus result{
1797 system->Load(*render_window, filename.toStdString(), program_id, program_index)}; 1797 system->Load(*render_window, filename.toStdString(), params)};
1798 1798
1799 const auto drd_callout = (UISettings::values.callout_flags.GetValue() & 1799 const auto drd_callout = (UISettings::values.callout_flags.GetValue() &
1800 static_cast<u32>(CalloutFlag::DRDDeprecation)) == 0; 1800 static_cast<u32>(CalloutFlag::DRDDeprecation)) == 0;
@@ -1917,12 +1917,12 @@ void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) {
1917 } 1917 }
1918} 1918}
1919 1919
1920void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index, 1920void GMainWindow::BootGame(const QString& filename, Service::AM::FrontendAppletParameters params,
1921 StartGameType type, AmLaunchType launch_type) { 1921 StartGameType type) {
1922 LOG_INFO(Frontend, "yuzu starting..."); 1922 LOG_INFO(Frontend, "yuzu starting...");
1923 1923
1924 if (program_id == 0 || 1924 if (params.program_id == 0 ||
1925 program_id > static_cast<u64>(Service::AM::AppletProgramId::MaxProgramId)) { 1925 params.program_id > static_cast<u64>(Service::AM::AppletProgramId::MaxProgramId)) {
1926 StoreRecentFile(filename); // Put the filename on top of the list 1926 StoreRecentFile(filename); // Put the filename on top of the list
1927 } 1927 }
1928 1928
@@ -1937,7 +1937,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
1937 1937
1938 ConfigureFilesystemProvider(filename.toStdString()); 1938 ConfigureFilesystemProvider(filename.toStdString());
1939 const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData()); 1939 const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData());
1940 const auto loader = Loader::GetLoader(*system, v_file, program_id, program_index); 1940 const auto loader = Loader::GetLoader(*system, v_file, params.program_id, params.program_index);
1941 1941
1942 if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success && 1942 if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success &&
1943 type == StartGameType::Normal) { 1943 type == StartGameType::Normal) {
@@ -1971,7 +1971,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
1971 // behavior of asking. 1971 // behavior of asking.
1972 user_flag_cmd_line = false; 1972 user_flag_cmd_line = false;
1973 1973
1974 if (!LoadROM(filename, program_id, program_index, launch_type)) { 1974 if (!LoadROM(filename, params)) {
1975 return; 1975 return;
1976 } 1976 }
1977 1977
@@ -2061,6 +2061,10 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
2061 OnStartGame(); 2061 OnStartGame();
2062} 2062}
2063 2063
2064void GMainWindow::BootGameFromList(const QString& filename, StartGameType with_config) {
2065 BootGame(filename, ApplicationAppletParameters(), with_config);
2066}
2067
2064bool GMainWindow::OnShutdownBegin() { 2068bool GMainWindow::OnShutdownBegin() {
2065 if (!emulation_running) { 2069 if (!emulation_running) {
2066 return false; 2070 return false;
@@ -2241,7 +2245,10 @@ void GMainWindow::UpdateRecentFiles() {
2241} 2245}
2242 2246
2243void GMainWindow::OnGameListLoadFile(QString game_path, u64 program_id) { 2247void GMainWindow::OnGameListLoadFile(QString game_path, u64 program_id) {
2244 BootGame(game_path, program_id); 2248 auto params = ApplicationAppletParameters();
2249 params.program_id = program_id;
2250
2251 BootGame(game_path, params);
2245} 2252}
2246 2253
2247void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target, 2254void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target,
@@ -3173,7 +3180,7 @@ void GMainWindow::OnMenuLoadFile() {
3173 } 3180 }
3174 3181
3175 UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); 3182 UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
3176 BootGame(filename); 3183 BootGame(filename, ApplicationAppletParameters());
3177} 3184}
3178 3185
3179void GMainWindow::OnMenuLoadFolder() { 3186void GMainWindow::OnMenuLoadFolder() {
@@ -3187,7 +3194,7 @@ void GMainWindow::OnMenuLoadFolder() {
3187 const QDir dir{dir_path}; 3194 const QDir dir{dir_path};
3188 const QStringList matching_main = dir.entryList({QStringLiteral("main")}, QDir::Files); 3195 const QStringList matching_main = dir.entryList({QStringLiteral("main")}, QDir::Files);
3189 if (matching_main.size() == 1) { 3196 if (matching_main.size() == 1) {
3190 BootGame(dir.path() + QDir::separator() + matching_main[0]); 3197 BootGame(dir.path() + QDir::separator() + matching_main[0], ApplicationAppletParameters());
3191 } else { 3198 } else {
3192 QMessageBox::warning(this, tr("Invalid Directory Selected"), 3199 QMessageBox::warning(this, tr("Invalid Directory Selected"),
3193 tr("The directory you have selected does not contain a 'main' file.")); 3200 tr("The directory you have selected does not contain a 'main' file."));
@@ -3381,7 +3388,7 @@ void GMainWindow::OnMenuRecentFile() {
3381 3388
3382 const QString filename = action->data().toString(); 3389 const QString filename = action->data().toString();
3383 if (QFileInfo::exists(filename)) { 3390 if (QFileInfo::exists(filename)) {
3384 BootGame(filename); 3391 BootGame(filename, ApplicationAppletParameters());
3385 } else { 3392 } else {
3386 // Display an error message and remove the file from the list. 3393 // Display an error message and remove the file from the list.
3387 QMessageBox::information(this, tr("File not found"), 3394 QMessageBox::information(this, tr("File not found"),
@@ -3419,7 +3426,7 @@ void GMainWindow::OnRestartGame() {
3419 // Make a copy since ShutdownGame edits game_path 3426 // Make a copy since ShutdownGame edits game_path
3420 const auto current_game = QString(current_game_path); 3427 const auto current_game = QString(current_game_path);
3421 ShutdownGame(); 3428 ShutdownGame();
3422 BootGame(current_game); 3429 BootGame(current_game, ApplicationAppletParameters());
3423 } 3430 }
3424} 3431}
3425 3432
@@ -3487,8 +3494,11 @@ void GMainWindow::OnLoadComplete() {
3487 3494
3488void GMainWindow::OnExecuteProgram(std::size_t program_index) { 3495void GMainWindow::OnExecuteProgram(std::size_t program_index) {
3489 ShutdownGame(); 3496 ShutdownGame();
3490 BootGame(last_filename_booted, 0, program_index, StartGameType::Normal, 3497
3491 AmLaunchType::ApplicationInitiated); 3498 auto params = ApplicationAppletParameters();
3499 params.program_index = static_cast<s32>(program_index);
3500 params.launch_type = Service::AM::LaunchType::ApplicationInitiated;
3501 BootGame(last_filename_booted, params);
3492} 3502}
3493 3503
3494void GMainWindow::OnExit() { 3504void GMainWindow::OnExit() {
@@ -4174,7 +4184,7 @@ void GMainWindow::OnAlbum() {
4174 4184
4175 const auto filename = QString::fromStdString(album_nca->GetFullPath()); 4185 const auto filename = QString::fromStdString(album_nca->GetFullPath());
4176 UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); 4186 UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
4177 BootGame(filename, AlbumId); 4187 BootGame(filename, LibraryAppletParameters(AlbumId, Service::AM::AppletId::PhotoViewer));
4178} 4188}
4179 4189
4180void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { 4190void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
@@ -4198,7 +4208,7 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
4198 4208
4199 const auto filename = QString::fromStdString(cabinet_nca->GetFullPath()); 4209 const auto filename = QString::fromStdString(cabinet_nca->GetFullPath());
4200 UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); 4210 UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
4201 BootGame(filename, CabinetId); 4211 BootGame(filename, LibraryAppletParameters(CabinetId, Service::AM::AppletId::Cabinet));
4202} 4212}
4203 4213
4204void GMainWindow::OnMiiEdit() { 4214void GMainWindow::OnMiiEdit() {
@@ -4221,7 +4231,7 @@ void GMainWindow::OnMiiEdit() {
4221 4231
4222 const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); 4232 const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
4223 UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); 4233 UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
4224 BootGame(filename, MiiEditId); 4234 BootGame(filename, LibraryAppletParameters(MiiEditId, Service::AM::AppletId::MiiEdit));
4225} 4235}
4226 4236
4227void GMainWindow::OnOpenControllerMenu() { 4237void GMainWindow::OnOpenControllerMenu() {
@@ -4245,7 +4255,8 @@ void GMainWindow::OnOpenControllerMenu() {
4245 4255
4246 const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath())); 4256 const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath()));
4247 UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); 4257 UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
4248 BootGame(filename, ControllerAppletId); 4258 BootGame(filename,
4259 LibraryAppletParameters(ControllerAppletId, Service::AM::AppletId::Controller));
4249} 4260}
4250 4261
4251void GMainWindow::OnCaptureScreenshot() { 4262void GMainWindow::OnCaptureScreenshot() {
@@ -4728,7 +4739,7 @@ bool GMainWindow::DropAction(QDropEvent* event) {
4728 } else { 4739 } else {
4729 // Game 4740 // Game
4730 if (ConfirmChangeGame()) { 4741 if (ConfirmChangeGame()) {
4731 BootGame(filename); 4742 BootGame(filename, ApplicationAppletParameters());
4732 } 4743 }
4733 } 4744 }
4734 return true; 4745 return true;
@@ -4943,6 +4954,19 @@ void GMainWindow::changeEvent(QEvent* event) {
4943 QWidget::changeEvent(event); 4954 QWidget::changeEvent(event);
4944} 4955}
4945 4956
4957Service::AM::FrontendAppletParameters GMainWindow::ApplicationAppletParameters() {
4958 return Service::AM::FrontendAppletParameters{};
4959}
4960
4961Service::AM::FrontendAppletParameters GMainWindow::LibraryAppletParameters(
4962 u64 program_id, Service::AM::AppletId applet_id) {
4963 return Service::AM::FrontendAppletParameters{
4964 .program_id = program_id,
4965 .applet_id = applet_id,
4966 .applet_type = Service::AM::AppletType::LibraryApplet,
4967 };
4968}
4969
4946void VolumeButton::wheelEvent(QWheelEvent* event) { 4970void VolumeButton::wheelEvent(QWheelEvent* event) {
4947 4971
4948 int num_degrees = event->angleDelta().y() / 8; 4972 int num_degrees = event->angleDelta().y() / 8;
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index c079baffa..aba61e388 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -64,11 +64,6 @@ enum class StartGameType {
64 Global, // Only uses global configuration 64 Global, // Only uses global configuration
65}; 65};
66 66
67enum class AmLaunchType {
68 UserInitiated,
69 ApplicationInitiated,
70};
71
72namespace Core { 67namespace Core {
73enum class SystemResultStatus : u32; 68enum class SystemResultStatus : u32;
74class System; 69class System;
@@ -101,6 +96,11 @@ namespace InputCommon {
101class InputSubsystem; 96class InputSubsystem;
102} 97}
103 98
99namespace Service::AM {
100struct FrontendAppletParameters;
101enum class AppletId : u32;
102} // namespace Service::AM
103
104namespace Service::AM::Frontend { 104namespace Service::AM::Frontend {
105enum class SwkbdResult : u32; 105enum class SwkbdResult : u32;
106enum class SwkbdTextCheckResult : u32; 106enum class SwkbdTextCheckResult : u32;
@@ -268,11 +268,10 @@ private:
268 void PreventOSSleep(); 268 void PreventOSSleep();
269 void AllowOSSleep(); 269 void AllowOSSleep();
270 270
271 bool LoadROM(const QString& filename, u64 program_id, std::size_t program_index, 271 bool LoadROM(const QString& filename, Service::AM::FrontendAppletParameters params);
272 AmLaunchType launch_type); 272 void BootGame(const QString& filename, Service::AM::FrontendAppletParameters params,
273 void BootGame(const QString& filename, u64 program_id = 0, std::size_t program_index = 0, 273 StartGameType with_config = StartGameType::Normal);
274 StartGameType with_config = StartGameType::Normal, 274 void BootGameFromList(const QString& filename, StartGameType with_config);
275 AmLaunchType launch_type = AmLaunchType::UserInitiated);
276 void ShutdownGame(); 275 void ShutdownGame();
277 276
278 void ShowTelemetryCallout(); 277 void ShowTelemetryCallout();
@@ -325,6 +324,10 @@ private:
325 void SetGamemodeEnabled(bool state); 324 void SetGamemodeEnabled(bool state);
326#endif 325#endif
327 326
327 Service::AM::FrontendAppletParameters ApplicationAppletParameters();
328 Service::AM::FrontendAppletParameters LibraryAppletParameters(u64 program_id,
329 Service::AM::AppletId applet_id);
330
328private slots: 331private slots:
329 void OnStartGame(); 332 void OnStartGame();
330 void OnRestartGame(); 333 void OnRestartGame();
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index c39ace2ec..3b321dad1 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -26,6 +26,7 @@
26#include "core/crypto/key_manager.h" 26#include "core/crypto/key_manager.h"
27#include "core/file_sys/registered_cache.h" 27#include "core/file_sys/registered_cache.h"
28#include "core/file_sys/vfs/vfs_real.h" 28#include "core/file_sys/vfs/vfs_real.h"
29#include "core/hle/service/am/applet_manager.h"
29#include "core/hle/service/filesystem/filesystem.h" 30#include "core/hle/service/filesystem/filesystem.h"
30#include "core/loader/loader.h" 31#include "core/loader/loader.h"
31#include "core/telemetry_session.h" 32#include "core/telemetry_session.h"
@@ -366,7 +367,10 @@ int main(int argc, char** argv) {
366 system.GetFileSystemController().CreateFactories(*system.GetFilesystem()); 367 system.GetFileSystemController().CreateFactories(*system.GetFilesystem());
367 system.GetUserChannel().clear(); 368 system.GetUserChannel().clear();
368 369
369 const Core::SystemResultStatus load_result{system.Load(*emu_window, filepath)}; 370 Service::AM::FrontendAppletParameters load_parameters{
371 .applet_id = Service::AM::AppletId::Application,
372 };
373 const Core::SystemResultStatus load_result{system.Load(*emu_window, filepath, load_parameters)};
370 374
371 switch (load_result) { 375 switch (load_result) {
372 case Core::SystemResultStatus::ErrorGetLoader: 376 case Core::SystemResultStatus::ErrorGetLoader: