early-access version 3862

This commit is contained in:
pineappleEA 2023-09-10 21:22:54 +02:00
parent a8f426f152
commit e3e1e1f1a9
17 changed files with 97 additions and 89 deletions

View file

@ -49,6 +49,8 @@ option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}")
option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON) option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON)
option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON)
CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Compile LDN room server" ON "NOT ANDROID" OFF) CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Compile LDN room server" ON "NOT ANDROID" OFF)
CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile Windows crash dump (Minidump) support" OFF "WIN32" OFF) CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile Windows crash dump (Minidump) support" OFF "WIN32" OFF)
@ -77,6 +79,24 @@ if (ANDROID OR WIN32 OR APPLE)
endif() endif()
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL}) option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL)
set(vvl_version "sdk-1.3.261.1")
set(vvl_zip_file "${CMAKE_BINARY_DIR}/externals/vvl-android.zip")
if (NOT EXISTS "${vvl_zip_file}")
# Download and extract validation layer release to externals directory
set(vvl_base_url "https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases/download")
file(DOWNLOAD "${vvl_base_url}/${vvl_version}/android-binaries-${vvl_version}-android.zip"
"${vvl_zip_file}" SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${vvl_zip_file}"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
endif()
# Copy the arm64 binary to src/android/app/main/jniLibs
set(vvl_lib_path "${CMAKE_CURRENT_SOURCE_DIR}/src/android/app/src/main/jniLibs/arm64-v8a/")
file(COPY "${CMAKE_BINARY_DIR}/externals/android-binaries-${vvl_version}/arm64-v8a/libVkLayer_khronos_validation.so"
DESTINATION "${vvl_lib_path}")
endif()
# On Android, fetch and compile libcxx before doing anything else # On Android, fetch and compile libcxx before doing anything else
if (ANDROID) if (ANDROID)
set(CMAKE_SKIP_INSTALL_RULES ON) set(CMAKE_SKIP_INSTALL_RULES ON)

View file

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 3861. This is the source code for early-access 3862.
## Legal Notice ## Legal Notice

View file

@ -270,6 +270,7 @@ public:
m_vulkan_library); m_vulkan_library);
m_system.SetFilesystem(m_vfs); m_system.SetFilesystem(m_vfs);
m_system.GetUserChannel().clear();
// Initialize system. // Initialize system.
jauto android_keyboard = std::make_unique<SoftwareKeyboard::AndroidKeyboard>(); jauto android_keyboard = std::make_unique<SoftwareKeyboard::AndroidKeyboard>();

View file

@ -571,6 +571,8 @@ struct System::Impl {
std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES> std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES>
gpu_dirty_memory_write_manager{}; gpu_dirty_memory_write_manager{};
std::deque<std::vector<u8>> user_channel;
}; };
System::System() : impl{std::make_unique<Impl>(*this)} {} System::System() : impl{std::make_unique<Impl>(*this)} {}
@ -1045,6 +1047,10 @@ void System::ExecuteProgram(std::size_t program_index) {
} }
} }
std::deque<std::vector<u8>>& System::GetUserChannel() {
return impl->user_channel;
}
void System::RegisterExitCallback(ExitCallback&& callback) { void System::RegisterExitCallback(ExitCallback&& callback) {
impl->exit_callback = std::move(callback); impl->exit_callback = std::move(callback);
} }

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <cstddef> #include <cstddef>
#include <deque>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
@ -459,6 +460,12 @@ public:
*/ */
void ExecuteProgram(std::size_t program_index); void ExecuteProgram(std::size_t program_index);
/**
* Gets a reference to the user channel stack.
* It is used to transfer data between programs.
*/
[[nodiscard]] std::deque<std::vector<u8>>& GetUserChannel();
/// Type used for the frontend to designate a callback for System to exit the application. /// Type used for the frontend to designate a callback for System to exit the application.
using ExitCallback = std::function<void()>; using ExitCallback = std::function<void()>;

View file

