summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/file_sys/control_metadata.cpp4
-rw-r--r--src/core/file_sys/control_metadata.h1
-rw-r--r--src/core/file_sys/savedata_factory.cpp9
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp38
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.h1
-rw-r--r--src/yuzu/game_list.cpp8
-rw-r--r--src/yuzu/game_list.h2
-rw-r--r--src/yuzu/main.cpp64
-rw-r--r--src/yuzu/main.h2
9 files changed, 98 insertions, 31 deletions
diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp
index f155a1341..63cd2eead 100644
--- a/src/core/file_sys/control_metadata.cpp
+++ b/src/core/file_sys/control_metadata.cpp
@@ -95,6 +95,10 @@ u32 NACP::GetSupportedLanguages() const {
95 return raw.supported_languages; 95 return raw.supported_languages;
96} 96}
97 97
98u64 NACP::GetDeviceSaveDataSize() const {
99 return raw.device_save_data_size;
100}
101
98std::vector<u8> NACP::GetRawBytes() const { 102std::vector<u8> NACP::GetRawBytes() const {
99 std::vector<u8> out(sizeof(RawNACP)); 103 std::vector<u8> out(sizeof(RawNACP));
100 std::memcpy(out.data(), &raw, sizeof(RawNACP)); 104 std::memcpy(out.data(), &raw, sizeof(RawNACP));
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h
index 2d8c251ac..e37b2fadf 100644
--- a/src/core/file_sys/control_metadata.h
+++ b/src/core/file_sys/control_metadata.h
@@ -113,6 +113,7 @@ public:
113 u32 GetSupportedLanguages() const; 113 u32 GetSupportedLanguages() const;
114 std::vector<u8> GetRawBytes() const; 114 std::vector<u8> GetRawBytes() const;
115 bool GetUserAccountSwitchLock() const; 115 bool GetUserAccountSwitchLock() const;
116 u64 GetDeviceSaveDataSize() const;
116 117
117private: 118private:
118 RawNACP raw{}; 119 RawNACP raw{};
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index f3def93ab..adfd2c1a4 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -57,7 +57,8 @@ void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) {
57bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataDescriptor& desc) { 57bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataDescriptor& desc) {
58 return desc.type == SaveDataType::CacheStorage || desc.type == SaveDataType::TemporaryStorage || 58 return desc.type == SaveDataType::CacheStorage || desc.type == SaveDataType::TemporaryStorage ||
59 (space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User 59 (space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User
60 desc.type == SaveDataType::SaveData && desc.title_id == 0 && desc.save_id == 0); 60 (desc.type == SaveDataType::SaveData || desc.type == SaveDataType::DeviceSaveData) &&
61 desc.title_id == 0 && desc.save_id == 0);
61} 62}
62 63
63} // Anonymous namespace 64} // Anonymous namespace
@@ -139,8 +140,10 @@ std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType typ
139 u128 user_id, u64 save_id) { 140 u128 user_id, u64 save_id) {
140 // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should 141 // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should
141 // be interpreted as the title id of the current process. 142 // be interpreted as the title id of the current process.
142 if (type == SaveDataType::SaveData && title_id == 0) { 143 if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) {
143 title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID(); 144 if (title_id == 0) {
145 title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID();
146 }
144 } 147 }
145 148
146 std::string out = GetSaveDataSpaceIdPath(space); 149 std::string out = GetSaveDataSpaceIdPath(space);
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index f6503fe2f..20c331b77 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -767,7 +767,7 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
767 {1014, nullptr, "OutputMultiProgramTagAccessLog"}, 767 {1014, nullptr, "OutputMultiProgramTagAccessLog"},
768 {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"}, 768 {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"},
769 {1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"}, 769 {1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"},
770 {1200, nullptr, "OpenMultiCommitManager"}, 770 {1200, &FSP_SRV::OpenMultiCommitManager, "OpenMultiCommitManager"},
771 {1300, nullptr, "OpenBisWiper"}, 771 {1300, nullptr, "OpenBisWiper"},
772 }; 772 };
773 // clang-format on 773 // clang-format on
@@ -988,4 +988,40 @@ void FSP_SRV::GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx) {
988 rb.Push(access_log_program_index); 988 rb.Push(access_log_program_index);
989} 989}
990 990
991class IMultiCommitManager final : public ServiceFramework<IMultiCommitManager> {
992public:
993 explicit IMultiCommitManager() : ServiceFramework("IMultiCommitManager") {
994 static const FunctionInfo functions[] = {
995 {1, &IMultiCommitManager::Add, "Add"},
996 {2, &IMultiCommitManager::Commit, "Commit"},
997 };
998 RegisterHandlers(functions);
999 }
1000
1001private:
1002 FileSys::VirtualFile backend;
1003
1004 void Add(Kernel::HLERequestContext& ctx) {
1005 LOG_WARNING(Service_FS, "(STUBBED) called");
1006
1007 IPC::ResponseBuilder rb{ctx, 2};
1008 rb.Push(RESULT_SUCCESS);
1009 }
1010
1011 void Commit(Kernel::HLERequestContext& ctx) {
1012 LOG_WARNING(Service_FS, "(STUBBED) called");
1013
1014 IPC::ResponseBuilder rb{ctx, 2};
1015 rb.Push(RESULT_SUCCESS);
1016 }
1017};
1018
1019void FSP_SRV::OpenMultiCommitManager(Kernel::HLERequestContext& ctx) {
1020 LOG_DEBUG(Service_FS, "called");
1021
1022 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1023 rb.Push(RESULT_SUCCESS);
1024 rb.PushIpcInterface<IMultiCommitManager>(std::make_shared<IMultiCommitManager>());
1025}
1026
991} // namespace Service::FileSystem 1027} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index d52b55999..dfb3e395b 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -50,6 +50,7 @@ private:
50 void OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); 50 void OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
51 void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx); 51 void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx);
52 void GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx); 52 void GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx);
53 void OpenMultiCommitManager(Kernel::HLERequestContext& ctx);
53 54
54 FileSystemController& fsc; 55 FileSystemController& fsc;
55 56
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index dccbabcbf..bfb600df0 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -488,11 +488,11 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, std::string pat
488 auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id); 488 auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
489 navigate_to_gamedb_entry->setVisible(it != compatibility_list.end() && program_id != 0); 489 navigate_to_gamedb_entry->setVisible(it != compatibility_list.end() && program_id != 0);
490 490
491 connect(open_save_location, &QAction::triggered, [this, program_id]() { 491 connect(open_save_location, &QAction::triggered, [this, program_id, path]() {
492 emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData); 492 emit OpenFolderRequested(GameListOpenTarget::SaveData, path);
493 }); 493 });
494 connect(open_lfs_location, &QAction::triggered, [this, program_id]() { 494 connect(open_lfs_location, &QAction::triggered, [this, program_id, path]() {
495 emit OpenFolderRequested(program_id, GameListOpenTarget::ModData); 495 emit OpenFolderRequested(GameListOpenTarget::ModData, path);
496 }); 496 });
497 connect(open_transferable_shader_cache, &QAction::triggered, 497 connect(open_transferable_shader_cache, &QAction::triggered,
498 [this, program_id]() { emit OpenTransferableShaderCacheRequested(program_id); }); 498 [this, program_id]() { emit OpenTransferableShaderCacheRequested(program_id); });
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index 878d94413..a38cb2fc3 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -73,7 +73,7 @@ public:
73signals: 73signals:
74 void GameChosen(QString game_path); 74 void GameChosen(QString game_path);
75 void ShouldCancelWorker(); 75 void ShouldCancelWorker();
76 void OpenFolderRequested(u64 program_id, GameListOpenTarget target); 76 void OpenFolderRequested(GameListOpenTarget target, const std::string& game_path);
77 void OpenTransferableShaderCacheRequested(u64 program_id); 77 void OpenTransferableShaderCacheRequested(u64 program_id);
78 void DumpRomFSRequested(u64 program_id, const std::string& game_path); 78 void DumpRomFSRequested(u64 program_id, const std::string& game_path);
79 void CopyTIDRequested(u64 program_id); 79 void CopyTIDRequested(u64 program_id);
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index dd6e5173e..0b291c7d0 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1155,39 +1155,61 @@ void GMainWindow::OnGameListLoadFile(QString game_path) {
1155 BootGame(game_path); 1155 BootGame(game_path);
1156} 1156}
1157 1157
1158void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target) { 1158void GMainWindow::OnGameListOpenFolder(GameListOpenTarget target, const std::string& game_path) {
1159 std::string path; 1159 std::string path;
1160 QString open_target; 1160 QString open_target;
1161
1162 const auto v_file = Core::GetGameFileFromPath(vfs, game_path);
1163 const auto loader = Loader::GetLoader(v_file);
1164 FileSys::NACP control{};
1165 u64 program_id{};
1166
1167 loader->ReadControlData(control);
1168 loader->ReadProgramId(program_id);
1169
1170 const bool has_user_save{control.GetDefaultNormalSaveSize() > 0};
1171 const bool has_device_save{control.GetDeviceSaveDataSize() > 0};
1172
1173 ASSERT_MSG(has_user_save != has_device_save, "Game uses both user and device savedata?");
1174
1161 switch (target) { 1175 switch (target) {
1162 case GameListOpenTarget::SaveData: { 1176 case GameListOpenTarget::SaveData: {
1163 open_target = tr("Save Data"); 1177 open_target = tr("Save Data");
1164 const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); 1178 const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir);
1165 ASSERT(program_id != 0); 1179 ASSERT(program_id != 0);
1166 1180
1167 const auto select_profile = [this] { 1181 if (has_user_save) {
1168 QtProfileSelectionDialog dialog(this); 1182 // User save data
1169 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | 1183 const auto select_profile = [this] {
1170 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); 1184 QtProfileSelectionDialog dialog(this);
1171 dialog.setWindowModality(Qt::WindowModal); 1185 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
1186 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
1187 dialog.setWindowModality(Qt::WindowModal);
1172 1188
1173 if (dialog.exec() == QDialog::Rejected) { 1189 if (dialog.exec() == QDialog::Rejected) {
1174 return -1; 1190 return -1;
1175 } 1191 }
1176 1192
1177 return dialog.GetIndex(); 1193 return dialog.GetIndex();
1178 }; 1194 };
1179 1195
1180 const auto index = select_profile(); 1196 const auto index = select_profile();
1181 if (index == -1) { 1197 if (index == -1) {
1182 return; 1198 return;
1183 } 1199 }
1184 1200
1185 Service::Account::ProfileManager manager; 1201 Service::Account::ProfileManager manager;
1186 const auto user_id = manager.GetUser(static_cast<std::size_t>(index)); 1202 const auto user_id = manager.GetUser(static_cast<std::size_t>(index));
1187 ASSERT(user_id); 1203 ASSERT(user_id);
1188 path = nand_dir + FileSys::SaveDataFactory::GetFullPath(FileSys::SaveDataSpaceId::NandUser, 1204 path = nand_dir + FileSys::SaveDataFactory::GetFullPath(
1189 FileSys::SaveDataType::SaveData, 1205 FileSys::SaveDataSpaceId::NandUser,
1190 program_id, user_id->uuid, 0); 1206 FileSys::SaveDataType::SaveData, program_id, user_id->uuid, 0);
1207 } else {
1208 // Device save data
1209 path = nand_dir + FileSys::SaveDataFactory::GetFullPath(
1210 FileSys::SaveDataSpaceId::NandUser,
1211 FileSys::SaveDataType::SaveData, program_id, {}, 0);
1212 }
1191 1213
1192 if (!FileUtil::Exists(path)) { 1214 if (!FileUtil::Exists(path)) {
1193 FileUtil::CreateFullPath(path); 1215 FileUtil::CreateFullPath(path);
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 4bff4330c..4f4c8ddbe 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -183,7 +183,7 @@ private slots:
183 void OnMenuReportCompatibility(); 183 void OnMenuReportCompatibility();
184 /// Called whenever a user selects a game in the game list widget. 184 /// Called whenever a user selects a game in the game list widget.
185 void OnGameListLoadFile(QString game_path); 185 void OnGameListLoadFile(QString game_path);
186 void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target); 186 void OnGameListOpenFolder(GameListOpenTarget target, const std::string& game_path);
187 void OnTransferableShaderCacheOpenFile(u64 program_id); 187 void OnTransferableShaderCacheOpenFile(u64 program_id);
188 void OnGameListDumpRomFS(u64 program_id, const std::string& game_path); 188 void OnGameListDumpRomFS(u64 program_id, const std::string& game_path);
189 void OnGameListCopyTID(u64 program_id); 189 void OnGameListCopyTID(u64 program_id);