summaryrefslogtreecommitdiff
path: root/src/frontend_common
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend_common')
-rw-r--r--src/frontend_common/content_manager.h155
1 files changed, 144 insertions, 11 deletions
diff --git a/src/frontend_common/content_manager.h b/src/frontend_common/content_manager.h
index 23f2979db..0b0fee73e 100644
--- a/src/frontend_common/content_manager.h
+++ b/src/frontend_common/content_manager.h
@@ -11,10 +11,12 @@
11#include "core/file_sys/content_archive.h" 11#include "core/file_sys/content_archive.h"
12#include "core/file_sys/mode.h" 12#include "core/file_sys/mode.h"
13#include "core/file_sys/nca_metadata.h" 13#include "core/file_sys/nca_metadata.h"
14#include "core/file_sys/patch_manager.h"
14#include "core/file_sys/registered_cache.h" 15#include "core/file_sys/registered_cache.h"
15#include "core/file_sys/submission_package.h" 16#include "core/file_sys/submission_package.h"
16#include "core/hle/service/filesystem/filesystem.h" 17#include "core/hle/service/filesystem/filesystem.h"
17#include "core/loader/loader.h" 18#include "core/loader/loader.h"
19#include "core/loader/nca.h"
18 20
19namespace ContentManager { 21namespace ContentManager {
20 22
@@ -25,6 +27,12 @@ enum class InstallResult {
25 BaseInstallAttempted, 27 BaseInstallAttempted,
26}; 28};
27 29
30enum class GameVerificationResult {
31 Success,
32 Failed,
33 NotImplemented,
34};
35
28/** 36/**
29 * \brief Removes a single installed DLC 37 * \brief Removes a single installed DLC
30 * \param fs_controller [FileSystemController] reference from the Core::System instance 38 * \param fs_controller [FileSystemController] reference from the Core::System instance
@@ -119,14 +127,14 @@ inline bool RemoveMod(const Service::FileSystem::FileSystemController& fs_contro
119 * \param system Raw pointer to the system instance 127 * \param system Raw pointer to the system instance
120 * \param vfs Raw pointer to the VfsFilesystem instance in Core::System 128 * \param vfs Raw pointer to the VfsFilesystem instance in Core::System
121 * \param filename Path to the NSP file 129 * \param filename Path to the NSP file
122 * \param callback Optional callback to report the progress of the installation. The first size_t 130 * \param callback Callback to report the progress of the installation. The first size_t
123 * parameter is the total size of the virtual file and the second is the current progress. If you 131 * parameter is the total size of the virtual file and the second is the current progress. If you
124 * return false to the callback, it will cancel the installation as soon as possible. 132 * return true to the callback, it will cancel the installation as soon as possible.
125 * \return [InstallResult] representing how the installation finished 133 * \return [InstallResult] representing how the installation finished
126 */ 134 */
127inline InstallResult InstallNSP( 135inline InstallResult InstallNSP(Core::System* system, FileSys::VfsFilesystem* vfs,
128 Core::System* system, FileSys::VfsFilesystem* vfs, const std::string& filename, 136 const std::string& filename,
129 const std::function<bool(size_t, size_t)>& callback = std::function<bool(size_t, size_t)>()) { 137 const std::function<bool(size_t, size_t)>& callback) {
130 const auto copy = [callback](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest, 138 const auto copy = [callback](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest,
131 std::size_t block_size) { 139 std::size_t block_size) {
132 if (src == nullptr || dest == nullptr) { 140 if (src == nullptr || dest == nullptr) {
@@ -184,15 +192,15 @@ inline InstallResult InstallNSP(
184 * \param filename Path to the NCA file 192 * \param filename Path to the NCA file
185 * \param registered_cache Raw pointer to the registered cache that the NCA will be installed to 193 * \param registered_cache Raw pointer to the registered cache that the NCA will be installed to
186 * \param title_type Type of NCA package to install 194 * \param title_type Type of NCA package to install
187 * \param callback Optional callback to report the progress of the installation. The first size_t 195 * \param callback Callback to report the progress of the installation. The first size_t
188 * parameter is the total size of the virtual file and the second is the current progress. If you 196 * parameter is the total size of the virtual file and the second is the current progress. If you
189 * return false to the callback, it will cancel the installation as soon as possible. 197 * return true to the callback, it will cancel the installation as soon as possible.
190 * \return [InstallResult] representing how the installation finished 198 * \return [InstallResult] representing how the installation finished
191 */ 199 */
192inline InstallResult InstallNCA( 200inline InstallResult InstallNCA(FileSys::VfsFilesystem* vfs, const std::string& filename,
193 FileSys::VfsFilesystem* vfs, const std::string& filename, 201 FileSys::RegisteredCache* registered_cache,
194 FileSys::RegisteredCache* registered_cache, const FileSys::TitleType title_type, 202 const FileSys::TitleType title_type,
195 const std::function<bool(size_t, size_t)>& callback = std::function<bool(size_t, size_t)>()) { 203 const std::function<bool(size_t, size_t)>& callback) {
196 const auto copy = [callback](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest, 204 const auto copy = [callback](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest,
197 std::size_t block_size) { 205 std::size_t block_size) {
198 if (src == nullptr || dest == nullptr) { 206 if (src == nullptr || dest == nullptr) {
@@ -235,4 +243,129 @@ inline InstallResult InstallNCA(
235 } 243 }
236} 244}
237 245
246/**
247 * \brief Verifies the installed contents for a given ManualContentProvider
248 * \param system Raw pointer to the system instance
249 * \param provider Raw pointer to the content provider that's tracking indexed games
250 * \param callback Callback to report the progress of the installation. The first size_t
251 * parameter is the total size of the installed contents and the second is the current progress. If
252 * you return true to the callback, it will cancel the installation as soon as possible.
253 * \return A list of entries that failed to install. Returns an empty vector if successful.
254 */
255inline std::vector<std::string> VerifyInstalledContents(
256 Core::System* system, FileSys::ManualContentProvider* provider,
257 const std::function<bool(size_t, size_t)>& callback) {
258 // Get content registries.
259 auto bis_contents = system->GetFileSystemController().GetSystemNANDContents();
260 auto user_contents = system->GetFileSystemController().GetUserNANDContents();
261
262 std::vector<FileSys::RegisteredCache*> content_providers;
263 if (bis_contents) {
264 content_providers.push_back(bis_contents);
265 }
266 if (user_contents) {
267 content_providers.push_back(user_contents);
268 }
269
270 // Get associated NCA files.
271 std::vector<FileSys::VirtualFile> nca_files;
272
273 // Get all installed IDs.
274 size_t total_size = 0;
275 for (auto nca_provider : content_providers) {
276 const auto entries = nca_provider->ListEntriesFilter();
277
278 for (const auto& entry : entries) {
279 auto nca_file = nca_provider->GetEntryRaw(entry.title_id, entry.type);
280 if (!nca_file) {
281 continue;
282 }
283
284 total_size += nca_file->GetSize();
285 nca_files.push_back(std::move(nca_file));
286 }
287 }
288
289 // Declare a list of file names which failed to verify.
290 std::vector<std::string> failed;
291
292 size_t processed_size = 0;
293 bool cancelled = false;
294 auto nca_callback = [&](size_t nca_processed, size_t nca_total) {
295 cancelled = callback(total_size, processed_size + nca_processed);
296 return !cancelled;
297 };
298
299 // Using the NCA loader, determine if all NCAs are valid.
300 for (auto& nca_file : nca_files) {
301 Loader::AppLoader_NCA nca_loader(nca_file);
302
303 auto status = nca_loader.VerifyIntegrity(nca_callback);
304 if (cancelled) {
305 break;
306 }
307 if (status != Loader::ResultStatus::Success) {
308 FileSys::NCA nca(nca_file);
309 const auto title_id = nca.GetTitleId();
310 std::string title_name = "unknown";
311
312 const auto control = provider->GetEntry(FileSys::GetBaseTitleID(title_id),
313 FileSys::ContentRecordType::Control);
314 if (control && control->GetStatus() == Loader::ResultStatus::Success) {
315 const FileSys::PatchManager pm{title_id, system->GetFileSystemController(),
316 *provider};
317 const auto [nacp, logo] = pm.ParseControlNCA(*control);
318 if (nacp) {
319 title_name = nacp->GetApplicationName();
320 }
321 }
322
323 if (title_id > 0) {
324 failed.push_back(
325 fmt::format("{} ({:016X}) ({})", nca_file->GetName(), title_id, title_name));
326 } else {
327 failed.push_back(fmt::format("{} (unknown)", nca_file->GetName()));
328 }
329 }
330
331 processed_size += nca_file->GetSize();
332 }
333 return failed;
334}
335
336/**
337 * \brief Verifies the contents of a given game
338 * \param system Raw pointer to the system instance
339 * \param game_path Patch to the game file
340 * \param callback Callback to report the progress of the installation. The first size_t
341 * parameter is the total size of the installed contents and the second is the current progress. If
342 * you return true to the callback, it will cancel the installation as soon as possible.
343 * \return GameVerificationResult representing how the verification process finished
344 */
345inline GameVerificationResult VerifyGameContents(
346 Core::System* system, const std::string& game_path,
347 const std::function<bool(size_t, size_t)>& callback) {
348 const auto loader = Loader::GetLoader(
349 *system, system->GetFilesystem()->OpenFile(game_path, FileSys::Mode::Read));
350 if (loader == nullptr) {
351 return GameVerificationResult::NotImplemented;
352 }
353
354 bool cancelled = false;
355 auto loader_callback = [&](size_t processed, size_t total) {
356 cancelled = callback(total, processed);
357 return !cancelled;
358 };
359
360 const auto status = loader->VerifyIntegrity(loader_callback);
361 if (cancelled || status == Loader::ResultStatus::ErrorIntegrityVerificationNotImplemented) {
362 return GameVerificationResult::NotImplemented;
363 }
364
365 if (status == Loader::ResultStatus::ErrorIntegrityVerificationFailed) {
366 return GameVerificationResult::Failed;
367 }
368 return GameVerificationResult::Success;
369}
370
238} // namespace ContentManager 371} // namespace ContentManager