@ -46,7 +46,7 @@ constexpr Result ResultNoMessages{ErrorModule::AM, 3};
constexpr Result ResultInvalidOffset{ErrorModule::AM, 503}; constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
enum class LaunchParameterKind : u32 { enum class LaunchParameterKind : u32 {
ApplicationSpecific = 1, UserChannel = 1,
AccountPreselectedUser = 2, AccountPreselectedUser = 2,
}; };
@ -1518,27 +1518,26 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto kind = rp.PopEnum<LaunchParameterKind>(); const auto kind = rp.PopEnum<LaunchParameterKind>();
LOG_DEBUG(Service_AM, "called, kind={:08X}", kind); LOG_INFO(Service_AM, "called, kind={:08X}", kind);
if (kind == LaunchParameterKind::ApplicationSpecific && !launch_popped_application_specific) { if (kind == LaunchParameterKind::UserChannel) {
const auto backend = BCAT::CreateBackendFromSettings(system, [this](u64 tid) { auto channel = system.GetUserChannel();
return system.GetFileSystemController().GetBCATDirectory(tid); if (channel.empty()) {
}); LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
const auto build_id_full = system.GetApplicationProcessBuildID(); IPC::ResponseBuilder rb{ctx, 2};
u64 build_id{}; rb.Push(AM::ResultNoDataInChannel);
std::memcpy(&build_id, build_id_full.data(), sizeof(u64));
auto data =
backend->GetLaunchParameter({system.GetApplicationProcessProgramID(), build_id});
if (data.has_value()) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IStorage>(system, std::move(*data));
launch_popped_application_specific = true;
return; return;
} }
auto data = channel.back();
channel.pop_back();
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IStorage>(system, std::move(data));
} else if (kind == LaunchParameterKind::AccountPreselectedUser && } else if (kind == LaunchParameterKind::AccountPreselectedUser &&
!launch_popped_account_preselect) { !launch_popped_account_preselect) {
// TODO: Verify this is hw-accurate
LaunchParameterAccountPreselectedUser params{}; LaunchParameterAccountPreselectedUser params{};
params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC; params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
@ -1550,7 +1549,6 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
params.current_user = *uuid; params.current_user = *uuid;
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser)); std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
@ -1558,12 +1556,11 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
rb.PushIpcInterface<IStorage>(system, std::move(buffer)); rb.PushIpcInterface<IStorage>(system, std::move(buffer));
launch_popped_account_preselect = true; launch_popped_account_preselect = true;
return; } else {
} LOG_ERROR(Service_AM, "Unknown launch parameter kind.");
LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(AM::ResultNoDataInChannel); rb.Push(AM::ResultNoDataInChannel);
}
} }
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) { void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
@ -1855,14 +1852,22 @@ void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
} }
void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) { void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called"); LOG_DEBUG(Service_AM, "(STUBBED) called");
system.GetUserChannel().clear();
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) { void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called"); LOG_DEBUG(Service_AM, "called");
IPC::RequestParser rp{ctx};
const auto storage = rp.PopIpcInterface<IStorage>().lock();
if (storage) {
system.GetUserChannel().push_back(storage->GetData());
}
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);

View file

@ -339,7 +339,6 @@ private:
KernelHelpers::ServiceContext service_context; KernelHelpers::ServiceContext service_context;
bool launch_popped_application_specific = false;
bool launch_popped_account_preselect = false; bool launch_popped_account_preselect = false;
s32 previous_program_index{-1}; s32 previous_program_index{-1};
Kernel::KEvent* gpu_error_detected_event; Kernel::KEvent* gpu_error_detected_event;

View file

@ -66,21 +66,6 @@ std::string BuildCommaSeparatedExtensions(
return fmt::format("{}", fmt::join(available_extensions, ",")); return fmt::format("{}", fmt::join(available_extensions, ","));
} }
DebugCallback MakeDebugCallback(const vk::Instance& instance, const vk::InstanceDispatch& dld) {
if (!Settings::values.renderer_debug) {
return DebugCallback{};
}
const std::optional properties = vk::EnumerateInstanceExtensionProperties(dld);
const auto it = std::ranges::find_if(*properties, [](const auto& prop) {
return std::strcmp(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, prop.extensionName) == 0;
});
if (it != properties->end()) {
return CreateDebugUtilsCallback(instance);
} else {
return CreateDebugReportCallback(instance);
}
}
} // Anonymous namespace } // Anonymous namespace
Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld, Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld,
@ -103,7 +88,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary(context.get())), cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary(context.get())),
instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type,
Settings::values.renderer_debug.GetValue())), Settings::values.renderer_debug.GetValue())),
debug_callback(MakeDebugCallback(instance, dld)), debug_messenger(Settings::values.renderer_debug ? CreateDebugUtilsCallback(instance)
: vk::DebugUtilsMessenger{}),
surface(CreateSurface(instance, render_window.GetWindowInfo())), surface(CreateSurface(instance, render_window.GetWindowInfo())),
device(CreateDevice(instance, dld, *surface)), memory_allocator(device), state_tracker(), device(CreateDevice(instance, dld, *surface)), memory_allocator(device), state_tracker(),
scheduler(device, state_tracker), scheduler(device, state_tracker),

