summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/file_sys/common_funcs.h56
-rw-r--r--src/core/file_sys/patch_manager.cpp4
-rw-r--r--src/core/file_sys/romfs_factory.cpp22
-rw-r--r--src/core/file_sys/romfs_factory.h4
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp88
-rw-r--r--src/core/hle/service/aoc/aoc_u.h2
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp25
-rw-r--r--src/core/hle/service/filesystem/filesystem.h4
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp28
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.h1
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp41
-rw-r--r--src/core/hle/service/hid/controllers/npad.h4
-rw-r--r--src/video_core/engines/maxwell_3d.h67
-rw-r--r--src/yuzu/main.cpp7
15 files changed, 304 insertions, 50 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 66de33799..949748178 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -41,6 +41,7 @@ add_library(core STATIC
41 file_sys/bis_factory.h 41 file_sys/bis_factory.h
42 file_sys/card_image.cpp 42 file_sys/card_image.cpp
43 file_sys/card_image.h 43 file_sys/card_image.h
44 file_sys/common_funcs.h
44 file_sys/content_archive.cpp 45 file_sys/content_archive.cpp
45 file_sys/content_archive.h 46 file_sys/content_archive.h
46 file_sys/control_metadata.cpp 47 file_sys/control_metadata.cpp
diff --git a/src/core/file_sys/common_funcs.h b/src/core/file_sys/common_funcs.h
new file mode 100644
index 000000000..7ed97aa50
--- /dev/null
+++ b/src/core/file_sys/common_funcs.h
@@ -0,0 +1,56 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9namespace FileSys {
10
11constexpr u64 AOC_TITLE_ID_MASK = 0x7FF;
12constexpr u64 AOC_TITLE_ID_OFFSET = 0x1000;
13constexpr u64 BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000;
14
15/**
16 * Gets the base title ID from a given title ID.
17 *
18 * @param title_id The title ID.
19 * @returns The base title ID.
20 */
21[[nodiscard]] constexpr u64 GetBaseTitleID(u64 title_id) {
22 return title_id & BASE_TITLE_ID_MASK;
23}
24
25/**
26 * Gets the base title ID with a program index offset from a given title ID.
27 *
28 * @param title_id The title ID.
29 * @param program_index The program index.
30 * @returns The base title ID with a program index offset.
31 */
32[[nodiscard]] constexpr u64 GetBaseTitleIDWithProgramIndex(u64 title_id, u64 program_index) {
33 return GetBaseTitleID(title_id) + program_index;
34}
35
36/**
37 * Gets the AOC (Add-On Content) base title ID from a given title ID.
38 *
39 * @param title_id The title ID.
40 * @returns The AOC base title ID.
41 */
42[[nodiscard]] constexpr u64 GetAOCBaseTitleID(u64 title_id) {
43 return GetBaseTitleID(title_id) + AOC_TITLE_ID_OFFSET;
44}
45
46/**
47 * Gets the AOC (Add-On Content) ID from a given AOC title ID.
48 *
49 * @param aoc_title_id The AOC title ID.
50 * @returns The AOC ID.
51 */
52[[nodiscard]] constexpr u64 GetAOCID(u64 aoc_title_id) {
53 return aoc_title_id & AOC_TITLE_ID_MASK;
54}
55
56} // namespace FileSys
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index e9d1607d0..7c3284df8 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -12,6 +12,7 @@
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "common/string_util.h" 13#include "common/string_util.h"
14#include "core/core.h" 14#include "core/core.h"
15#include "core/file_sys/common_funcs.h"
15#include "core/file_sys/content_archive.h" 16#include "core/file_sys/content_archive.h"
16#include "core/file_sys/control_metadata.h" 17#include "core/file_sys/control_metadata.h"
17#include "core/file_sys/ips_layer.h" 18#include "core/file_sys/ips_layer.h"
@@ -30,7 +31,6 @@ namespace FileSys {
30namespace { 31namespace {
31 32
32constexpr u32 SINGLE_BYTE_MODULUS = 0x100; 33constexpr u32 SINGLE_BYTE_MODULUS = 0x100;
33constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000;
34 34
35constexpr std::array<const char*, 14> EXEFS_FILE_NAMES{ 35constexpr std::array<const char*, 14> EXEFS_FILE_NAMES{
36 "main", "main.npdm", "rtld", "sdk", "subsdk0", "subsdk1", "subsdk2", 36 "main", "main.npdm", "rtld", "sdk", "subsdk0", "subsdk1", "subsdk2",
@@ -532,7 +532,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
532 dlc_match.reserve(dlc_entries.size()); 532 dlc_match.reserve(dlc_entries.size());
533 std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match), 533 std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match),
534 [this](const ContentProviderEntry& entry) { 534 [this](const ContentProviderEntry& entry) {
535 return (entry.title_id & DLC_BASE_TITLE_ID_MASK) == title_id && 535 return GetBaseTitleID(entry.title_id) == title_id &&
536 content_provider.GetEntry(entry)->GetStatus() == 536 content_provider.GetEntry(entry)->GetStatus() ==
537 Loader::ResultStatus::Success; 537 Loader::ResultStatus::Success;
538 }); 538 });
diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp
index 987199747..f4e16e4be 100644
--- a/src/core/file_sys/romfs_factory.cpp
+++ b/src/core/file_sys/romfs_factory.cpp
@@ -7,6 +7,7 @@
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/file_sys/card_image.h" 9#include "core/file_sys/card_image.h"
10#include "core/file_sys/common_funcs.h"
10#include "core/file_sys/content_archive.h" 11#include "core/file_sys/content_archive.h"
11#include "core/file_sys/nca_metadata.h" 12#include "core/file_sys/nca_metadata.h"
12#include "core/file_sys/patch_manager.h" 13#include "core/file_sys/patch_manager.h"
@@ -47,6 +48,27 @@ ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_titl
47 patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw)); 48 patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw));
48} 49}
49 50
51ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecordType type) const {
52 auto nca = content_provider.GetEntry(title_id, type);
53
54 if (nca == nullptr) {
55 // TODO: Find the right error code to use here
56 return RESULT_UNKNOWN;
57 }
58
59 const PatchManager patch_manager{title_id, filesystem_controller, content_provider};
60
61 return MakeResult<VirtualFile>(
62 patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), type));
63}
64
65ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFSWithProgramIndex(
66 u64 title_id, u8 program_index, ContentRecordType type) const {
67 const auto res_title_id = GetBaseTitleIDWithProgramIndex(title_id, program_index);
68
69 return OpenPatchedRomFS(res_title_id, type);
70}
71
50ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage, 72ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage,
51 ContentRecordType type) const { 73 ContentRecordType type) const {
52 const std::shared_ptr<NCA> res = GetEntry(title_id, storage, type); 74 const std::shared_ptr<NCA> res = GetEntry(title_id, storage, type);
diff --git a/src/core/file_sys/romfs_factory.h b/src/core/file_sys/romfs_factory.h
index ec704dfa8..96dd0d578 100644
--- a/src/core/file_sys/romfs_factory.h
+++ b/src/core/file_sys/romfs_factory.h
@@ -42,6 +42,10 @@ public:
42 42
43 void SetPackedUpdate(VirtualFile update_raw); 43 void SetPackedUpdate(VirtualFile update_raw);
44 [[nodiscard]] ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const; 44 [[nodiscard]] ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const;
45 [[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFS(u64 title_id,
46 ContentRecordType type) const;
47 [[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFSWithProgramIndex(
48 u64 title_id, u8 program_index, ContentRecordType type) const;
45 [[nodiscard]] ResultVal<VirtualFile> Open(u64 title_id, StorageId storage, 49 [[nodiscard]] ResultVal<VirtualFile> Open(u64 title_id, StorageId storage,
46 ContentRecordType type) const; 50 ContentRecordType type) const;
47 51
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 6abac3f78..23e28565b 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -7,6 +7,7 @@
7#include <vector> 7#include <vector>
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/file_sys/common_funcs.h"
10#include "core/file_sys/content_archive.h" 11#include "core/file_sys/content_archive.h"
11#include "core/file_sys/control_metadata.h" 12#include "core/file_sys/control_metadata.h"
12#include "core/file_sys/nca_metadata.h" 13#include "core/file_sys/nca_metadata.h"
@@ -23,11 +24,8 @@
23 24
24namespace Service::AOC { 25namespace Service::AOC {
25 26
26constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000;
27constexpr u64 DLC_BASE_TO_AOC_ID = 0x1000;
28
29static bool CheckAOCTitleIDMatchesBase(u64 title_id, u64 base) { 27static bool CheckAOCTitleIDMatchesBase(u64 title_id, u64 base) {
30 return (title_id & DLC_BASE_TITLE_ID_MASK) == base; 28 return FileSys::GetBaseTitleID(title_id) == base;
31} 29}
32 30
33static std::vector<u64> AccumulateAOCTitleIDs(Core::System& system) { 31static std::vector<u64> AccumulateAOCTitleIDs(Core::System& system) {
@@ -48,6 +46,62 @@ static std::vector<u64> AccumulateAOCTitleIDs(Core::System& system) {
48 return add_on_content; 46 return add_on_content;
49} 47}
50 48
49class IPurchaseEventManager final : public ServiceFramework<IPurchaseEventManager> {
50public:
51 explicit IPurchaseEventManager(Core::System& system_)
52 : ServiceFramework{system_, "IPurchaseEventManager"} {
53 // clang-format off
54 static const FunctionInfo functions[] = {
55 {0, &IPurchaseEventManager::SetDefaultDeliveryTarget, "SetDefaultDeliveryTarget"},
56 {1, &IPurchaseEventManager::SetDeliveryTarget, "SetDeliveryTarget"},
57 {2, &IPurchaseEventManager::GetPurchasedEventReadableHandle, "GetPurchasedEventReadableHandle"},
58 {3, nullptr, "PopPurchasedProductInfo"},
59 {4, nullptr, "PopPurchasedProductInfoWithUid"},
60 };
61 // clang-format on
62
63 RegisterHandlers(functions);
64
65 purchased_event = Kernel::WritableEvent::CreateEventPair(
66 system.Kernel(), "IPurchaseEventManager:PurchasedEvent");
67 }
68
69private:
70 void SetDefaultDeliveryTarget(Kernel::HLERequestContext& ctx) {
71 IPC::RequestParser rp{ctx};
72
73 const auto unknown_1 = rp.Pop<u64>();
74 [[maybe_unused]] const auto unknown_2 = ctx.ReadBuffer();
75
76 LOG_WARNING(Service_AOC, "(STUBBED) called, unknown_1={}", unknown_1);
77
78 IPC::ResponseBuilder rb{ctx, 2};
79 rb.Push(RESULT_SUCCESS);
80 }
81
82 void SetDeliveryTarget(Kernel::HLERequestContext& ctx) {
83 IPC::RequestParser rp{ctx};
84
85 const auto unknown_1 = rp.Pop<u64>();
86 [[maybe_unused]] const auto unknown_2 = ctx.ReadBuffer();
87
88 LOG_WARNING(Service_AOC, "(STUBBED) called, unknown_1={}", unknown_1);
89
90 IPC::ResponseBuilder rb{ctx, 2};
91 rb.Push(RESULT_SUCCESS);
92 }
93
94 void GetPurchasedEventReadableHandle(Kernel::HLERequestContext& ctx) {
95 LOG_WARNING(Service_AOC, "called");
96
97 IPC::ResponseBuilder rb{ctx, 2, 1};
98 rb.Push(RESULT_SUCCESS);
99 rb.PushCopyObjects(purchased_event.readable);
100 }
101
102 Kernel::EventPair purchased_event;
103};
104
51AOC_U::AOC_U(Core::System& system_) 105AOC_U::AOC_U(Core::System& system_)
52 : ServiceFramework{system_, "aoc:u"}, add_on_content{AccumulateAOCTitleIDs(system)} { 106 : ServiceFramework{system_, "aoc:u"}, add_on_content{AccumulateAOCTitleIDs(system)} {
53 // clang-format off 107 // clang-format off
@@ -62,8 +116,8 @@ AOC_U::AOC_U(Core::System& system_)
62 {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"}, 116 {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"},
63 {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"}, 117 {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"},
64 {9, nullptr, "GetAddOnContentLostErrorCode"}, 118 {9, nullptr, "GetAddOnContentLostErrorCode"},
65 {100, nullptr, "CreateEcPurchasedEventManager"}, 119 {100, &AOC_U::CreateEcPurchasedEventManager, "CreateEcPurchasedEventManager"},
66 {101, nullptr, "CreatePermanentEcPurchasedEventManager"}, 120 {101, &AOC_U::CreatePermanentEcPurchasedEventManager, "CreatePermanentEcPurchasedEventManager"},
67 }; 121 };
68 // clang-format on 122 // clang-format on
69 123
@@ -123,11 +177,11 @@ void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) {
123 const auto& disabled = Settings::values.disabled_addons[current]; 177 const auto& disabled = Settings::values.disabled_addons[current];
124 if (std::find(disabled.begin(), disabled.end(), "DLC") == disabled.end()) { 178 if (std::find(disabled.begin(), disabled.end(), "DLC") == disabled.end()) {
125 for (u64 content_id : add_on_content) { 179 for (u64 content_id : add_on_content) {
126 if ((content_id & DLC_BASE_TITLE_ID_MASK) != current) { 180 if (FileSys::GetBaseTitleID(content_id) != current) {
127 continue; 181 continue;
128 } 182 }
129 183
130 out.push_back(static_cast<u32>(content_id & 0x7FF)); 184 out.push_back(static_cast<u32>(FileSys::GetAOCID(content_id)));
131 } 185 }
132 } 186 }
133 187
@@ -169,7 +223,7 @@ void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) {
169 223
170 const auto res = pm.GetControlMetadata(); 224 const auto res = pm.GetControlMetadata();
171 if (res.first == nullptr) { 225 if (res.first == nullptr) {
172 rb.Push(title_id + DLC_BASE_TO_AOC_ID); 226 rb.Push(FileSys::GetAOCBaseTitleID(title_id));
173 return; 227 return;
174 } 228 }
175 229
@@ -201,6 +255,22 @@ void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) {
201 rb.PushCopyObjects(aoc_change_event.readable); 255 rb.PushCopyObjects(aoc_change_event.readable);
202} 256}
203 257
258void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) {
259 LOG_WARNING(Service_AOC, "(STUBBED) called");
260
261 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
262 rb.Push(RESULT_SUCCESS);
263 rb.PushIpcInterface<IPurchaseEventManager>(system);
264}
265
266void AOC_U::CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx) {
267 LOG_WARNING(Service_AOC, "(STUBBED) called");
268
269 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
270 rb.Push(RESULT_SUCCESS);
271 rb.PushIpcInterface<IPurchaseEventManager>(system);
272}
273
204void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { 274void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
205 std::make_shared<AOC_U>(system)->InstallAsService(service_manager); 275 std::make_shared<AOC_U>(system)->InstallAsService(service_manager);
206} 276}
diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h
index 7628f4568..26ee51be0 100644
--- a/src/core/hle/service/aoc/aoc_u.h
+++ b/src/core/hle/service/aoc/aoc_u.h
@@ -27,6 +27,8 @@ private:
27 void GetAddOnContentBaseId(Kernel::HLERequestContext& ctx); 27 void GetAddOnContentBaseId(Kernel::HLERequestContext& ctx);
28 void PrepareAddOnContent(Kernel::HLERequestContext& ctx); 28 void PrepareAddOnContent(Kernel::HLERequestContext& ctx);
29 void GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx); 29 void GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx);
30 void CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx);
31 void CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx);
30 32
31 std::vector<u64> add_on_content; 33 std::vector<u64> add_on_content;
32 Kernel::EventPair aoc_change_event; 34 Kernel::EventPair aoc_change_event;
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 6af818b5a..b15c737e1 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -298,6 +298,31 @@ ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFSCurrentProcess()
298 return romfs_factory->OpenCurrentProcess(system.CurrentProcess()->GetTitleID()); 298 return romfs_factory->OpenCurrentProcess(system.CurrentProcess()->GetTitleID());
299} 299}
300 300
301ResultVal<FileSys::VirtualFile> FileSystemController::OpenPatchedRomFS(
302 u64 title_id, FileSys::ContentRecordType type) const {
303 LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}", title_id);
304
305 if (romfs_factory == nullptr) {
306 // TODO: Find a better error code for this
307 return RESULT_UNKNOWN;
308 }
309
310 return romfs_factory->OpenPatchedRomFS(title_id, type);
311}
312
313ResultVal<FileSys::VirtualFile> FileSystemController::OpenPatchedRomFSWithProgramIndex(
314 u64 title_id, u8 program_index, FileSys::ContentRecordType type) const {
315 LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}, program_index={}", title_id,
316 program_index);
317
318 if (romfs_factory == nullptr) {
319 // TODO: Find a better error code for this
320 return RESULT_UNKNOWN;
321 }
322
323 return romfs_factory->OpenPatchedRomFSWithProgramIndex(title_id, program_index, type);
324}
325
301ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFS( 326ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFS(
302 u64 title_id, FileSys::StorageId storage_id, FileSys::ContentRecordType type) const { 327 u64 title_id, FileSys::StorageId storage_id, FileSys::ContentRecordType type) const {
303 LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}, storage_id={:02X}, type={:02X}", 328 LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}, storage_id={:02X}, type={:02X}",
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 6dbbf0b2b..7102d3f9a 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -66,6 +66,10 @@ public:
66 66
67 void SetPackedUpdate(FileSys::VirtualFile update_raw); 67 void SetPackedUpdate(FileSys::VirtualFile update_raw);
68 ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() const; 68 ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() const;
69 ResultVal<FileSys::VirtualFile> OpenPatchedRomFS(u64 title_id,
70 FileSys::ContentRecordType type) const;
71 ResultVal<FileSys::VirtualFile> OpenPatchedRomFSWithProgramIndex(
72 u64 title_id, u8 program_index, FileSys::ContentRecordType type) const;
69 ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id, 73 ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
70 FileSys::ContentRecordType type) const; 74 FileSys::ContentRecordType type) const;
71 ResultVal<FileSys::VirtualDir> CreateSaveData( 75 ResultVal<FileSys::VirtualDir> CreateSaveData(
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index ef15160bf..9cc260515 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -717,7 +717,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
717 {202, &FSP_SRV::OpenDataStorageByDataId, "OpenDataStorageByDataId"}, 717 {202, &FSP_SRV::OpenDataStorageByDataId, "OpenDataStorageByDataId"},
718 {203, &FSP_SRV::OpenPatchDataStorageByCurrentProcess, "OpenPatchDataStorageByCurrentProcess"}, 718 {203, &FSP_SRV::OpenPatchDataStorageByCurrentProcess, "OpenPatchDataStorageByCurrentProcess"},
719 {204, nullptr, "OpenDataFileSystemByProgramIndex"}, 719 {204, nullptr, "OpenDataFileSystemByProgramIndex"},
720 {205, nullptr, "OpenDataStorageByProgramIndex"}, 720 {205, &FSP_SRV::OpenDataStorageWithProgramIndex, "OpenDataStorageWithProgramIndex"},
721 {400, nullptr, "OpenDeviceOperator"}, 721 {400, nullptr, "OpenDeviceOperator"},
722 {500, nullptr, "OpenSdCardDetectionEventNotifier"}, 722 {500, nullptr, "OpenSdCardDetectionEventNotifier"},
723 {501, nullptr, "OpenGameCardDetectionEventNotifier"}, 723 {501, nullptr, "OpenGameCardDetectionEventNotifier"},
@@ -994,6 +994,32 @@ void FSP_SRV::OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ct
994 rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); 994 rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
995} 995}
996 996
997void FSP_SRV::OpenDataStorageWithProgramIndex(Kernel::HLERequestContext& ctx) {
998 IPC::RequestParser rp{ctx};
999
1000 const auto program_index = rp.PopRaw<u8>();
1001
1002 LOG_DEBUG(Service_FS, "called, program_index={}", program_index);
1003
1004 auto romfs = fsc.OpenPatchedRomFSWithProgramIndex(
1005 system.CurrentProcess()->GetTitleID(), program_index, FileSys::ContentRecordType::Program);
1006
1007 if (romfs.Failed()) {
1008 // TODO: Find the right error code to use here
1009 LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index);
1010
1011 IPC::ResponseBuilder rb{ctx, 2};
1012 rb.Push(RESULT_UNKNOWN);
1013 return;
1014 }
1015
1016 auto storage = std::make_shared<IStorage>(system, std::move(romfs.Unwrap()));
1017
1018 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1019 rb.Push(RESULT_SUCCESS);
1020 rb.PushIpcInterface<IStorage>(std::move(storage));
1021}
1022
997void FSP_SRV::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { 1023void FSP_SRV::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
998 IPC::RequestParser rp{ctx}; 1024 IPC::RequestParser rp{ctx};
999 log_mode = rp.PopEnum<LogMode>(); 1025 log_mode = rp.PopEnum<LogMode>();
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index 472286d6e..8ed933279 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -49,6 +49,7 @@ private:
49 void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); 49 void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
50 void OpenDataStorageByDataId(Kernel::HLERequestContext& ctx); 50 void OpenDataStorageByDataId(Kernel::HLERequestContext& ctx);
51 void OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); 51 void OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
52 void OpenDataStorageWithProgramIndex(Kernel::HLERequestContext& ctx);
52 void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); 53 void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
53 void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); 54 void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
54 void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx); 55 void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 66c4fe60a..f6a0770bf 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -116,6 +116,31 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) {
116 } 116 }
117} 117}
118 118
119bool Controller_NPad::IsNpadIdValid(u32 npad_id) {
120 switch (npad_id) {
121 case 0:
122 case 1:
123 case 2:
124 case 3:
125 case 4:
126 case 5:
127 case 6:
128 case 7:
129 case NPAD_UNKNOWN:
130 case NPAD_HANDHELD:
131 return true;
132 default:
133 LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
134 return false;
135 }
136}
137
138bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) {
139 return IsNpadIdValid(device_handle.npad_id) &&
140 device_handle.npad_type < NpadType::MaxNpadType &&
141 device_handle.device_index < DeviceIndex::MaxDeviceIndex;
142}
143
119Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} 144Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {}
120 145
121Controller_NPad::~Controller_NPad() { 146Controller_NPad::~Controller_NPad() {
@@ -742,6 +767,10 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size
742 767
743void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, 768void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle,
744 const VibrationValue& vibration_value) { 769 const VibrationValue& vibration_value) {
770 if (!IsDeviceHandleValid(vibration_device_handle)) {
771 return;
772 }
773
745 if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { 774 if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
746 return; 775 return;
747 } 776 }
@@ -798,12 +827,20 @@ void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibrat
798 827
799Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( 828Controller_NPad::VibrationValue Controller_NPad::GetLastVibration(
800 const DeviceHandle& vibration_device_handle) const { 829 const DeviceHandle& vibration_device_handle) const {
830 if (!IsDeviceHandleValid(vibration_device_handle)) {
831 return {};
832 }
833
801 const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); 834 const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
802 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); 835 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
803 return latest_vibration_values[npad_index][device_index]; 836 return latest_vibration_values[npad_index][device_index];
804} 837}
805 838
806void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { 839void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) {
840 if (!IsDeviceHandleValid(vibration_device_handle)) {
841 return;
842 }
843
807 const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); 844 const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
808 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); 845 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
809 InitializeVibrationDeviceAtIndex(npad_index, device_index); 846 InitializeVibrationDeviceAtIndex(npad_index, device_index);
@@ -824,6 +861,10 @@ void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
824} 861}
825 862
826bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const { 863bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const {
864 if (!IsDeviceHandleValid(vibration_device_handle)) {
865 return false;
866 }
867
827 const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); 868 const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
828 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); 869 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
829 return vibration_devices_mounted[npad_index][device_index]; 870 return vibration_devices_mounted[npad_index][device_index];
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 96f319294..9fac00231 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -56,12 +56,14 @@ public:
56 JoyconLeft = 6, 56 JoyconLeft = 6,
57 JoyconRight = 7, 57 JoyconRight = 7,
58 Pokeball = 9, 58 Pokeball = 9,
59 MaxNpadType = 10,
59 }; 60 };
60 61
61 enum class DeviceIndex : u8 { 62 enum class DeviceIndex : u8 {
62 Left = 0, 63 Left = 0,
63 Right = 1, 64 Right = 1,
64 None = 2, 65 None = 2,
66 MaxDeviceIndex = 3,
65 }; 67 };
66 68
67 enum class GyroscopeZeroDriftMode : u32 { 69 enum class GyroscopeZeroDriftMode : u32 {
@@ -213,6 +215,8 @@ public:
213 static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); 215 static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type);
214 static std::size_t NPadIdToIndex(u32 npad_id); 216 static std::size_t NPadIdToIndex(u32 npad_id);
215 static u32 IndexToNPad(std::size_t index); 217 static u32 IndexToNPad(std::size_t index);
218 static bool IsNpadIdValid(u32 npad_id);
219 static bool IsDeviceHandleValid(const DeviceHandle& device_handle);
216 220
217private: 221private:
218 struct CommonHeader { 222 struct CommonHeader {
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index b0d9559d0..564acbc53 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -1473,39 +1473,6 @@ private:
1473 1473
1474 void ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument, bool is_last_call); 1474 void ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument, bool is_last_call);
1475 1475
1476 Core::System& system;
1477 MemoryManager& memory_manager;
1478
1479 VideoCore::RasterizerInterface* rasterizer = nullptr;
1480
1481 /// Start offsets of each macro in macro_memory
1482 std::array<u32, 0x80> macro_positions = {};
1483
1484 std::array<bool, Regs::NUM_REGS> mme_inline{};
1485
1486 /// Macro method that is currently being executed / being fed parameters.
1487 u32 executing_macro = 0;
1488 /// Parameters that have been submitted to the macro call so far.
1489 std::vector<u32> macro_params;
1490
1491 /// Interpreter for the macro codes uploaded to the GPU.
1492 std::unique_ptr<MacroEngine> macro_engine;
1493
1494 static constexpr u32 null_cb_data = 0xFFFFFFFF;
1495 struct {
1496 std::array<std::array<u32, 0x4000>, 16> buffer;
1497 u32 current{null_cb_data};
1498 u32 id{null_cb_data};
1499 u32 start_pos{};
1500 u32 counter{};
1501 } cb_data_state;
1502
1503 Upload::State upload_state;
1504
1505 bool execute_on{true};
1506
1507 std::array<u8, Regs::NUM_REGS> dirty_pointers{};
1508
1509 /// Retrieves information about a specific TIC entry from the TIC buffer. 1476 /// Retrieves information about a specific TIC entry from the TIC buffer.
1510 Texture::TICEntry GetTICEntry(u32 tic_index) const; 1477 Texture::TICEntry GetTICEntry(u32 tic_index) const;
1511 1478
@@ -1514,8 +1481,8 @@ private:
1514 1481
1515 /** 1482 /**
1516 * Call a macro on this engine. 1483 * Call a macro on this engine.
1484 *
1517 * @param method Method to call 1485 * @param method Method to call
1518 * @param num_parameters Number of arguments
1519 * @param parameters Arguments to the method call 1486 * @param parameters Arguments to the method call
1520 */ 1487 */
1521 void CallMacroMethod(u32 method, const std::vector<u32>& parameters); 1488 void CallMacroMethod(u32 method, const std::vector<u32>& parameters);
@@ -1564,6 +1531,38 @@ private:
1564 1531
1565 /// Returns a query's value or an empty object if the value will be deferred through a cache. 1532 /// Returns a query's value or an empty object if the value will be deferred through a cache.
1566 std::optional<u64> GetQueryResult(); 1533 std::optional<u64> GetQueryResult();
1534
1535 Core::System& system;
1536 MemoryManager& memory_manager;
1537
1538 VideoCore::RasterizerInterface* rasterizer = nullptr;
1539
1540 /// Start offsets of each macro in macro_memory
1541 std::array<u32, 0x80> macro_positions{};
1542
1543 std::array<bool, Regs::NUM_REGS> mme_inline{};
1544
1545 /// Macro method that is currently being executed / being fed parameters.
1546 u32 executing_macro = 0;
1547 /// Parameters that have been submitted to the macro call so far.
1548 std::vector<u32> macro_params;
1549
1550 /// Interpreter for the macro codes uploaded to the GPU.
1551 std::unique_ptr<MacroEngine> macro_engine;
1552
1553 static constexpr u32 null_cb_data = 0xFFFFFFFF;
1554 struct CBDataState {
1555 std::array<std::array<u32, 0x4000>, 16> buffer;
1556 u32 current{null_cb_data};
1557 u32 id{null_cb_data};
1558 u32 start_pos{};
1559 u32 counter{};
1560 };
1561 CBDataState cb_data_state;
1562
1563 Upload::State upload_state;
1564
1565 bool execute_on{true};
1567}; 1566};
1568 1567
1569#define ASSERT_REG_POSITION(field_name, position) \ 1568#define ASSERT_REG_POSITION(field_name, position) \
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 26f5e42ed..3461fa675 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -83,6 +83,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
83#include "core/core.h" 83#include "core/core.h"
84#include "core/crypto/key_manager.h" 84#include "core/crypto/key_manager.h"
85#include "core/file_sys/card_image.h" 85#include "core/file_sys/card_image.h"
86#include "core/file_sys/common_funcs.h"
86#include "core/file_sys/content_archive.h" 87#include "core/file_sys/content_archive.h"
87#include "core/file_sys/control_metadata.h" 88#include "core/file_sys/control_metadata.h"
88#include "core/file_sys/patch_manager.h" 89#include "core/file_sys/patch_manager.h"
@@ -148,8 +149,6 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
148 149
149constexpr int default_mouse_timeout = 2500; 150constexpr int default_mouse_timeout = 2500;
150 151
151constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000;
152
153/** 152/**
154 * "Callouts" are one-time instructional messages shown to the user. In the config settings, there 153 * "Callouts" are one-time instructional messages shown to the user. In the config settings, there
155 * is a bitfield "callout_flags" options, used to track if a message has already been shown to the 154 * is a bitfield "callout_flags" options, used to track if a message has already been shown to the
@@ -1529,7 +1528,7 @@ void GMainWindow::RemoveAddOnContent(u64 program_id, const QString& entry_type)
1529 FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); 1528 FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
1530 1529
1531 for (const auto& entry : dlc_entries) { 1530 for (const auto& entry : dlc_entries) {
1532 if ((entry.title_id & DLC_BASE_TITLE_ID_MASK) == program_id) { 1531 if (FileSys::GetBaseTitleID(entry.title_id) == program_id) {
1533 const auto res = 1532 const auto res =
1534 fs_controller.GetUserNANDContents()->RemoveExistingEntry(entry.title_id) || 1533 fs_controller.GetUserNANDContents()->RemoveExistingEntry(entry.title_id) ||
1535 fs_controller.GetSDMCContents()->RemoveExistingEntry(entry.title_id); 1534 fs_controller.GetSDMCContents()->RemoveExistingEntry(entry.title_id);
@@ -2709,7 +2708,7 @@ std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProv
2709 dlc_match.reserve(dlc_entries.size()); 2708 dlc_match.reserve(dlc_entries.size());
2710 std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match), 2709 std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match),
2711 [&program_id, &installed](const FileSys::ContentProviderEntry& entry) { 2710 [&program_id, &installed](const FileSys::ContentProviderEntry& entry) {
2712 return (entry.title_id & DLC_BASE_TITLE_ID_MASK) == program_id && 2711 return FileSys::GetBaseTitleID(entry.title_id) == program_id &&
2713 installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success; 2712 installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success;
2714 }); 2713 });
2715 2714