summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt40
-rw-r--r--externals/CMakeLists.txt2
-rw-r--r--src/audio_core/command_generator.cpp9
-rw-r--r--src/common/settings.cpp2
-rw-r--r--src/common/settings.h10
-rw-r--r--src/common/uuid.h5
-rw-r--r--src/core/CMakeLists.txt72
-rw-r--r--src/core/core.cpp17
-rw-r--r--src/core/core.h2
-rw-r--r--src/core/file_sys/card_image.cpp18
-rw-r--r--src/core/file_sys/card_image.h3
-rw-r--r--src/core/file_sys/content_archive.cpp1
-rw-r--r--src/core/file_sys/submission_package.cpp71
-rw-r--r--src/core/file_sys/submission_package.h11
-rw-r--r--src/core/frontend/applets/software_keyboard.h2
-rw-r--r--src/core/frontend/applets/web_browser.h2
-rw-r--r--src/core/hardware_interrupt_manager.cpp2
-rw-r--r--src/core/hle/service/acc/acc.cpp2
-rw-r--r--src/core/hle/service/acc/acc.h2
-rw-r--r--src/core/hle/service/am/am.cpp10
-rw-r--r--src/core/hle/service/am/applets/applet_controller.cpp (renamed from src/core/hle/service/am/applets/controller.cpp)2
-rw-r--r--src/core/hle/service/am/applets/applet_controller.h (renamed from src/core/hle/service/am/applets/controller.h)0
-rw-r--r--src/core/hle/service/am/applets/applet_error.cpp (renamed from src/core/hle/service/am/applets/error.cpp)2
-rw-r--r--src/core/hle/service/am/applets/applet_error.h (renamed from src/core/hle/service/am/applets/error.h)0
-rw-r--r--src/core/hle/service/am/applets/applet_general_backend.cpp (renamed from src/core/hle/service/am/applets/general_backend.cpp)2
-rw-r--r--src/core/hle/service/am/applets/applet_general_backend.h (renamed from src/core/hle/service/am/applets/general_backend.h)0
-rw-r--r--src/core/hle/service/am/applets/applet_profile_select.cpp (renamed from src/core/hle/service/am/applets/profile_select.cpp)2
-rw-r--r--src/core/hle/service/am/applets/applet_profile_select.h (renamed from src/core/hle/service/am/applets/profile_select.h)0
-rw-r--r--src/core/hle/service/am/applets/applet_software_keyboard.cpp (renamed from src/core/hle/service/am/applets/software_keyboard.cpp)2
-rw-r--r--src/core/hle/service/am/applets/applet_software_keyboard.h (renamed from src/core/hle/service/am/applets/software_keyboard.h)2
-rw-r--r--src/core/hle/service/am/applets/applet_software_keyboard_types.h (renamed from src/core/hle/service/am/applets/software_keyboard_types.h)0
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.cpp (renamed from src/core/hle/service/am/applets/web_browser.cpp)15
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.h (renamed from src/core/hle/service/am/applets/web_browser.h)2
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser_types.h (renamed from src/core/hle/service/am/applets/web_types.h)0
-rw-r--r--src/core/hle/service/am/applets/applets.cpp12
-rw-r--r--src/core/hle/service/apm/apm.cpp2
-rw-r--r--src/core/hle/service/apm/apm_controller.cpp (renamed from src/core/hle/service/apm/controller.cpp)2
-rw-r--r--src/core/hle/service/apm/apm_controller.h (renamed from src/core/hle/service/apm/controller.h)0
-rw-r--r--src/core/hle/service/apm/apm_interface.cpp (renamed from src/core/hle/service/apm/interface.cpp)4
-rw-r--r--src/core/hle/service/apm/apm_interface.h (renamed from src/core/hle/service/apm/interface.h)0
-rw-r--r--src/core/hle/service/bcat/backend/boxcat.cpp3
-rw-r--r--src/core/hle/service/bcat/bcat.h2
-rw-r--r--src/core/hle/service/bcat/bcat_module.cpp (renamed from src/core/hle/service/bcat/module.cpp)2
-rw-r--r--src/core/hle/service/bcat/bcat_module.h (renamed from src/core/hle/service/bcat/module.h)0
-rw-r--r--src/core/hle/service/friend/friend.cpp2
-rw-r--r--src/core/hle/service/friend/friend_interface.cpp (renamed from src/core/hle/service/friend/interface.cpp)2
-rw-r--r--src/core/hle/service/friend/friend_interface.h (renamed from src/core/hle/service/friend/interface.h)0
-rw-r--r--src/core/hle/service/glue/arp.cpp2
-rw-r--r--src/core/hle/service/glue/glue_manager.cpp (renamed from src/core/hle/service/glue/manager.cpp)2
-rw-r--r--src/core/hle/service/glue/glue_manager.h (renamed from src/core/hle/service/glue/manager.h)0
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp5
-rw-r--r--src/core/hle/service/mii/mii.cpp2
-rw-r--r--src/core/hle/service/mii/mii_manager.cpp (renamed from src/core/hle/service/mii/manager.cpp)2
-rw-r--r--src/core/hle/service/mii/mii_manager.h (renamed from src/core/hle/service/mii/manager.h)0
-rw-r--r--src/core/hle/service/mii/raw_data.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp85
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp2
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.cpp (renamed from src/core/hle/service/nvdrv/interface.cpp)2
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.h (renamed from src/core/hle/service/nvdrv/interface.h)0
-rw-r--r--src/core/hle/service/pctl/pctl.h2
-rw-r--r--src/core/hle/service/pctl/pctl_module.cpp (renamed from src/core/hle/service/pctl/module.cpp)2
-rw-r--r--src/core/hle/service/pctl/pctl_module.h (renamed from src/core/hle/service/pctl/module.h)0
-rw-r--r--src/core/hle/service/service.cpp6
-rw-r--r--src/core/hle/service/sm/sm.cpp2
-rw-r--r--src/core/hle/service/sm/sm_controller.cpp (renamed from src/core/hle/service/sm/controller.cpp)2
-rw-r--r--src/core/hle/service/sm/sm_controller.h (renamed from src/core/hle/service/sm/controller.h)0
-rw-r--r--src/core/hle/service/spl/csrng.h2
-rw-r--r--src/core/hle/service/spl/spl.h2
-rw-r--r--src/core/hle/service/spl/spl_module.cpp (renamed from src/core/hle/service/spl/module.cpp)2
-rw-r--r--src/core/hle/service/spl/spl_module.h (renamed from src/core/hle/service/spl/module.h)0
-rw-r--r--src/core/hle/service/time/time.cpp2
-rw-r--r--src/core/hle/service/time/time_interface.cpp (renamed from src/core/hle/service/time/interface.cpp)2
-rw-r--r--src/core/hle/service/time/time_interface.h (renamed from src/core/hle/service/time/interface.h)0
-rw-r--r--src/core/loader/loader.cpp13
-rw-r--r--src/core/loader/loader.h13
-rw-r--r--src/core/loader/nsp.cpp34
-rw-r--r--src/core/loader/nsp.h4
-rw-r--r--src/core/loader/xci.cpp14
-rw-r--r--src/core/loader/xci.h3
-rw-r--r--src/input_common/main.cpp4
-rw-r--r--src/input_common/mouse/mouse_poller.cpp2
-rw-r--r--src/input_common/sdl/sdl_impl.cpp4
-rw-r--r--src/input_common/sdl/sdl_impl.h8
-rw-r--r--src/video_core/command_classes/vic.cpp21
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp8
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp5
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp31
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h6
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp33
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp6
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp6
-rw-r--r--src/video_core/texture_cache/texture_cache.h6
-rw-r--r--src/video_core/texture_cache/util.cpp86
-rw-r--r--src/web_service/web_backend.cpp10
-rw-r--r--src/yuzu/CMakeLists.txt25
-rw-r--r--src/yuzu/applets/qt_controller.cpp (renamed from src/yuzu/applets/controller.cpp)4
-rw-r--r--src/yuzu/applets/qt_controller.h (renamed from src/yuzu/applets/controller.h)0
-rw-r--r--src/yuzu/applets/qt_controller.ui (renamed from src/yuzu/applets/controller.ui)0
-rw-r--r--src/yuzu/applets/qt_error.cpp (renamed from src/yuzu/applets/error.cpp)2
-rw-r--r--src/yuzu/applets/qt_error.h (renamed from src/yuzu/applets/error.h)0
-rw-r--r--src/yuzu/applets/qt_profile_select.cpp (renamed from src/yuzu/applets/profile_select.cpp)2
-rw-r--r--src/yuzu/applets/qt_profile_select.h (renamed from src/yuzu/applets/profile_select.h)0
-rw-r--r--src/yuzu/applets/qt_software_keyboard.cpp (renamed from src/yuzu/applets/software_keyboard.cpp)4
-rw-r--r--src/yuzu/applets/qt_software_keyboard.h (renamed from src/yuzu/applets/software_keyboard.h)0
-rw-r--r--src/yuzu/applets/qt_software_keyboard.ui (renamed from src/yuzu/applets/software_keyboard.ui)0
-rw-r--r--src/yuzu/applets/qt_web_browser.cpp (renamed from src/yuzu/applets/web_browser.cpp)4
-rw-r--r--src/yuzu/applets/qt_web_browser.h (renamed from src/yuzu/applets/web_browser.h)0
-rw-r--r--src/yuzu/applets/qt_web_browser_scripts.h (renamed from src/yuzu/applets/web_browser_scripts.h)0
-rw-r--r--src/yuzu/bootmanager.cpp15
-rw-r--r--src/yuzu/configuration/config.cpp25
-rw-r--r--src/yuzu/configuration/configure_audio.cpp13
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp18
-rw-r--r--src/yuzu/configuration/configure_input_advanced.ui15
-rw-r--r--src/yuzu/game_list.cpp8
-rw-r--r--src/yuzu/game_list.h5
-rw-r--r--src/yuzu/game_list_worker.cpp44
-rw-r--r--src/yuzu/main.cpp33
-rw-r--r--src/yuzu/main.h6
-rw-r--r--src/yuzu_cmd/CMakeLists.txt5
-rw-r--r--src/yuzu_cmd/config.cpp30
-rw-r--r--src/yuzu_cmd/default_ini.h146
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp8
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp8
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp28
125 files changed, 682 insertions, 556 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 716256cd5..857550e71 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,7 +13,7 @@ project(yuzu)
13option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) 13option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
14CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF) 14CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF)
15# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion 15# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion
16option(YUZU_ALLOW_SYSTEM_SDL2 "Try using system SDL2 before fallling back to one from externals" OFF) 16CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF)
17 17
18option(ENABLE_QT "Enable the Qt frontend" ON) 18option(ENABLE_QT "Enable the Qt frontend" ON)
19option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) 19option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
@@ -254,7 +254,9 @@ if(ENABLE_QT)
254 254
255 # Check for system Qt on Linux, fallback to bundled Qt 255 # Check for system Qt on Linux, fallback to bundled Qt
256 if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") 256 if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
257 find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets) 257 if (NOT YUZU_USE_BUNDLED_QT)
258 find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets)
259 endif()
258 if (NOT Qt5_FOUND OR YUZU_USE_BUNDLED_QT) 260 if (NOT Qt5_FOUND OR YUZU_USE_BUNDLED_QT)
259 # Check for dependencies, then enable bundled Qt download 261 # Check for dependencies, then enable bundled Qt download
260 262
@@ -337,6 +339,8 @@ if(ENABLE_QT)
337 endif() 339 endif()
338 endif() 340 endif()
339 341
342 set(YUZU_QT_NO_CMAKE_SYSTEM_PATH)
343
340 # Workaround for an issue where conan tries to build Qt from scratch instead of download prebuilt binaries 344 # Workaround for an issue where conan tries to build Qt from scratch instead of download prebuilt binaries
341 set(QT_PREFIX_HINT) 345 set(QT_PREFIX_HINT)
342 346
@@ -354,8 +358,10 @@ if(ENABLE_QT)
354 endif() 358 endif()
355 359
356 set(QT_PREFIX_HINT HINTS "${QT_PREFIX}") 360 set(QT_PREFIX_HINT HINTS "${QT_PREFIX}")
361
362 set(YUZU_QT_NO_CMAKE_SYSTEM_PATH "NO_CMAKE_SYSTEM_PATH")
357 endif() 363 endif()
358 find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets ${QT_PREFIX_HINT} NO_CMAKE_SYSTEM_PATH) 364 find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})
359 if (YUZU_USE_QT_WEB_ENGINE) 365 if (YUZU_USE_QT_WEB_ENGINE)
360 find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets) 366 find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets)
361 endif() 367 endif()
@@ -387,26 +393,20 @@ if (ENABLE_SDL2)
387 add_library(SDL2 INTERFACE) 393 add_library(SDL2 INTERFACE)
388 target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}") 394 target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}")
389 target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}") 395 target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}")
396 elseif (YUZU_USE_EXTERNAL_SDL2)
397 message(STATUS "Using SDL2 from externals.")
390 else() 398 else()
391 if (YUZU_ALLOW_SYSTEM_SDL2) 399 find_package(SDL2 2.0.15 REQUIRED)
392 find_package(SDL2 2.0.15 QUIET)
393
394 if (SDL2_FOUND)
395 # Some installations don't set SDL2_LIBRARIES
396 if("${SDL2_LIBRARIES}" STREQUAL "")
397 message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
398 set(SDL2_LIBRARIES "SDL2::SDL2")
399 endif()
400 400
401 include_directories(SYSTEM ${SDL2_INCLUDE_DIRS}) 401 # Some installations don't set SDL2_LIBRARIES
402 add_library(SDL2 INTERFACE) 402 if("${SDL2_LIBRARIES}" STREQUAL "")
403 target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}") 403 message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
404 else() 404 set(SDL2_LIBRARIES "SDL2::SDL2")
405 message(STATUS "SDL2 2.0.15 or newer not found, falling back to externals.")
406 endif()
407 else()
408 message(STATUS "Using SDL2 from externals.")
409 endif() 405 endif()
406
407 include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
408 add_library(SDL2 INTERFACE)
409 target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
410 endif() 410 endif()
411endif() 411endif()
412 412
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index fd427a912..4b8d35548 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -51,7 +51,7 @@ if (NOT LIBUSB_FOUND OR YUZU_USE_BUNDLED_LIBUSB)
51endif() 51endif()
52 52
53# SDL2 53# SDL2
54if (NOT SDL2_FOUND AND ENABLE_SDL2) 54if (YUZU_USE_EXTERNAL_SDL2)
55 if (NOT WIN32) 55 if (NOT WIN32)
56 # Yuzu itself needs: Events Joystick Haptic Sensor Timers Audio 56 # Yuzu itself needs: Events Joystick Haptic Sensor Timers Audio
57 # Yuzu-cmd also needs: Video (depends on Loadso/Dlopen) 57 # Yuzu-cmd also needs: Video (depends on Loadso/Dlopen)
diff --git a/src/audio_core/command_generator.cpp b/src/audio_core/command_generator.cpp
index b99d0fc91..45b2eef52 100644
--- a/src/audio_core/command_generator.cpp
+++ b/src/audio_core/command_generator.cpp
@@ -42,6 +42,15 @@ void ApplyMix(std::span<s32> output, std::span<const s32> input, s32 gain, s32 s
42 42
43s32 ApplyMixRamp(std::span<s32> output, std::span<const s32> input, float gain, float delta, 43s32 ApplyMixRamp(std::span<s32> output, std::span<const s32> input, float gain, float delta,
44 s32 sample_count) { 44 s32 sample_count) {
45 // XC2 passes in NaN mix volumes, causing further issues as we handle everything as s32 rather
46 // than float, so the NaN propogation is lost. As the samples get further modified for
47 // volume etc, they can get out of NaN range, so a later heuristic for catching this is
48 // more difficult. Handle it here by setting these samples to silence.
49 if (std::isnan(gain)) {
50 gain = 0.0f;
51 delta = 0.0f;
52 }
53
45 s32 x = 0; 54 s32 x = 0;
46 for (s32 i = 0; i < sample_count; i++) { 55 for (s32 i = 0; i < sample_count; i++) {
47 x = static_cast<s32>(static_cast<float>(input[i]) * gain); 56 x = static_cast<s32>(static_cast<float>(input[i]) * gain);
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index e1973af85..bf5514386 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -103,7 +103,7 @@ float Volume() {
103 if (values.audio_muted) { 103 if (values.audio_muted) {
104 return 0.0f; 104 return 0.0f;
105 } 105 }
106 return values.volume.GetValue(); 106 return values.volume.GetValue() / 100.0f;
107} 107}
108 108
109void RestoreGlobalState(bool is_powered_on) { 109void RestoreGlobalState(bool is_powered_on) {
diff --git a/src/common/settings.h b/src/common/settings.h
index 71d0f864f..ce1bc647d 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -278,7 +278,7 @@ struct Values {
278 BasicSetting<std::string> sink_id{"auto", "output_engine"}; 278 BasicSetting<std::string> sink_id{"auto", "output_engine"};
279 BasicSetting<bool> audio_muted{false, "audio_muted"}; 279 BasicSetting<bool> audio_muted{false, "audio_muted"};
280 Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"}; 280 Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"};
281 Setting<float> volume{1.0f, "volume"}; 281 Setting<u8> volume{100, "volume"};
282 282
283 // Core 283 // Core
284 Setting<bool> use_multi_core{true, "use_multi_core"}; 284 Setting<bool> use_multi_core{true, "use_multi_core"};
@@ -336,9 +336,9 @@ struct Values {
336 Setting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; 336 Setting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"};
337 Setting<bool> use_caches_gc{false, "use_caches_gc"}; 337 Setting<bool> use_caches_gc{false, "use_caches_gc"};
338 338
339 Setting<float> bg_red{0.0f, "bg_red"}; 339 Setting<u8> bg_red{0, "bg_red"};
340 Setting<float> bg_green{0.0f, "bg_green"}; 340 Setting<u8> bg_green{0, "bg_green"};
341 Setting<float> bg_blue{0.0f, "bg_blue"}; 341 Setting<u8> bg_blue{0, "bg_blue"};
342 342
343 // System 343 // System
344 Setting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"}; 344 Setting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"};
@@ -368,7 +368,7 @@ struct Values {
368 "udp_input_servers"}; 368 "udp_input_servers"};
369 369
370 BasicSetting<bool> mouse_panning{false, "mouse_panning"}; 370 BasicSetting<bool> mouse_panning{false, "mouse_panning"};
371 BasicSetting<float> mouse_panning_sensitivity{1.0f, "mouse_panning_sensitivity"}; 371 BasicSetting<u8> mouse_panning_sensitivity{10, "mouse_panning_sensitivity"};
372 BasicSetting<bool> mouse_enabled{false, "mouse_enabled"}; 372 BasicSetting<bool> mouse_enabled{false, "mouse_enabled"};
373 std::string mouse_device; 373 std::string mouse_device;
374 MouseButtonsRaw mouse_buttons; 374 MouseButtonsRaw mouse_buttons;
diff --git a/src/common/uuid.h b/src/common/uuid.h
index 2e7a18405..0ffa37e7c 100644
--- a/src/common/uuid.h
+++ b/src/common/uuid.h
@@ -20,12 +20,11 @@ struct UUID {
20 constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {} 20 constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {}
21 21
22 [[nodiscard]] constexpr explicit operator bool() const { 22 [[nodiscard]] constexpr explicit operator bool() const {
23 return uuid[0] != INVALID_UUID[0] && uuid[1] != INVALID_UUID[1]; 23 return uuid != INVALID_UUID;
24 } 24 }
25 25
26 [[nodiscard]] constexpr bool operator==(const UUID& rhs) const { 26 [[nodiscard]] constexpr bool operator==(const UUID& rhs) const {
27 // TODO(DarkLordZach): Replace with uuid == rhs.uuid with C++20 27 return uuid == rhs.uuid;
28 return uuid[0] == rhs.uuid[0] && uuid[1] == rhs.uuid[1];
29 } 28 }
30 29
31 [[nodiscard]] constexpr bool operator!=(const UUID& rhs) const { 30 [[nodiscard]] constexpr bool operator!=(const UUID& rhs) const {
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index b2b0dbe05..c7b899131 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -272,22 +272,22 @@ add_library(core STATIC
272 hle/service/am/applet_ae.h 272 hle/service/am/applet_ae.h
273 hle/service/am/applet_oe.cpp 273 hle/service/am/applet_oe.cpp
274 hle/service/am/applet_oe.h 274 hle/service/am/applet_oe.h
275 hle/service/am/applets/applet_controller.cpp
276 hle/service/am/applets/applet_controller.h
277 hle/service/am/applets/applet_error.cpp
278 hle/service/am/applets/applet_error.h
279 hle/service/am/applets/applet_general_backend.cpp
280 hle/service/am/applets/applet_general_backend.h
281 hle/service/am/applets/applet_profile_select.cpp
282 hle/service/am/applets/applet_profile_select.h
283 hle/service/am/applets/applet_software_keyboard.cpp
284 hle/service/am/applets/applet_software_keyboard.h
285 hle/service/am/applets/applet_software_keyboard_types.h
286 hle/service/am/applets/applet_web_browser.cpp
287 hle/service/am/applets/applet_web_browser.h
288 hle/service/am/applets/applet_web_browser_types.h
275 hle/service/am/applets/applets.cpp 289 hle/service/am/applets/applets.cpp
276 hle/service/am/applets/applets.h 290 hle/service/am/applets/applets.h
277 hle/service/am/applets/controller.cpp
278 hle/service/am/applets/controller.h
279 hle/service/am/applets/error.cpp
280 hle/service/am/applets/error.h
281 hle/service/am/applets/general_backend.cpp
282 hle/service/am/applets/general_backend.h
283 hle/service/am/applets/profile_select.cpp
284 hle/service/am/applets/profile_select.h
285 hle/service/am/applets/software_keyboard.cpp
286 hle/service/am/applets/software_keyboard.h
287 hle/service/am/applets/software_keyboard_types.h
288 hle/service/am/applets/web_browser.cpp
289 hle/service/am/applets/web_browser.h
290 hle/service/am/applets/web_types.h
291 hle/service/am/idle.cpp 291 hle/service/am/idle.cpp
292 hle/service/am/idle.h 292 hle/service/am/idle.h
293 hle/service/am/omm.cpp 293 hle/service/am/omm.cpp
@@ -300,10 +300,10 @@ add_library(core STATIC
300 hle/service/aoc/aoc_u.h 300 hle/service/aoc/aoc_u.h
301 hle/service/apm/apm.cpp 301 hle/service/apm/apm.cpp
302 hle/service/apm/apm.h 302 hle/service/apm/apm.h
303 hle/service/apm/controller.cpp 303 hle/service/apm/apm_controller.cpp
304 hle/service/apm/controller.h 304 hle/service/apm/apm_controller.h
305 hle/service/apm/interface.cpp 305 hle/service/apm/apm_interface.cpp
306 hle/service/apm/interface.h 306 hle/service/apm/apm_interface.h
307 hle/service/audio/audctl.cpp 307 hle/service/audio/audctl.cpp
308 hle/service/audio/audctl.h 308 hle/service/audio/audctl.h
309 hle/service/audio/auddbg.cpp 309 hle/service/audio/auddbg.cpp
@@ -335,8 +335,8 @@ add_library(core STATIC
335 hle/service/bcat/backend/backend.h 335 hle/service/bcat/backend/backend.h
336 hle/service/bcat/bcat.cpp 336 hle/service/bcat/bcat.cpp
337 hle/service/bcat/bcat.h 337 hle/service/bcat/bcat.h
338 hle/service/bcat/module.cpp 338 hle/service/bcat/bcat_module.cpp
339 hle/service/bcat/module.h 339 hle/service/bcat/bcat_module.h
340 hle/service/bpc/bpc.cpp 340 hle/service/bpc/bpc.cpp
341 hle/service/bpc/bpc.h 341 hle/service/bpc/bpc.h
342 hle/service/btdrv/btdrv.cpp 342 hle/service/btdrv/btdrv.cpp
@@ -382,8 +382,8 @@ add_library(core STATIC
382 hle/service/friend/errors.h 382 hle/service/friend/errors.h
383 hle/service/friend/friend.cpp 383 hle/service/friend/friend.cpp
384 hle/service/friend/friend.h 384 hle/service/friend/friend.h
385 hle/service/friend/interface.cpp 385 hle/service/friend/friend_interface.cpp
386 hle/service/friend/interface.h 386 hle/service/friend/friend_interface.h
387 hle/service/glue/arp.cpp 387 hle/service/glue/arp.cpp
388 hle/service/glue/arp.h 388 hle/service/glue/arp.h
389 hle/service/glue/bgtc.cpp 389 hle/service/glue/bgtc.cpp
@@ -393,8 +393,8 @@ add_library(core STATIC
393 hle/service/glue/errors.h 393 hle/service/glue/errors.h
394 hle/service/glue/glue.cpp 394 hle/service/glue/glue.cpp
395 hle/service/glue/glue.h 395 hle/service/glue/glue.h
396 hle/service/glue/manager.cpp 396 hle/service/glue/glue_manager.cpp
397 hle/service/glue/manager.h 397 hle/service/glue/glue_manager.h
398 hle/service/grc/grc.cpp 398 hle/service/grc/grc.cpp
399 hle/service/grc/grc.h 399 hle/service/grc/grc.h
400 hle/service/hid/hid.cpp 400 hle/service/hid/hid.cpp
@@ -435,10 +435,10 @@ add_library(core STATIC
435 hle/service/lm/lm.h 435 hle/service/lm/lm.h
436 hle/service/mig/mig.cpp 436 hle/service/mig/mig.cpp
437 hle/service/mig/mig.h 437 hle/service/mig/mig.h
438 hle/service/mii/manager.cpp
439 hle/service/mii/manager.h
440 hle/service/mii/mii.cpp 438 hle/service/mii/mii.cpp
441 hle/service/mii/mii.h 439 hle/service/mii/mii.h
440 hle/service/mii/mii_manager.cpp
441 hle/service/mii/mii_manager.h
442 hle/service/mii/raw_data.cpp 442 hle/service/mii/raw_data.cpp
443 hle/service/mii/raw_data.h 443 hle/service/mii/raw_data.h
444 hle/service/mii/types.h 444 hle/service/mii/types.h
@@ -486,11 +486,11 @@ add_library(core STATIC
486 hle/service/nvdrv/devices/nvhost_vic.h 486 hle/service/nvdrv/devices/nvhost_vic.h
487 hle/service/nvdrv/devices/nvmap.cpp 487 hle/service/nvdrv/devices/nvmap.cpp
488 hle/service/nvdrv/devices/nvmap.h 488 hle/service/nvdrv/devices/nvmap.h
489 hle/service/nvdrv/interface.cpp
490 hle/service/nvdrv/interface.h
491 hle/service/nvdrv/nvdata.h 489 hle/service/nvdrv/nvdata.h
492 hle/service/nvdrv/nvdrv.cpp 490 hle/service/nvdrv/nvdrv.cpp
493 hle/service/nvdrv/nvdrv.h 491 hle/service/nvdrv/nvdrv.h
492 hle/service/nvdrv/nvdrv_interface.cpp
493 hle/service/nvdrv/nvdrv_interface.h
494 hle/service/nvdrv/nvmemp.cpp 494 hle/service/nvdrv/nvmemp.cpp
495 hle/service/nvdrv/nvmemp.h 495 hle/service/nvdrv/nvmemp.h
496 hle/service/nvdrv/syncpoint_manager.cpp 496 hle/service/nvdrv/syncpoint_manager.cpp
@@ -503,10 +503,10 @@ add_library(core STATIC
503 hle/service/olsc/olsc.h 503 hle/service/olsc/olsc.h
504 hle/service/pcie/pcie.cpp 504 hle/service/pcie/pcie.cpp
505 hle/service/pcie/pcie.h 505 hle/service/pcie/pcie.h
506 hle/service/pctl/module.cpp
507 hle/service/pctl/module.h
508 hle/service/pctl/pctl.cpp 506 hle/service/pctl/pctl.cpp
509 hle/service/pctl/pctl.h 507 hle/service/pctl/pctl.h
508 hle/service/pctl/pctl_module.cpp
509 hle/service/pctl/pctl_module.h
510 hle/service/pcv/pcv.cpp 510 hle/service/pcv/pcv.cpp
511 hle/service/pcv/pcv.h 511 hle/service/pcv/pcv.h
512 hle/service/pm/pm.cpp 512 hle/service/pm/pm.cpp
@@ -529,10 +529,10 @@ add_library(core STATIC
529 hle/service/set/set_sys.h 529 hle/service/set/set_sys.h
530 hle/service/set/settings.cpp 530 hle/service/set/settings.cpp
531 hle/service/set/settings.h 531 hle/service/set/settings.h
532 hle/service/sm/controller.cpp
533 hle/service/sm/controller.h
534 hle/service/sm/sm.cpp 532 hle/service/sm/sm.cpp
535 hle/service/sm/sm.h 533 hle/service/sm/sm.h
534 hle/service/sm/sm_controller.cpp
535 hle/service/sm/sm_controller.h
536 hle/service/sockets/bsd.cpp 536 hle/service/sockets/bsd.cpp
537 hle/service/sockets/bsd.h 537 hle/service/sockets/bsd.h
538 hle/service/sockets/ethc.cpp 538 hle/service/sockets/ethc.cpp
@@ -547,10 +547,10 @@ add_library(core STATIC
547 hle/service/sockets/sockets_translate.h 547 hle/service/sockets/sockets_translate.h
548 hle/service/spl/csrng.cpp 548 hle/service/spl/csrng.cpp
549 hle/service/spl/csrng.h 549 hle/service/spl/csrng.h
550 hle/service/spl/module.cpp
551 hle/service/spl/module.h
552 hle/service/spl/spl.cpp 550 hle/service/spl/spl.cpp
553 hle/service/spl/spl.h 551 hle/service/spl/spl.h
552 hle/service/spl/spl_module.cpp
553 hle/service/spl/spl_module.h
554 hle/service/spl/spl_results.h 554 hle/service/spl/spl_results.h
555 hle/service/spl/spl_types.h 555 hle/service/spl/spl_types.h
556 hle/service/ssl/ssl.cpp 556 hle/service/ssl/ssl.cpp
@@ -559,8 +559,6 @@ add_library(core STATIC
559 hle/service/time/ephemeral_network_system_clock_context_writer.h 559 hle/service/time/ephemeral_network_system_clock_context_writer.h
560 hle/service/time/ephemeral_network_system_clock_core.h 560 hle/service/time/ephemeral_network_system_clock_core.h
561 hle/service/time/errors.h 561 hle/service/time/errors.h
562 hle/service/time/interface.cpp
563 hle/service/time/interface.h
564 hle/service/time/local_system_clock_context_writer.h 562 hle/service/time/local_system_clock_context_writer.h
565 hle/service/time/network_system_clock_context_writer.h 563 hle/service/time/network_system_clock_context_writer.h
566 hle/service/time/standard_local_system_clock_core.h 564 hle/service/time/standard_local_system_clock_core.h
@@ -578,6 +576,8 @@ add_library(core STATIC
578 hle/service/time/tick_based_steady_clock_core.h 576 hle/service/time/tick_based_steady_clock_core.h
579 hle/service/time/time.cpp 577 hle/service/time/time.cpp
580 hle/service/time/time.h 578 hle/service/time/time.h
579 hle/service/time/time_interface.cpp
580 hle/service/time/time_interface.h
581 hle/service/time/time_manager.cpp 581 hle/service/time/time_manager.cpp
582 hle/service/time/time_manager.h 582 hle/service/time/time_manager.h
583 hle/service/time/time_sharedmemory.cpp 583 hle/service/time/time_sharedmemory.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 891f1cb49..15226cf41 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -35,9 +35,9 @@
35#include "core/hle/kernel/kernel.h" 35#include "core/hle/kernel/kernel.h"
36#include "core/hle/kernel/physical_core.h" 36#include "core/hle/kernel/physical_core.h"
37#include "core/hle/service/am/applets/applets.h" 37#include "core/hle/service/am/applets/applets.h"
38#include "core/hle/service/apm/controller.h" 38#include "core/hle/service/apm/apm_controller.h"
39#include "core/hle/service/filesystem/filesystem.h" 39#include "core/hle/service/filesystem/filesystem.h"
40#include "core/hle/service/glue/manager.h" 40#include "core/hle/service/glue/glue_manager.h"
41#include "core/hle/service/hid/hid.h" 41#include "core/hle/service/hid/hid.h"
42#include "core/hle/service/service.h" 42#include "core/hle/service/service.h"
43#include "core/hle/service/sm/sm.h" 43#include "core/hle/service/sm/sm.h"
@@ -216,9 +216,9 @@ struct System::Impl {
216 } 216 }
217 217
218 ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath, 218 ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath,
219 std::size_t program_index) { 219 u64 program_id, std::size_t program_index) {
220 app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath), 220 app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath),
221 program_index); 221 program_id, program_index);
222 222
223 if (!app_loader) { 223 if (!app_loader) {
224 LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); 224 LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
@@ -269,11 +269,10 @@ struct System::Impl {
269 } 269 }
270 } 270 }
271 271
272 u64 title_id{0}; 272 if (app_loader->ReadProgramId(program_id) != Loader::ResultStatus::Success) {
273 if (app_loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) {
274 LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", load_result); 273 LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", load_result);
275 } 274 }
276 perf_stats = std::make_unique<PerfStats>(title_id); 275 perf_stats = std::make_unique<PerfStats>(program_id);
277 // Reset counters and set time origin to current frame 276 // Reset counters and set time origin to current frame
278 GetAndResetPerfStats(); 277 GetAndResetPerfStats();
279 perf_stats->BeginSystemFrame(); 278 perf_stats->BeginSystemFrame();
@@ -459,8 +458,8 @@ void System::Shutdown() {
459} 458}
460 459
461System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath, 460System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
462 std::size_t program_index) { 461 u64 program_id, std::size_t program_index) {
463 return impl->Load(*this, emu_window, filepath, program_index); 462 return impl->Load(*this, emu_window, filepath, program_id, program_index);
464} 463}
465 464
466bool System::IsPoweredOn() const { 465bool System::IsPoweredOn() const {
diff --git a/src/core/core.h b/src/core/core.h
index 8b93ba998..b93c32e60 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -175,7 +175,7 @@ public:
175 * @returns ResultStatus code, indicating if the operation succeeded. 175 * @returns ResultStatus code, indicating if the operation succeeded.
176 */ 176 */
177 [[nodiscard]] ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath, 177 [[nodiscard]] ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
178 std::size_t program_index = 0); 178 u64 program_id = 0, std::size_t program_index = 0);
179 179
180 /** 180 /**
181 * Indicates if the emulated system is powered on (all subsystems initialized and able to run an 181 * Indicates if the emulated system is powered on (all subsystems initialized and able to run an
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp
index db2f6a955..755d3303e 100644
--- a/src/core/file_sys/card_image.cpp
+++ b/src/core/file_sys/card_image.cpp
@@ -29,7 +29,7 @@ constexpr std::array partition_names{
29 "logo", 29 "logo",
30}; 30};
31 31
32XCI::XCI(VirtualFile file_, std::size_t program_index) 32XCI::XCI(VirtualFile file_, u64 program_id, size_t program_index)
33 : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, 33 : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA},
34 partitions(partition_names.size()), 34 partitions(partition_names.size()),
35 partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} { 35 partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} {
@@ -63,12 +63,12 @@ XCI::XCI(VirtualFile file_, std::size_t program_index)
63 63
64 secure_partition = std::make_shared<NSP>( 64 secure_partition = std::make_shared<NSP>(
65 main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)]), 65 main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)]),
66 program_index); 66 program_id, program_index);
67 67
68 ncas = secure_partition->GetNCAsCollapsed(); 68 ncas = secure_partition->GetNCAsCollapsed();
69 program = 69 program =
70 secure_partition->GetNCA(secure_partition->GetProgramTitleID(), ContentRecordType::Program); 70 secure_partition->GetNCA(secure_partition->GetProgramTitleID(), ContentRecordType::Program);
71 program_nca_status = secure_partition->GetProgramStatus(secure_partition->GetProgramTitleID()); 71 program_nca_status = secure_partition->GetProgramStatus();
72 if (program_nca_status == Loader::ResultStatus::ErrorNSPMissingProgramNCA) { 72 if (program_nca_status == Loader::ResultStatus::ErrorNSPMissingProgramNCA) {
73 program_nca_status = Loader::ResultStatus::ErrorXCIMissingProgramNCA; 73 program_nca_status = Loader::ResultStatus::ErrorXCIMissingProgramNCA;
74 } 74 }
@@ -174,6 +174,10 @@ u64 XCI::GetProgramTitleID() const {
174 return secure_partition->GetProgramTitleID(); 174 return secure_partition->GetProgramTitleID();
175} 175}
176 176
177std::vector<u64> XCI::GetProgramTitleIDs() const {
178 return secure_partition->GetProgramTitleIDs();
179}
180
177u32 XCI::GetSystemUpdateVersion() { 181u32 XCI::GetSystemUpdateVersion() {
178 const auto update = GetPartition(XCIPartition::Update); 182 const auto update = GetPartition(XCIPartition::Update);
179 if (update == nullptr) { 183 if (update == nullptr) {
@@ -229,9 +233,11 @@ const std::vector<std::shared_ptr<NCA>>& XCI::GetNCAs() const {
229} 233}
230 234
231std::shared_ptr<NCA> XCI::GetNCAByType(NCAContentType type) const { 235std::shared_ptr<NCA> XCI::GetNCAByType(NCAContentType type) const {
232 const auto iter = 236 const auto program_id = secure_partition->GetProgramTitleID();
233 std::find_if(ncas.begin(), ncas.end(), 237 const auto iter = std::find_if(
234 [type](const std::shared_ptr<NCA>& nca) { return nca->GetType() == type; }); 238 ncas.begin(), ncas.end(), [this, type, program_id](const std::shared_ptr<NCA>& nca) {
239 return nca->GetType() == type && nca->GetTitleId() == program_id;
240 });
235 return iter == ncas.end() ? nullptr : *iter; 241 return iter == ncas.end() ? nullptr : *iter;
236} 242}
237 243
diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h
index 4960e90fe..0fd9fa87c 100644
--- a/src/core/file_sys/card_image.h
+++ b/src/core/file_sys/card_image.h
@@ -78,7 +78,7 @@ enum class XCIPartition : u8 { Update, Normal, Secure, Logo };
78 78
79class XCI : public ReadOnlyVfsDirectory { 79class XCI : public ReadOnlyVfsDirectory {
80public: 80public:
81 explicit XCI(VirtualFile file, std::size_t program_index = 0); 81 explicit XCI(VirtualFile file, u64 program_id = 0, size_t program_index = 0);
82 ~XCI() override; 82 ~XCI() override;
83 83
84 Loader::ResultStatus GetStatus() const; 84 Loader::ResultStatus GetStatus() const;
@@ -104,6 +104,7 @@ public:
104 VirtualFile GetLogoPartitionRaw() const; 104 VirtualFile GetLogoPartitionRaw() const;
105 105
106 u64 GetProgramTitleID() const; 106 u64 GetProgramTitleID() const;
107 std::vector<u64> GetProgramTitleIDs() const;
107 u32 GetSystemUpdateVersion(); 108 u32 GetSystemUpdateVersion();
108 u64 GetSystemUpdateTitleID() const; 109 u64 GetSystemUpdateTitleID() const;
109 110
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index 24eff210f..7019a7a68 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -5,7 +5,6 @@
5#include <algorithm> 5#include <algorithm>
6#include <cstring> 6#include <cstring>
7#include <optional> 7#include <optional>
8#include <ranges>
9#include <utility> 8#include <utility>
10 9
11#include "common/logging/log.h" 10#include "common/logging/log.h"
diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp
index d51d469e3..f192dffa5 100644
--- a/src/core/file_sys/submission_package.cpp
+++ b/src/core/file_sys/submission_package.cpp
@@ -20,8 +20,9 @@
20 20
21namespace FileSys { 21namespace FileSys {
22 22
23NSP::NSP(VirtualFile file_, std::size_t program_index_) 23NSP::NSP(VirtualFile file_, u64 title_id_, std::size_t program_index_)
24 : file(std::move(file_)), program_index(program_index_), status{Loader::ResultStatus::Success}, 24 : file(std::move(file_)), expected_program_id(title_id_),
25 program_index(program_index_), status{Loader::ResultStatus::Success},
25 pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} { 26 pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} {
26 if (pfs->GetStatus() != Loader::ResultStatus::Success) { 27 if (pfs->GetStatus() != Loader::ResultStatus::Success) {
27 status = pfs->GetStatus(); 28 status = pfs->GetStatus();
@@ -46,60 +47,59 @@ Loader::ResultStatus NSP::GetStatus() const {
46 return status; 47 return status;
47} 48}
48 49
49Loader::ResultStatus NSP::GetProgramStatus(u64 title_id) const { 50Loader::ResultStatus NSP::GetProgramStatus() const {
50 if (IsExtractedType() && GetExeFS() != nullptr && FileSys::IsDirectoryExeFS(GetExeFS())) { 51 if (IsExtractedType() && GetExeFS() != nullptr && FileSys::IsDirectoryExeFS(GetExeFS())) {
51 return Loader::ResultStatus::Success; 52 return Loader::ResultStatus::Success;
52 } 53 }
53 54
54 const auto iter = program_status.find(title_id); 55 const auto iter = program_status.find(GetProgramTitleID());
55 if (iter == program_status.end()) 56 if (iter == program_status.end())
56 return Loader::ResultStatus::ErrorNSPMissingProgramNCA; 57 return Loader::ResultStatus::ErrorNSPMissingProgramNCA;
57 return iter->second; 58 return iter->second;
58} 59}
59 60
60u64 NSP::GetFirstTitleID() const {
61 if (IsExtractedType()) {
62 return GetProgramTitleID();
63 }
64
65 if (program_status.empty())
66 return 0;
67 return program_status.begin()->first;
68}
69
70u64 NSP::GetProgramTitleID() const { 61u64 NSP::GetProgramTitleID() const {
71 if (IsExtractedType()) { 62 if (IsExtractedType()) {
72 if (GetExeFS() == nullptr || !IsDirectoryExeFS(GetExeFS())) { 63 return GetExtractedTitleID() + program_index;
73 return 0; 64 }
74 }
75 65
76 ProgramMetadata meta; 66 auto program_id = expected_program_id;
77 if (meta.Load(GetExeFS()->GetFile("main.npdm")) == Loader::ResultStatus::Success) { 67 if (program_id == 0) {
78 return meta.GetTitleID(); 68 if (!program_status.empty()) {
79 } else { 69 program_id = program_status.begin()->first;
80 return 0;
81 } 70 }
82 } 71 }
83 72
84 const auto out = GetFirstTitleID(); 73 program_id = program_id + program_index;
85 if ((out & 0x800) == 0) 74 if (program_status.find(program_id) != program_status.end()) {
86 return out; 75 return program_id;
76 }
87 77
88 const auto ids = GetTitleIDs(); 78 const auto ids = GetProgramTitleIDs();
89 const auto iter = 79 const auto iter =
90 std::find_if(ids.begin(), ids.end(), [](u64 tid) { return (tid & 0x800) == 0; }); 80 std::find_if(ids.begin(), ids.end(), [](u64 tid) { return (tid & 0x800) == 0; });
91 return iter == ids.end() ? out : *iter; 81 return iter == ids.end() ? 0 : *iter;
82}
83
84u64 NSP::GetExtractedTitleID() const {
85 if (GetExeFS() == nullptr || !IsDirectoryExeFS(GetExeFS())) {
86 return 0;
87 }
88
89 ProgramMetadata meta;
90 if (meta.Load(GetExeFS()->GetFile("main.npdm")) == Loader::ResultStatus::Success) {
91 return meta.GetTitleID();
92 } else {
93 return 0;
94 }
92} 95}
93 96
94std::vector<u64> NSP::GetTitleIDs() const { 97std::vector<u64> NSP::GetProgramTitleIDs() const {
95 if (IsExtractedType()) { 98 if (IsExtractedType()) {
96 return {GetProgramTitleID()}; 99 return {GetExtractedTitleID()};
97 } 100 }
98 101
99 std::vector<u64> out; 102 std::vector<u64> out{program_ids.cbegin(), program_ids.cend()};
100 out.reserve(ncas.size());
101 for (const auto& kv : ncas)
102 out.push_back(kv.first);
103 return out; 103 return out;
104} 104}
105 105
@@ -146,7 +146,7 @@ std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type, TitleType
146 if (extracted) 146 if (extracted)
147 LOG_WARNING(Service_FS, "called on an NSP that is of type extracted."); 147 LOG_WARNING(Service_FS, "called on an NSP that is of type extracted.");
148 148
149 const auto title_id_iter = ncas.find(title_id + program_index); 149 const auto title_id_iter = ncas.find(title_id);
150 if (title_id_iter == ncas.end()) 150 if (title_id_iter == ncas.end())
151 return nullptr; 151 return nullptr;
152 152
@@ -160,7 +160,7 @@ std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type, TitleType
160VirtualFile NSP::GetNCAFile(u64 title_id, ContentRecordType type, TitleType title_type) const { 160VirtualFile NSP::GetNCAFile(u64 title_id, ContentRecordType type, TitleType title_type) const {
161 if (extracted) 161 if (extracted)
162 LOG_WARNING(Service_FS, "called on an NSP that is of type extracted."); 162 LOG_WARNING(Service_FS, "called on an NSP that is of type extracted.");
163 const auto nca = GetNCA(title_id, type); 163 const auto nca = GetNCA(title_id, type, title_type);
164 if (nca != nullptr) 164 if (nca != nullptr)
165 return nca->GetBaseFile(); 165 return nca->GetBaseFile();
166 return nullptr; 166 return nullptr;
@@ -286,6 +286,7 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
286 286
287 if (next_nca->GetType() == NCAContentType::Program) { 287 if (next_nca->GetType() == NCAContentType::Program) {
288 program_status[next_nca->GetTitleId()] = next_nca->GetStatus(); 288 program_status[next_nca->GetTitleId()] = next_nca->GetStatus();
289 program_ids.insert(next_nca->GetTitleId() & 0xFFFFFFFFFFFFF000);
289 } 290 }
290 291
291 if (next_nca->GetStatus() != Loader::ResultStatus::Success && 292 if (next_nca->GetStatus() != Loader::ResultStatus::Success &&
diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h
index ecb3b6f15..030f36c09 100644
--- a/src/core/file_sys/submission_package.h
+++ b/src/core/file_sys/submission_package.h
@@ -6,6 +6,7 @@
6 6
7#include <map> 7#include <map>
8#include <memory> 8#include <memory>
9#include <set>
9#include <vector> 10#include <vector>
10#include "common/common_types.h" 11#include "common/common_types.h"
11#include "core/file_sys/vfs.h" 12#include "core/file_sys/vfs.h"
@@ -27,15 +28,15 @@ enum class ContentRecordType : u8;
27 28
28class NSP : public ReadOnlyVfsDirectory { 29class NSP : public ReadOnlyVfsDirectory {
29public: 30public:
30 explicit NSP(VirtualFile file_, std::size_t program_index_ = 0); 31 explicit NSP(VirtualFile file_, u64 title_id = 0, std::size_t program_index_ = 0);
31 ~NSP() override; 32 ~NSP() override;
32 33
33 Loader::ResultStatus GetStatus() const; 34 Loader::ResultStatus GetStatus() const;
34 Loader::ResultStatus GetProgramStatus(u64 title_id) const; 35 Loader::ResultStatus GetProgramStatus() const;
35 // Should only be used when one title id can be assured. 36 // Should only be used when one title id can be assured.
36 u64 GetFirstTitleID() const;
37 u64 GetProgramTitleID() const; 37 u64 GetProgramTitleID() const;
38 std::vector<u64> GetTitleIDs() const; 38 u64 GetExtractedTitleID() const;
39 std::vector<u64> GetProgramTitleIDs() const;
39 40
40 bool IsExtractedType() const; 41 bool IsExtractedType() const;
41 42
@@ -69,6 +70,7 @@ private:
69 70
70 VirtualFile file; 71 VirtualFile file;
71 72
73 const u64 expected_program_id;
72 const std::size_t program_index; 74 const std::size_t program_index;
73 75
74 bool extracted = false; 76 bool extracted = false;
@@ -78,6 +80,7 @@ private:
78 std::shared_ptr<PartitionFilesystem> pfs; 80 std::shared_ptr<PartitionFilesystem> pfs;
79 // Map title id -> {map type -> NCA} 81 // Map title id -> {map type -> NCA}
80 std::map<u64, std::map<std::pair<TitleType, ContentRecordType>, std::shared_ptr<NCA>>> ncas; 82 std::map<u64, std::map<std::pair<TitleType, ContentRecordType>, std::shared_ptr<NCA>>> ncas;
83 std::set<u64> program_ids;
81 std::vector<VirtualFile> ticket_files; 84 std::vector<VirtualFile> ticket_files;
82 85
83 Core::Crypto::KeyManager& keys; 86 Core::Crypto::KeyManager& keys;
diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h
index 506eb35bb..228a548d4 100644
--- a/src/core/frontend/applets/software_keyboard.h
+++ b/src/core/frontend/applets/software_keyboard.h
@@ -9,7 +9,7 @@
9 9
10#include "common/common_types.h" 10#include "common/common_types.h"
11 11
12#include "core/hle/service/am/applets/software_keyboard_types.h" 12#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
13 13
14namespace Core::Frontend { 14namespace Core::Frontend {
15 15
diff --git a/src/core/frontend/applets/web_browser.h b/src/core/frontend/applets/web_browser.h
index d7bd44c27..915dde677 100644
--- a/src/core/frontend/applets/web_browser.h
+++ b/src/core/frontend/applets/web_browser.h
@@ -7,7 +7,7 @@
7#include <functional> 7#include <functional>
8#include <string_view> 8#include <string_view>
9 9
10#include "core/hle/service/am/applets/web_types.h" 10#include "core/hle/service/am/applets/applet_web_browser_types.h"
11 11
12namespace Core::Frontend { 12namespace Core::Frontend {
13 13
diff --git a/src/core/hardware_interrupt_manager.cpp b/src/core/hardware_interrupt_manager.cpp
index 645f26e91..290db505e 100644
--- a/src/core/hardware_interrupt_manager.cpp
+++ b/src/core/hardware_interrupt_manager.cpp
@@ -5,7 +5,7 @@
5#include "core/core.h" 5#include "core/core.h"
6#include "core/core_timing.h" 6#include "core/core_timing.h"
7#include "core/hardware_interrupt_manager.h" 7#include "core/hardware_interrupt_manager.h"
8#include "core/hle/service/nvdrv/interface.h" 8#include "core/hle/service/nvdrv/nvdrv_interface.h"
9#include "core/hle/service/sm/sm.h" 9#include "core/hle/service/sm/sm.h"
10 10
11namespace Core::Hardware { 11namespace Core::Hardware {
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index d1c1fb71d..2e969f2a8 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -26,7 +26,7 @@
26#include "core/hle/service/acc/errors.h" 26#include "core/hle/service/acc/errors.h"
27#include "core/hle/service/acc/profile_manager.h" 27#include "core/hle/service/acc/profile_manager.h"
28#include "core/hle/service/glue/arp.h" 28#include "core/hle/service/glue/arp.h"
29#include "core/hle/service/glue/manager.h" 29#include "core/hle/service/glue/glue_manager.h"
30#include "core/hle/service/sm/sm.h" 30#include "core/hle/service/sm/sm.h"
31#include "core/loader/loader.h" 31#include "core/loader/loader.h"
32 32
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h
index 0e3ad8ec6..a83a480cd 100644
--- a/src/core/hle/service/acc/acc.h
+++ b/src/core/hle/service/acc/acc.h
@@ -5,7 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include "common/uuid.h" 7#include "common/uuid.h"
8#include "core/hle/service/glue/manager.h" 8#include "core/hle/service/glue/glue_manager.h"
9#include "core/hle/service/service.h" 9#include "core/hle/service/service.h"
10 10
11namespace Service::Account { 11namespace Service::Account {
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 23ebc1138..a538f82e3 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -24,16 +24,16 @@
24#include "core/hle/service/am/am.h" 24#include "core/hle/service/am/am.h"
25#include "core/hle/service/am/applet_ae.h" 25#include "core/hle/service/am/applet_ae.h"
26#include "core/hle/service/am/applet_oe.h" 26#include "core/hle/service/am/applet_oe.h"
27#include "core/hle/service/am/applets/applet_profile_select.h"
28#include "core/hle/service/am/applets/applet_software_keyboard.h"
29#include "core/hle/service/am/applets/applet_web_browser.h"
27#include "core/hle/service/am/applets/applets.h" 30#include "core/hle/service/am/applets/applets.h"
28#include "core/hle/service/am/applets/profile_select.h"
29#include "core/hle/service/am/applets/software_keyboard.h"
30#include "core/hle/service/am/applets/web_browser.h"
31#include "core/hle/service/am/idle.h" 31#include "core/hle/service/am/idle.h"
32#include "core/hle/service/am/omm.h" 32#include "core/hle/service/am/omm.h"
33#include "core/hle/service/am/spsm.h" 33#include "core/hle/service/am/spsm.h"
34#include "core/hle/service/am/tcap.h" 34#include "core/hle/service/am/tcap.h"
35#include "core/hle/service/apm/controller.h" 35#include "core/hle/service/apm/apm_controller.h"
36#include "core/hle/service/apm/interface.h" 36#include "core/hle/service/apm/apm_interface.h"
37#include "core/hle/service/bcat/backend/backend.h" 37#include "core/hle/service/bcat/backend/backend.h"
38#include "core/hle/service/filesystem/filesystem.h" 38#include "core/hle/service/filesystem/filesystem.h"
39#include "core/hle/service/ns/ns.h" 39#include "core/hle/service/ns/ns.h"
diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp
index 218c8d1e4..12682effe 100644
--- a/src/core/hle/service/am/applets/controller.cpp
+++ b/src/core/hle/service/am/applets/applet_controller.cpp
@@ -12,7 +12,7 @@
12#include "core/frontend/applets/controller.h" 12#include "core/frontend/applets/controller.h"
13#include "core/hle/result.h" 13#include "core/hle/result.h"
14#include "core/hle/service/am/am.h" 14#include "core/hle/service/am/am.h"
15#include "core/hle/service/am/applets/controller.h" 15#include "core/hle/service/am/applets/applet_controller.h"
16#include "core/hle/service/hid/controllers/npad.h" 16#include "core/hle/service/hid/controllers/npad.h"
17 17
18namespace Service::AM::Applets { 18namespace Service::AM::Applets {
diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/applet_controller.h
index 20617e91f..20617e91f 100644
--- a/src/core/hle/service/am/applets/controller.h
+++ b/src/core/hle/service/am/applets/applet_controller.h
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/applet_error.cpp
index c724e5d5b..ef6854d62 100644
--- a/src/core/hle/service/am/applets/error.cpp
+++ b/src/core/hle/service/am/applets/applet_error.cpp
@@ -11,7 +11,7 @@
11#include "core/frontend/applets/error.h" 11#include "core/frontend/applets/error.h"
12#include "core/hle/kernel/k_process.h" 12#include "core/hle/kernel/k_process.h"
13#include "core/hle/service/am/am.h" 13#include "core/hle/service/am/am.h"
14#include "core/hle/service/am/applets/error.h" 14#include "core/hle/service/am/applets/applet_error.h"
15#include "core/reporter.h" 15#include "core/reporter.h"
16 16
17namespace Service::AM::Applets { 17namespace Service::AM::Applets {
diff --git a/src/core/hle/service/am/applets/error.h b/src/core/hle/service/am/applets/applet_error.h
index 8aa9046a5..8aa9046a5 100644
--- a/src/core/hle/service/am/applets/error.h
+++ b/src/core/hle/service/am/applets/applet_error.h
diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/applet_general_backend.cpp
index 9fcb9f95b..0f413f9a0 100644
--- a/src/core/hle/service/am/applets/general_backend.cpp
+++ b/src/core/hle/service/am/applets/applet_general_backend.cpp
@@ -12,7 +12,7 @@
12#include "core/hle/kernel/k_process.h" 12#include "core/hle/kernel/k_process.h"
13#include "core/hle/result.h" 13#include "core/hle/result.h"
14#include "core/hle/service/am/am.h" 14#include "core/hle/service/am/am.h"
15#include "core/hle/service/am/applets/general_backend.h" 15#include "core/hle/service/am/applets/applet_general_backend.h"
16#include "core/reporter.h" 16#include "core/reporter.h"
17 17
18namespace Service::AM::Applets { 18namespace Service::AM::Applets {
diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/applet_general_backend.h
index 7496ded88..7496ded88 100644
--- a/src/core/hle/service/am/applets/general_backend.h
+++ b/src/core/hle/service/am/applets/applet_general_backend.h
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/applet_profile_select.cpp
index 37048be26..bdc21778e 100644
--- a/src/core/hle/service/am/applets/profile_select.cpp
+++ b/src/core/hle/service/am/applets/applet_profile_select.cpp
@@ -9,7 +9,7 @@
9#include "core/core.h" 9#include "core/core.h"
10#include "core/frontend/applets/profile_select.h" 10#include "core/frontend/applets/profile_select.h"
11#include "core/hle/service/am/am.h" 11#include "core/hle/service/am/am.h"
12#include "core/hle/service/am/applets/profile_select.h" 12#include "core/hle/service/am/applets/applet_profile_select.h"
13 13
14namespace Service::AM::Applets { 14namespace Service::AM::Applets {
15 15
diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/applet_profile_select.h
index 8fb76e6c4..8fb76e6c4 100644
--- a/src/core/hle/service/am/applets/profile_select.h
+++ b/src/core/hle/service/am/applets/applet_profile_select.h
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
index 00dfe1675..7cae90609 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
@@ -6,7 +6,7 @@
6#include "core/core.h" 6#include "core/core.h"
7#include "core/frontend/applets/software_keyboard.h" 7#include "core/frontend/applets/software_keyboard.h"
8#include "core/hle/service/am/am.h" 8#include "core/hle/service/am/am.h"
9#include "core/hle/service/am/applets/software_keyboard.h" 9#include "core/hle/service/am/applets/applet_software_keyboard.h"
10 10
11namespace Service::AM::Applets { 11namespace Service::AM::Applets {
12 12
diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/applet_software_keyboard.h
index e3fc733d0..9aef1bf11 100644
--- a/src/core/hle/service/am/applets/software_keyboard.h
+++ b/src/core/hle/service/am/applets/applet_software_keyboard.h
@@ -7,8 +7,8 @@
7#include "common/common_funcs.h" 7#include "common/common_funcs.h"
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "core/hle/result.h" 9#include "core/hle/result.h"
10#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
10#include "core/hle/service/am/applets/applets.h" 11#include "core/hle/service/am/applets/applets.h"
11#include "core/hle/service/am/applets/software_keyboard_types.h"
12 12
13namespace Core { 13namespace Core {
14class System; 14class System;
diff --git a/src/core/hle/service/am/applets/software_keyboard_types.h b/src/core/hle/service/am/applets/applet_software_keyboard_types.h
index 21aa8e800..21aa8e800 100644
--- a/src/core/hle/service/am/applets/software_keyboard_types.h
+++ b/src/core/hle/service/am/applets/applet_software_keyboard_types.h
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp
index 3b28e829b..35f194961 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/applet_web_browser.cpp
@@ -21,7 +21,7 @@
21#include "core/hle/kernel/k_process.h" 21#include "core/hle/kernel/k_process.h"
22#include "core/hle/result.h" 22#include "core/hle/result.h"
23#include "core/hle/service/am/am.h" 23#include "core/hle/service/am/am.h"
24#include "core/hle/service/am/applets/web_browser.h" 24#include "core/hle/service/am/applets/applet_web_browser.h"
25#include "core/hle/service/filesystem/filesystem.h" 25#include "core/hle/service/filesystem/filesystem.h"
26#include "core/hle/service/ns/pl_u.h" 26#include "core/hle/service/ns/pl_u.h"
27 27
@@ -58,6 +58,16 @@ std::string GetMainURL(const std::string& url) {
58 return url.substr(0, index); 58 return url.substr(0, index);
59} 59}
60 60
61std::string ResolveURL(const std::string& url) {
62 const auto index = url.find_first_of('%');
63
64 if (index == std::string::npos) {
65 return url;
66 }
67
68 return url.substr(0, index) + "lp1" + url.substr(index + 1);
69}
70
61WebArgInputTLVMap ReadWebArgs(const std::vector<u8>& web_arg, WebArgHeader& web_arg_header) { 71WebArgInputTLVMap ReadWebArgs(const std::vector<u8>& web_arg, WebArgHeader& web_arg_header) {
62 std::memcpy(&web_arg_header, web_arg.data(), sizeof(WebArgHeader)); 72 std::memcpy(&web_arg_header, web_arg.data(), sizeof(WebArgHeader));
63 73
@@ -407,6 +417,9 @@ void WebBrowser::InitializeShare() {}
407 417
408void WebBrowser::InitializeWeb() { 418void WebBrowser::InitializeWeb() {
409 external_url = ParseStringValue(GetInputTLVData(WebArgInputTLVType::InitialURL).value()); 419 external_url = ParseStringValue(GetInputTLVData(WebArgInputTLVType::InitialURL).value());
420
421 // Resolve Nintendo CDN URLs.
422 external_url = ResolveURL(external_url);
410} 423}
411 424
412void WebBrowser::InitializeWifi() {} 425void WebBrowser::InitializeWifi() {}
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/applet_web_browser.h
index 9f81214b6..4f9e81b79 100644
--- a/src/core/hle/service/am/applets/web_browser.h
+++ b/src/core/hle/service/am/applets/applet_web_browser.h
@@ -11,8 +11,8 @@
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "core/file_sys/vfs_types.h" 12#include "core/file_sys/vfs_types.h"
13#include "core/hle/result.h" 13#include "core/hle/result.h"
14#include "core/hle/service/am/applets/applet_web_browser_types.h"
14#include "core/hle/service/am/applets/applets.h" 15#include "core/hle/service/am/applets/applets.h"
15#include "core/hle/service/am/applets/web_types.h"
16 16
17namespace Core { 17namespace Core {
18class System; 18class System;
diff --git a/src/core/hle/service/am/applets/web_types.h b/src/core/hle/service/am/applets/applet_web_browser_types.h
index 419c2bf79..419c2bf79 100644
--- a/src/core/hle/service/am/applets/web_types.h
+++ b/src/core/hle/service/am/applets/applet_web_browser_types.h
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index ae995df6b..2b7685d42 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -17,13 +17,13 @@
17#include "core/hle/service/am/am.h" 17#include "core/hle/service/am/am.h"
18#include "core/hle/service/am/applet_ae.h" 18#include "core/hle/service/am/applet_ae.h"
19#include "core/hle/service/am/applet_oe.h" 19#include "core/hle/service/am/applet_oe.h"
20#include "core/hle/service/am/applets/applet_controller.h"
21#include "core/hle/service/am/applets/applet_error.h"
22#include "core/hle/service/am/applets/applet_general_backend.h"
23#include "core/hle/service/am/applets/applet_profile_select.h"
24#include "core/hle/service/am/applets/applet_software_keyboard.h"
25#include "core/hle/service/am/applets/applet_web_browser.h"
20#include "core/hle/service/am/applets/applets.h" 26#include "core/hle/service/am/applets/applets.h"
21#include "core/hle/service/am/applets/controller.h"
22#include "core/hle/service/am/applets/error.h"
23#include "core/hle/service/am/applets/general_backend.h"
24#include "core/hle/service/am/applets/profile_select.h"
25#include "core/hle/service/am/applets/software_keyboard.h"
26#include "core/hle/service/am/applets/web_browser.h"
27#include "core/hle/service/sm/sm.h" 27#include "core/hle/service/sm/sm.h"
28 28
29namespace Service::AM::Applets { 29namespace Service::AM::Applets {
diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp
index 97d6619dd..f5ebfe8d6 100644
--- a/src/core/hle/service/apm/apm.cpp
+++ b/src/core/hle/service/apm/apm.cpp
@@ -5,7 +5,7 @@
5#include "core/core.h" 5#include "core/core.h"
6#include "core/hle/ipc_helpers.h" 6#include "core/hle/ipc_helpers.h"
7#include "core/hle/service/apm/apm.h" 7#include "core/hle/service/apm/apm.h"
8#include "core/hle/service/apm/interface.h" 8#include "core/hle/service/apm/apm_interface.h"
9 9
10namespace Service::APM { 10namespace Service::APM {
11 11
diff --git a/src/core/hle/service/apm/controller.cpp b/src/core/hle/service/apm/apm_controller.cpp
index 8bfa7c0e4..98839fe97 100644
--- a/src/core/hle/service/apm/controller.cpp
+++ b/src/core/hle/service/apm/apm_controller.cpp
@@ -9,7 +9,7 @@
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/settings.h" 10#include "common/settings.h"
11#include "core/core_timing.h" 11#include "core/core_timing.h"
12#include "core/hle/service/apm/controller.h" 12#include "core/hle/service/apm/apm_controller.h"
13 13
14namespace Service::APM { 14namespace Service::APM {
15 15
diff --git a/src/core/hle/service/apm/controller.h b/src/core/hle/service/apm/apm_controller.h
index 8d48e0104..8d48e0104 100644
--- a/src/core/hle/service/apm/controller.h
+++ b/src/core/hle/service/apm/apm_controller.h
diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/apm_interface.cpp
index d69ddd135..e58bad083 100644
--- a/src/core/hle/service/apm/interface.cpp
+++ b/src/core/hle/service/apm/apm_interface.cpp
@@ -5,8 +5,8 @@
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "core/hle/ipc_helpers.h" 6#include "core/hle/ipc_helpers.h"
7#include "core/hle/service/apm/apm.h" 7#include "core/hle/service/apm/apm.h"
8#include "core/hle/service/apm/controller.h" 8#include "core/hle/service/apm/apm_controller.h"
9#include "core/hle/service/apm/interface.h" 9#include "core/hle/service/apm/apm_interface.h"
10 10
11namespace Service::APM { 11namespace Service::APM {
12 12
diff --git a/src/core/hle/service/apm/interface.h b/src/core/hle/service/apm/apm_interface.h
index 063ad5308..063ad5308 100644
--- a/src/core/hle/service/apm/interface.h
+++ b/src/core/hle/service/apm/apm_interface.h
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp
index dc15cf58b..7ca7f2aac 100644
--- a/src/core/hle/service/bcat/backend/boxcat.cpp
+++ b/src/core/hle/service/bcat/backend/boxcat.cpp
@@ -7,6 +7,9 @@
7#ifdef __GNUC__ 7#ifdef __GNUC__
8#pragma GCC diagnostic push 8#pragma GCC diagnostic push
9#pragma GCC diagnostic ignored "-Wshadow" 9#pragma GCC diagnostic ignored "-Wshadow"
10#ifndef __clang__
11#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
12#endif
10#endif 13#endif
11#include <httplib.h> 14#include <httplib.h>
12#include <mbedtls/sha256.h> 15#include <mbedtls/sha256.h>
diff --git a/src/core/hle/service/bcat/bcat.h b/src/core/hle/service/bcat/bcat.h
index d72798980..1eba477da 100644
--- a/src/core/hle/service/bcat/bcat.h
+++ b/src/core/hle/service/bcat/bcat.h
@@ -4,7 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "core/hle/service/bcat/module.h" 7#include "core/hle/service/bcat/bcat_module.h"
8 8
9namespace Core { 9namespace Core {
10class System; 10class System;
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/bcat_module.cpp
index f85444da8..72294eb2e 100644
--- a/src/core/hle/service/bcat/module.cpp
+++ b/src/core/hle/service/bcat/bcat_module.cpp
@@ -17,7 +17,7 @@
17#include "core/hle/kernel/k_writable_event.h" 17#include "core/hle/kernel/k_writable_event.h"
18#include "core/hle/service/bcat/backend/backend.h" 18#include "core/hle/service/bcat/backend/backend.h"
19#include "core/hle/service/bcat/bcat.h" 19#include "core/hle/service/bcat/bcat.h"
20#include "core/hle/service/bcat/module.h" 20#include "core/hle/service/bcat/bcat_module.h"
21#include "core/hle/service/filesystem/filesystem.h" 21#include "core/hle/service/filesystem/filesystem.h"
22 22
23namespace Service::BCAT { 23namespace Service::BCAT {
diff --git a/src/core/hle/service/bcat/module.h b/src/core/hle/service/bcat/bcat_module.h
index 738731c06..738731c06 100644
--- a/src/core/hle/service/bcat/module.h
+++ b/src/core/hle/service/bcat/bcat_module.h
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index c5f88bce7..a3c939c0c 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -12,7 +12,7 @@
12#include "core/hle/kernel/k_writable_event.h" 12#include "core/hle/kernel/k_writable_event.h"
13#include "core/hle/service/friend/errors.h" 13#include "core/hle/service/friend/errors.h"
14#include "core/hle/service/friend/friend.h" 14#include "core/hle/service/friend/friend.h"
15#include "core/hle/service/friend/interface.h" 15#include "core/hle/service/friend/friend_interface.h"
16 16
17namespace Service::Friend { 17namespace Service::Friend {
18 18
diff --git a/src/core/hle/service/friend/interface.cpp b/src/core/hle/service/friend/friend_interface.cpp
index 7368ccec2..9b18b2a32 100644
--- a/src/core/hle/service/friend/interface.cpp
+++ b/src/core/hle/service/friend/friend_interface.cpp
@@ -2,7 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/service/friend/interface.h" 5#include "core/hle/service/friend/friend_interface.h"
6 6
7namespace Service::Friend { 7namespace Service::Friend {
8 8
diff --git a/src/core/hle/service/friend/interface.h b/src/core/hle/service/friend/friend_interface.h
index 43d914b32..43d914b32 100644
--- a/src/core/hle/service/friend/interface.h
+++ b/src/core/hle/service/friend/friend_interface.h
diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp
index ca25df67e..5a3b54cc1 100644
--- a/src/core/hle/service/glue/arp.cpp
+++ b/src/core/hle/service/glue/arp.cpp
@@ -13,7 +13,7 @@
13#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
14#include "core/hle/service/glue/arp.h" 14#include "core/hle/service/glue/arp.h"
15#include "core/hle/service/glue/errors.h" 15#include "core/hle/service/glue/errors.h"
16#include "core/hle/service/glue/manager.h" 16#include "core/hle/service/glue/glue_manager.h"
17#include "core/hle/service/service.h" 17#include "core/hle/service/service.h"
18 18
19namespace Service::Glue { 19namespace Service::Glue {
diff --git a/src/core/hle/service/glue/manager.cpp b/src/core/hle/service/glue/glue_manager.cpp
index 9b1754cf8..aa9d48c0c 100644
--- a/src/core/hle/service/glue/manager.cpp
+++ b/src/core/hle/service/glue/glue_manager.cpp
@@ -3,7 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/service/glue/errors.h" 5#include "core/hle/service/glue/errors.h"
6#include "core/hle/service/glue/manager.h" 6#include "core/hle/service/glue/glue_manager.h"
7 7
8namespace Service::Glue { 8namespace Service::Glue {
9 9
diff --git a/src/core/hle/service/glue/manager.h b/src/core/hle/service/glue/glue_manager.h
index a7f5ce3ee..a7f5ce3ee 100644
--- a/src/core/hle/service/glue/manager.h
+++ b/src/core/hle/service/glue/glue_manager.h
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 1eb02aee2..6ce1360e3 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -941,6 +941,11 @@ void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_de
941 941
942void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, 942void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index,
943 std::size_t device_index) { 943 std::size_t device_index) {
944 if (!Settings::values.vibration_enabled.GetValue()) {
945 vibration_devices_mounted[npad_index][device_index] = false;
946 return;
947 }
948
944 if (vibrations[npad_index][device_index]) { 949 if (vibrations[npad_index][device_index]) {
945 vibration_devices_mounted[npad_index][device_index] = 950 vibration_devices_mounted[npad_index][device_index] =
946 vibrations[npad_index][device_index]->GetStatus() == 1; 951 vibrations[npad_index][device_index]->GetStatus() == 1;
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
index bbd81a88a..9d863486a 100644
--- a/src/core/hle/service/mii/mii.cpp
+++ b/src/core/hle/service/mii/mii.cpp
@@ -7,8 +7,8 @@
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/hle/ipc_helpers.h" 8#include "core/hle/ipc_helpers.h"
9#include "core/hle/kernel/hle_ipc.h" 9#include "core/hle/kernel/hle_ipc.h"
10#include "core/hle/service/mii/manager.h"
11#include "core/hle/service/mii/mii.h" 10#include "core/hle/service/mii/mii.h"
11#include "core/hle/service/mii/mii_manager.h"
12#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
13#include "core/hle/service/sm/sm.h" 13#include "core/hle/service/sm/sm.h"
14 14
diff --git a/src/core/hle/service/mii/manager.cpp b/src/core/hle/service/mii/mii_manager.cpp
index 869d2763f..4fef2aea4 100644
--- a/src/core/hle/service/mii/manager.cpp
+++ b/src/core/hle/service/mii/mii_manager.cpp
@@ -10,7 +10,7 @@
10#include "common/string_util.h" 10#include "common/string_util.h"
11 11
12#include "core/hle/service/acc/profile_manager.h" 12#include "core/hle/service/acc/profile_manager.h"
13#include "core/hle/service/mii/manager.h" 13#include "core/hle/service/mii/mii_manager.h"
14#include "core/hle/service/mii/raw_data.h" 14#include "core/hle/service/mii/raw_data.h"
15#include "core/hle/service/mii/types.h" 15#include "core/hle/service/mii/types.h"
16 16
diff --git a/src/core/hle/service/mii/manager.h b/src/core/hle/service/mii/mii_manager.h
index 8e048fc56..8e048fc56 100644
--- a/src/core/hle/service/mii/manager.h
+++ b/src/core/hle/service/mii/mii_manager.h
diff --git a/src/core/hle/service/mii/raw_data.h b/src/core/hle/service/mii/raw_data.h
index 0e35d69d2..a0d2b9d3a 100644
--- a/src/core/hle/service/mii/raw_data.h
+++ b/src/core/hle/service/mii/raw_data.h
@@ -7,7 +7,7 @@
7#include <array> 7#include <array>
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/hle/service/mii/manager.h" 10#include "core/hle/service/mii/mii_manager.h"
11 11
12namespace Service::Mii::RawData { 12namespace Service::Mii::RawData {
13 13
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
index 98e6296f1..1403a39d0 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
@@ -19,26 +19,29 @@
19namespace Service::Nvidia::Devices { 19namespace Service::Nvidia::Devices {
20 20
21namespace { 21namespace {
22// Splice vectors will copy count amount of type T from the input vector into the dst vector. 22// Copies count amount of type T from the input vector into the dst vector.
23// Returns the number of bytes written into dst.
23template <typename T> 24template <typename T>
24std::size_t SpliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count, 25std::size_t SliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count,
25 std::size_t offset) { 26 std::size_t offset) {
26 if (!dst.empty()) { 27 if (dst.empty()) {
27 std::memcpy(dst.data(), input.data() + offset, count * sizeof(T)); 28 return 0;
28 } 29 }
29 return 0; 30 const size_t bytes_copied = count * sizeof(T);
31 std::memcpy(dst.data(), input.data() + offset, bytes_copied);
32 return bytes_copied;
30} 33}
31 34
32// Write vectors will write data to the output buffer 35// Writes the data in src to an offset into the dst vector. The offset is specified in bytes
36// Returns the number of bytes written into dst.
33template <typename T> 37template <typename T>
34std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) { 38std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) {
35 if (src.empty()) { 39 if (src.empty()) {
36 return 0; 40 return 0;
37 } else {
38 std::memcpy(dst.data() + offset, src.data(), src.size() * sizeof(T));
39 offset += src.size() * sizeof(T);
40 return offset;
41 } 41 }
42 const size_t bytes_copied = src.size() * sizeof(T);
43 std::memcpy(dst.data() + offset, src.data(), bytes_copied);
44 return bytes_copied;
42} 45}
43} // Anonymous namespace 46} // Anonymous namespace
44 47
@@ -62,7 +65,6 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u
62 LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); 65 LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count);
63 66
64 // Instantiate param buffers 67 // Instantiate param buffers
65 std::size_t offset = sizeof(IoctlSubmit);
66 std::vector<CommandBuffer> command_buffers(params.cmd_buffer_count); 68 std::vector<CommandBuffer> command_buffers(params.cmd_buffer_count);
67 std::vector<Reloc> relocs(params.relocation_count); 69 std::vector<Reloc> relocs(params.relocation_count);
68 std::vector<u32> reloc_shifts(params.relocation_count); 70 std::vector<u32> reloc_shifts(params.relocation_count);
@@ -70,13 +72,14 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u
70 std::vector<SyncptIncr> wait_checks(params.syncpoint_count); 72 std::vector<SyncptIncr> wait_checks(params.syncpoint_count);
71 std::vector<Fence> fences(params.fence_count); 73 std::vector<Fence> fences(params.fence_count);
72 74
73 // Splice input into their respective buffers 75 // Slice input into their respective buffers
74 offset = SpliceVectors(input, command_buffers, params.cmd_buffer_count, offset); 76 std::size_t offset = sizeof(IoctlSubmit);
75 offset = SpliceVectors(input, relocs, params.relocation_count, offset); 77 offset += SliceVectors(input, command_buffers, params.cmd_buffer_count, offset);
76 offset = SpliceVectors(input, reloc_shifts, params.relocation_count, offset); 78 offset += SliceVectors(input, relocs, params.relocation_count, offset);
77 offset = SpliceVectors(input, syncpt_increments, params.syncpoint_count, offset); 79 offset += SliceVectors(input, reloc_shifts, params.relocation_count, offset);
78 offset = SpliceVectors(input, wait_checks, params.syncpoint_count, offset); 80 offset += SliceVectors(input, syncpt_increments, params.syncpoint_count, offset);
79 offset = SpliceVectors(input, fences, params.fence_count, offset); 81 offset += SliceVectors(input, wait_checks, params.syncpoint_count, offset);
82 offset += SliceVectors(input, fences, params.fence_count, offset);
80 83
81 auto& gpu = system.GPU(); 84 auto& gpu = system.GPU();
82 if (gpu.UseNvdec()) { 85 if (gpu.UseNvdec()) {
@@ -88,35 +91,27 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u
88 } 91 }
89 } 92 }
90 for (const auto& cmd_buffer : command_buffers) { 93 for (const auto& cmd_buffer : command_buffers) {
91 auto object = nvmap_dev->GetObject(cmd_buffer.memory_id); 94 const auto object = nvmap_dev->GetObject(cmd_buffer.memory_id);
92 ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); 95 ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;);
93 const auto map = FindBufferMap(object->dma_map_addr);
94 if (!map) {
95 LOG_ERROR(Service_NVDRV, "Tried to submit an invalid offset 0x{:X} dma 0x{:X}",
96 object->addr, object->dma_map_addr);
97 return NvResult::Success;
98 }
99 Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); 96 Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count);
100 gpu.MemoryManager().ReadBlock(map->StartAddr() + cmd_buffer.offset, cmdlist.data(), 97 system.Memory().ReadBlock(object->addr + cmd_buffer.offset, cmdlist.data(),
101 cmdlist.size() * sizeof(u32)); 98 cmdlist.size() * sizeof(u32));
102 gpu.PushCommandBuffer(cmdlist); 99 gpu.PushCommandBuffer(cmdlist);
103 } 100 }
104 if (gpu.UseNvdec()) { 101 if (gpu.UseNvdec()) {
105
106 fences[0].value = syncpoint_manager.IncreaseSyncpoint(fences[0].id, 1); 102 fences[0].value = syncpoint_manager.IncreaseSyncpoint(fences[0].id, 1);
107
108 Tegra::ChCommandHeaderList cmdlist{{(4 << 28) | fences[0].id}}; 103 Tegra::ChCommandHeaderList cmdlist{{(4 << 28) | fences[0].id}};
109 gpu.PushCommandBuffer(cmdlist); 104 gpu.PushCommandBuffer(cmdlist);
110 } 105 }
111 std::memcpy(output.data(), &params, sizeof(IoctlSubmit)); 106 std::memcpy(output.data(), &params, sizeof(IoctlSubmit));
112 // Some games expect command_buffers to be written back 107 // Some games expect command_buffers to be written back
113 offset = sizeof(IoctlSubmit); 108 offset = sizeof(IoctlSubmit);
114 offset = WriteVectors(output, command_buffers, offset); 109 offset += WriteVectors(output, command_buffers, offset);
115 offset = WriteVectors(output, relocs, offset); 110 offset += WriteVectors(output, relocs, offset);
116 offset = WriteVectors(output, reloc_shifts, offset); 111 offset += WriteVectors(output, reloc_shifts, offset);
117 offset = WriteVectors(output, syncpt_increments, offset); 112 offset += WriteVectors(output, syncpt_increments, offset);
118 offset = WriteVectors(output, wait_checks, offset); 113 offset += WriteVectors(output, wait_checks, offset);
119 offset = WriteVectors(output, fences, offset); 114 offset += WriteVectors(output, fences, offset);
120 115
121 return NvResult::Success; 116 return NvResult::Success;
122} 117}
@@ -148,14 +143,14 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto
148 std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer)); 143 std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
149 std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); 144 std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
150 145
151 SpliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); 146 SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer));
152 147
153 auto& gpu = system.GPU(); 148 auto& gpu = system.GPU();
154 149
155 for (auto& cmf_buff : cmd_buffer_handles) { 150 for (auto& cmd_buffer : cmd_buffer_handles) {
156 auto object{nvmap_dev->GetObject(cmf_buff.map_handle)}; 151 auto object{nvmap_dev->GetObject(cmd_buffer.map_handle)};
157 if (!object) { 152 if (!object) {
158 LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); 153 LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmd_buffer.map_handle);
159 std::memcpy(output.data(), &params, output.size()); 154 std::memcpy(output.data(), &params, output.size());
160 return NvResult::InvalidState; 155 return NvResult::InvalidState;
161 } 156 }
@@ -170,7 +165,7 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto
170 if (!object->dma_map_addr) { 165 if (!object->dma_map_addr) {
171 LOG_ERROR(Service_NVDRV, "failed to map size={}", object->size); 166 LOG_ERROR(Service_NVDRV, "failed to map size={}", object->size);
172 } else { 167 } else {
173 cmf_buff.map_address = object->dma_map_addr; 168 cmd_buffer.map_address = object->dma_map_addr;
174 AddBufferMap(object->dma_map_addr, object->size, object->addr, 169 AddBufferMap(object->dma_map_addr, object->size, object->addr,
175 object->status == nvmap::Object::Status::Allocated); 170 object->status == nvmap::Object::Status::Allocated);
176 } 171 }
@@ -186,14 +181,14 @@ NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vec
186 IoctlMapBuffer params{}; 181 IoctlMapBuffer params{};
187 std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer)); 182 std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
188 std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); 183 std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
189 SpliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); 184 SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer));
190 185
191 auto& gpu = system.GPU(); 186 auto& gpu = system.GPU();
192 187
193 for (auto& cmf_buff : cmd_buffer_handles) { 188 for (auto& cmd_buffer : cmd_buffer_handles) {
194 const auto object{nvmap_dev->GetObject(cmf_buff.map_handle)}; 189 const auto object{nvmap_dev->GetObject(cmd_buffer.map_handle)};
195 if (!object) { 190 if (!object) {
196 LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); 191 LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmd_buffer.map_handle);
197 std::memcpy(output.data(), &params, output.size()); 192 std::memcpy(output.data(), &params, output.size());
198 return NvResult::InvalidState; 193 return NvResult::InvalidState;
199 } 194 }
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 74796dce1..03992af5e 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -20,8 +20,8 @@
20#include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h" 20#include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h"
21#include "core/hle/service/nvdrv/devices/nvhost_vic.h" 21#include "core/hle/service/nvdrv/devices/nvhost_vic.h"
22#include "core/hle/service/nvdrv/devices/nvmap.h" 22#include "core/hle/service/nvdrv/devices/nvmap.h"
23#include "core/hle/service/nvdrv/interface.h"
24#include "core/hle/service/nvdrv/nvdrv.h" 23#include "core/hle/service/nvdrv/nvdrv.h"
24#include "core/hle/service/nvdrv/nvdrv_interface.h"
25#include "core/hle/service/nvdrv/nvmemp.h" 25#include "core/hle/service/nvdrv/nvmemp.h"
26#include "core/hle/service/nvdrv/syncpoint_manager.h" 26#include "core/hle/service/nvdrv/syncpoint_manager.h"
27#include "core/hle/service/nvflinger/nvflinger.h" 27#include "core/hle/service/nvflinger/nvflinger.h"
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
index e4d495000..d61fb73dc 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
@@ -10,9 +10,9 @@
10#include "core/hle/kernel/k_thread.h" 10#include "core/hle/kernel/k_thread.h"
11#include "core/hle/kernel/k_writable_event.h" 11#include "core/hle/kernel/k_writable_event.h"
12#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
13#include "core/hle/service/nvdrv/interface.h"
14#include "core/hle/service/nvdrv/nvdata.h" 13#include "core/hle/service/nvdrv/nvdata.h"
15#include "core/hle/service/nvdrv/nvdrv.h" 14#include "core/hle/service/nvdrv/nvdrv.h"
15#include "core/hle/service/nvdrv/nvdrv_interface.h"
16 16
17namespace Service::Nvidia { 17namespace Service::Nvidia {
18 18
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h
index 0e764c53f..0e764c53f 100644
--- a/src/core/hle/service/nvdrv/interface.h
+++ b/src/core/hle/service/nvdrv/nvdrv_interface.h
diff --git a/src/core/hle/service/pctl/pctl.h b/src/core/hle/service/pctl/pctl.h
index ea3b97823..1d28900b2 100644
--- a/src/core/hle/service/pctl/pctl.h
+++ b/src/core/hle/service/pctl/pctl.h
@@ -4,7 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "core/hle/service/pctl/module.h" 7#include "core/hle/service/pctl/pctl_module.h"
8 8
9namespace Core { 9namespace Core {
10class System; 10class System;
diff --git a/src/core/hle/service/pctl/module.cpp b/src/core/hle/service/pctl/pctl_module.cpp
index 1e31d05a6..6949fcf3b 100644
--- a/src/core/hle/service/pctl/module.cpp
+++ b/src/core/hle/service/pctl/pctl_module.cpp
@@ -8,8 +8,8 @@
8#include "core/file_sys/patch_manager.h" 8#include "core/file_sys/patch_manager.h"
9#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
10#include "core/hle/kernel/k_process.h" 10#include "core/hle/kernel/k_process.h"
11#include "core/hle/service/pctl/module.h"
12#include "core/hle/service/pctl/pctl.h" 11#include "core/hle/service/pctl/pctl.h"
12#include "core/hle/service/pctl/pctl_module.h"
13 13
14namespace Service::PCTL { 14namespace Service::PCTL {
15 15
diff --git a/src/core/hle/service/pctl/module.h b/src/core/hle/service/pctl/pctl_module.h
index f25c5c557..f25c5c557 100644
--- a/src/core/hle/service/pctl/module.h
+++ b/src/core/hle/service/pctl/pctl_module.h
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 663b83cd3..e6fba88b2 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -21,7 +21,7 @@
21#include "core/hle/service/aoc/aoc_u.h" 21#include "core/hle/service/aoc/aoc_u.h"
22#include "core/hle/service/apm/apm.h" 22#include "core/hle/service/apm/apm.h"
23#include "core/hle/service/audio/audio.h" 23#include "core/hle/service/audio/audio.h"
24#include "core/hle/service/bcat/module.h" 24#include "core/hle/service/bcat/bcat_module.h"
25#include "core/hle/service/bpc/bpc.h" 25#include "core/hle/service/bpc/bpc.h"
26#include "core/hle/service/btdrv/btdrv.h" 26#include "core/hle/service/btdrv/btdrv.h"
27#include "core/hle/service/btm/btm.h" 27#include "core/hle/service/btm/btm.h"
@@ -54,7 +54,7 @@
54#include "core/hle/service/nvflinger/nvflinger.h" 54#include "core/hle/service/nvflinger/nvflinger.h"
55#include "core/hle/service/olsc/olsc.h" 55#include "core/hle/service/olsc/olsc.h"
56#include "core/hle/service/pcie/pcie.h" 56#include "core/hle/service/pcie/pcie.h"
57#include "core/hle/service/pctl/module.h" 57#include "core/hle/service/pctl/pctl_module.h"
58#include "core/hle/service/pcv/pcv.h" 58#include "core/hle/service/pcv/pcv.h"
59#include "core/hle/service/pm/pm.h" 59#include "core/hle/service/pm/pm.h"
60#include "core/hle/service/prepo/prepo.h" 60#include "core/hle/service/prepo/prepo.h"
@@ -64,7 +64,7 @@
64#include "core/hle/service/set/settings.h" 64#include "core/hle/service/set/settings.h"
65#include "core/hle/service/sm/sm.h" 65#include "core/hle/service/sm/sm.h"
66#include "core/hle/service/sockets/sockets.h" 66#include "core/hle/service/sockets/sockets.h"
67#include "core/hle/service/spl/module.h" 67#include "core/hle/service/spl/spl_module.h"
68#include "core/hle/service/ssl/ssl.h" 68#include "core/hle/service/ssl/ssl.h"
69#include "core/hle/service/time/time.h" 69#include "core/hle/service/time/time.h"
70#include "core/hle/service/usb/usb.h" 70#include "core/hle/service/usb/usb.h"
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index c7828c3bd..15034abed 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -14,8 +14,8 @@
14#include "core/hle/kernel/k_server_session.h" 14#include "core/hle/kernel/k_server_session.h"
15#include "core/hle/kernel/k_session.h" 15#include "core/hle/kernel/k_session.h"
16#include "core/hle/result.h" 16#include "core/hle/result.h"
17#include "core/hle/service/sm/controller.h"
18#include "core/hle/service/sm/sm.h" 17#include "core/hle/service/sm/sm.h"
18#include "core/hle/service/sm/sm_controller.h"
19 19
20namespace Service::SM { 20namespace Service::SM {
21 21
diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/sm_controller.cpp
index 8b9418e0f..b5fbc4569 100644
--- a/src/core/hle/service/sm/controller.cpp
+++ b/src/core/hle/service/sm/sm_controller.cpp
@@ -13,7 +13,7 @@
13#include "core/hle/kernel/k_server_port.h" 13#include "core/hle/kernel/k_server_port.h"
14#include "core/hle/kernel/k_server_session.h" 14#include "core/hle/kernel/k_server_session.h"
15#include "core/hle/kernel/k_session.h" 15#include "core/hle/kernel/k_session.h"
16#include "core/hle/service/sm/controller.h" 16#include "core/hle/service/sm/sm_controller.h"
17 17
18namespace Service::SM { 18namespace Service::SM {
19 19
diff --git a/src/core/hle/service/sm/controller.h b/src/core/hle/service/sm/sm_controller.h
index 7494f898d..7494f898d 100644
--- a/src/core/hle/service/sm/controller.h
+++ b/src/core/hle/service/sm/sm_controller.h
diff --git a/src/core/hle/service/spl/csrng.h b/src/core/hle/service/spl/csrng.h
index 5c0bd2199..0d03cc6cb 100644
--- a/src/core/hle/service/spl/csrng.h
+++ b/src/core/hle/service/spl/csrng.h
@@ -4,7 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "core/hle/service/spl/module.h" 7#include "core/hle/service/spl/spl_module.h"
8 8
9namespace Core { 9namespace Core {
10class System; 10class System;
diff --git a/src/core/hle/service/spl/spl.h b/src/core/hle/service/spl/spl.h
index 9b35012ed..5599c0c01 100644
--- a/src/core/hle/service/spl/spl.h
+++ b/src/core/hle/service/spl/spl.h
@@ -4,7 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "core/hle/service/spl/module.h" 7#include "core/hle/service/spl/spl_module.h"
8 8
9namespace Core { 9namespace Core {
10class System; 10class System;
diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/spl_module.cpp
index ebb179aa8..918633af5 100644
--- a/src/core/hle/service/spl/module.cpp
+++ b/src/core/hle/service/spl/spl_module.cpp
@@ -13,8 +13,8 @@
13#include "core/hle/api_version.h" 13#include "core/hle/api_version.h"
14#include "core/hle/ipc_helpers.h" 14#include "core/hle/ipc_helpers.h"
15#include "core/hle/service/spl/csrng.h" 15#include "core/hle/service/spl/csrng.h"
16#include "core/hle/service/spl/module.h"
17#include "core/hle/service/spl/spl.h" 16#include "core/hle/service/spl/spl.h"
17#include "core/hle/service/spl/spl_module.h"
18 18
19namespace Service::SPL { 19namespace Service::SPL {
20 20
diff --git a/src/core/hle/service/spl/module.h b/src/core/hle/service/spl/spl_module.h
index 61630df80..61630df80 100644
--- a/src/core/hle/service/spl/module.h
+++ b/src/core/hle/service/spl/spl_module.h
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index d6f710eba..8fdd5076f 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -11,8 +11,8 @@
11#include "core/hle/kernel/k_client_port.h" 11#include "core/hle/kernel/k_client_port.h"
12#include "core/hle/kernel/k_scheduler.h" 12#include "core/hle/kernel/k_scheduler.h"
13#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
14#include "core/hle/service/time/interface.h"
15#include "core/hle/service/time/time.h" 14#include "core/hle/service/time/time.h"
15#include "core/hle/service/time/time_interface.h"
16#include "core/hle/service/time/time_sharedmemory.h" 16#include "core/hle/service/time/time_sharedmemory.h"
17#include "core/hle/service/time/time_zone_service.h" 17#include "core/hle/service/time/time_zone_service.h"
18 18
diff --git a/src/core/hle/service/time/interface.cpp b/src/core/hle/service/time/time_interface.cpp
index 53a204796..bb7b6b5c1 100644
--- a/src/core/hle/service/time/interface.cpp
+++ b/src/core/hle/service/time/time_interface.cpp
@@ -2,7 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/service/time/interface.h" 5#include "core/hle/service/time/time_interface.h"
6 6
7namespace Service::Time { 7namespace Service::Time {
8 8
diff --git a/src/core/hle/service/time/interface.h b/src/core/hle/service/time/time_interface.h
index c41766f1a..c41766f1a 100644
--- a/src/core/hle/service/time/interface.h
+++ b/src/core/hle/service/time/time_interface.h
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 228dc6389..199e69e89 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -206,7 +206,8 @@ AppLoader::~AppLoader() = default;
206 * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type 206 * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type
207 */ 207 */
208static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::VirtualFile file, 208static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::VirtualFile file,
209 FileType type, std::size_t program_index) { 209 FileType type, u64 program_id,
210 std::size_t program_index) {
210 switch (type) { 211 switch (type) {
211 // Standard ELF file format. 212 // Standard ELF file format.
212 case FileType::ELF: 213 case FileType::ELF:
@@ -227,7 +228,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V
227 // NX XCI (nX Card Image) file format. 228 // NX XCI (nX Card Image) file format.
228 case FileType::XCI: 229 case FileType::XCI:
229 return std::make_unique<AppLoader_XCI>(std::move(file), system.GetFileSystemController(), 230 return std::make_unique<AppLoader_XCI>(std::move(file), system.GetFileSystemController(),
230 system.GetContentProvider(), program_index); 231 system.GetContentProvider(), program_id,
232 program_index);
231 233
232 // NX NAX (NintendoAesXts) file format. 234 // NX NAX (NintendoAesXts) file format.
233 case FileType::NAX: 235 case FileType::NAX:
@@ -236,7 +238,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V
236 // NX NSP (Nintendo Submission Package) file format 238 // NX NSP (Nintendo Submission Package) file format
237 case FileType::NSP: 239 case FileType::NSP:
238 return std::make_unique<AppLoader_NSP>(std::move(file), system.GetFileSystemController(), 240 return std::make_unique<AppLoader_NSP>(std::move(file), system.GetFileSystemController(),
239 system.GetContentProvider(), program_index); 241 system.GetContentProvider(), program_id,
242 program_index);
240 243
241 // NX KIP (Kernel Internal Process) file format 244 // NX KIP (Kernel Internal Process) file format
242 case FileType::KIP: 245 case FileType::KIP:
@@ -252,7 +255,7 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V
252} 255}
253 256
254std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file, 257std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file,
255 std::size_t program_index) { 258 u64 program_id, std::size_t program_index) {
256 FileType type = IdentifyFile(file); 259 FileType type = IdentifyFile(file);
257 const FileType filename_type = GuessFromFilename(file->GetName()); 260 const FileType filename_type = GuessFromFilename(file->GetName());
258 261
@@ -266,7 +269,7 @@ std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile
266 269
267 LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type)); 270 LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type));
268 271
269 return GetFileLoader(system, std::move(file), type, program_index); 272 return GetFileLoader(system, std::move(file), type, program_id, program_index);
270} 273}
271 274
272} // namespace Loader 275} // namespace Loader
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index edc8bb257..7b1bac3f7 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -227,6 +227,17 @@ public:
227 } 227 }
228 228
229 /** 229 /**
230 * Get the program ids of the application
231 *
232 * @param[out] out_program_ids Reference to store program ids into
233 *
234 * @return ResultStatus result of function
235 */
236 virtual ResultStatus ReadProgramIds(std::vector<u64>& out_program_ids) {
237 return ResultStatus::ErrorNotImplemented;
238 }
239
240 /**
230 * Get the RomFS of the application 241 * Get the RomFS of the application
231 * Since the RomFS can be huge, we return a file reference instead of copying to a buffer 242 * Since the RomFS can be huge, we return a file reference instead of copying to a buffer
232 * 243 *
@@ -324,6 +335,6 @@ protected:
324 * @return the best loader for this file. 335 * @return the best loader for this file.
325 */ 336 */
326std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file, 337std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file,
327 std::size_t program_index = 0); 338 u64 program_id = 0, std::size_t program_index = 0);
328 339
329} // namespace Loader 340} // namespace Loader
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index d815a7cd3..8b167ad3c 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -23,10 +23,9 @@ namespace Loader {
23 23
24AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file_, 24AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file_,
25 const Service::FileSystem::FileSystemController& fsc, 25 const Service::FileSystem::FileSystemController& fsc,
26 const FileSys::ContentProvider& content_provider, 26 const FileSys::ContentProvider& content_provider, u64 program_id,
27 std::size_t program_index) 27 std::size_t program_index)
28 : AppLoader(file_), nsp(std::make_unique<FileSys::NSP>(file_, program_index)), 28 : AppLoader(file_), nsp(std::make_unique<FileSys::NSP>(file_, program_id, program_index)) {
29 title_id(nsp->GetProgramTitleID()) {
30 29
31 if (nsp->GetStatus() != ResultStatus::Success) { 30 if (nsp->GetStatus() != ResultStatus::Success) {
32 return; 31 return;
@@ -46,12 +45,8 @@ AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file_,
46 return pm.ParseControlNCA(*control_nca); 45 return pm.ParseControlNCA(*control_nca);
47 }(); 46 }();
48 47
49 if (title_id == 0) {
50 return;
51 }
52
53 secondary_loader = std::make_unique<AppLoader_NCA>( 48 secondary_loader = std::make_unique<AppLoader_NCA>(
54 nsp->GetNCAFile(title_id, FileSys::ContentRecordType::Program)); 49 nsp->GetNCAFile(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Program));
55 } 50 }
56} 51}
57 52
@@ -68,10 +63,11 @@ FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& nsp_file) {
68 } 63 }
69 64
70 // Non-Extracted Type case 65 // Non-Extracted Type case
66 const auto program_id = nsp.GetProgramTitleID();
71 if (!nsp.IsExtractedType() && 67 if (!nsp.IsExtractedType() &&
72 nsp.GetNCA(nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program) != nullptr && 68 nsp.GetNCA(program_id, FileSys::ContentRecordType::Program) != nullptr &&
73 AppLoader_NCA::IdentifyType(nsp.GetNCAFile( 69 AppLoader_NCA::IdentifyType(
74 nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program)) == FileType::NCA) { 70 nsp.GetNCAFile(program_id, FileSys::ContentRecordType::Program)) == FileType::NCA) {
75 return FileType::NSP; 71 return FileType::NSP;
76 } 72 }
77 } 73 }
@@ -84,6 +80,8 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::KProcess& process, Core::S
84 return {ResultStatus::ErrorAlreadyLoaded, {}}; 80 return {ResultStatus::ErrorAlreadyLoaded, {}};
85 } 81 }
86 82
83 const auto title_id = nsp->GetProgramTitleID();
84
87 if (!nsp->IsExtractedType() && title_id == 0) { 85 if (!nsp->IsExtractedType() && title_id == 0) {
88 return {ResultStatus::ErrorNSPMissingProgramNCA, {}}; 86 return {ResultStatus::ErrorNSPMissingProgramNCA, {}};
89 } 87 }
@@ -93,7 +91,7 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::KProcess& process, Core::S
93 return {nsp_status, {}}; 91 return {nsp_status, {}};
94 } 92 }
95 93
96 const auto nsp_program_status = nsp->GetProgramStatus(title_id); 94 const auto nsp_program_status = nsp->GetProgramStatus();
97 if (nsp_program_status != ResultStatus::Success) { 95 if (nsp_program_status != ResultStatus::Success) {
98 return {nsp_program_status, {}}; 96 return {nsp_program_status, {}};
99 } 97 }
@@ -134,8 +132,8 @@ ResultStatus AppLoader_NSP::ReadUpdateRaw(FileSys::VirtualFile& out_file) {
134 return ResultStatus::ErrorNoPackedUpdate; 132 return ResultStatus::ErrorNoPackedUpdate;
135 } 133 }
136 134
137 const auto read = 135 const auto read = nsp->GetNCAFile(FileSys::GetUpdateTitleID(nsp->GetProgramTitleID()),
138 nsp->GetNCAFile(FileSys::GetUpdateTitleID(title_id), FileSys::ContentRecordType::Program); 136 FileSys::ContentRecordType::Program);
139 137
140 if (read == nullptr) { 138 if (read == nullptr) {
141 return ResultStatus::ErrorNoPackedUpdate; 139 return ResultStatus::ErrorNoPackedUpdate;
@@ -151,11 +149,15 @@ ResultStatus AppLoader_NSP::ReadUpdateRaw(FileSys::VirtualFile& out_file) {
151} 149}
152 150
153ResultStatus AppLoader_NSP::ReadProgramId(u64& out_program_id) { 151ResultStatus AppLoader_NSP::ReadProgramId(u64& out_program_id) {
154 if (title_id == 0) { 152 out_program_id = nsp->GetProgramTitleID();
153 if (out_program_id == 0) {
155 return ResultStatus::ErrorNotInitialized; 154 return ResultStatus::ErrorNotInitialized;
156 } 155 }
156 return ResultStatus::Success;
157}
157 158
158 out_program_id = title_id; 159ResultStatus AppLoader_NSP::ReadProgramIds(std::vector<u64>& out_program_ids) {
160 out_program_ids = nsp->GetProgramTitleIDs();
159 return ResultStatus::Success; 161 return ResultStatus::Success;
160} 162}
161 163
diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h
index 644c0ff58..50406a92e 100644
--- a/src/core/loader/nsp.h
+++ b/src/core/loader/nsp.h
@@ -28,7 +28,7 @@ class AppLoader_NSP final : public AppLoader {
28public: 28public:
29 explicit AppLoader_NSP(FileSys::VirtualFile file_, 29 explicit AppLoader_NSP(FileSys::VirtualFile file_,
30 const Service::FileSystem::FileSystemController& fsc, 30 const Service::FileSystem::FileSystemController& fsc,
31 const FileSys::ContentProvider& content_provider, 31 const FileSys::ContentProvider& content_provider, u64 program_id,
32 std::size_t program_index); 32 std::size_t program_index);
33 ~AppLoader_NSP() override; 33 ~AppLoader_NSP() override;
34 34
@@ -51,6 +51,7 @@ public:
51 u64 ReadRomFSIVFCOffset() const override; 51 u64 ReadRomFSIVFCOffset() const override;
52 ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) override; 52 ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) override;
53 ResultStatus ReadProgramId(u64& out_program_id) override; 53 ResultStatus ReadProgramId(u64& out_program_id) override;
54 ResultStatus ReadProgramIds(std::vector<u64>& out_program_ids) override;
54 ResultStatus ReadIcon(std::vector<u8>& buffer) override; 55 ResultStatus ReadIcon(std::vector<u8>& buffer) override;
55 ResultStatus ReadTitle(std::string& title) override; 56 ResultStatus ReadTitle(std::string& title) override;
56 ResultStatus ReadControlData(FileSys::NACP& nacp) override; 57 ResultStatus ReadControlData(FileSys::NACP& nacp) override;
@@ -67,7 +68,6 @@ private:
67 68
68 FileSys::VirtualFile icon_file; 69 FileSys::VirtualFile icon_file;
69 std::unique_ptr<FileSys::NACP> nacp_file; 70 std::unique_ptr<FileSys::NACP> nacp_file;
70 u64 title_id;
71}; 71};
72 72
73} // namespace Loader 73} // namespace Loader
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index 635d6ae15..269603eef 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -22,9 +22,9 @@ namespace Loader {
22 22
23AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file_, 23AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file_,
24 const Service::FileSystem::FileSystemController& fsc, 24 const Service::FileSystem::FileSystemController& fsc,
25 const FileSys::ContentProvider& content_provider, 25 const FileSys::ContentProvider& content_provider, u64 program_id,
26 std::size_t program_index) 26 std::size_t program_index)
27 : AppLoader(file_), xci(std::make_unique<FileSys::XCI>(file_, program_index)), 27 : AppLoader(file_), xci(std::make_unique<FileSys::XCI>(file_, program_id, program_index)),
28 nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) { 28 nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) {
29 if (xci->GetStatus() != ResultStatus::Success) { 29 if (xci->GetStatus() != ResultStatus::Success) {
30 return; 30 return;
@@ -121,6 +121,11 @@ ResultStatus AppLoader_XCI::ReadProgramId(u64& out_program_id) {
121 return nca_loader->ReadProgramId(out_program_id); 121 return nca_loader->ReadProgramId(out_program_id);
122} 122}
123 123
124ResultStatus AppLoader_XCI::ReadProgramIds(std::vector<u64>& out_program_ids) {
125 out_program_ids = xci->GetProgramTitleIDs();
126 return ResultStatus::Success;
127}
128
124ResultStatus AppLoader_XCI::ReadIcon(std::vector<u8>& buffer) { 129ResultStatus AppLoader_XCI::ReadIcon(std::vector<u8>& buffer) {
125 if (icon_file == nullptr) { 130 if (icon_file == nullptr) {
126 return ResultStatus::ErrorNoControl; 131 return ResultStatus::ErrorNoControl;
@@ -149,8 +154,9 @@ ResultStatus AppLoader_XCI::ReadControlData(FileSys::NACP& control) {
149} 154}
150 155
151ResultStatus AppLoader_XCI::ReadManualRomFS(FileSys::VirtualFile& out_file) { 156ResultStatus AppLoader_XCI::ReadManualRomFS(FileSys::VirtualFile& out_file) {
152 const auto nca = xci->GetSecurePartitionNSP()->GetNCA(xci->GetProgramTitleID(), 157 const auto nca =
153 FileSys::ContentRecordType::HtmlDocument); 158 xci->GetSecurePartitionNSP()->GetNCA(xci->GetSecurePartitionNSP()->GetProgramTitleID(),
159 FileSys::ContentRecordType::HtmlDocument);
154 if (xci->GetStatus() != ResultStatus::Success || nca == nullptr) { 160 if (xci->GetStatus() != ResultStatus::Success || nca == nullptr) {
155 return ResultStatus::ErrorXCIMissingPartition; 161 return ResultStatus::ErrorXCIMissingPartition;
156 } 162 }
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
index 708155c30..30caaf90e 100644
--- a/src/core/loader/xci.h
+++ b/src/core/loader/xci.h
@@ -28,7 +28,7 @@ class AppLoader_XCI final : public AppLoader {
28public: 28public:
29 explicit AppLoader_XCI(FileSys::VirtualFile file_, 29 explicit AppLoader_XCI(FileSys::VirtualFile file_,
30 const Service::FileSystem::FileSystemController& fsc, 30 const Service::FileSystem::FileSystemController& fsc,
31 const FileSys::ContentProvider& content_provider, 31 const FileSys::ContentProvider& content_provider, u64 program_id,
32 std::size_t program_index); 32 std::size_t program_index);
33 ~AppLoader_XCI() override; 33 ~AppLoader_XCI() override;
34 34
@@ -51,6 +51,7 @@ public:
51 u64 ReadRomFSIVFCOffset() const override; 51 u64 ReadRomFSIVFCOffset() const override;
52 ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) override; 52 ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) override;
53 ResultStatus ReadProgramId(u64& out_program_id) override; 53 ResultStatus ReadProgramId(u64& out_program_id) override;
54 ResultStatus ReadProgramIds(std::vector<u64>& out_program_ids) override;
54 ResultStatus ReadIcon(std::vector<u8>& buffer) override; 55 ResultStatus ReadIcon(std::vector<u8>& buffer) override;
55 ResultStatus ReadTitle(std::string& title) override; 56 ResultStatus ReadTitle(std::string& title) override;
56 ResultStatus ReadControlData(FileSys::NACP& control) override; 57 ResultStatus ReadControlData(FileSys::NACP& control) override;
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index 7399c3648..8de3d4520 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -294,8 +294,8 @@ void InputSubsystem::ReloadInputDevices() {
294 impl->udp->ReloadSockets(); 294 impl->udp->ReloadSockets();
295} 295}
296 296
297std::vector<std::unique_ptr<Polling::DevicePoller>> InputSubsystem::GetPollers( 297std::vector<std::unique_ptr<Polling::DevicePoller>> InputSubsystem::GetPollers([
298 Polling::DeviceType type) const { 298 [maybe_unused]] Polling::DeviceType type) const {
299#ifdef HAVE_SDL2 299#ifdef HAVE_SDL2
300 return impl->sdl->GetPollers(type); 300 return impl->sdl->GetPollers(type);
301#else 301#else
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp
index 45b3d7340..efcdd85d2 100644
--- a/src/input_common/mouse/mouse_poller.cpp
+++ b/src/input_common/mouse/mouse_poller.cpp
@@ -84,7 +84,7 @@ public:
84 std::lock_guard lock{mutex}; 84 std::lock_guard lock{mutex};
85 const auto axis_value = 85 const auto axis_value =
86 static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis)); 86 static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis));
87 const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue(); 87 const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue() * 0.10f;
88 return axis_value * sensitivity / (100.0f * range); 88 return axis_value * sensitivity / (100.0f * range);
89 } 89 }
90 90
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index 68672a92b..1656b85fb 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -130,10 +130,10 @@ public:
130 130
131 if (sdl_controller) { 131 if (sdl_controller) {
132 return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 132 return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high,
133 rumble_max_duration_ms) == 0; 133 rumble_max_duration_ms) != -1;
134 } else if (sdl_joystick) { 134 } else if (sdl_joystick) {
135 return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 135 return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high,
136 rumble_max_duration_ms) == 0; 136 rumble_max_duration_ms) != -1;
137 } 137 }
138 138
139 return false; 139 return false;
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h
index b77afcbd8..7a9ad6346 100644
--- a/src/input_common/sdl/sdl_impl.h
+++ b/src/input_common/sdl/sdl_impl.h
@@ -10,15 +10,7 @@
10#include <thread> 10#include <thread>
11#include <unordered_map> 11#include <unordered_map>
12 12
13// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307
14#ifdef __GNUC__
15#pragma GCC diagnostic push
16#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
17#endif
18#include <SDL.h> 13#include <SDL.h>
19#ifdef __GNUC__
20#pragma GCC diagnostic pop
21#endif
22 14
23#include "common/common_types.h" 15#include "common/common_types.h"
24#include "common/threadsafe_queue.h" 16#include "common/threadsafe_queue.h"
diff --git a/src/video_core/command_classes/vic.cpp b/src/video_core/command_classes/vic.cpp
index ff3db0aee..ffb7c82a1 100644
--- a/src/video_core/command_classes/vic.cpp
+++ b/src/video_core/command_classes/vic.cpp
@@ -129,28 +129,27 @@ void Vic::Execute() {
129 129
130 const std::size_t surface_width = config.surface_width_minus1 + 1; 130 const std::size_t surface_width = config.surface_width_minus1 + 1;
131 const std::size_t surface_height = config.surface_height_minus1 + 1; 131 const std::size_t surface_height = config.surface_height_minus1 + 1;
132 const std::size_t half_width = surface_width / 2; 132 const auto frame_width = std::min(surface_width, static_cast<size_t>(frame->width));
133 const std::size_t half_height = config.surface_height_minus1 / 2; 133 const auto frame_height = std::min(surface_height, static_cast<size_t>(frame->height));
134 const std::size_t half_width = frame_width / 2;
135 const std::size_t half_height = frame_height / 2;
134 const std::size_t aligned_width = (surface_width + 0xff) & ~0xff; 136 const std::size_t aligned_width = (surface_width + 0xff) & ~0xff;
135 137
136 const auto* luma_ptr = frame->data[0]; 138 const auto* luma_ptr = frame->data[0];
137 const auto* chroma_b_ptr = frame->data[1]; 139 const auto* chroma_b_ptr = frame->data[1];
138 const auto* chroma_r_ptr = frame->data[2]; 140 const auto* chroma_r_ptr = frame->data[2];
139 const auto stride = frame->linesize[0]; 141 const auto stride = static_cast<size_t>(frame->linesize[0]);
140 const auto half_stride = frame->linesize[1]; 142 const auto half_stride = static_cast<size_t>(frame->linesize[1]);
141 143
142 luma_buffer.resize(aligned_width * surface_height); 144 luma_buffer.resize(aligned_width * surface_height);
143 chroma_buffer.resize(aligned_width * half_height); 145 chroma_buffer.resize(aligned_width * surface_height / 2);
144 146
145 // Populate luma buffer 147 // Populate luma buffer
146 for (std::size_t y = 0; y < surface_height - 1; ++y) { 148 for (std::size_t y = 0; y < frame_height; ++y) {
147 const std::size_t src = y * stride; 149 const std::size_t src = y * stride;
148 const std::size_t dst = y * aligned_width; 150 const std::size_t dst = y * aligned_width;
149 151 for (std::size_t x = 0; x < frame_width; ++x) {
150 const std::size_t size = surface_width; 152 luma_buffer[dst + x] = luma_ptr[src + x];
151
152 for (std::size_t offset = 0; offset < size; ++offset) {
153 luma_buffer[dst + offset] = luma_ptr[src + offset];
154 } 153 }
155 } 154 }
156 gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), 155 gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(),
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 25fe61566..cf3b789e3 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -122,7 +122,7 @@ private:
122 bool has_broken_texture_view_formats = false; 122 bool has_broken_texture_view_formats = false;
123 123
124 StagingBuffers upload_buffers{GL_MAP_WRITE_BIT, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT}; 124 StagingBuffers upload_buffers{GL_MAP_WRITE_BIT, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT};
125 StagingBuffers download_buffers{GL_MAP_READ_BIT, GL_MAP_READ_BIT}; 125 StagingBuffers download_buffers{GL_MAP_READ_BIT | GL_CLIENT_STORAGE_BIT, GL_MAP_READ_BIT};
126 126
127 OGLTexture null_image_1d_array; 127 OGLTexture null_image_1d_array;
128 OGLTexture null_image_cube_array; 128 OGLTexture null_image_cube_array;
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index a718bff7a..c12929de6 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -229,9 +229,6 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color
229} 229}
230 230
231void RendererOpenGL::InitOpenGLObjects() { 231void RendererOpenGL::InitOpenGLObjects() {
232 glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
233 Settings::values.bg_blue.GetValue(), 0.0f);
234
235 // Create shader programs 232 // Create shader programs
236 OGLShader vertex_shader; 233 OGLShader vertex_shader;
237 vertex_shader.Create(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER); 234 vertex_shader.Create(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER);
@@ -337,8 +334,9 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
337void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { 334void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
338 if (renderer_settings.set_background_color) { 335 if (renderer_settings.set_background_color) {
339 // Update background color before drawing 336 // Update background color before drawing
340 glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(), 337 glClearColor(Settings::values.bg_red.GetValue() / 255.0f,
341 Settings::values.bg_blue.GetValue(), 0.0f); 338 Settings::values.bg_green.GetValue() / 255.0f,
339 Settings::values.bg_blue.GetValue() / 255.0f, 1.0f);
342 } 340 }
343 341
344 // Set projection matrix 342 // Set projection matrix
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index a1a32aabe..363134129 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -225,8 +225,11 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, bool
225 descriptor_set = descriptor_sets[image_index], buffer = *buffer, 225 descriptor_set = descriptor_sets[image_index], buffer = *buffer,
226 size = swapchain.GetSize(), pipeline = *pipeline, 226 size = swapchain.GetSize(), pipeline = *pipeline,
227 layout = *pipeline_layout](vk::CommandBuffer cmdbuf) { 227 layout = *pipeline_layout](vk::CommandBuffer cmdbuf) {
228 const f32 bg_red = Settings::values.bg_red.GetValue() / 255.0f;
229 const f32 bg_green = Settings::values.bg_green.GetValue() / 255.0f;
230 const f32 bg_blue = Settings::values.bg_blue.GetValue() / 255.0f;
228 const VkClearValue clear_color{ 231 const VkClearValue clear_color{
229 .color = {.float32 = {0.0f, 0.0f, 0.0f, 0.0f}}, 232 .color = {.float32 = {bg_red, bg_green, bg_blue, 1.0f}},
230 }; 233 };
231 const VkRenderPassBeginInfo renderpass_bi{ 234 const VkRenderPassBeginInfo renderpass_bi{
232 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 235 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 11e86174e..0def1e769 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -176,8 +176,8 @@ void BufferCacheRuntime::BindIndexBuffer(PrimitiveTopology topology, IndexFormat
176 } 176 }
177 if (vk_buffer == VK_NULL_HANDLE) { 177 if (vk_buffer == VK_NULL_HANDLE) {
178 // Vulkan doesn't support null index buffers. Replace it with our own null buffer. 178 // Vulkan doesn't support null index buffers. Replace it with our own null buffer.
179 ReserveNullIndexBuffer(); 179 ReserveNullBuffer();
180 vk_buffer = *null_index_buffer; 180 vk_buffer = *null_buffer;
181 } 181 }
182 scheduler.Record([vk_buffer, vk_offset, vk_index_type](vk::CommandBuffer cmdbuf) { 182 scheduler.Record([vk_buffer, vk_offset, vk_index_type](vk::CommandBuffer cmdbuf) {
183 cmdbuf.BindIndexBuffer(vk_buffer, vk_offset, vk_index_type); 183 cmdbuf.BindIndexBuffer(vk_buffer, vk_offset, vk_index_type);
@@ -185,6 +185,13 @@ void BufferCacheRuntime::BindIndexBuffer(PrimitiveTopology topology, IndexFormat
185} 185}
186 186
187void BufferCacheRuntime::BindQuadArrayIndexBuffer(u32 first, u32 count) { 187void BufferCacheRuntime::BindQuadArrayIndexBuffer(u32 first, u32 count) {
188 if (count == 0) {
189 ReserveNullBuffer();
190 scheduler.Record([this](vk::CommandBuffer cmdbuf) {
191 cmdbuf.BindIndexBuffer(*null_buffer, 0, VK_INDEX_TYPE_UINT32);
192 });
193 return;
194 }
188 ReserveQuadArrayLUT(first + count, true); 195 ReserveQuadArrayLUT(first + count, true);
189 196
190 // The LUT has the indices 0, 1, 2, and 3 copied as an array 197 // The LUT has the indices 0, 1, 2, and 3 copied as an array
@@ -219,6 +226,14 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer,
219 // Already logged in the rasterizer 226 // Already logged in the rasterizer
220 return; 227 return;
221 } 228 }
229 if (buffer == VK_NULL_HANDLE) {
230 // Vulkan doesn't support null transform feedback buffers.
231 // Replace it with our own null buffer.
232 ReserveNullBuffer();
233 buffer = *null_buffer;
234 offset = 0;
235 size = 0;
236 }
222 scheduler.Record([index, buffer, offset, size](vk::CommandBuffer cmdbuf) { 237 scheduler.Record([index, buffer, offset, size](vk::CommandBuffer cmdbuf) {
223 const VkDeviceSize vk_offset = offset; 238 const VkDeviceSize vk_offset = offset;
224 const VkDeviceSize vk_size = size; 239 const VkDeviceSize vk_size = size;
@@ -303,11 +318,11 @@ void BufferCacheRuntime::ReserveQuadArrayLUT(u32 num_indices, bool wait_for_idle
303 }); 318 });
304} 319}
305 320
306void BufferCacheRuntime::ReserveNullIndexBuffer() { 321void BufferCacheRuntime::ReserveNullBuffer() {
307 if (null_index_buffer) { 322 if (null_buffer) {
308 return; 323 return;
309 } 324 }
310 null_index_buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{ 325 null_buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{
311 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 326 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
312 .pNext = nullptr, 327 .pNext = nullptr,
313 .flags = 0, 328 .flags = 0,
@@ -318,12 +333,12 @@ void BufferCacheRuntime::ReserveNullIndexBuffer() {
318 .pQueueFamilyIndices = nullptr, 333 .pQueueFamilyIndices = nullptr,
319 }); 334 });
320 if (device.HasDebuggingToolAttached()) { 335 if (device.HasDebuggingToolAttached()) {
321 null_index_buffer.SetObjectNameEXT("Null index buffer"); 336 null_buffer.SetObjectNameEXT("Null index buffer");
322 } 337 }
323 null_index_buffer_commit = memory_allocator.Commit(null_index_buffer, MemoryUsage::DeviceLocal); 338 null_buffer_commit = memory_allocator.Commit(null_buffer, MemoryUsage::DeviceLocal);
324 339
325 scheduler.RequestOutsideRenderPassOperationContext(); 340 scheduler.RequestOutsideRenderPassOperationContext();
326 scheduler.Record([buffer = *null_index_buffer](vk::CommandBuffer cmdbuf) { 341 scheduler.Record([buffer = *null_buffer](vk::CommandBuffer cmdbuf) {
327 cmdbuf.FillBuffer(buffer, 0, VK_WHOLE_SIZE, 0); 342 cmdbuf.FillBuffer(buffer, 0, VK_WHOLE_SIZE, 0);
328 }); 343 });
329} 344}
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 60d49386e..3bb81d5b3 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -94,7 +94,7 @@ private:
94 94
95 void ReserveQuadArrayLUT(u32 num_indices, bool wait_for_idle); 95 void ReserveQuadArrayLUT(u32 num_indices, bool wait_for_idle);
96 96
97 void ReserveNullIndexBuffer(); 97 void ReserveNullBuffer();
98 98
99 const Device& device; 99 const Device& device;
100 MemoryAllocator& memory_allocator; 100 MemoryAllocator& memory_allocator;
@@ -107,8 +107,8 @@ private:
107 VkIndexType quad_array_lut_index_type{}; 107 VkIndexType quad_array_lut_index_type{};
108 u32 current_num_indices = 0; 108 u32 current_num_indices = 0;
109 109
110 vk::Buffer null_index_buffer; 110 vk::Buffer null_buffer;
111 MemoryCommit null_index_buffer_commit; 111 MemoryCommit null_buffer_commit;
112 112
113 Uint8Pass uint8_pass; 113 Uint8Pass uint8_pass;
114 QuadIndexedPass quad_index_pass; 114 QuadIndexedPass quad_index_pass;
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index 205cd3b05..4181d83ee 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -374,20 +374,20 @@ void ASTCDecoderPass::MakeDataBuffer() {
374 374
375 scheduler.Record([src = staging_ref.buffer, offset = staging_ref.offset, dst = *data_buffer, 375 scheduler.Record([src = staging_ref.buffer, offset = staging_ref.offset, dst = *data_buffer,
376 TOTAL_BUFFER_SIZE](vk::CommandBuffer cmdbuf) { 376 TOTAL_BUFFER_SIZE](vk::CommandBuffer cmdbuf) {
377 cmdbuf.CopyBuffer(src, dst, 377 static constexpr VkMemoryBarrier write_barrier{
378 VkBufferCopy{ 378 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
379 .srcOffset = offset, 379 .pNext = nullptr,
380 .dstOffset = 0, 380 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
381 .size = TOTAL_BUFFER_SIZE, 381 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
382 }); 382 };
383 cmdbuf.PipelineBarrier( 383 const VkBufferCopy copy{
384 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 384 .srcOffset = offset,
385 VkMemoryBarrier{ 385 .dstOffset = 0,
386 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, 386 .size = TOTAL_BUFFER_SIZE,
387 .pNext = nullptr, 387 };
388 .srcAccessMask = 0, 388 cmdbuf.CopyBuffer(src, dst, copy);
389 .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, 389 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
390 }); 390 0, write_barrier);
391 }); 391 });
392} 392}
393 393
@@ -411,7 +411,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
411 const VkImageMemoryBarrier image_barrier{ 411 const VkImageMemoryBarrier image_barrier{
412 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 412 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
413 .pNext = nullptr, 413 .pNext = nullptr,
414 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, 414 .srcAccessMask = is_initialized ? VK_ACCESS_SHADER_WRITE_BIT : VkAccessFlags{},
415 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, 415 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
416 .oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED, 416 .oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
417 .newLayout = VK_IMAGE_LAYOUT_GENERAL, 417 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
@@ -426,7 +426,8 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
426 .layerCount = VK_REMAINING_ARRAY_LAYERS, 426 .layerCount = VK_REMAINING_ARRAY_LAYERS,
427 }, 427 },
428 }; 428 };
429 cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT : 0, 429 cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
430 : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
430 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier); 431 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
431 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline); 432 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
432 }); 433 });
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index fd9eed3e3..f57c15b37 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -357,11 +357,13 @@ void RasterizerVulkan::Clear() {
357 .height = std::min(clear_rect.rect.extent.height, render_area.height), 357 .height = std::min(clear_rect.rect.extent.height, render_area.height),
358 }; 358 };
359 359
360 if (use_color) { 360 const u32 color_attachment = regs.clear_buffers.RT;
361 const auto attachment_aspect_mask = framebuffer->ImageRanges()[color_attachment].aspectMask;
362 const bool is_color_rt = (attachment_aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != 0;
363 if (use_color && is_color_rt) {
361 VkClearValue clear_value; 364 VkClearValue clear_value;
362 std::memcpy(clear_value.color.float32, regs.clear_color, sizeof(regs.clear_color)); 365 std::memcpy(clear_value.color.float32, regs.clear_color, sizeof(regs.clear_color));
363 366
364 const u32 color_attachment = regs.clear_buffers.RT;
365 scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) { 367 scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) {
366 const VkClearAttachment attachment{ 368 const VkClearAttachment attachment{
367 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 369 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index a2ab4d1ee..fd01c902c 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -608,7 +608,10 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
608 const VkImageAspectFlags aspect_mask = ImageAspectMask(src.format); 608 const VkImageAspectFlags aspect_mask = ImageAspectMask(src.format);
609 const bool is_dst_msaa = dst.Samples() != VK_SAMPLE_COUNT_1_BIT; 609 const bool is_dst_msaa = dst.Samples() != VK_SAMPLE_COUNT_1_BIT;
610 const bool is_src_msaa = src.Samples() != VK_SAMPLE_COUNT_1_BIT; 610 const bool is_src_msaa = src.Samples() != VK_SAMPLE_COUNT_1_BIT;
611 ASSERT(aspect_mask == ImageAspectMask(dst.format)); 611 if (aspect_mask != ImageAspectMask(dst.format)) {
612 UNIMPLEMENTED_MSG("Incompatible blit from format {} to {}", src.format, dst.format);
613 return;
614 }
612 if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT && !is_src_msaa && !is_dst_msaa) { 615 if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT && !is_src_msaa && !is_dst_msaa) {
613 blit_image_helper.BlitColor(dst_framebuffer, src, dst_region, src_region, filter, 616 blit_image_helper.BlitColor(dst_framebuffer, src, dst_region, src_region, filter,
614 operation); 617 operation);
@@ -911,6 +914,7 @@ void Image::UploadMemory(const StagingBufferRef& map,
911 914
912void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) { 915void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) {
913 std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask); 916 std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask);
917 scheduler->RequestOutsideRenderPassOperationContext();
914 scheduler->Record([buffer = map.buffer, image = *image, aspect_mask = aspect_mask, 918 scheduler->Record([buffer = map.buffer, image = *image, aspect_mask = aspect_mask,
915 vk_copies](vk::CommandBuffer cmdbuf) { 919 vk_copies](vk::CommandBuffer cmdbuf) {
916 const VkImageMemoryBarrier read_barrier{ 920 const VkImageMemoryBarrier read_barrier{
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 01de2d498..85ce06d56 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -599,6 +599,12 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
599 using namespace VideoCommon::Dirty; 599 using namespace VideoCommon::Dirty;
600 auto& flags = maxwell3d.dirty.flags; 600 auto& flags = maxwell3d.dirty.flags;
601 if (!flags[Dirty::RenderTargets]) { 601 if (!flags[Dirty::RenderTargets]) {
602 for (size_t index = 0; index < NUM_RT; ++index) {
603 ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index];
604 PrepareImageView(color_buffer_id, true, is_clear && IsFullClear(color_buffer_id));
605 }
606 const ImageViewId depth_buffer_id = render_targets.depth_buffer_id;
607 PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id));
602 return; 608 return;
603 } 609 }
604 flags[Dirty::RenderTargets] = false; 610 flags[Dirty::RenderTargets] = false;
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index c872517b8..59cf2f561 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -169,23 +169,6 @@ template <u32 GOB_EXTENT>
169 return Common::DivCeil(AdjustMipSize(size, level), block_size); 169 return Common::DivCeil(AdjustMipSize(size, level), block_size);
170} 170}
171 171
172[[nodiscard]] constexpr std::pair<int, int> Samples(int num_samples) {
173 switch (num_samples) {
174 case 1:
175 return {1, 1};
176 case 2:
177 return {2, 1};
178 case 4:
179 return {2, 2};
180 case 8:
181 return {4, 2};
182 case 16:
183 return {4, 4};
184 }
185 UNREACHABLE_MSG("Invalid number of samples={}", num_samples);
186 return {1, 1};
187}
188
189[[nodiscard]] constexpr Extent2D DefaultBlockSize(PixelFormat format) { 172[[nodiscard]] constexpr Extent2D DefaultBlockSize(PixelFormat format) {
190 return {DefaultBlockWidth(format), DefaultBlockHeight(format)}; 173 return {DefaultBlockWidth(format), DefaultBlockHeight(format)};
191} 174}
@@ -283,14 +266,13 @@ template <u32 GOB_EXTENT>
283} 266}
284 267
285[[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block, 268[[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block,
286 u32 num_samples, u32 tile_width_spacing) { 269 u32 tile_width_spacing) {
287 const auto [samples_x, samples_y] = Samples(num_samples);
288 const u32 bytes_per_block = BytesPerBlock(format); 270 const u32 bytes_per_block = BytesPerBlock(format);
289 return { 271 return {
290 .size = 272 .size =
291 { 273 {
292 .width = size.width * samples_x, 274 .width = size.width,
293 .height = size.height * samples_y, 275 .height = size.height,
294 .depth = size.depth, 276 .depth = size.depth,
295 }, 277 },
296 .block = block, 278 .block = block,
@@ -301,14 +283,12 @@ template <u32 GOB_EXTENT>
301} 283}
302 284
303[[nodiscard]] constexpr LevelInfo MakeLevelInfo(const ImageInfo& info) { 285[[nodiscard]] constexpr LevelInfo MakeLevelInfo(const ImageInfo& info) {
304 return MakeLevelInfo(info.format, info.size, info.block, info.num_samples, 286 return MakeLevelInfo(info.format, info.size, info.block, info.tile_width_spacing);
305 info.tile_width_spacing);
306} 287}
307 288
308[[nodiscard]] constexpr u32 CalculateLevelOffset(PixelFormat format, Extent3D size, Extent3D block, 289[[nodiscard]] constexpr u32 CalculateLevelOffset(PixelFormat format, Extent3D size, Extent3D block,
309 u32 num_samples, u32 tile_width_spacing, 290 u32 tile_width_spacing, u32 level) {
310 u32 level) { 291 const LevelInfo info = MakeLevelInfo(format, size, block, tile_width_spacing);
311 const LevelInfo info = MakeLevelInfo(format, size, block, num_samples, tile_width_spacing);
312 u32 offset = 0; 292 u32 offset = 0;
313 for (u32 current_level = 0; current_level < level; ++current_level) { 293 for (u32 current_level = 0; current_level < level; ++current_level) {
314 offset += CalculateLevelSize(info, current_level); 294 offset += CalculateLevelSize(info, current_level);
@@ -645,8 +625,8 @@ u32 CalculateLayerStride(const ImageInfo& info) noexcept {
645 625
646u32 CalculateLayerSize(const ImageInfo& info) noexcept { 626u32 CalculateLayerSize(const ImageInfo& info) noexcept {
647 ASSERT(info.type != ImageType::Linear); 627 ASSERT(info.type != ImageType::Linear);
648 return CalculateLevelOffset(info.format, info.size, info.block, info.num_samples, 628 return CalculateLevelOffset(info.format, info.size, info.block, info.tile_width_spacing,
649 info.tile_width_spacing, info.resources.levels); 629 info.resources.levels);
650} 630}
651 631
652LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept { 632LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept {
@@ -1195,37 +1175,37 @@ static_assert(CalculateLevelSize(LevelInfo{{1920, 1080, 1}, {0, 2, 0}, {1, 1}, 2
1195 0x7f8000); 1175 0x7f8000);
1196static_assert(CalculateLevelSize(LevelInfo{{32, 32, 1}, {0, 0, 4}, {1, 1}, 4, 0}, 0) == 0x4000); 1176static_assert(CalculateLevelSize(LevelInfo{{32, 32, 1}, {0, 0, 4}, {1, 1}, 4, 0}, 0) == 0x4000);
1197 1177
1198static_assert(CalculateLevelOffset(PixelFormat::R8_SINT, {1920, 1080, 1}, {0, 2, 0}, 1, 0, 7) == 1178static_assert(CalculateLevelOffset(PixelFormat::R8_SINT, {1920, 1080, 1}, {0, 2, 0}, 0, 7) ==
1199 0x2afc00); 1179 0x2afc00);
1200static_assert(CalculateLevelOffset(PixelFormat::ASTC_2D_12X12_UNORM, {8192, 4096, 1}, {0, 2, 0}, 1, 1180static_assert(CalculateLevelOffset(PixelFormat::ASTC_2D_12X12_UNORM, {8192, 4096, 1}, {0, 2, 0}, 0,
1201 0, 12) == 0x50d200); 1181 12) == 0x50d200);
1202 1182
1203static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 1, 0, 1183static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 0, 0) ==
1204 0) == 0); 1184 0);
1205static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 1, 0, 1185static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 0, 1) ==
1206 1) == 0x400000); 1186 0x400000);
1207static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 1, 0, 1187static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 0, 2) ==
1208 2) == 0x500000); 1188 0x500000);
1209static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 1, 0, 1189static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 0, 3) ==
1210 3) == 0x540000); 1190 0x540000);
1211static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 1, 0, 1191static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 0, 4) ==
1212 4) == 0x550000); 1192 0x550000);
1213static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 1, 0, 1193static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 0, 5) ==
1214 5) == 0x554000); 1194 0x554000);
1215static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 1, 0, 1195static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 0, 6) ==
1216 6) == 0x555000); 1196 0x555000);
1217static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 1, 0, 1197static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 0, 7) ==
1218 7) == 0x555400); 1198 0x555400);
1219static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 1, 0, 1199static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 0, 8) ==
1220 8) == 0x555600); 1200 0x555600);
1221static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 1, 0, 1201static_assert(CalculateLevelOffset(PixelFormat::A8B8G8R8_UNORM, {1024, 1024, 1}, {0, 4, 0}, 0, 9) ==
1222 9) == 0x555800); 1202 0x555800);
1223 1203
1224constexpr u32 ValidateLayerSize(PixelFormat format, u32 width, u32 height, u32 block_height, 1204constexpr u32 ValidateLayerSize(PixelFormat format, u32 width, u32 height, u32 block_height,
1225 u32 tile_width_spacing, u32 level) { 1205 u32 tile_width_spacing, u32 level) {
1226 const Extent3D size{width, height, 1}; 1206 const Extent3D size{width, height, 1};
1227 const Extent3D block{0, block_height, 0}; 1207 const Extent3D block{0, block_height, 0};
1228 const u32 offset = CalculateLevelOffset(format, size, block, 1, tile_width_spacing, level); 1208 const u32 offset = CalculateLevelOffset(format, size, block, tile_width_spacing, level);
1229 return AlignLayerSize(offset, size, block, DefaultBlockHeight(format), tile_width_spacing); 1209 return AlignLayerSize(offset, size, block, DefaultBlockHeight(format), tile_width_spacing);
1230} 1210}
1231 1211
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp
index e04f7dfc6..b1e02c57a 100644
--- a/src/web_service/web_backend.cpp
+++ b/src/web_service/web_backend.cpp
@@ -8,7 +8,17 @@
8#include <string> 8#include <string>
9 9
10#include <fmt/format.h> 10#include <fmt/format.h>
11
12#ifdef __GNUC__
13#pragma GCC diagnostic push
14#ifndef __clang__
15#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
16#endif
17#endif
11#include <httplib.h> 18#include <httplib.h>
19#ifdef __GNUC__
20#pragma GCC diagnostic pop
21#endif
12 22
13#include "common/logging/log.h" 23#include "common/logging/log.h"
14#include "web_service/web_backend.h" 24#include "web_service/web_backend.h"
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index f870b33b1..cb4bdcc7e 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -15,18 +15,19 @@ add_executable(yuzu
15 about_dialog.cpp 15 about_dialog.cpp
16 about_dialog.h 16 about_dialog.h
17 aboutdialog.ui 17 aboutdialog.ui
18 applets/controller.cpp 18 applets/qt_controller.cpp
19 applets/controller.h 19 applets/qt_controller.h
20 applets/controller.ui 20 applets/qt_controller.ui
21 applets/error.cpp 21 applets/qt_error.cpp
22 applets/error.h 22 applets/qt_error.h
23 applets/profile_select.cpp 23 applets/qt_profile_select.cpp
24 applets/profile_select.h 24 applets/qt_profile_select.h
25 applets/software_keyboard.cpp 25 applets/qt_software_keyboard.cpp
26 applets/software_keyboard.h 26 applets/qt_software_keyboard.h
27 applets/software_keyboard.ui 27 applets/qt_software_keyboard.ui
28 applets/web_browser.cpp 28 applets/qt_web_browser.cpp
29 applets/web_browser.h 29 applets/qt_web_browser.h
30 applets/qt_web_browser_scripts.h
30 bootmanager.cpp 31 bootmanager.cpp
31 bootmanager.h 32 bootmanager.h
32 compatdb.ui 33 compatdb.ui
diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 836d90fda..97106d2cc 100644
--- a/src/yuzu/applets/controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -12,8 +12,8 @@
12#include "core/hle/service/hid/controllers/npad.h" 12#include "core/hle/service/hid/controllers/npad.h"
13#include "core/hle/service/hid/hid.h" 13#include "core/hle/service/hid/hid.h"
14#include "core/hle/service/sm/sm.h" 14#include "core/hle/service/sm/sm.h"
15#include "ui_controller.h" 15#include "ui_qt_controller.h"
16#include "yuzu/applets/controller.h" 16#include "yuzu/applets/qt_controller.h"
17#include "yuzu/configuration/configure_input.h" 17#include "yuzu/configuration/configure_input.h"
18#include "yuzu/configuration/configure_input_profile_dialog.h" 18#include "yuzu/configuration/configure_input_profile_dialog.h"
19#include "yuzu/configuration/configure_motion_touch.h" 19#include "yuzu/configuration/configure_motion_touch.h"
diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/qt_controller.h
index 9b57aea1a..9b57aea1a 100644
--- a/src/yuzu/applets/controller.h
+++ b/src/yuzu/applets/qt_controller.h
diff --git a/src/yuzu/applets/controller.ui b/src/yuzu/applets/qt_controller.ui
index c8cb6bcf3..c8cb6bcf3 100644
--- a/src/yuzu/applets/controller.ui
+++ b/src/yuzu/applets/qt_controller.ui
diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/qt_error.cpp
index 085688cd4..45cf64603 100644
--- a/src/yuzu/applets/error.cpp
+++ b/src/yuzu/applets/qt_error.cpp
@@ -4,7 +4,7 @@
4 4
5#include <QDateTime> 5#include <QDateTime>
6#include "core/hle/lock.h" 6#include "core/hle/lock.h"
7#include "yuzu/applets/error.h" 7#include "yuzu/applets/qt_error.h"
8#include "yuzu/main.h" 8#include "yuzu/main.h"
9 9
10QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) { 10QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) {
diff --git a/src/yuzu/applets/error.h b/src/yuzu/applets/qt_error.h
index 8bd895a32..8bd895a32 100644
--- a/src/yuzu/applets/error.h
+++ b/src/yuzu/applets/qt_error.h
diff --git a/src/yuzu/applets/profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp
index 62fd1141c..a56638e21 100644
--- a/src/yuzu/applets/profile_select.cpp
+++ b/src/yuzu/applets/qt_profile_select.cpp
@@ -14,7 +14,7 @@
14#include "common/string_util.h" 14#include "common/string_util.h"
15#include "core/constants.h" 15#include "core/constants.h"
16#include "core/hle/lock.h" 16#include "core/hle/lock.h"
17#include "yuzu/applets/profile_select.h" 17#include "yuzu/applets/qt_profile_select.h"
18#include "yuzu/main.h" 18#include "yuzu/main.h"
19 19
20namespace { 20namespace {
diff --git a/src/yuzu/applets/profile_select.h b/src/yuzu/applets/qt_profile_select.h
index 4e9037488..4e9037488 100644
--- a/src/yuzu/applets/profile_select.h
+++ b/src/yuzu/applets/qt_profile_select.h
diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp
index aa453a79f..848801cec 100644
--- a/src/yuzu/applets/software_keyboard.cpp
+++ b/src/yuzu/applets/qt_software_keyboard.cpp
@@ -11,8 +11,8 @@
11#include "common/string_util.h" 11#include "common/string_util.h"
12#include "core/core.h" 12#include "core/core.h"
13#include "core/frontend/input_interpreter.h" 13#include "core/frontend/input_interpreter.h"
14#include "ui_software_keyboard.h" 14#include "ui_qt_software_keyboard.h"
15#include "yuzu/applets/software_keyboard.h" 15#include "yuzu/applets/qt_software_keyboard.h"
16#include "yuzu/main.h" 16#include "yuzu/main.h"
17#include "yuzu/util/overlay_dialog.h" 17#include "yuzu/util/overlay_dialog.h"
18 18
diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/qt_software_keyboard.h
index 1a03c098c..1a03c098c 100644
--- a/src/yuzu/applets/software_keyboard.h
+++ b/src/yuzu/applets/qt_software_keyboard.h
diff --git a/src/yuzu/applets/software_keyboard.ui b/src/yuzu/applets/qt_software_keyboard.ui
index b0a1fcde9..b0a1fcde9 100644
--- a/src/yuzu/applets/software_keyboard.ui
+++ b/src/yuzu/applets/qt_software_keyboard.ui
diff --git a/src/yuzu/applets/web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp
index 34d3feb55..b112dd7b0 100644
--- a/src/yuzu/applets/web_browser.cpp
+++ b/src/yuzu/applets/qt_web_browser.cpp
@@ -17,8 +17,8 @@
17#include "core/frontend/input_interpreter.h" 17#include "core/frontend/input_interpreter.h"
18#include "input_common/keyboard.h" 18#include "input_common/keyboard.h"
19#include "input_common/main.h" 19#include "input_common/main.h"
20#include "yuzu/applets/web_browser.h" 20#include "yuzu/applets/qt_web_browser.h"
21#include "yuzu/applets/web_browser_scripts.h" 21#include "yuzu/applets/qt_web_browser_scripts.h"
22#include "yuzu/main.h" 22#include "yuzu/main.h"
23#include "yuzu/util/url_request_interceptor.h" 23#include "yuzu/util/url_request_interceptor.h"
24 24
diff --git a/src/yuzu/applets/web_browser.h b/src/yuzu/applets/qt_web_browser.h
index 7ad07409f..7ad07409f 100644
--- a/src/yuzu/applets/web_browser.h
+++ b/src/yuzu/applets/qt_web_browser.h
diff --git a/src/yuzu/applets/web_browser_scripts.h b/src/yuzu/applets/qt_web_browser_scripts.h
index 992837a85..992837a85 100644
--- a/src/yuzu/applets/web_browser_scripts.h
+++ b/src/yuzu/applets/qt_web_browser_scripts.h
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 7524e3c40..d72ca5acc 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -411,8 +411,9 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
411 if (event->source() == Qt::MouseEventSynthesizedBySystem) { 411 if (event->source() == Qt::MouseEventSynthesizedBySystem) {
412 return; 412 return;
413 } 413 }
414 414 // Qt sometimes returns the parent coordinates. To avoid this we read the global mouse
415 auto pos = event->pos(); 415 // coordinates and map them to the current render area
416 const auto pos = mapFromGlobal(QCursor::pos());
416 const auto [x, y] = ScaleTouch(pos); 417 const auto [x, y] = ScaleTouch(pos);
417 const auto button = QtButtonToMouseButton(event->button()); 418 const auto button = QtButtonToMouseButton(event->button());
418 input_subsystem->GetMouse()->PressButton(x, y, button); 419 input_subsystem->GetMouse()->PressButton(x, y, button);
@@ -429,7 +430,9 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
429 if (event->source() == Qt::MouseEventSynthesizedBySystem) { 430 if (event->source() == Qt::MouseEventSynthesizedBySystem) {
430 return; 431 return;
431 } 432 }
432 auto pos = event->pos(); 433 // Qt sometimes returns the parent coordinates. To avoid this we read the global mouse
434 // coordinates and map them to the current render area
435 const auto pos = mapFromGlobal(QCursor::pos());
433 const auto [x, y] = ScaleTouch(pos); 436 const auto [x, y] = ScaleTouch(pos);
434 const int center_x = width() / 2; 437 const int center_x = width() / 2;
435 const int center_y = height() / 2; 438 const int center_y = height() / 2;
@@ -564,6 +567,12 @@ std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedCont
564bool GRenderWindow::InitRenderTarget() { 567bool GRenderWindow::InitRenderTarget() {
565 ReleaseRenderTarget(); 568 ReleaseRenderTarget();
566 569
570 {
571 // Create a dummy render widget so that Qt
572 // places the render window at the correct position.
573 const RenderWidget dummy_widget{this};
574 }
575
567 first_frame = false; 576 first_frame = false;
568 577
569 switch (Settings::values.renderer_backend.GetValue()) { 578 switch (Settings::values.renderer_backend.GetValue()) {
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 8c71ad5c1..a5e032959 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -311,16 +311,6 @@ void Config::WriteBasicSetting(const Settings::BasicSetting<std::string>& settin
311 qt_config->setValue(name, QString::fromStdString(value)); 311 qt_config->setValue(name, QString::fromStdString(value));
312} 312}
313 313
314// Explicit float definition: use a double as Qt doesn't write legible floats to config files
315template <>
316void Config::WriteBasicSetting(const Settings::BasicSetting<float>& setting) {
317 const QString name = QString::fromStdString(setting.GetLabel());
318 const double value = setting.GetValue();
319 qt_config->setValue(name + QStringLiteral("/default"),
320 setting.GetValue() == setting.GetDefault());
321 qt_config->setValue(name, value);
322}
323
324template <typename Type> 314template <typename Type>
325void Config::WriteBasicSetting(const Settings::BasicSetting<Type>& setting) { 315void Config::WriteBasicSetting(const Settings::BasicSetting<Type>& setting) {
326 const QString name = QString::fromStdString(setting.GetLabel()); 316 const QString name = QString::fromStdString(setting.GetLabel());
@@ -329,21 +319,6 @@ void Config::WriteBasicSetting(const Settings::BasicSetting<Type>& setting) {
329 qt_config->setValue(name, value); 319 qt_config->setValue(name, value);
330} 320}
331 321
332// Explicit float definition: use a double as Qt doesn't write legible floats to config files
333template <>
334void Config::WriteGlobalSetting(const Settings::Setting<float>& setting) {
335 const QString name = QString::fromStdString(setting.GetLabel());
336 const double value = setting.GetValue(global);
337 if (!global) {
338 qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal());
339 }
340 if (global || !setting.UsingGlobal()) {
341 qt_config->setValue(name + QStringLiteral("/default"),
342 setting.GetValue(global) == setting.GetDefault());
343 qt_config->setValue(name, value);
344 }
345}
346
347template <typename Type> 322template <typename Type>
348void Config::WriteGlobalSetting(const Settings::Setting<Type>& setting) { 323void Config::WriteGlobalSetting(const Settings::Setting<Type>& setting) {
349 const QString name = QString::fromStdString(setting.GetLabel()); 324 const QString name = QString::fromStdString(setting.GetLabel());
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index 5aba1a3b2..1d84bf4ed 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -47,7 +47,8 @@ void ConfigureAudio::SetConfiguration() {
47 47
48 SetAudioDeviceFromDeviceID(); 48 SetAudioDeviceFromDeviceID();
49 49
50 ui->volume_slider->setValue(Settings::values.volume.GetValue() * ui->volume_slider->maximum()); 50 const auto volume_value = static_cast<int>(Settings::values.volume.GetValue());
51 ui->volume_slider->setValue(volume_value);
51 52
52 ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching.GetValue()); 53 ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching.GetValue());
53 54
@@ -112,18 +113,16 @@ void ConfigureAudio::ApplyConfiguration() {
112 113
113 // Guard if during game and set to game-specific value 114 // Guard if during game and set to game-specific value
114 if (Settings::values.volume.UsingGlobal()) { 115 if (Settings::values.volume.UsingGlobal()) {
115 Settings::values.volume.SetValue( 116 const auto volume = static_cast<u8>(ui->volume_slider->value());
116 static_cast<float>(ui->volume_slider->sliderPosition()) / 117 Settings::values.volume.SetValue(volume);
117 ui->volume_slider->maximum());
118 } 118 }
119 } else { 119 } else {
120 if (ui->volume_combo_box->currentIndex() == 0) { 120 if (ui->volume_combo_box->currentIndex() == 0) {
121 Settings::values.volume.SetGlobal(true); 121 Settings::values.volume.SetGlobal(true);
122 } else { 122 } else {
123 Settings::values.volume.SetGlobal(false); 123 Settings::values.volume.SetGlobal(false);
124 Settings::values.volume.SetValue( 124 const auto volume = static_cast<u8>(ui->volume_slider->value());
125 static_cast<float>(ui->volume_slider->sliderPosition()) / 125 Settings::values.volume.SetValue(volume);
126 ui->volume_slider->maximum());
127 } 126 }
128 } 127 }
129} 128}
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 41a69d9b8..4d5b4c0e6 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -101,9 +101,9 @@ void ConfigureGraphics::SetConfiguration() {
101 ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal()); 101 ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal());
102 } 102 }
103 103
104 UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red.GetValue(), 104 UpdateBackgroundColorButton(QColor::fromRgb(Settings::values.bg_red.GetValue(),
105 Settings::values.bg_green.GetValue(), 105 Settings::values.bg_green.GetValue(),
106 Settings::values.bg_blue.GetValue())); 106 Settings::values.bg_blue.GetValue()));
107 UpdateDeviceComboBox(); 107 UpdateDeviceComboBox();
108} 108}
109 109
@@ -132,9 +132,9 @@ void ConfigureGraphics::ApplyConfiguration() {
132 Settings::values.vulkan_device.SetValue(vulkan_device); 132 Settings::values.vulkan_device.SetValue(vulkan_device);
133 } 133 }
134 if (Settings::values.bg_red.UsingGlobal()) { 134 if (Settings::values.bg_red.UsingGlobal()) {
135 Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF())); 135 Settings::values.bg_red.SetValue(static_cast<u8>(bg_color.red()));
136 Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF())); 136 Settings::values.bg_green.SetValue(static_cast<u8>(bg_color.green()));
137 Settings::values.bg_blue.SetValue(static_cast<float>(bg_color.blueF())); 137 Settings::values.bg_blue.SetValue(static_cast<u8>(bg_color.blue()));
138 } 138 }
139 } else { 139 } else {
140 if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { 140 if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
@@ -159,9 +159,9 @@ void ConfigureGraphics::ApplyConfiguration() {
159 Settings::values.bg_red.SetGlobal(false); 159 Settings::values.bg_red.SetGlobal(false);
160 Settings::values.bg_green.SetGlobal(false); 160 Settings::values.bg_green.SetGlobal(false);
161 Settings::values.bg_blue.SetGlobal(false); 161 Settings::values.bg_blue.SetGlobal(false);
162 Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF())); 162 Settings::values.bg_red.SetValue(static_cast<u8>(bg_color.red()));
163 Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF())); 163 Settings::values.bg_green.SetValue(static_cast<u8>(bg_color.green()));
164 Settings::values.bg_blue.SetValue(static_cast<float>(bg_color.blueF())); 164 Settings::values.bg_blue.SetValue(static_cast<u8>(bg_color.blue()));
165 } 165 }
166 } 166 }
167} 167}
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui
index 173130d8d..d3ef5bd06 100644
--- a/src/yuzu/configuration/configure_input_advanced.ui
+++ b/src/yuzu/configuration/configure_input_advanced.ui
@@ -2573,27 +2573,24 @@
2573 </widget> 2573 </widget>
2574 </item> 2574 </item>
2575 <item row="2" column="2"> 2575 <item row="2" column="2">
2576 <widget class="QDoubleSpinBox" name="mouse_panning_sensitivity"> 2576 <widget class="QSpinBox" name="mouse_panning_sensitivity">
2577 <property name="toolTip"> 2577 <property name="toolTip">
2578 <string>Mouse sensitivity</string> 2578 <string>Mouse sensitivity</string>
2579 </property> 2579 </property>
2580 <property name="alignment"> 2580 <property name="alignment">
2581 <set>Qt::AlignCenter</set> 2581 <set>Qt::AlignCenter</set>
2582 </property> 2582 </property>
2583 <property name="decimals"> 2583 <property name="suffix">
2584 <number>2</number> 2584 <string>%</string>
2585 </property> 2585 </property>
2586 <property name="minimum"> 2586 <property name="minimum">
2587 <double>0.100000000000000</double> 2587 <number>1</number>
2588 </property> 2588 </property>
2589 <property name="maximum"> 2589 <property name="maximum">
2590 <double>16.000000000000000</double> 2590 <number>100</number>
2591 </property>
2592 <property name="singleStep">
2593 <double>0.010000000000000</double>
2594 </property> 2591 </property>
2595 <property name="value"> 2592 <property name="value">
2596 <double>1.000000000000000</double> 2593 <number>100</number>
2597 </property> 2594 </property>
2598 </widget> 2595 </widget>
2599 </item> 2596 </item>
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 218b4782b..76c063c97 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -404,9 +404,11 @@ void GameList::ValidateEntry(const QModelIndex& item) {
404 return; 404 return;
405 } 405 }
406 406
407 const auto title_id = selected.data(GameListItemPath::ProgramIdRole).toULongLong();
408
407 // Users usually want to run a different game after closing one 409 // Users usually want to run a different game after closing one
408 search_field->clear(); 410 search_field->clear();
409 emit GameChosen(file_path); 411 emit GameChosen(file_path, title_id);
410 break; 412 break;
411 } 413 }
412 case GameListItemType::AddDir: 414 case GameListItemType::AddDir:
@@ -548,10 +550,10 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
548 emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path); 550 emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path);
549 }); 551 });
550 connect(start_game, &QAction::triggered, [this, path]() { 552 connect(start_game, &QAction::triggered, [this, path]() {
551 emit BootGame(QString::fromStdString(path), 0, StartGameType::Normal); 553 emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Normal);
552 }); 554 });
553 connect(start_game_global, &QAction::triggered, [this, path]() { 555 connect(start_game_global, &QAction::triggered, [this, path]() {
554 emit BootGame(QString::fromStdString(path), 0, StartGameType::Global); 556 emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Global);
555 }); 557 });
556 connect(open_mod_location, &QAction::triggered, [this, program_id, path]() { 558 connect(open_mod_location, &QAction::triggered, [this, program_id, path]() {
557 emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path); 559 emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path);
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index 50402da51..c9a9f4654 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -88,8 +88,9 @@ public:
88 static const QStringList supported_file_extensions; 88 static const QStringList supported_file_extensions;
89 89
90signals: 90signals:
91 void BootGame(const QString& game_path, std::size_t program_index, StartGameType type); 91 void BootGame(const QString& game_path, u64 program_id, std::size_t program_index,
92 void GameChosen(const QString& game_path); 92 StartGameType type);
93 void GameChosen(const QString& game_path, const u64 title_id = 0);
93 void ShouldCancelWorker(); 94 void ShouldCancelWorker();
94 void OpenFolderRequested(u64 program_id, GameListOpenTarget target, 95 void OpenFolderRequested(u64 program_id, GameListOpenTarget target,
95 const std::string& game_path); 96 const std::string& game_path);
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index 33cc90d5a..2d5492157 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -336,18 +336,44 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
336 } 336 }
337 } 337 }
338 } else { 338 } else {
339 std::vector<u8> icon; 339 std::vector<u64> program_ids;
340 [[maybe_unused]] const auto res1 = loader->ReadIcon(icon); 340 loader->ReadProgramIds(program_ids);
341
342 if (res2 == Loader::ResultStatus::Success && program_ids.size() > 1 &&
343 (file_type == Loader::FileType::XCI || file_type == Loader::FileType::NSP)) {
344 for (const auto id : program_ids) {
345 loader = Loader::GetLoader(system, file, id);
346 if (!loader) {
347 continue;
348 }
349
350 std::vector<u8> icon;
351 [[maybe_unused]] const auto res1 = loader->ReadIcon(icon);
341 352
342 std::string name = " "; 353 std::string name = " ";
343 [[maybe_unused]] const auto res3 = loader->ReadTitle(name); 354 [[maybe_unused]] const auto res3 = loader->ReadTitle(name);
344 355
345 const FileSys::PatchManager patch{program_id, system.GetFileSystemController(), 356 const FileSys::PatchManager patch{id, system.GetFileSystemController(),
346 system.GetContentProvider()}; 357 system.GetContentProvider()};
358
359 emit EntryReady(MakeGameListEntry(physical_name, name, icon, *loader, id,
360 compatibility_list, patch),
361 parent_dir);
362 }
363 } else {
364 std::vector<u8> icon;
365 [[maybe_unused]] const auto res1 = loader->ReadIcon(icon);
347 366
348 emit EntryReady(MakeGameListEntry(physical_name, name, icon, *loader, program_id, 367 std::string name = " ";
349 compatibility_list, patch), 368 [[maybe_unused]] const auto res3 = loader->ReadTitle(name);
350 parent_dir); 369
370 const FileSys::PatchManager patch{program_id, system.GetFileSystemController(),
371 system.GetContentProvider()};
372
373 emit EntryReady(MakeGameListEntry(physical_name, name, icon, *loader,
374 program_id, compatibility_list, patch),
375 parent_dir);
376 }
351 } 377 }
352 } else if (is_dir) { 378 } else if (is_dir) {
353 watch_list.append(QString::fromStdString(physical_name)); 379 watch_list.append(QString::fromStdString(physical_name));
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index cb9c01154..03a909d17 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -11,11 +11,11 @@
11#endif 11#endif
12 12
13// VFS includes must be before glad as they will conflict with Windows file api, which uses defines. 13// VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
14#include "applets/controller.h" 14#include "applets/qt_controller.h"
15#include "applets/error.h" 15#include "applets/qt_error.h"
16#include "applets/profile_select.h" 16#include "applets/qt_profile_select.h"
17#include "applets/software_keyboard.h" 17#include "applets/qt_software_keyboard.h"
18#include "applets/web_browser.h" 18#include "applets/qt_web_browser.h"
19#include "common/nvidia_flags.h" 19#include "common/nvidia_flags.h"
20#include "configuration/configure_input.h" 20#include "configuration/configure_input.h"
21#include "configuration/configure_per_game.h" 21#include "configuration/configure_per_game.h"
@@ -1221,7 +1221,7 @@ void GMainWindow::AllowOSSleep() {
1221#endif 1221#endif
1222} 1222}
1223 1223
1224bool GMainWindow::LoadROM(const QString& filename, std::size_t program_index) { 1224bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index) {
1225 // Shutdown previous session if the emu thread is still active... 1225 // Shutdown previous session if the emu thread is still active...
1226 if (emu_thread != nullptr) 1226 if (emu_thread != nullptr)
1227 ShutdownGame(); 1227 ShutdownGame();
@@ -1244,7 +1244,7 @@ bool GMainWindow::LoadROM(const QString& filename, std::size_t program_index) {
1244 }); 1244 });
1245 1245
1246 const Core::System::ResultStatus result{ 1246 const Core::System::ResultStatus result{
1247 system.Load(*render_window, filename.toStdString(), program_index)}; 1247 system.Load(*render_window, filename.toStdString(), program_id, program_index)};
1248 1248
1249 const auto drd_callout = (UISettings::values.callout_flags.GetValue() & 1249 const auto drd_callout = (UISettings::values.callout_flags.GetValue() &
1250 static_cast<u32>(CalloutFlag::DRDDeprecation)) == 0; 1250 static_cast<u32>(CalloutFlag::DRDDeprecation)) == 0;
@@ -1331,7 +1331,8 @@ void GMainWindow::SelectAndSetCurrentUser() {
1331 Settings::values.current_user = dialog.GetIndex(); 1331 Settings::values.current_user = dialog.GetIndex();
1332} 1332}
1333 1333
1334void GMainWindow::BootGame(const QString& filename, std::size_t program_index, StartGameType type) { 1334void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index,
1335 StartGameType type) {
1335 LOG_INFO(Frontend, "yuzu starting..."); 1336 LOG_INFO(Frontend, "yuzu starting...");
1336 StoreRecentFile(filename); // Put the filename on top of the list 1337 StoreRecentFile(filename); // Put the filename on top of the list
1337 1338
@@ -1341,7 +1342,7 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index, S
1341 1342
1342 auto& system = Core::System::GetInstance(); 1343 auto& system = Core::System::GetInstance();
1343 const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData()); 1344 const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData());
1344 const auto loader = Loader::GetLoader(system, v_file, program_index); 1345 const auto loader = Loader::GetLoader(system, v_file, program_id, program_index);
1345 1346
1346 if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success && 1347 if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success &&
1347 type == StartGameType::Normal) { 1348 type == StartGameType::Normal) {
@@ -1369,7 +1370,7 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index, S
1369 SelectAndSetCurrentUser(); 1370 SelectAndSetCurrentUser();
1370 } 1371 }
1371 1372
1372 if (!LoadROM(filename, program_index)) 1373 if (!LoadROM(filename, program_id, program_index))
1373 return; 1374 return;
1374 1375
1375 // Create and start the emulation thread 1376 // Create and start the emulation thread
@@ -1431,8 +1432,10 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index, S
1431 std::filesystem::path{filename.toStdU16String()}.filename()); 1432 std::filesystem::path{filename.toStdU16String()}.filename());
1432 } 1433 }
1433 const bool is_64bit = system.Kernel().CurrentProcess()->Is64BitProcess(); 1434 const bool is_64bit = system.Kernel().CurrentProcess()->Is64BitProcess();
1434 const auto instruction_set_suffix = is_64bit ? " (64-bit)" : " (32-bit)"; 1435 const auto instruction_set_suffix = is_64bit ? tr("(64-bit)") : tr("(32-bit)");
1435 title_name += instruction_set_suffix; 1436 title_name = tr("%1 %2", "%1 is the title name. %2 indicates if the title is 64-bit or 32-bit")
1437 .arg(QString::fromStdString(title_name), instruction_set_suffix)
1438 .toStdString();
1436 LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version); 1439 LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version);
1437 const auto gpu_vendor = system.GPU().Renderer().GetDeviceVendor(); 1440 const auto gpu_vendor = system.GPU().Renderer().GetDeviceVendor();
1438 UpdateWindowTitle(title_name, title_version, gpu_vendor); 1441 UpdateWindowTitle(title_name, title_version, gpu_vendor);
@@ -1546,8 +1549,8 @@ void GMainWindow::UpdateRecentFiles() {
1546 ui.menu_recent_files->setEnabled(num_recent_files != 0); 1549 ui.menu_recent_files->setEnabled(num_recent_files != 0);
1547} 1550}
1548 1551
1549void GMainWindow::OnGameListLoadFile(QString game_path) { 1552void GMainWindow::OnGameListLoadFile(QString game_path, u64 program_id) {
1550 BootGame(game_path); 1553 BootGame(game_path, program_id);
1551} 1554}
1552 1555
1553void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target, 1556void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target,
@@ -2448,7 +2451,7 @@ void GMainWindow::OnLoadComplete() {
2448 2451
2449void GMainWindow::OnExecuteProgram(std::size_t program_index) { 2452void GMainWindow::OnExecuteProgram(std::size_t program_index) {
2450 ShutdownGame(); 2453 ShutdownGame();
2451 BootGame(last_filename_booted, program_index); 2454 BootGame(last_filename_booted, 0, program_index);
2452} 2455}
2453 2456
2454void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) { 2457void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 45c8310e1..a50e5b9fe 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -186,8 +186,8 @@ private:
186 void PreventOSSleep(); 186 void PreventOSSleep();
187 void AllowOSSleep(); 187 void AllowOSSleep();
188 188
189 bool LoadROM(const QString& filename, std::size_t program_index); 189 bool LoadROM(const QString& filename, u64 program_id, std::size_t program_index);
190 void BootGame(const QString& filename, std::size_t program_index = 0, 190 void BootGame(const QString& filename, u64 program_id = 0, std::size_t program_index = 0,
191 StartGameType with_config = StartGameType::Normal); 191 StartGameType with_config = StartGameType::Normal);
192 void ShutdownGame(); 192 void ShutdownGame();
193 193
@@ -238,7 +238,7 @@ private slots:
238 void OnOpenQuickstartGuide(); 238 void OnOpenQuickstartGuide();
239 void OnOpenFAQ(); 239 void OnOpenFAQ();
240 /// Called whenever a user selects a game in the game list widget. 240 /// Called whenever a user selects a game in the game list widget.
241 void OnGameListLoadFile(QString game_path); 241 void OnGameListLoadFile(QString game_path, u64 program_id);
242 void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target, 242 void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target,
243 const std::string& game_path); 243 const std::string& game_path);
244 void OnTransferableShaderCacheOpenFile(u64 program_id); 244 void OnTransferableShaderCacheOpenFile(u64 program_id);
diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt
index 4bf25727b..e55a19649 100644
--- a/src/yuzu_cmd/CMakeLists.txt
+++ b/src/yuzu_cmd/CMakeLists.txt
@@ -38,6 +38,11 @@ target_include_directories(yuzu-cmd PRIVATE ${RESOURCES_DIR})
38 38
39target_include_directories(yuzu-cmd PRIVATE ../../externals/Vulkan-Headers/include) 39target_include_directories(yuzu-cmd PRIVATE ../../externals/Vulkan-Headers/include)
40 40
41if (YUZU_USE_EXTERNAL_SDL2)
42 target_compile_definitions(yuzu-cmd PRIVATE -DYUZU_USE_EXTERNAL_SDL2)
43 target_include_directories(yuzu-cmd PRIVATE ${PROJECT_BINARY_DIR}/externals/SDL/include)
44endif()
45
41if(UNIX AND NOT APPLE) 46if(UNIX AND NOT APPLE)
42 install(TARGETS yuzu-cmd RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") 47 install(TARGETS yuzu-cmd RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
43endif() 48endif()
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 325584a1a..b18056baf 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -242,17 +242,15 @@ static const std::array<int, 8> keyboard_mods{
242}; 242};
243 243
244template <> 244template <>
245void Config::ReadSetting(const std::string& group, Settings::BasicSetting<float>& setting) {
246 setting = sdl2_config->GetReal(group, setting.GetLabel(), setting.GetDefault());
247}
248template <>
249void Config::ReadSetting(const std::string& group, Settings::BasicSetting<std::string>& setting) { 245void Config::ReadSetting(const std::string& group, Settings::BasicSetting<std::string>& setting) {
250 setting = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault()); 246 setting = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault());
251} 247}
248
252template <> 249template <>
253void Config::ReadSetting(const std::string& group, Settings::BasicSetting<bool>& setting) { 250void Config::ReadSetting(const std::string& group, Settings::BasicSetting<bool>& setting) {
254 setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault()); 251 setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
255} 252}
253
256template <typename Type> 254template <typename Type>
257void Config::ReadSetting(const std::string& group, Settings::BasicSetting<Type>& setting) { 255void Config::ReadSetting(const std::string& group, Settings::BasicSetting<Type>& setting) {
258 setting = static_cast<Type>(sdl2_config->GetInteger(group, setting.GetLabel(), 256 setting = static_cast<Type>(sdl2_config->GetInteger(group, setting.GetLabel(),
@@ -294,6 +292,8 @@ void Config::ReadValues() {
294 292
295 ReadSetting("ControlsGeneral", Settings::values.motion_device); 293 ReadSetting("ControlsGeneral", Settings::values.motion_device);
296 294
295 ReadSetting("ControlsGeneral", Settings::values.touch_device);
296
297 ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled); 297 ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled);
298 298
299 ReadSetting("ControlsGeneral", Settings::values.debug_pad_enabled); 299 ReadSetting("ControlsGeneral", Settings::values.debug_pad_enabled);
@@ -416,11 +416,31 @@ void Config::ReadValues() {
416 } 416 }
417 417
418 ReadSetting("System", Settings::values.language_index); 418 ReadSetting("System", Settings::values.language_index);
419 ReadSetting("System", Settings::values.region_index);
419 ReadSetting("System", Settings::values.time_zone_index); 420 ReadSetting("System", Settings::values.time_zone_index);
421 ReadSetting("System", Settings::values.sound_index);
420 422
421 // Core 423 // Core
422 ReadSetting("Core", Settings::values.use_multi_core); 424 ReadSetting("Core", Settings::values.use_multi_core);
423 425
426 // Cpu
427 ReadSetting("Cpu", Settings::values.cpu_accuracy);
428 ReadSetting("Cpu", Settings::values.cpu_debug_mode);
429 ReadSetting("Cpu", Settings::values.cpuopt_page_tables);
430 ReadSetting("Cpu", Settings::values.cpuopt_block_linking);
431 ReadSetting("Cpu", Settings::values.cpuopt_return_stack_buffer);
432 ReadSetting("Cpu", Settings::values.cpuopt_fast_dispatcher);
433 ReadSetting("Cpu", Settings::values.cpuopt_context_elimination);
434 ReadSetting("Cpu", Settings::values.cpuopt_const_prop);
435 ReadSetting("Cpu", Settings::values.cpuopt_misc_ir);
436 ReadSetting("Cpu", Settings::values.cpuopt_reduce_misalign_checks);
437 ReadSetting("Cpu", Settings::values.cpuopt_fastmem);
438 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma);
439 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error);
440 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr);
441 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_inaccurate_nan);
442 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_fastmem_check);
443
424 // Renderer 444 // Renderer
425 ReadSetting("Renderer", Settings::values.renderer_backend); 445 ReadSetting("Renderer", Settings::values.renderer_backend);
426 ReadSetting("Renderer", Settings::values.renderer_debug); 446 ReadSetting("Renderer", Settings::values.renderer_debug);
@@ -440,6 +460,7 @@ void Config::ReadValues() {
440 ReadSetting("Renderer", Settings::values.use_nvdec_emulation); 460 ReadSetting("Renderer", Settings::values.use_nvdec_emulation);
441 ReadSetting("Renderer", Settings::values.accelerate_astc); 461 ReadSetting("Renderer", Settings::values.accelerate_astc);
442 ReadSetting("Renderer", Settings::values.use_fast_gpu_time); 462 ReadSetting("Renderer", Settings::values.use_fast_gpu_time);
463 ReadSetting("Renderer", Settings::values.use_caches_gc);
443 464
444 ReadSetting("Renderer", Settings::values.bg_red); 465 ReadSetting("Renderer", Settings::values.bg_red);
445 ReadSetting("Renderer", Settings::values.bg_green); 466 ReadSetting("Renderer", Settings::values.bg_green);
@@ -460,7 +481,6 @@ void Config::ReadValues() {
460 // Debugging 481 // Debugging
461 Settings::values.record_frame_times = 482 Settings::values.record_frame_times =
462 sdl2_config->GetBoolean("Debugging", "record_frame_times", false); 483 sdl2_config->GetBoolean("Debugging", "record_frame_times", false);
463 ReadSetting("Debugging", Settings::values.program_args);
464 ReadSetting("Debugging", Settings::values.dump_exefs); 484 ReadSetting("Debugging", Settings::values.dump_exefs);
465 ReadSetting("Debugging", Settings::values.dump_nso); 485 ReadSetting("Debugging", Settings::values.dump_nso);
466 ReadSetting("Debugging", Settings::values.enable_fs_access_log); 486 ReadSetting("Debugging", Settings::values.enable_fs_access_log);
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index cc9850aad..b362f10b4 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -65,6 +65,13 @@ button_screenshot=
65lstick= 65lstick=
66rstick= 66rstick=
67 67
68# To use the debug_pad, prepend `debug_pad_` before each button setting above.
69# i.e. debug_pad_button_a=
70
71# Enable debug pad inputs to the guest
72# 0 (default): Disabled, 1: Enabled
73debug_pad_enabled =
74
68# Whether to enable or disable vibration 75# Whether to enable or disable vibration
69# 0: Disabled, 1 (default): Enabled 76# 0: Disabled, 1 (default): Enabled
70vibration_enabled= 77vibration_enabled=
@@ -73,6 +80,10 @@ vibration_enabled=
73# 0 (default): Disabled, 1: Enabled 80# 0 (default): Disabled, 1: Enabled
74enable_accurate_vibrations= 81enable_accurate_vibrations=
75 82
83# Enables controller motion inputs
84# 0: Disabled, 1 (default): Enabled
85motion_enabled =
86
76# for motion input, the following devices are available: 87# for motion input, the following devices are available:
77# - "motion_emu" (default) for emulating motion input from mouse input. Required parameters: 88# - "motion_emu" (default) for emulating motion input from mouse input. Required parameters:
78# - "update_period": update period in milliseconds (default to 100) 89# - "update_period": update period in milliseconds (default to 100)
@@ -98,19 +109,30 @@ use_touch_from_button=
98#touch_from_button_maps_0_bind_1=bar 109#touch_from_button_maps_0_bind_1=bar
99# etc. 110# etc.
100 111
101# Most desktop operating systems do not expose a way to poll the motion state of the controllers 112# List of Cemuhook UDP servers, delimited by ','.
102# so as a way around it, cemuhook created a udp client/server protocol to broadcast the data directly 113# Default: 127.0.0.1:26760
103# from a controller device to the client program. Citra has a client that can connect and read 114# Example: 127.0.0.1:26760,123.4.5.67:26761
104# from any cemuhook compatible motion program. 115udp_input_servers =
105 116
106# IPv4 address of the udp input server (Default "127.0.0.1") 117# Enable controlling an axis via a mouse input.
107udp_input_address=127.0.0.1 118# 0 (default): Off, 1: On
119mouse_panning =
120
121# Set mouse sensitivity.
122# Default: 1.0
123mouse_panning_sensitivity =
124
125# Emulate an analog control stick from keyboard inputs.
126# 0 (default): Disabled, 1: Enabled
127emulate_analog_keyboard =
108 128
109# Port of the udp input server. (Default 26760) 129# Enable mouse inputs to the guest
110udp_input_port= 130# 0 (default): Disabled, 1: Enabled
131mouse_enabled =
111 132
112# The pad to request data on. Should be between 0 (Pad 1) and 3 (Pad 4). (Default 0) 133# Enable keyboard inputs to the guest
113udp_pad_index= 134# 0 (default): Disabled, 1: Enabled
135keyboard_enabled =
114 136
115[Core] 137[Core]
116# Whether to use multi-core for CPU emulation 138# Whether to use multi-core for CPU emulation
@@ -118,6 +140,17 @@ udp_pad_index=
118use_multi_core= 140use_multi_core=
119 141
120[Cpu] 142[Cpu]
143# Adjusts various optimizations.
144# Auto-select mode enables choice unsafe optimizations.
145# Accurate enables only safe optimizations.
146# Unsafe allows any unsafe optimizations.
147# 0 (default): Auto-select, 1: Accurate, 2: Enable unsafe optimizations
148cpu_accuracy =
149
150# Allow disabling safe optimizations.
151# 0 (default): Disabled, 1: Enabled
152cpu_debug_mode =
153
121# Enable inline page tables optimization (faster guest memory access) 154# Enable inline page tables optimization (faster guest memory access)
122# 0: Disabled, 1 (default): Enabled 155# 0: Disabled, 1 (default): Enabled
123cpuopt_page_tables = 156cpuopt_page_tables =
@@ -154,6 +187,31 @@ cpuopt_reduce_misalign_checks =
154# 0: Disabled, 1 (default): Enabled 187# 0: Disabled, 1 (default): Enabled
155cpuopt_fastmem = 188cpuopt_fastmem =
156 189
190# Enable unfuse FMA (improve performance on CPUs without FMA)
191# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
192# 0: Disabled, 1 (default): Enabled
193cpuopt_unsafe_unfuse_fma =
194
195# Enable faster FRSQRTE and FRECPE
196# Only enabled if cpu_accuracy is set to Unsafe.
197# 0: Disabled, 1 (default): Enabled
198cpuopt_unsafe_reduce_fp_error =
199
200# Enable faster ASIMD instructions (32 bits only)
201# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
202# 0: Disabled, 1 (default): Enabled
203cpuopt_unsafe_ignore_standard_fpcr =
204
205# Enable inaccurate NaN handling
206# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
207# 0: Disabled, 1 (default): Enabled
208cpuopt_unsafe_inaccurate_nan =
209
210# Disable address space checks (64 bits only)
211# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
212# 0: Disabled, 1 (default): Enabled
213cpuopt_unsafe_fastmem_check =
214
157[Renderer] 215[Renderer]
158# Which backend API to use. 216# Which backend API to use.
159# 0 (default): OpenGL, 1: Vulkan 217# 0 (default): OpenGL, 1: Vulkan
@@ -166,14 +224,6 @@ debug =
166# Which Vulkan physical device to use (defaults to 0) 224# Which Vulkan physical device to use (defaults to 0)
167vulkan_device = 225vulkan_device =
168 226
169# Whether to use software or hardware rendering.
170# 0: Software, 1 (default): Hardware
171use_hw_renderer =
172
173# Whether to use the Just-In-Time (JIT) compiler for shader emulation
174# 0: Interpreter (slow), 1 (default): JIT (fast)
175use_shader_jit =
176
177# Aspect ratio 227# Aspect ratio
178# 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Stretch to Window 228# 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Stretch to Window
179aspect_ratio = 229aspect_ratio =
@@ -211,57 +261,31 @@ use_frame_limit =
211frame_limit = 261frame_limit =
212 262
213# Whether to use disk based shader cache 263# Whether to use disk based shader cache
214# 0 (default): Off, 1 : On 264# 0: Off, 1 (default): On
215use_disk_shader_cache = 265use_disk_shader_cache =
216 266
217# Which gpu accuracy level to use 267# Which gpu accuracy level to use
218# 0 (Normal), 1 (High), 2 (Extreme) 268# 0: Normal, 1 (default): High, 2: Extreme (Very slow)
219gpu_accuracy = 269gpu_accuracy =
220 270
221# Whether to use asynchronous GPU emulation 271# Whether to use asynchronous GPU emulation
222# 0 : Off (slow), 1 (default): On (fast) 272# 0 : Off (slow), 1 (default): On (fast)
223use_asynchronous_gpu_emulation = 273use_asynchronous_gpu_emulation =
224 274
225# Forces VSync on the display thread. Usually doesn't impact performance, but on some drivers it can 275# Inform the guest that GPU operations completed more quickly than they did.
226# so only turn this off if you notice a speed difference.
227# 0: Off, 1 (default): On 276# 0: Off, 1 (default): On
228use_vsync = 277use_fast_gpu_time =
229 278
230# Whether to use garbage collection or not for GPU caches. 279# Whether to use garbage collection or not for GPU caches.
231# 0 (default): Off, 1: On 280# 0 (default): Off, 1: On
232use_caches_gc = 281use_caches_gc =
233 282
234# The clear color for the renderer. What shows up on the sides of the bottom screen. 283# The clear color for the renderer. What shows up on the sides of the bottom screen.
235# Must be in range of 0.0-1.0. Defaults to 1.0 for all. 284# Must be in range of 0-255. Defaults to 0 for all.
236bg_red = 285bg_red =
237bg_blue = 286bg_blue =
238bg_green = 287bg_green =
239 288
240[Layout]
241# Layout for the screen inside the render window.
242# 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen
243layout_option =
244
245# Toggle custom layout (using the settings below) on or off.
246# 0 (default): Off, 1: On
247custom_layout =
248
249# Screen placement when using Custom layout option
250# 0x, 0y is the top left corner of the render window.
251custom_top_left =
252custom_top_top =
253custom_top_right =
254custom_top_bottom =
255custom_bottom_left =
256custom_bottom_top =
257custom_bottom_right =
258custom_bottom_bottom =
259
260# Swaps the prominent screen with the other screen.
261# For example, if Single Screen is chosen, setting this to 1 will display the bottom screen instead of the top screen.
262# 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent
263swap_screen =
264
265[Audio] 289[Audio]
266# Which audio output engine to use. 290# Which audio output engine to use.
267# auto (default): Auto-select 291# auto (default): Auto-select
@@ -281,7 +305,7 @@ enable_audio_stretching =
281output_device = 305output_device =
282 306
283# Output volume. 307# Output volume.
284# 1.0 (default): 100%, 0.0; mute 308# 100 (default): 100%, 0; mute
285volume = 309volume =
286 310
287[Data Storage] 311[Data Storage]
@@ -308,10 +332,6 @@ gamecard_path =
308# 1 (default): Yes, 0: No 332# 1 (default): Yes, 0: No
309use_docked_mode = 333use_docked_mode =
310 334
311# Allow the use of NFC in games
312# 1 (default): Yes, 0 : No
313enable_nfc =
314
315# Sets the seed for the RNG generator built into the switch 335# Sets the seed for the RNG generator built into the switch
316# rng_seed will be ignored and randomly generated if rng_seed_enabled is false 336# rng_seed will be ignored and randomly generated if rng_seed_enabled is false
317rng_seed_enabled = 337rng_seed_enabled =
@@ -323,10 +343,6 @@ rng_seed =
323custom_rtc_enabled = 343custom_rtc_enabled =
324custom_rtc = 344custom_rtc =
325 345
326# Sets the account username, max length is 32 characters
327# yuzu (default)
328username = yuzu
329
330# Sets the systems language index 346# Sets the systems language index
331# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese, 347# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese,
332# 7: Korean, 8: Dutch, 9: Portuguese, 10: Russian, 11: Taiwanese, 12: British English, 13: Canadian French, 348# 7: Korean, 8: Dutch, 9: Portuguese, 10: Russian, 11: Taiwanese, 12: British English, 13: Canadian French,
@@ -335,17 +351,25 @@ language_index =
335 351
336# The system region that yuzu will use during emulation 352# The system region that yuzu will use during emulation
337# -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan 353# -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan
338region_value = 354region_index =
339 355
340# The system time zone that yuzu will use during emulation 356# The system time zone that yuzu will use during emulation
341# 0: Auto-select (default), 1: Default (system archive value), Others: Index for specified time zone 357# 0: Auto-select (default), 1: Default (system archive value), Others: Index for specified time zone
342time_zone_index = 358time_zone_index =
343 359
360# Sets the sound output mode.
361# 0: Mono, 1 (default): Stereo, 2: Surround
362sound_index =
363
344[Miscellaneous] 364[Miscellaneous]
345# A filter which removes logs below a certain logging level. 365# A filter which removes logs below a certain logging level.
346# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical 366# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical
347log_filter = *:Trace 367log_filter = *:Trace
348 368
369# Use developer keys
370# 0 (default): Disabled, 1: Enabled
371use_dev_keys =
372
349[Debugging] 373[Debugging]
350# Record frame time data, can be found in the log directory. Boolean value 374# Record frame time data, can be found in the log directory. Boolean value
351record_frame_times = 375record_frame_times =
@@ -355,6 +379,8 @@ dump_exefs=false
355dump_nso=false 379dump_nso=false
356# Determines whether or not yuzu will save the filesystem access log. 380# Determines whether or not yuzu will save the filesystem access log.
357enable_fs_access_log=false 381enable_fs_access_log=false
382# Enables verbose reporting services
383reporting_services =
358# Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode 384# Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode
359# false: Retail/Normal Mode (default), true: Kiosk Mode 385# false: Retail/Normal Mode (default), true: Kiosk Mode
360quest_flag = 386quest_flag =
@@ -393,4 +419,4 @@ title_ids =
393# For each title ID, have a key/value pair called `disabled_<title_id>` equal to the names of the add-ons to disable (sep. by '|') 419# For each title ID, have a key/value pair called `disabled_<title_id>` equal to the names of the add-ons to disable (sep. by '|')
394# e.x. disabled_0100000000010000 = Update|DLC <- disables Updates and DLC on Super Mario Odyssey 420# e.x. disabled_0100000000010000 = Update|DLC <- disables Updates and DLC on Super Mario Odyssey
395)"; 421)";
396} 422} // namespace DefaultINI
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index 06b20c975..896181f0b 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -2,15 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307
6#ifdef __clang__
7#pragma clang diagnostic push
8#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
9#endif
10#include <SDL.h> 5#include <SDL.h>
11#ifdef __clang__
12#pragma clang diagnostic pop
13#endif
14 6
15#include "common/logging/log.h" 7#include "common/logging/log.h"
16#include "common/scm_rev.h" 8#include "common/scm_rev.h"
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
index 837a44be7..eadb41790 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -7,15 +7,7 @@
7#include <string> 7#include <string>
8 8
9#define SDL_MAIN_HANDLED 9#define SDL_MAIN_HANDLED
10// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307
11#ifdef __clang__
12#pragma clang diagnostic push
13#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
14#endif
15#include <SDL.h> 10#include <SDL.h>
16#ifdef __clang__
17#pragma clang diagnostic pop
18#endif
19 11
20#include <fmt/format.h> 12#include <fmt/format.h>
21#include <glad/glad.h> 13#include <glad/glad.h>
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
index 3401ad4b4..152e56db8 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
@@ -15,16 +15,13 @@
15#include "video_core/renderer_vulkan/renderer_vulkan.h" 15#include "video_core/renderer_vulkan/renderer_vulkan.h"
16#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" 16#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h"
17 17
18// Include these late to avoid polluting everything with Xlib macros 18#ifdef YUZU_USE_EXTERNAL_SDL2
19// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307 19// Include this before SDL.h to prevent the external from including a dummy
20#ifdef __clang__ 20#define USING_GENERATED_CONFIG_H
21#pragma clang diagnostic push 21#include <SDL_config.h>
22#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
23#endif 22#endif
23
24#include <SDL.h> 24#include <SDL.h>
25#ifdef __clang__
26#pragma clang diagnostic pop
27#endif
28#include <SDL_syswm.h> 25#include <SDL_syswm.h>
29 26
30EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem) 27EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem)
@@ -51,6 +48,11 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste
51 window_info.type = Core::Frontend::WindowSystemType::Windows; 48 window_info.type = Core::Frontend::WindowSystemType::Windows;
52 window_info.render_surface = reinterpret_cast<void*>(wm.info.win.window); 49 window_info.render_surface = reinterpret_cast<void*>(wm.info.win.window);
53 break; 50 break;
51#else
52 case SDL_SYSWM_TYPE::SDL_SYSWM_WINDOWS:
53 LOG_CRITICAL(Frontend, "Window manager subsystem Windows not compiled");
54 std::exit(EXIT_FAILURE);
55 break;
54#endif 56#endif
55#ifdef SDL_VIDEO_DRIVER_X11 57#ifdef SDL_VIDEO_DRIVER_X11
56 case SDL_SYSWM_TYPE::SDL_SYSWM_X11: 58 case SDL_SYSWM_TYPE::SDL_SYSWM_X11:
@@ -58,6 +60,11 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste
58 window_info.display_connection = wm.info.x11.display; 60 window_info.display_connection = wm.info.x11.display;
59 window_info.render_surface = reinterpret_cast<void*>(wm.info.x11.window); 61 window_info.render_surface = reinterpret_cast<void*>(wm.info.x11.window);
60 break; 62 break;
63#else
64 case SDL_SYSWM_TYPE::SDL_SYSWM_X11:
65 LOG_CRITICAL(Frontend, "Window manager subsystem X11 not compiled");
66 std::exit(EXIT_FAILURE);
67 break;
61#endif 68#endif
62#ifdef SDL_VIDEO_DRIVER_WAYLAND 69#ifdef SDL_VIDEO_DRIVER_WAYLAND
63 case SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND: 70 case SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND:
@@ -65,6 +72,11 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste
65 window_info.display_connection = wm.info.wl.display; 72 window_info.display_connection = wm.info.wl.display;
66 window_info.render_surface = wm.info.wl.surface; 73 window_info.render_surface = wm.info.wl.surface;
67 break; 74 break;
75#else
76 case SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND:
77 LOG_CRITICAL(Frontend, "Window manager subsystem Wayland not compiled");
78 std::exit(EXIT_FAILURE);
79 break;
68#endif 80#endif
69 default: 81 default:
70 LOG_CRITICAL(Frontend, "Window manager subsystem not implemented"); 82 LOG_CRITICAL(Frontend, "Window manager subsystem not implemented");