View file

@ -35,8 +35,6 @@ class GPU;
namespace Vulkan { namespace Vulkan {
using DebugCallback = std::variant<vk::DebugUtilsMessenger, vk::DebugReportCallback>;
Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld, Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld,
VkSurfaceKHR surface); VkSurfaceKHR surface);
@ -75,7 +73,7 @@ private:
vk::InstanceDispatch dld; vk::InstanceDispatch dld;
vk::Instance instance; vk::Instance instance;
DebugCallback debug_callback; vk::DebugUtilsMessenger debug_messenger;
vk::SurfaceKHR surface; vk::SurfaceKHR surface;
ScreenInfo screen_info; ScreenInfo screen_info;

View file

@ -63,22 +63,6 @@ VkBool32 DebugUtilCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
return VK_FALSE; return VK_FALSE;
} }
VkBool32 DebugReportCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType,
uint64_t object, size_t location, int32_t messageCode,
const char* pLayerPrefix, const char* pMessage, void* pUserData) {
const VkDebugReportFlagBitsEXT severity = static_cast<VkDebugReportFlagBitsEXT>(flags);
const std::string_view message{pMessage};
if (severity & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
LOG_CRITICAL(Render_Vulkan, "{}", message);
} else if (severity & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
LOG_WARNING(Render_Vulkan, "{}", message);
} else if (severity & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
LOG_INFO(Render_Vulkan, "{}", message);
} else if (severity & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
LOG_DEBUG(Render_Vulkan, "{}", message);
}
return VK_FALSE;
}
} // Anonymous namespace } // Anonymous namespace
vk::DebugUtilsMessenger CreateDebugUtilsCallback(const vk::Instance& instance) { vk::DebugUtilsMessenger CreateDebugUtilsCallback(const vk::Instance& instance) {
@ -98,15 +82,4 @@ vk::DebugUtilsMessenger CreateDebugUtilsCallback(const vk::Instance& instance) {
}); });
} }
vk::DebugReportCallback CreateDebugReportCallback(const vk::Instance& instance) {
return instance.CreateDebugReportCallback({
.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
.pNext = nullptr,
.flags = VK_DEBUG_REPORT_DEBUG_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT,
.pfnCallback = DebugReportCallback,
.pUserData = nullptr,
});
}
} // namespace Vulkan } // namespace Vulkan

View file

@ -9,6 +9,4 @@ namespace Vulkan {
vk::DebugUtilsMessenger CreateDebugUtilsCallback(const vk::Instance& instance); vk::DebugUtilsMessenger CreateDebugUtilsCallback(const vk::Instance& instance);
vk::DebugReportCallback CreateDebugReportCallback(const vk::Instance& instance);
} // namespace Vulkan } // namespace Vulkan

View file

@ -76,11 +76,9 @@ namespace {
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
} }
#endif #endif
if (enable_validation) { if (enable_validation &&
const bool debug_utils = AreExtensionsSupported(dld, std::array{VK_EXT_DEBUG_UTILS_EXTENSION_NAME})) {
AreExtensionsSupported(dld, std::array{VK_EXT_DEBUG_UTILS_EXTENSION_NAME}); extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
extensions.push_back(debug_utils ? VK_EXT_DEBUG_UTILS_EXTENSION_NAME
: VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
} }
return extensions; return extensions;
} }

View file

