From 10aac376d1d0fccb5b993bd3f95db42de0ceba12 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 9 Aug 2018 20:43:45 -0400 Subject: common: Move hex string processing to separate file --- src/common/CMakeLists.txt | 2 ++ src/common/hex_util.cpp | 27 +++++++++++++++++++++++++++ src/common/hex_util.h | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 src/common/hex_util.cpp create mode 100644 src/common/hex_util.h (limited to 'src/common') diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index d5d4f6f82..2ad456864 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -40,6 +40,8 @@ add_library(common STATIC file_util.cpp file_util.h hash.h + hex_util.cpp + hex_util.h logging/backend.cpp logging/backend.h logging/filter.cpp diff --git a/src/common/hex_util.cpp b/src/common/hex_util.cpp new file mode 100644 index 000000000..ae17c89d4 --- /dev/null +++ b/src/common/hex_util.cpp @@ -0,0 +1,27 @@ +// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/hex_util.h" + +u8 ToHexNibble(char c1) { + if (c1 >= 65 && c1 <= 70) + return c1 - 55; + if (c1 >= 97 && c1 <= 102) + return c1 - 87; + if (c1 >= 48 && c1 <= 57) + return c1 - 48; + throw std::logic_error("Invalid hex digit"); +} + +std::array operator""_array16(const char* str, size_t len) { + if (len != 32) + throw std::logic_error("Not of correct size."); + return HexStringToArray<16>(str); +} + +std::array operator""_array32(const char* str, size_t len) { + if (len != 64) + throw std::logic_error("Not of correct size."); + return HexStringToArray<32>(str); +} diff --git a/src/common/hex_util.h b/src/common/hex_util.h new file mode 100644 index 000000000..f16c58aab --- /dev/null +++ b/src/common/hex_util.h @@ -0,0 +1,35 @@ +// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include "common/common_types.h" + +u8 ToHexNibble(char c1); + +template +std::array HexStringToArray(std::string_view str) { + std::array out{}; + if constexpr (le) { + for (size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) + out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]); + } else { + for (size_t i = 0; i < 2 * Size; i += 2) + out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]); + } + return out; +} + +template +std::string HexArrayToString(std::array array, bool upper = true) { + std::string out; + for (u8 c : array) + out += fmt::format(upper ? "{:02X}" : "{:02x}", c); + return out; +} + +std::array operator"" _array16(const char* str, size_t len); +std::array operator"" _array32(const char* str, size_t len); -- cgit v1.2.3 From b70a831608caf78831e23575aa2fca19bf0d3491 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 9 Aug 2018 20:44:21 -0400 Subject: file_util: Add getter for NAND registration directory --- src/common/file_util.cpp | 6 ++++++ src/common/file_util.h | 2 ++ 2 files changed, 8 insertions(+) (limited to 'src/common') diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 3ce590062..b30a67ff9 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -750,6 +750,12 @@ std::string GetHactoolConfigurationPath() { #endif } +std::string GetNANDRegistrationDir(bool system) { + if (system) + return GetUserPath(UserPath::NANDDir) + "system/Contents/registered/"; + return GetUserPath(UserPath::NANDDir) + "user/Contents/registered/"; +} + size_t WriteStringToFile(bool text_file, const std::string& str, const char* filename) { return FileUtil::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size()); } diff --git a/src/common/file_util.h b/src/common/file_util.h index 2711872ae..2f13d0b6b 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h @@ -129,6 +129,8 @@ const std::string& GetUserPath(UserPath path, const std::string& new_path = ""); std::string GetHactoolConfigurationPath(); +std::string GetNANDRegistrationDir(bool system = false); + // Returns the path to where the sys file are std::string GetSysDirectory(); -- cgit v1.2.3 From 167bfddafadb843236c0fa683cf97eaffaa5ea1a Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 9 Aug 2018 23:10:32 -0400 Subject: file_sys: Comply to style guidelines --- src/common/hex_util.h | 2 ++ src/core/file_sys/nca_metadata.cpp | 10 +++++---- src/core/file_sys/nca_metadata.h | 4 ++++ src/core/file_sys/registered_cache.cpp | 24 ++++++++++---------- src/core/file_sys/registered_cache.h | 13 ++++++----- src/core/file_sys/vfs_concat.cpp | 8 +++---- src/core/file_sys/vfs_concat.h | 6 ++--- src/yuzu/main.cpp | 40 +++++++++++++++++----------------- 8 files changed, 60 insertions(+), 47 deletions(-) (limited to 'src/common') diff --git a/src/common/hex_util.h b/src/common/hex_util.h index f16c58aab..13d586015 100644 --- a/src/common/hex_util.h +++ b/src/common/hex_util.h @@ -5,6 +5,8 @@ #pragma once #include +#include +#include #include #include "common/common_types.h" diff --git a/src/core/file_sys/nca_metadata.cpp b/src/core/file_sys/nca_metadata.cpp index fa06897b7..118a0c287 100644 --- a/src/core/file_sys/nca_metadata.cpp +++ b/src/core/file_sys/nca_metadata.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/common_funcs.h" #include "common/swap.h" #include "content_archive.h" @@ -67,9 +68,10 @@ const std::vector& CNMT::GetMetaRecords() const { bool CNMT::UnionRecords(const CNMT& other) { bool change = false; for (const auto& rec : other.content_records) { - const auto iter = std::find_if( - content_records.begin(), content_records.end(), - [rec](const ContentRecord& r) { return r.nca_id == rec.nca_id && r.type == rec.type; }); + const auto iter = std::find_if(content_records.begin(), content_records.end(), + [&rec](const ContentRecord& r) { + return r.nca_id == rec.nca_id && r.type == rec.type; + }); if (iter == content_records.end()) { content_records.emplace_back(rec); ++header->number_content_entries; @@ -78,7 +80,7 @@ bool CNMT::UnionRecords(const CNMT& other) { } for (const auto& rec : other.meta_records) { const auto iter = - std::find_if(meta_records.begin(), meta_records.end(), [rec](const MetaRecord& r) { + std::find_if(meta_records.begin(), meta_records.end(), [&rec](const MetaRecord& r) { return r.title_id == rec.title_id && r.title_version == rec.title_version && r.type == rec.type; }); diff --git a/src/core/file_sys/nca_metadata.h b/src/core/file_sys/nca_metadata.h index 7b0725f36..6cd919e54 100644 --- a/src/core/file_sys/nca_metadata.h +++ b/src/core/file_sys/nca_metadata.h @@ -4,7 +4,11 @@ #pragma once +#include #include +#include +#include "common/common_types.h" +#include "common/swap.h" #include "core/file_sys/vfs.h" namespace FileSys { diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 766fef254..3e7706171 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -23,13 +23,13 @@ bool operator<(const RegisteredCacheEntry& lhs, const RegisteredCacheEntry& rhs) } static bool FollowsTwoDigitDirFormat(std::string_view name) { - const static std::regex two_digit_regex( + static const std::regex two_digit_regex( "000000[0123456789abcdefABCDEF][0123456789abcdefABCDEF]"); return std::regex_match(name.begin(), name.end(), two_digit_regex); } static bool FollowsNcaIdFormat(std::string_view name) { - const static std::regex nca_id_regex("[0123456789abcdefABCDEF]+.nca"); + static const std::regex nca_id_regex("[0123456789abcdefABCDEF]+.nca"); return name.size() == 36 && std::regex_match(name.begin(), name.end(), nca_id_regex); } @@ -56,7 +56,7 @@ static std::string GetCNMTName(TitleType type, u64 title_id) { "" ///< Currently unknown 'DeltaTitle' }; - size_t index = static_cast(type); + auto index = static_cast(type); if (index >= 0x80) index -= 0x80; return fmt::format("{}_{:016x}.cnmt", TITLE_TYPE_NAMES[index], title_id); @@ -90,15 +90,15 @@ VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir, VirtualFile file = nullptr; const auto files = nca_dir->GetFiles(); - if (files.size() == 1 && files[0]->GetName() == "00") + if (files.size() == 1 && files[0]->GetName() == "00") { file = files[0]; - else { + } else { std::vector concat; for (u8 i = 0; i < 0x10; ++i) { auto next = nca_dir->GetFile(fmt::format("{:02X}", i)); - if (next != nullptr) + if (next != nullptr) { concat.push_back(std::move(next)); - else { + } else { next = nca_dir->GetFile(fmt::format("{:02x}", i)); if (next != nullptr) concat.push_back(std::move(next)); @@ -146,7 +146,8 @@ boost::optional RegisteredCache::GetNcaIDFromMetadata(u64 title_id, return boost::make_optional(iter->nca_id); } -void RegisteredCache::AccumulateFiles(std::vector& ids) const { +std::vector RegisteredCache::AccumulateFiles() const { + std::vector ids; for (const auto& d2_dir : dir->GetSubdirectories()) { if (FollowsNcaIdFormat(d2_dir->GetName())) { ids.push_back(HexStringToArray<0x10, true>(d2_dir->GetName().substr(0, 0x20))); @@ -175,6 +176,7 @@ void RegisteredCache::AccumulateFiles(std::vector& ids) const { if (FollowsNcaIdFormat(d2_file->GetName())) ids.push_back(HexStringToArray<0x10, true>(d2_file->GetName().substr(0, 0x20))); } + return ids; } void RegisteredCache::ProcessFiles(const std::vector& ids) { @@ -185,8 +187,9 @@ void RegisteredCache::ProcessFiles(const std::vector& ids) { continue; const auto nca = std::make_shared(parser(file, id)); if (nca->GetStatus() != Loader::ResultStatus::Success || - nca->GetType() != NCAContentType::Meta) + nca->GetType() != NCAContentType::Meta) { continue; + } const auto section0 = nca->GetSubdirectories()[0]; @@ -218,8 +221,7 @@ void RegisteredCache::AccumulateYuzuMeta() { void RegisteredCache::Refresh() { if (dir == nullptr) return; - std::vector ids; - AccumulateFiles(ids); + const auto ids = AccumulateFiles(); ProcessFiles(ids); AccumulateYuzuMeta(); } diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index ba2e3403f..baaed02dd 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h @@ -5,14 +5,17 @@ #pragma once #include +#include #include #include #include +#include #include #include "common/common_funcs.h" +#include "common/common_types.h" #include "content_archive.h" +#include "core/file_sys/nca_metadata.h" #include "core/file_sys/vfs.h" -#include "nca_metadata.h" namespace FileSys { class XCI; @@ -49,9 +52,9 @@ public: // Parsing function defines the conversion from raw file to NCA. If there are other steps // besides creating the NCA from the file (e.g. NAX0 on SD Card), that should go in a custom // parsing function. - RegisteredCache(VirtualDir dir, - RegisteredCacheParsingFunction parsing_function = - [](const VirtualFile& file, const NcaID& id) { return file; }); + explicit RegisteredCache(VirtualDir dir, + RegisteredCacheParsingFunction parsing_function = + [](const VirtualFile& file, const NcaID& id) { return file; }); void Refresh(); @@ -86,7 +89,7 @@ private: void IterateAllMetadata(std::vector& out, std::function proc, std::function filter) const; - void AccumulateFiles(std::vector& ids) const; + std::vector AccumulateFiles() const; void ProcessFiles(const std::vector& ids); void AccumulateYuzuMeta(); boost::optional GetNcaIDFromMetadata(u64 title_id, ContentRecordType type) const; diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp index 1d439e0a4..88a9a5259 100644 --- a/src/core/file_sys/vfs_concat.cpp +++ b/src/core/file_sys/vfs_concat.cpp @@ -9,17 +9,17 @@ namespace FileSys { -VirtualFile ConcatenateFiles(std::vector files, std::string_view name) { +VirtualFile ConcatenateFiles(std::vector files, std::string name) { if (files.empty()) return nullptr; if (files.size() == 1) return files[0]; - return std::shared_ptr(new ConcatenatedVfsFile(std::move(files), name)); + return std::shared_ptr(new ConcatenatedVfsFile(std::move(files), std::move(name))); } -ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector files_, std::string_view name) - : name(name) { +ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector files_, std::string name) + : name(std::move(name)) { size_t next_offset = 0; for (const auto& file : files_) { files[next_offset] = file; diff --git a/src/core/file_sys/vfs_concat.h b/src/core/file_sys/vfs_concat.h index d319c5786..686d32515 100644 --- a/src/core/file_sys/vfs_concat.h +++ b/src/core/file_sys/vfs_concat.h @@ -12,14 +12,14 @@ namespace FileSys { // Wrapper function to allow for more efficient handling of files.size() == 0, 1 cases. -VirtualFile ConcatenateFiles(std::vector files, std::string_view name = ""); +VirtualFile ConcatenateFiles(std::vector files, std::string name = ""); // Class that wraps multiple vfs files and concatenates them, making reads seamless. Currently // read-only. class ConcatenatedVfsFile : public VfsFile { - friend VirtualFile ConcatenateFiles(std::vector files, std::string_view name); + friend VirtualFile ConcatenateFiles(std::vector files, std::string name); - ConcatenatedVfsFile(std::vector files, std::string_view name); + ConcatenatedVfsFile(std::vector files, std::string name); public: std::string GetName() const override; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index c48191486..fd237df43 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -619,7 +619,7 @@ void GMainWindow::OnMenuLoadFolder() { } void GMainWindow::OnMenuInstallToNAND() { - const static QString file_filter = + const QString file_filter = tr("Installable Switch File (*.nca *.xci);;Nintendo Content Archive (*.nca);;NX Cartridge " "Image (*.xci)"); QString filename = QFileDialog::getOpenFileName(this, tr("Install File"), @@ -629,36 +629,36 @@ void GMainWindow::OnMenuInstallToNAND() { const auto xci = std::make_shared( vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); if (xci->GetStatus() != Loader::ResultStatus::Success) { - QMessageBox::critical( + QMessageBox::warning( this, tr("Failed to Install XCI"), tr("The XCI file you provided is invalid. Please double-check your encryption " "keys and the file and try again.")); return; } - if (!Service::FileSystem::GetUserNANDContents()->InstallEntry(xci)) { - QMessageBox::critical( - this, tr("Failed to Install XCI"), - tr("There was an error while attempting to install the provided XCI file. It " - "could have an incorrect format or be missing a metadata entry. Please " - "double-check your file and try again.")); - } else { + if (Service::FileSystem::GetUserNANDContents()->InstallEntry(xci)) { QMessageBox::information(this, tr("Successfully Installed XCI"), tr("The file was successfully installed.")); game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan); + } else { + QMessageBox::warning( + this, tr("Failed to Install XCI"), + tr("There was an error while attempting to install the provided XCI file. It " + "could have an incorrect format or be missing a metadata entry. Please " + "double-check your file and try again.")); } } else { const auto nca = std::make_shared( vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); if (nca->GetStatus() != Loader::ResultStatus::Success) { - QMessageBox::critical( + QMessageBox::warning( this, tr("Failed to Install NCA"), tr("The NCA file you provided is invalid. Please double-check your encryption " "keys and the file and try again.")); return; } - const static QStringList tt_options{"System Application", + static const QStringList tt_options{"System Application", "System Archive", "System Application Update", "Firmware Package (Type A)", @@ -676,26 +676,26 @@ void GMainWindow::OnMenuInstallToNAND() { auto index = tt_options.indexOf(item); if (!ok || index == -1) { - QMessageBox::critical(this, tr("Failed to Install NCA"), - tr("The title type you selected for the NCA is invalid.")); + QMessageBox::warning(this, tr("Failed to Install NCA"), + tr("The title type you selected for the NCA is invalid.")); return; } if (index >= 5) index += 0x80; - if (!Service::FileSystem::GetUserNANDContents()->InstallEntry( + if (Service::FileSystem::GetUserNANDContents()->InstallEntry( nca, static_cast(index))) { - QMessageBox::critical(this, tr("Failed to Install NCA"), - tr("There was an error while attempting to install the " - "provided NCA file. An error might have occured creating " - "the metadata file or parsing the NCA. Please " - "double-check your file and try again.")); - } else { QMessageBox::information(this, tr("Successfully Installed NCA"), tr("The file was successfully installed.")); game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan); + } else { + QMessageBox::warning(this, tr("Failed to Install NCA"), + tr("There was an error while attempting to install the " + "provided NCA file. An error might have occured creating " + "the metadata file or parsing the NCA. Please " + "double-check your file and try again.")); } } } -- cgit v1.2.3