@ -593,10 +593,12 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path); emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path);
}); });
connect(start_game, &QAction::triggered, [this, path]() { connect(start_game, &QAction::triggered, [this, path]() {
emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Normal); emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Normal,
AmLaunchType::UserInitiated);
}); });
connect(start_game_global, &QAction::triggered, [this, path]() { connect(start_game_global, &QAction::triggered, [this, path]() {
emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Global); emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Global,
AmLaunchType::UserInitiated);
}); });
connect(open_mod_location, &QAction::triggered, [this, program_id, path]() { connect(open_mod_location, &QAction::triggered, [this, program_id, path]() {
emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path); emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path);

View file

@ -29,6 +29,7 @@ class GameListWorker;
class GameListSearchField; class GameListSearchField;
class GameListDir; class GameListDir;
class GMainWindow; class GMainWindow;
enum class AmLaunchType;
enum class StartGameType; enum class StartGameType;
namespace FileSys { namespace FileSys {
@ -106,7 +107,7 @@ public:
signals: signals:
void BootGame(const QString& game_path, u64 program_id, std::size_t program_index, void BootGame(const QString& game_path, u64 program_id, std::size_t program_index,
StartGameType type); StartGameType type, AmLaunchType launch_type);
void GameChosen(const QString& game_path, const u64 title_id = 0); void GameChosen(const QString& game_path, const u64 title_id = 0);
void ShouldCancelWorker(); void ShouldCancelWorker();
void OpenFolderRequested(u64 program_id, GameListOpenTarget target, void OpenFolderRequested(u64 program_id, GameListOpenTarget target,

View file

@ -1710,7 +1710,8 @@ void GMainWindow::AllowOSSleep() {
#endif #endif
} }
bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index) { bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index,
AmLaunchType launch_type) {
// Shutdown previous session if the emu thread is still active... // Shutdown previous session if the emu thread is still active...
if (emu_thread != nullptr) { if (emu_thread != nullptr) {
ShutdownGame(); ShutdownGame();
@ -1722,6 +1723,10 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
system->SetFilesystem(vfs); system->SetFilesystem(vfs);
if (launch_type == AmLaunchType::UserInitiated) {
system->GetUserChannel().clear();
}
system->SetAppletFrontendSet({ system->SetAppletFrontendSet({
std::make_unique<QtAmiiboSettings>(*this), // Amiibo Settings std::make_unique<QtAmiiboSettings>(*this), // Amiibo Settings
(UISettings::values.controller_applet_disabled.GetValue() == true) (UISettings::values.controller_applet_disabled.GetValue() == true)
@ -1861,7 +1866,7 @@ void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) {
} }
void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index, void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index,
StartGameType type) { StartGameType type, AmLaunchType launch_type) {
LOG_INFO(Frontend, "yuzu starting..."); LOG_INFO(Frontend, "yuzu starting...");
StoreRecentFile(filename); // Put the filename on top of the list StoreRecentFile(filename); // Put the filename on top of the list
@ -1905,7 +1910,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
} }
} }
if (!LoadROM(filename, program_id, program_index)) { if (!LoadROM(filename, program_id, program_index, launch_type)) {
return; return;
} }
@ -3392,7 +3397,8 @@ void GMainWindow::OnLoadComplete() {
void GMainWindow::OnExecuteProgram(std::size_t program_index) { void GMainWindow::OnExecuteProgram(std::size_t program_index) {
ShutdownGame(); ShutdownGame();
BootGame(last_filename_booted, 0, program_index); BootGame(last_filename_booted, 0, program_index, StartGameType::Normal,
AmLaunchType::ApplicationInitiated);
} }
void GMainWindow::OnExit() { void GMainWindow::OnExit() {

View file

@ -58,6 +58,11 @@ enum class StartGameType {
Global, // Only uses global configuration Global, // Only uses global configuration
}; };
enum class AmLaunchType {
UserInitiated,
ApplicationInitiated,
};
namespace Core { namespace Core {
enum class SystemResultStatus : u32; enum class SystemResultStatus : u32;
class System; class System;
@ -243,9 +248,11 @@ private:
void PreventOSSleep(); void PreventOSSleep();
void AllowOSSleep(); void AllowOSSleep();
bool LoadROM(const QString& filename, u64 program_id, std::size_t program_index); bool LoadROM(const QString& filename, u64 program_id, std::size_t program_index,
AmLaunchType launch_type);
void BootGame(const QString& filename, u64 program_id = 0, std::size_t program_index = 0, void BootGame(const QString& filename, u64 program_id = 0, std::size_t program_index = 0,
StartGameType with_config = StartGameType::Normal); StartGameType with_config = StartGameType::Normal,
AmLaunchType launch_type = AmLaunchType::UserInitiated);
void ShutdownGame(); void ShutdownGame();
void ShowTelemetryCallout(); void ShowTelemetryCallout();

View file

@ -358,6 +358,7 @@ int main(int argc, char** argv) {
system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>()); system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
system.SetFilesystem(std::make_shared<FileSys::RealVfsFilesystem>()); system.SetFilesystem(std::make_shared<FileSys::RealVfsFilesystem>());
system.GetFileSystemController().CreateFactories(*system.GetFilesystem()); system.GetFileSystemController().CreateFactories(*system.GetFilesystem());
system.GetUserChannel().clear();
const Core::SystemResultStatus load_result{system.Load(*emu_window, filepath)}; const Core::SystemResultStatus load_result{system.Load(*emu_window, filepath)};