diff options
Diffstat (limited to 'src/core')
48 files changed, 423 insertions, 710 deletions
diff --git a/src/core/arm/cpu_interrupt_handler.cpp b/src/core/arm/cpu_interrupt_handler.cpp index df0350881..9c8898700 100644 --- a/src/core/arm/cpu_interrupt_handler.cpp +++ b/src/core/arm/cpu_interrupt_handler.cpp @@ -7,9 +7,7 @@ namespace Core { -CPUInterruptHandler::CPUInterruptHandler() : is_interrupted{} { - interrupt_event = std::make_unique<Common::Event>(); -} +CPUInterruptHandler::CPUInterruptHandler() : interrupt_event{std::make_unique<Common::Event>()} {} CPUInterruptHandler::~CPUInterruptHandler() = default; @@ -17,7 +15,7 @@ void CPUInterruptHandler::SetInterrupt(bool is_interrupted_) { if (is_interrupted_) { interrupt_event->Set(); } - this->is_interrupted = is_interrupted_; + is_interrupted = is_interrupted_; } void CPUInterruptHandler::AwaitInterrupt() { diff --git a/src/core/arm/cpu_interrupt_handler.h b/src/core/arm/cpu_interrupt_handler.h index 3d062d326..71e582f79 100644 --- a/src/core/arm/cpu_interrupt_handler.h +++ b/src/core/arm/cpu_interrupt_handler.h @@ -4,6 +4,7 @@ #pragma once +#include <atomic> #include <memory> namespace Common { @@ -32,8 +33,8 @@ public: void AwaitInterrupt(); private: - bool is_interrupted{}; std::unique_ptr<Common::Event> interrupt_event; + std::atomic_bool is_interrupted{false}; }; } // namespace Core diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 443ca72eb..b5f28a86e 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -143,7 +143,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& config.wall_clock_cntpct = uses_wall_clock; // Safe optimizations - if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) { + if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { if (!Settings::values.cpuopt_page_tables) { config.page_table = nullptr; } @@ -170,6 +170,17 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& } } + // Unsafe optimizations + if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) { + config.unsafe_optimizations = true; + if (Settings::values.cpuopt_unsafe_unfuse_fma) { + config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; + } + if (Settings::values.cpuopt_unsafe_reduce_fp_error) { + config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; + } + } + return std::make_unique<Dynarmic::A32::Jit>(config); } diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index a63a04a25..ce9968724 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -195,7 +195,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& config.wall_clock_cntpct = uses_wall_clock; // Safe optimizations - if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) { + if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { if (!Settings::values.cpuopt_page_tables) { config.page_table = nullptr; } @@ -222,6 +222,17 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& } } + // Unsafe optimizations + if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) { + config.unsafe_optimizations = true; + if (Settings::values.cpuopt_unsafe_unfuse_fma) { + config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; + } + if (Settings::values.cpuopt_unsafe_reduce_fp_error) { + config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; + } + } + return std::make_shared<Dynarmic::A64::Jit>(config); } diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 71af26ec5..e6c8461a5 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -7,14 +7,14 @@ #include <string> #include <tuple> -#include "common/assert.h" #include "common/microprofile.h" #include "core/core_timing.h" #include "core/core_timing_util.h" +#include "core/hardware_properties.h" namespace Core::Timing { -constexpr u64 MAX_SLICE_LENGTH = 4000; +constexpr s64 MAX_SLICE_LENGTH = 4000; std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) { return std::make_shared<EventType>(std::move(callback), std::move(name)); @@ -37,10 +37,8 @@ struct CoreTiming::Event { } }; -CoreTiming::CoreTiming() { - clock = - Common::CreateBestMatchingClock(Core::Hardware::BASE_CLOCK_RATE, Core::Hardware::CNTFREQ); -} +CoreTiming::CoreTiming() + : clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {} CoreTiming::~CoreTiming() = default; @@ -136,7 +134,7 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, void CoreTiming::AddTicks(u64 ticks) { this->ticks += ticks; - downcount -= ticks; + downcount -= static_cast<s64>(ticks); } void CoreTiming::Idle() { diff --git a/src/core/core_timing_util.cpp b/src/core/core_timing_util.cpp index aefc63663..8ce8e602e 100644 --- a/src/core/core_timing_util.cpp +++ b/src/core/core_timing_util.cpp @@ -8,6 +8,7 @@ #include <limits> #include "common/logging/log.h" #include "common/uint128.h" +#include "core/hardware_properties.h" namespace Core::Timing { diff --git a/src/core/core_timing_util.h b/src/core/core_timing_util.h index 2ed979e14..e4a046bf9 100644 --- a/src/core/core_timing_util.h +++ b/src/core/core_timing_util.h @@ -6,7 +6,6 @@ #include <chrono> #include "common/common_types.h" -#include "core/hardware_properties.h" namespace Core::Timing { diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 358943429..688b99eba 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -41,9 +41,9 @@ void CpuManager::Shutdown() { running_mode = false; Pause(false); if (is_multicore) { - for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { - core_data[core].host_thread->join(); - core_data[core].host_thread.reset(); + for (auto& data : core_data) { + data.host_thread->join(); + data.host_thread.reset(); } } else { core_data[0].host_thread->join(); @@ -166,25 +166,23 @@ void CpuManager::MultiCorePause(bool paused) { bool all_not_barrier = false; while (!all_not_barrier) { all_not_barrier = true; - for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { - all_not_barrier &= - !core_data[core].is_running.load() && core_data[core].initialized.load(); + for (const auto& data : core_data) { + all_not_barrier &= !data.is_running.load() && data.initialized.load(); } } - for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { - core_data[core].enter_barrier->Set(); + for (auto& data : core_data) { + data.enter_barrier->Set(); } if (paused_state.load()) { bool all_barrier = false; while (!all_barrier) { all_barrier = true; - for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { - all_barrier &= - core_data[core].is_paused.load() && core_data[core].initialized.load(); + for (const auto& data : core_data) { + all_barrier &= data.is_paused.load() && data.initialized.load(); } } - for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { - core_data[core].exit_barrier->Set(); + for (auto& data : core_data) { + data.exit_barrier->Set(); } } } else { @@ -192,9 +190,8 @@ void CpuManager::MultiCorePause(bool paused) { bool all_barrier = false; while (!all_barrier) { all_barrier = true; - for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { - all_barrier &= - core_data[core].is_paused.load() && core_data[core].initialized.load(); + for (const auto& data : core_data) { + all_barrier &= data.is_paused.load() && data.initialized.load(); } } /// Don't release the barrier @@ -331,7 +328,7 @@ void CpuManager::RunThread(std::size_t core) { system.RegisterCoreThread(core); std::string name; if (is_multicore) { - name = "yuzu:CoreCPUThread_" + std::to_string(core); + name = "yuzu:CPUCore_" + std::to_string(core); } else { name = "yuzu:CPUThread"; } diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 8783d1ac2..dc591c730 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -36,6 +36,7 @@ #include "core/settings.h" namespace Core::Crypto { +namespace { constexpr u64 CURRENT_CRYPTO_REVISION = 0x5; constexpr u64 FULL_TICKET_SIZE = 0x400; @@ -49,7 +50,72 @@ constexpr std::array eticket_source_hashes{ }; // clang-format on -const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{ +constexpr std::array<std::pair<std::string_view, KeyIndex<S128KeyType>>, 30> s128_file_id{{ + {"eticket_rsa_kek", {S128KeyType::ETicketRSAKek, 0, 0}}, + {"eticket_rsa_kek_source", + {S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKek), 0}}, + {"eticket_rsa_kekek_source", + {S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKekek), 0}}, + {"rsa_kek_mask_0", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Mask0), 0}}, + {"rsa_kek_seed_3", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Seed3), 0}}, + {"rsa_oaep_kek_generation_source", + {S128KeyType::Source, static_cast<u64>(SourceKeyType::RSAOaepKekGeneration), 0}}, + {"sd_card_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek), 0}}, + {"aes_kek_generation_source", + {S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration), 0}}, + {"aes_key_generation_source", + {S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKeyGeneration), 0}}, + {"package2_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Package2), 0}}, + {"master_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Master), 0}}, + {"header_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::HeaderKek), 0}}, + {"key_area_key_application_source", + {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey), + static_cast<u64>(KeyAreaKeyType::Application)}}, + {"key_area_key_ocean_source", + {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey), + static_cast<u64>(KeyAreaKeyType::Ocean)}}, + {"key_area_key_system_source", + {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey), + static_cast<u64>(KeyAreaKeyType::System)}}, + {"titlekek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Titlekek), 0}}, + {"keyblob_mac_key_source", + {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC), 0}}, + {"tsec_key", {S128KeyType::TSEC, 0, 0}}, + {"secure_boot_key", {S128KeyType::SecureBoot, 0, 0}}, + {"sd_seed", {S128KeyType::SDSeed, 0, 0}}, + {"bis_key_0_crypt", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Crypto)}}, + {"bis_key_0_tweak", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Tweak)}}, + {"bis_key_1_crypt", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Crypto)}}, + {"bis_key_1_tweak", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Tweak)}}, + {"bis_key_2_crypt", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Crypto)}}, + {"bis_key_2_tweak", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Tweak)}}, + {"bis_key_3_crypt", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Crypto)}}, + {"bis_key_3_tweak", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Tweak)}}, + {"header_kek", {S128KeyType::HeaderKek, 0, 0}}, + {"sd_card_kek", {S128KeyType::SDKek, 0, 0}}, +}}; + +auto Find128ByName(std::string_view name) { + return std::find_if(s128_file_id.begin(), s128_file_id.end(), + [&name](const auto& pair) { return pair.first == name; }); +} + +constexpr std::array<std::pair<std::string_view, KeyIndex<S256KeyType>>, 6> s256_file_id{{ + {"header_key", {S256KeyType::Header, 0, 0}}, + {"sd_card_save_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save), 0}}, + {"sd_card_nca_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::NCA), 0}}, + {"header_key_source", {S256KeyType::HeaderSource, 0, 0}}, + {"sd_card_save_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::Save), 0}}, + {"sd_card_nca_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::NCA), 0}}, +}}; + +auto Find256ByName(std::string_view name) { + return std::find_if(s256_file_id.begin(), s256_file_id.end(), + [&name](const auto& pair) { return pair.first == name; }); +} + +using KeyArray = std::array<std::pair<std::pair<S128KeyType, u64>, std::string_view>, 7>; +constexpr KeyArray KEYS_VARIABLE_LENGTH{{ {{S128KeyType::Master, 0}, "master_key_"}, {{S128KeyType::Package1, 0}, "package1_key_"}, {{S128KeyType::Package2, 0}, "package2_key_"}, @@ -57,14 +123,13 @@ const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{ {{S128KeyType::Source, static_cast<u64>(SourceKeyType::Keyblob)}, "keyblob_key_source_"}, {{S128KeyType::Keyblob, 0}, "keyblob_key_"}, {{S128KeyType::KeyblobMAC, 0}, "keyblob_mac_key_"}, -}; +}}; -namespace { template <std::size_t Size> bool IsAllZeroArray(const std::array<u8, Size>& array) { return std::all_of(array.begin(), array.end(), [](const auto& elem) { return elem == 0; }); } -} // namespace +} // Anonymous namespace u64 GetSignatureTypeDataSize(SignatureType type) { switch (type) { @@ -564,13 +629,13 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) { s128_keys[{S128KeyType::Titlekey, rights_id[1], rights_id[0]}] = key; } else { out[0] = Common::ToLower(out[0]); - if (s128_file_id.find(out[0]) != s128_file_id.end()) { - const auto index = s128_file_id.at(out[0]); - Key128 key = Common::HexStringToArray<16>(out[1]); + if (const auto iter128 = Find128ByName(out[0]); iter128 != s128_file_id.end()) { + const auto& index = iter128->second; + const Key128 key = Common::HexStringToArray<16>(out[1]); s128_keys[{index.type, index.field1, index.field2}] = key; - } else if (s256_file_id.find(out[0]) != s256_file_id.end()) { - const auto index = s256_file_id.at(out[0]); - Key256 key = Common::HexStringToArray<32>(out[1]); + } else if (const auto iter256 = Find256ByName(out[0]); iter256 != s256_file_id.end()) { + const auto& index = iter256->second; + const Key256 key = Common::HexStringToArray<32>(out[1]); s256_keys[{index.type, index.field1, index.field2}] = key; } else if (out[0].compare(0, 8, "keyblob_") == 0 && out[0].compare(0, 9, "keyblob_k") != 0) { @@ -742,8 +807,7 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) { } const auto iter2 = std::find_if( - s128_file_id.begin(), s128_file_id.end(), - [&id, &field1, &field2](const std::pair<std::string, KeyIndex<S128KeyType>> elem) { + s128_file_id.begin(), s128_file_id.end(), [&id, &field1, &field2](const auto& elem) { return std::tie(elem.second.type, elem.second.field1, elem.second.field2) == std::tie(id, field1, field2); }); @@ -753,9 +817,11 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) { // Variable cases if (id == S128KeyType::KeyArea) { - static constexpr std::array<const char*, 3> kak_names = {"key_area_key_application_{:02X}", - "key_area_key_ocean_{:02X}", - "key_area_key_system_{:02X}"}; + static constexpr std::array<const char*, 3> kak_names = { + "key_area_key_application_{:02X}", + "key_area_key_ocean_{:02X}", + "key_area_key_system_{:02X}", + }; WriteKeyToFile(category, fmt::format(kak_names.at(field2), field1), key); } else if (id == S128KeyType::Master) { WriteKeyToFile(category, fmt::format("master_key_{:02X}", field1), key); @@ -781,8 +847,7 @@ void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) { return; } const auto iter = std::find_if( - s256_file_id.begin(), s256_file_id.end(), - [&id, &field1, &field2](const std::pair<std::string, KeyIndex<S256KeyType>> elem) { + s256_file_id.begin(), s256_file_id.end(), [&id, &field1, &field2](const auto& elem) { return std::tie(elem.second.type, elem.second.field1, elem.second.field2) == std::tie(id, field1, field2); }); @@ -1245,58 +1310,4 @@ bool KeyManager::AddTicketPersonalized(Ticket raw) { SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]); return true; } - -const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> KeyManager::s128_file_id = { - {"eticket_rsa_kek", {S128KeyType::ETicketRSAKek, 0, 0}}, - {"eticket_rsa_kek_source", - {S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKek), 0}}, - {"eticket_rsa_kekek_source", - {S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKekek), 0}}, - {"rsa_kek_mask_0", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Mask0), 0}}, - {"rsa_kek_seed_3", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Seed3), 0}}, - {"rsa_oaep_kek_generation_source", - {S128KeyType::Source, static_cast<u64>(SourceKeyType::RSAOaepKekGeneration), 0}}, - {"sd_card_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek), 0}}, - {"aes_kek_generation_source", - {S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration), 0}}, - {"aes_key_generation_source", - {S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKeyGeneration), 0}}, - {"package2_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Package2), 0}}, - {"master_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Master), 0}}, - {"header_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::HeaderKek), 0}}, - {"key_area_key_application_source", - {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey), - static_cast<u64>(KeyAreaKeyType::Application)}}, - {"key_area_key_ocean_source", - {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey), - static_cast<u64>(KeyAreaKeyType::Ocean)}}, - {"key_area_key_system_source", - {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey), - static_cast<u64>(KeyAreaKeyType::System)}}, - {"titlekek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Titlekek), 0}}, - {"keyblob_mac_key_source", - {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC), 0}}, - {"tsec_key", {S128KeyType::TSEC, 0, 0}}, - {"secure_boot_key", {S128KeyType::SecureBoot, 0, 0}}, - {"sd_seed", {S128KeyType::SDSeed, 0, 0}}, - {"bis_key_0_crypt", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Crypto)}}, - {"bis_key_0_tweak", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Tweak)}}, - {"bis_key_1_crypt", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Crypto)}}, - {"bis_key_1_tweak", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Tweak)}}, - {"bis_key_2_crypt", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Crypto)}}, - {"bis_key_2_tweak", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Tweak)}}, - {"bis_key_3_crypt", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Crypto)}}, - {"bis_key_3_tweak", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Tweak)}}, - {"header_kek", {S128KeyType::HeaderKek, 0, 0}}, - {"sd_card_kek", {S128KeyType::SDKek, 0, 0}}, -}; - -const boost::container::flat_map<std::string, KeyIndex<S256KeyType>> KeyManager::s256_file_id = { - {"header_key", {S256KeyType::Header, 0, 0}}, - {"sd_card_save_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save), 0}}, - {"sd_card_nca_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::NCA), 0}}, - {"header_key_source", {S256KeyType::HeaderSource, 0, 0}}, - {"sd_card_save_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::Save), 0}}, - {"sd_card_nca_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::NCA), 0}}, -}; } // namespace Core::Crypto diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h index bdca3770a..321b75323 100644 --- a/src/core/crypto/key_manager.h +++ b/src/core/crypto/key_manager.h @@ -10,7 +10,6 @@ #include <string> #include <variant> -#include <boost/container/flat_map.hpp> #include <fmt/format.h> #include "common/common_funcs.h" #include "common/common_types.h" @@ -293,9 +292,6 @@ private: void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0); void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0); - - static const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> s128_file_id; - static const boost::container::flat_map<std::string, KeyIndex<S256KeyType>> s256_file_id; }; Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed); diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index 46136d04a..5f1c86a09 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -26,6 +26,7 @@ #include "core/file_sys/vfs.h" #include "core/file_sys/vfs_offset.h" #include "core/file_sys/vfs_vector.h" +#include "core/loader/loader.h" using Common::AsArray; diff --git a/src/core/file_sys/bis_factory.cpp b/src/core/file_sys/bis_factory.cpp index 9ffda2e14..e04a54c3c 100644 --- a/src/core/file_sys/bis_factory.cpp +++ b/src/core/file_sys/bis_factory.cpp @@ -8,7 +8,6 @@ #include "core/file_sys/bis_factory.h" #include "core/file_sys/mode.h" #include "core/file_sys/registered_cache.h" -#include "core/settings.h" namespace FileSys { diff --git a/src/core/file_sys/bis_factory.h b/src/core/file_sys/bis_factory.h index 8f0451c98..438d3f8d8 100644 --- a/src/core/file_sys/bis_factory.h +++ b/src/core/file_sys/bis_factory.h @@ -6,7 +6,8 @@ #include <memory> -#include "core/file_sys/vfs.h" +#include "common/common_types.h" +#include "core/file_sys/vfs_types.h" namespace FileSys { diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index 664a47e7f..956da68f7 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp @@ -8,11 +8,11 @@ #include <fmt/ostream.h> #include "common/logging/log.h" +#include "core/crypto/key_manager.h" #include "core/file_sys/card_image.h" #include "core/file_sys/content_archive.h" #include "core/file_sys/nca_metadata.h" #include "core/file_sys/partition_filesystem.h" -#include "core/file_sys/romfs.h" #include "core/file_sys/submission_package.h" #include "core/file_sys/vfs_concat.h" #include "core/file_sys/vfs_offset.h" @@ -31,7 +31,8 @@ constexpr std::array partition_names{ XCI::XCI(VirtualFile file_) : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, - partitions(partition_names.size()), partitions_raw(partition_names.size()) { + partitions(partition_names.size()), + partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} { if (file->ReadObject(&header) != sizeof(GamecardHeader)) { status = Loader::ResultStatus::ErrorBadXCIHeader; return; diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h index e1b136426..2d0a0f285 100644 --- a/src/core/file_sys/card_image.h +++ b/src/core/file_sys/card_image.h @@ -9,9 +9,12 @@ #include <vector> #include "common/common_types.h" #include "common/swap.h" -#include "core/crypto/key_manager.h" #include "core/file_sys/vfs.h" +namespace Core::Crypto { +class KeyManager; +} + namespace Loader { enum class ResultStatus : u16; } @@ -140,6 +143,6 @@ private: u64 update_normal_partition_end; - Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); + Core::Crypto::KeyManager& keys; }; } // namespace FileSys diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 5039341c7..426fb6bb5 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -10,10 +10,10 @@ #include "common/logging/log.h" #include "core/crypto/aes_util.h" #include "core/crypto/ctr_encryption_layer.h" +#include "core/crypto/key_manager.h" #include "core/file_sys/content_archive.h" #include "core/file_sys/nca_patch.h" #include "core/file_sys/partition_filesystem.h" -#include "core/file_sys/romfs.h" #include "core/file_sys/vfs_offset.h" #include "core/loader/loader.h" @@ -119,7 +119,8 @@ static bool IsValidNCA(const NCAHeader& header) { } NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset) - : file(std::move(file_)), bktr_base_romfs(std::move(bktr_base_romfs_)) { + : file(std::move(file_)), + bktr_base_romfs(std::move(bktr_base_romfs_)), keys{Core::Crypto::KeyManager::Instance()} { if (file == nullptr) { status = Loader::ResultStatus::ErrorNullFile; return; diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h index d25cbcf91..69292232a 100644 --- a/src/core/file_sys/content_archive.h +++ b/src/core/file_sys/content_archive.h @@ -158,7 +158,7 @@ private: bool encrypted = false; bool is_update = false; - Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); + Core::Crypto::KeyManager& keys; }; } // namespace FileSys diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp index 63cd2eead..b0a130345 100644 --- a/src/core/file_sys/control_metadata.cpp +++ b/src/core/file_sys/control_metadata.cpp @@ -5,6 +5,7 @@ #include "common/string_util.h" #include "common/swap.h" #include "core/file_sys/control_metadata.h" +#include "core/file_sys/vfs.h" namespace FileSys { diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h index e37b2fadf..9ab86e35b 100644 --- a/src/core/file_sys/control_metadata.h +++ b/src/core/file_sys/control_metadata.h @@ -10,7 +10,7 @@ #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" -#include "core/file_sys/vfs.h" +#include "core/file_sys/vfs_types.h" namespace FileSys { diff --git a/src/core/file_sys/kernel_executable.cpp b/src/core/file_sys/kernel_executable.cpp index 76313679d..ef93ef3ed 100644 --- a/src/core/file_sys/kernel_executable.cpp +++ b/src/core/file_sys/kernel_executable.cpp @@ -2,9 +2,12 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <cstring> + #include "common/string_util.h" #include "core/file_sys/kernel_executable.h" #include "core/file_sys/vfs_offset.h" +#include "core/loader/loader.h" namespace FileSys { diff --git a/src/core/file_sys/kernel_executable.h b/src/core/file_sys/kernel_executable.h index 324a57384..044c554d3 100644 --- a/src/core/file_sys/kernel_executable.h +++ b/src/core/file_sys/kernel_executable.h @@ -4,10 +4,17 @@ #pragma once +#include <array> +#include <vector> + #include "common/common_funcs.h" +#include "common/common_types.h" #include "common/swap.h" #include "core/file_sys/vfs_types.h" -#include "core/loader/loader.h" + +namespace Loader { +enum class ResultStatus : u16; +} namespace FileSys { diff --git a/src/core/file_sys/nca_metadata.cpp b/src/core/file_sys/nca_metadata.cpp index 93d0df6b9..2d1476e3a 100644 --- a/src/core/file_sys/nca_metadata.cpp +++ b/src/core/file_sys/nca_metadata.cpp @@ -7,6 +7,7 @@ #include "common/logging/log.h" #include "common/swap.h" #include "core/file_sys/nca_metadata.h" +#include "core/file_sys/vfs.h" namespace FileSys { diff --git a/src/core/file_sys/nca_metadata.h b/src/core/file_sys/nca_metadata.h index 1f82fff0a..53535e5f5 100644 --- a/src/core/file_sys/nca_metadata.h +++ b/src/core/file_sys/nca_metadata.h @@ -10,7 +10,7 @@ #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" -#include "core/file_sys/vfs.h" +#include "core/file_sys/vfs_types.h" namespace FileSys { class CNMT; diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp index 846986736..48a2ed4d4 100644 --- a/src/core/file_sys/partition_filesystem.cpp +++ b/src/core/file_sys/partition_filesystem.cpp @@ -21,7 +21,7 @@ bool PartitionFilesystem::Header::HasValidMagicValue() const { magic == Common::MakeMagic('P', 'F', 'S', '0'); } -PartitionFilesystem::PartitionFilesystem(std::shared_ptr<VfsFile> file) { +PartitionFilesystem::PartitionFilesystem(VirtualFile file) { // At least be as large as the header if (file->GetSize() < sizeof(Header)) { status = Loader::ResultStatus::ErrorBadPFSHeader; @@ -89,11 +89,11 @@ std::map<std::string, u64> PartitionFilesystem::GetFileSizes() const { return sizes; } -std::vector<std::shared_ptr<VfsFile>> PartitionFilesystem::GetFiles() const { +std::vector<VirtualFile> PartitionFilesystem::GetFiles() const { return pfs_files; } -std::vector<std::shared_ptr<VfsDirectory>> PartitionFilesystem::GetSubdirectories() const { +std::vector<VirtualDir> PartitionFilesystem::GetSubdirectories() const { return {}; } @@ -101,7 +101,7 @@ std::string PartitionFilesystem::GetName() const { return is_hfs ? "HFS0" : "PFS0"; } -std::shared_ptr<VfsDirectory> PartitionFilesystem::GetParentDirectory() const { +VirtualDir PartitionFilesystem::GetParentDirectory() const { // TODO(DarkLordZach): Add support for nested containers. return nullptr; } diff --git a/src/core/file_sys/partition_filesystem.h b/src/core/file_sys/partition_filesystem.h index 279193b19..0f831148e 100644 --- a/src/core/file_sys/partition_filesystem.h +++ b/src/core/file_sys/partition_filesystem.h @@ -24,7 +24,7 @@ namespace FileSys { */ class PartitionFilesystem : public ReadOnlyVfsDirectory { public: - explicit PartitionFilesystem(std::shared_ptr<VfsFile> file); + explicit PartitionFilesystem(VirtualFile file); ~PartitionFilesystem() override; Loader::ResultStatus GetStatus() const; @@ -32,10 +32,10 @@ public: std::map<std::string, u64> GetFileOffsets() const; std::map<std::string, u64> GetFileSizes() const; - std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; - std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override; + std::vector<VirtualFile> GetFiles() const override; + std::vector<VirtualDir> GetSubdirectories() const override; std::string GetName() const override; - std::shared_ptr<VfsDirectory> GetParentDirectory() const override; + VirtualDir GetParentDirectory() const override; void PrintDebugInfo() const; private: diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 729dbb5f4..c228d253e 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -49,8 +49,7 @@ std::string FormatTitleVersion(u32 version, TitleVersionFormat format) { return fmt::format("v{}.{}.{}", bytes[3], bytes[2], bytes[1]); } -std::shared_ptr<VfsDirectory> FindSubdirectoryCaseless(const std::shared_ptr<VfsDirectory> dir, - std::string_view name) { +VirtualDir FindSubdirectoryCaseless(const VirtualDir dir, std::string_view name) { #ifdef _WIN32 return dir->GetSubdirectory(name); #else diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index f4cb918dd..f12d0629f 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -9,7 +9,7 @@ #include <string> #include "common/common_types.h" #include "core/file_sys/nca_metadata.h" -#include "core/file_sys/vfs.h" +#include "core/file_sys/vfs_types.h" #include "core/memory/dmnt_cheat_types.h" namespace Core { @@ -31,8 +31,7 @@ std::string FormatTitleVersion(u32 version, // Returns a directory with name matching name case-insensitive. Returns nullptr if directory // doesn't have a directory with name. -std::shared_ptr<VfsDirectory> FindSubdirectoryCaseless(const std::shared_ptr<VfsDirectory> dir, - std::string_view name); +VirtualDir FindSubdirectoryCaseless(VirtualDir dir, std::string_view name); // A centralized class to manage patches to games. class PatchManager { diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp index 43169bf9f..9cf49bf44 100644 --- a/src/core/file_sys/program_metadata.cpp +++ b/src/core/file_sys/program_metadata.cpp @@ -7,6 +7,7 @@ #include "common/logging/log.h" #include "core/file_sys/program_metadata.h" +#include "core/file_sys/vfs.h" #include "core/loader/loader.h" namespace FileSys { diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h index 35069972b..455532567 100644 --- a/src/core/file_sys/program_metadata.h +++ b/src/core/file_sys/program_metadata.h @@ -9,7 +9,7 @@ #include "common/bit_field.h" #include "common/common_types.h" #include "common/swap.h" -#include "core/file_sys/vfs.h" +#include "core/file_sys/vfs_types.h" namespace Loader { enum class ResultStatus : u16; diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index e42b677f7..da01002d5 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -257,8 +257,7 @@ std::vector<NcaID> PlaceholderCache::List() const { for (const auto& sdir : dir->GetSubdirectories()) { for (const auto& file : sdir->GetFiles()) { const auto name = file->GetName(); - if (name.length() == 36 && name[32] == '.' && name[33] == 'n' && name[34] == 'c' && - name[35] == 'a') { + if (name.length() == 36 && name.ends_with(".nca")) { out.push_back(Common::HexStringToArray<0x10>(name.substr(0, 32))); } } @@ -621,25 +620,25 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists, const VfsCopyFunction& copy) { - CNMTHeader header{ - nca.GetTitleId(), // Title ID - 0, // Ignore/Default title version - type, // Type - {}, // Padding - 0x10, // Default table offset - 1, // 1 Content Entry - 0, // No Meta Entries - {}, // Padding - {}, // Reserved 1 - 0, // Is committed - 0, // Required download system version - {}, // Reserved 2 + const CNMTHeader header{ + .title_id = nca.GetTitleId(), + .title_version = 0, + .type = type, + .reserved = {}, + .table_offset = 0x10, + .number_content_entries = 1, + .number_meta_entries = 0, + .attributes = 0, + .reserved2 = {}, + .is_committed = 0, + .required_download_system_version = 0, + .reserved3 = {}, }; - OptionalHeader opt_header{0, 0}; + const OptionalHeader opt_header{0, 0}; ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}}; const auto& data = nca.GetBaseFile()->ReadBytes(0x100000); mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0); - memcpy(&c_rec.nca_id, &c_rec.hash, 16); + std::memcpy(&c_rec.nca_id, &c_rec.hash, 16); const CNMT new_cnmt(header, opt_header, {c_rec}, {}); if (!RawInstallYuzuMeta(new_cnmt)) { return InstallResult::ErrorMetaFailed; diff --git a/src/core/file_sys/romfs.h b/src/core/file_sys/romfs.h index 2fd07ed04..82e683782 100644 --- a/src/core/file_sys/romfs.h +++ b/src/core/file_sys/romfs.h @@ -4,7 +4,6 @@ #pragma once -#include <array> #include "core/file_sys/vfs.h" namespace FileSys { diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp index 6f732e4d8..cb56d8f2d 100644 --- a/src/core/file_sys/sdmc_factory.cpp +++ b/src/core/file_sys/sdmc_factory.cpp @@ -5,8 +5,8 @@ #include <memory> #include "core/file_sys/registered_cache.h" #include "core/file_sys/sdmc_factory.h" +#include "core/file_sys/vfs.h" #include "core/file_sys/xts_archive.h" -#include "core/settings.h" namespace FileSys { diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h index 42dc4e08a..2bb92ba93 100644 --- a/src/core/file_sys/sdmc_factory.h +++ b/src/core/file_sys/sdmc_factory.h @@ -5,7 +5,7 @@ #pragma once #include <memory> -#include "core/file_sys/vfs.h" +#include "core/file_sys/vfs_types.h" #include "core/hle/result.h" namespace FileSys { diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp index 175a8266a..b9ce93b7c 100644 --- a/src/core/file_sys/submission_package.cpp +++ b/src/core/file_sys/submission_package.cpp @@ -54,7 +54,7 @@ void SetTicketKeys(const std::vector<VirtualFile>& files) { NSP::NSP(VirtualFile file_) : file(std::move(file_)), status{Loader::ResultStatus::Success}, - pfs(std::make_shared<PartitionFilesystem>(file)) { + pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} { if (pfs->GetStatus() != Loader::ResultStatus::Success) { status = pfs->GetStatus(); return; diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h index cf89de6a9..2db5e46b8 100644 --- a/src/core/file_sys/submission_package.h +++ b/src/core/file_sys/submission_package.h @@ -10,6 +10,10 @@ #include "common/common_types.h" #include "core/file_sys/vfs.h" +namespace Core::Crypto { +class KeyManager; +} + namespace Loader { enum class ResultStatus : u16; } @@ -73,7 +77,7 @@ private: std::map<u64, std::map<std::pair<TitleType, ContentRecordType>, std::shared_ptr<NCA>>> ncas; std::vector<VirtualFile> ticket_files; - Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); + Core::Crypto::KeyManager& keys; VirtualFile romfs; VirtualDir exefs; diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index 1dbf632c1..488687ba9 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp @@ -72,8 +72,10 @@ VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const { VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); - if (cache.find(path) != cache.end()) { - auto weak = cache[path]; + + if (const auto weak_iter = cache.find(path); weak_iter != cache.cend()) { + const auto& weak = weak_iter->second; + if (!weak.expired()) { return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, weak.lock(), path, perms)); } @@ -84,7 +86,7 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { } auto backing = std::make_shared<FS::IOFile>(path, ModeFlagsToString(perms).c_str()); - cache[path] = backing; + cache.insert_or_assign(path, backing); // Cannot use make_shared as RealVfsFile constructor is private return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms)); @@ -116,11 +118,12 @@ VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) { const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); + const auto cached_file_iter = cache.find(old_path); - if (cache.find(old_path) != cache.end()) { - auto file = cache[old_path].lock(); + if (cached_file_iter != cache.cend()) { + auto file = cached_file_iter->second.lock(); - if (!cache[old_path].expired()) { + if (!cached_file_iter->second.expired()) { file->Close(); } @@ -131,7 +134,7 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_ cache.erase(old_path); file->Open(new_path, "r+b"); - cache[new_path] = file; + cache.insert_or_assign(new_path, std::move(file)); } else { UNREACHABLE(); return nullptr; @@ -142,12 +145,15 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_ bool RealVfsFilesystem::DeleteFile(std::string_view path_) { const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); - if (cache.find(path) != cache.end()) { - if (!cache[path].expired()) { - cache[path].lock()->Close(); + const auto cached_iter = cache.find(path); + + if (cached_iter != cache.cend()) { + if (!cached_iter->second.expired()) { + cached_iter->second.lock()->Close(); } cache.erase(path); } + return FS::Delete(path); } @@ -192,21 +198,25 @@ VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_, } for (auto& kv : cache) { - // Path in cache starts with old_path - if (kv.first.rfind(old_path, 0) == 0) { - const auto file_old_path = - FS::SanitizePath(kv.first, FS::DirectorySeparator::PlatformDefault); - const auto file_new_path = - FS::SanitizePath(new_path + DIR_SEP + kv.first.substr(old_path.size()), - FS::DirectorySeparator::PlatformDefault); - auto cached = cache[file_old_path]; - if (!cached.expired()) { - auto file = cached.lock(); - file->Open(file_new_path, "r+b"); - cache.erase(file_old_path); - cache[file_new_path] = file; - } + // If the path in the cache doesn't start with old_path, then bail on this file. + if (kv.first.rfind(old_path, 0) != 0) { + continue; + } + + const auto file_old_path = + FS::SanitizePath(kv.first, FS::DirectorySeparator::PlatformDefault); + auto file_new_path = FS::SanitizePath(new_path + DIR_SEP + kv.first.substr(old_path.size()), + FS::DirectorySeparator::PlatformDefault); + const auto& cached = cache[file_old_path]; + + if (cached.expired()) { + continue; } + + auto file = cached.lock(); + file->Open(file_new_path, "r+b"); + cache.erase(file_old_path); + cache.insert_or_assign(std::move(file_new_path), std::move(file)); } return OpenDirectory(new_path, Mode::ReadWrite); @@ -214,15 +224,21 @@ VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_, bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) { const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); + for (auto& kv : cache) { - // Path in cache starts with old_path - if (kv.first.rfind(path, 0) == 0) { - if (!cache[kv.first].expired()) { - cache[kv.first].lock()->Close(); - } - cache.erase(kv.first); + // If the path in the cache doesn't start with path, then bail on this file. + if (kv.first.rfind(path, 0) != 0) { + continue; } + + const auto& entry = cache[kv.first]; + if (!entry.expired()) { + entry.lock()->Close(); + } + + cache.erase(kv.first); } + return FS::DeleteDirRecursively(path); } @@ -260,14 +276,14 @@ bool RealVfsFile::IsReadable() const { } std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { - if (!backing->Seek(offset, SEEK_SET)) { + if (!backing->Seek(static_cast<s64>(offset), SEEK_SET)) { return 0; } return backing->ReadBytes(data, length); } std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { - if (!backing->Seek(offset, SEEK_SET)) { + if (!backing->Seek(static_cast<s64>(offset), SEEK_SET)) { return 0; } return backing->WriteBytes(data, length); diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp index ccf5966d0..24c58e7ae 100644 --- a/src/core/file_sys/xts_archive.cpp +++ b/src/core/file_sys/xts_archive.cpp @@ -15,8 +15,9 @@ #include "common/hex_util.h" #include "common/string_util.h" #include "core/crypto/aes_util.h" +#include "core/crypto/key_manager.h" #include "core/crypto/xts_encryption_layer.h" -#include "core/file_sys/partition_filesystem.h" +#include "core/file_sys/content_archive.h" #include "core/file_sys/vfs_offset.h" #include "core/file_sys/xts_archive.h" #include "core/loader/loader.h" @@ -43,7 +44,9 @@ static bool CalculateHMAC256(Destination* out, const SourceKey* key, std::size_t return true; } -NAX::NAX(VirtualFile file_) : header(std::make_unique<NAXHeader>()), file(std::move(file_)) { +NAX::NAX(VirtualFile file_) + : header(std::make_unique<NAXHeader>()), + file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} { std::string path = Common::FS::SanitizePath(file->GetFullPath()); static const std::regex nax_path_regex("/registered/(000000[0-9A-F]{2})/([0-9A-F]{32})\\.nca", std::regex_constants::ECMAScript | @@ -60,7 +63,8 @@ NAX::NAX(VirtualFile file_) : header(std::make_unique<NAXHeader>()), file(std::m } NAX::NAX(VirtualFile file_, std::array<u8, 0x10> nca_id) - : header(std::make_unique<NAXHeader>()), file(std::move(file_)) { + : header(std::make_unique<NAXHeader>()), + file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} { Core::Crypto::SHA256Hash hash{}; mbedtls_sha256_ret(nca_id.data(), nca_id.size(), hash.data(), 0); status = Parse(fmt::format("/registered/000000{:02X}/{}.nca", hash[0], diff --git a/src/core/file_sys/xts_archive.h b/src/core/file_sys/xts_archive.h index 563531bb6..c472e226e 100644 --- a/src/core/file_sys/xts_archive.h +++ b/src/core/file_sys/xts_archive.h @@ -9,12 +9,16 @@ #include "common/common_types.h" #include "common/swap.h" #include "core/crypto/key_manager.h" -#include "core/file_sys/content_archive.h" #include "core/file_sys/vfs.h" -#include "core/loader/loader.h" + +namespace Loader { +enum class ResultStatus : u16; +} namespace FileSys { +class NCA; + struct NAXHeader { std::array<u8, 0x20> hmac; u64_le magic; @@ -62,6 +66,6 @@ private: VirtualFile dec_file; - Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); + Core::Crypto::KeyManager& keys; }; } // namespace FileSys diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h index 91ecc30ab..e2e3bbbb3 100644 --- a/src/core/frontend/framebuffer_layout.h +++ b/src/core/frontend/framebuffer_layout.h @@ -4,6 +4,7 @@ #pragma once +#include "common/common_types.h" #include "common/math_util.h" namespace Layout { diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index cabe8d418..f2b0fe2fd 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -219,6 +219,7 @@ struct KernelCore::Impl { return static_cast<u32>(system.GetCpuManager().CurrentCore()); } } + std::unique_lock lock{register_thread_mutex}; const auto it = host_thread_ids.find(this_id); if (it == host_thread_ids.end()) { return Core::INVALID_HOST_THREAD_ID; @@ -324,7 +325,7 @@ struct KernelCore::Impl { std::unordered_map<std::thread::id, u32> host_thread_ids; u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads; - std::mutex register_thread_mutex; + mutable std::mutex register_thread_mutex; // Kernel memory management std::unique_ptr<Memory::MemoryManager> memory_manager; diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 0e7794dc7..45fde8df2 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -24,6 +24,7 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff; constexpr std::size_t NPAD_OFFSET = 0x9A00; constexpr u32 BATTERY_FULL = 2; constexpr u32 MAX_NPAD_ID = 7; +constexpr std::size_t HANDHELD_INDEX = 8; constexpr std::array<u32, 10> npad_id_list{ 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, }; @@ -33,19 +34,41 @@ enum class JoystickId : std::size_t { Joystick_Right, }; -static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type) { +Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad( + Settings::ControllerType type) { switch (type) { case Settings::ControllerType::ProController: - return Controller_NPad::NPadControllerType::ProController; - case Settings::ControllerType::DualJoycon: - return Controller_NPad::NPadControllerType::JoyDual; + return NPadControllerType::ProController; + case Settings::ControllerType::DualJoyconDetached: + return NPadControllerType::JoyDual; case Settings::ControllerType::LeftJoycon: - return Controller_NPad::NPadControllerType::JoyLeft; + return NPadControllerType::JoyLeft; case Settings::ControllerType::RightJoycon: - return Controller_NPad::NPadControllerType::JoyRight; + return NPadControllerType::JoyRight; + case Settings::ControllerType::Handheld: + return NPadControllerType::Handheld; default: UNREACHABLE(); - return Controller_NPad::NPadControllerType::JoyDual; + return NPadControllerType::ProController; + } +} + +Settings::ControllerType Controller_NPad::MapNPadToSettingsType( + Controller_NPad::NPadControllerType type) { + switch (type) { + case NPadControllerType::ProController: + return Settings::ControllerType::ProController; + case NPadControllerType::JoyDual: + return Settings::ControllerType::DualJoyconDetached; + case NPadControllerType::JoyLeft: + return Settings::ControllerType::LeftJoycon; + case NPadControllerType::JoyRight: + return Settings::ControllerType::RightJoycon; + case NPadControllerType::Handheld: + return Settings::ControllerType::Handheld; + default: + UNREACHABLE(); + return Settings::ControllerType::ProController; } } @@ -60,9 +83,9 @@ std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { case 6: case 7: return npad_id; - case 8: + case HANDHELD_INDEX: case NPAD_HANDHELD: - return 8; + return HANDHELD_INDEX; case 9: case NPAD_UNKNOWN: return 9; @@ -83,7 +106,7 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { case 6: case 7: return static_cast<u32>(index); - case 8: + case HANDHELD_INDEX: return NPAD_HANDHELD; case 9: return NPAD_UNKNOWN; @@ -96,25 +119,35 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} Controller_NPad::~Controller_NPad() = default; -void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { +void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { const auto controller_type = connected_controllers[controller_idx].type; auto& controller = shared_memory_entries[controller_idx]; if (controller_type == NPadControllerType::None) { + styleset_changed_events[controller_idx].writable->Signal(); return; } controller.joy_styles.raw = 0; // Zero out controller.device_type.raw = 0; + controller.properties.raw = 0; switch (controller_type) { case NPadControllerType::None: UNREACHABLE(); break; + case NPadControllerType::ProController: + controller.joy_styles.pro_controller.Assign(1); + controller.device_type.pro_controller.Assign(1); + controller.properties.is_vertical.Assign(1); + controller.properties.use_plus.Assign(1); + controller.properties.use_minus.Assign(1); + controller.pad_assignment = NPadAssignments::Single; + break; case NPadControllerType::Handheld: controller.joy_styles.handheld.Assign(1); controller.device_type.handheld.Assign(1); - controller.pad_assignment = NPadAssignments::Dual; controller.properties.is_vertical.Assign(1); controller.properties.use_plus.Assign(1); controller.properties.use_minus.Assign(1); + controller.pad_assignment = NPadAssignments::Dual; break; case NPadControllerType::JoyDual: controller.joy_styles.joycon_dual.Assign(1); @@ -144,14 +177,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.device_type.pokeball.Assign(1); controller.pad_assignment = NPadAssignments::Single; break; - case NPadControllerType::ProController: - controller.joy_styles.pro_controller.Assign(1); - controller.device_type.pro_controller.Assign(1); - controller.properties.is_vertical.Assign(1); - controller.properties.use_plus.Assign(1); - controller.properties.use_minus.Assign(1); - controller.pad_assignment = NPadAssignments::Single; - break; } controller.single_color_error = ColorReadError::ReadOk; @@ -192,36 +217,25 @@ void Controller_NPad::OnInit() { style.pokeball.Assign(1); } - std::transform( - Settings::values.players.begin(), Settings::values.players.end(), - connected_controllers.begin(), [](const Settings::PlayerInput& player) { - return ControllerHolder{MapSettingsTypeToNPad(player.type), player.connected}; - }); - - std::stable_partition(connected_controllers.begin(), connected_controllers.begin() + 8, - [](const ControllerHolder& holder) { return holder.is_connected; }); + std::transform(Settings::values.players.begin(), Settings::values.players.end(), + connected_controllers.begin(), [](const Settings::PlayerInput& player) { + return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), + player.connected}; + }); // Account for handheld - if (connected_controllers[8].is_connected) - connected_controllers[8].type = NPadControllerType::Handheld; + if (connected_controllers[HANDHELD_INDEX].is_connected) { + connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; + } supported_npad_id_types.resize(npad_id_list.size()); std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), npad_id_list.size() * sizeof(u32)); - // Add a default dual joycon controller if none are present. - if (std::none_of(connected_controllers.begin(), connected_controllers.end(), - [](const ControllerHolder& controller) { return controller.is_connected; })) { - supported_npad_id_types.resize(npad_id_list.size()); - std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), - npad_id_list.size() * sizeof(u32)); - AddNewController(NPadControllerType::JoyDual); - } - for (std::size_t i = 0; i < connected_controllers.size(); ++i) { const auto& controller = connected_controllers[i]; if (controller.is_connected) { - AddNewControllerAt(controller.type, IndexToNPad(i)); + AddNewControllerAt(controller.type, i); } } } @@ -309,8 +323,9 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t data_len) { - if (!IsControllerActivated()) + if (!IsControllerActivated()) { return; + } for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { auto& npad = shared_memory_entries[i]; const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, @@ -360,13 +375,25 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; libnx_entry.connection_status.raw = 0; + libnx_entry.connection_status.IsConnected.Assign(1); switch (controller_type) { case NPadControllerType::None: UNREACHABLE(); break; + case NPadControllerType::ProController: + main_controller.connection_status.raw = 0; + main_controller.connection_status.IsConnected.Assign(1); + main_controller.connection_status.IsWired.Assign(1); + main_controller.pad.pad_states.raw = pad_state.pad_states.raw; + main_controller.pad.l_stick = pad_state.l_stick; + main_controller.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsWired.Assign(1); + break; case NPadControllerType::Handheld: handheld_entry.connection_status.raw = 0; + handheld_entry.connection_status.IsConnected.Assign(1); handheld_entry.connection_status.IsWired.Assign(1); handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); handheld_entry.connection_status.IsRightJoyConnected.Assign(1); @@ -375,57 +402,52 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; handheld_entry.pad.l_stick = pad_state.l_stick; handheld_entry.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsWired.Assign(1); + libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); + libnx_entry.connection_status.IsRightJoyConnected.Assign(1); + libnx_entry.connection_status.IsLeftJoyWired.Assign(1); + libnx_entry.connection_status.IsRightJoyWired.Assign(1); break; case NPadControllerType::JoyDual: dual_entry.connection_status.raw = 0; - + dual_entry.connection_status.IsConnected.Assign(1); dual_entry.connection_status.IsLeftJoyConnected.Assign(1); dual_entry.connection_status.IsRightJoyConnected.Assign(1); - dual_entry.connection_status.IsConnected.Assign(1); - - libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); - libnx_entry.connection_status.IsRightJoyConnected.Assign(1); - libnx_entry.connection_status.IsConnected.Assign(1); - dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; dual_entry.pad.l_stick = pad_state.l_stick; dual_entry.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); + libnx_entry.connection_status.IsRightJoyConnected.Assign(1); break; case NPadControllerType::JoyLeft: left_entry.connection_status.raw = 0; - left_entry.connection_status.IsConnected.Assign(1); + left_entry.connection_status.IsLeftJoyConnected.Assign(1); left_entry.pad.pad_states.raw = pad_state.pad_states.raw; left_entry.pad.l_stick = pad_state.l_stick; left_entry.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); break; case NPadControllerType::JoyRight: right_entry.connection_status.raw = 0; - right_entry.connection_status.IsConnected.Assign(1); + right_entry.connection_status.IsRightJoyConnected.Assign(1); right_entry.pad.pad_states.raw = pad_state.pad_states.raw; right_entry.pad.l_stick = pad_state.l_stick; right_entry.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsRightJoyConnected.Assign(1); break; case NPadControllerType::Pokeball: pokeball_entry.connection_status.raw = 0; - pokeball_entry.connection_status.IsConnected.Assign(1); - pokeball_entry.connection_status.IsWired.Assign(1); - pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; pokeball_entry.pad.l_stick = pad_state.l_stick; pokeball_entry.pad.r_stick = pad_state.r_stick; break; - case NPadControllerType::ProController: - main_controller.connection_status.raw = 0; - - main_controller.connection_status.IsConnected.Assign(1); - main_controller.connection_status.IsWired.Assign(1); - main_controller.pad.pad_states.raw = pad_state.pad_states.raw; - main_controller.pad.l_stick = pad_state.l_stick; - main_controller.pad.r_stick = pad_state.r_stick; - break; } // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate @@ -453,26 +475,6 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { supported_npad_id_types.clear(); supported_npad_id_types.resize(length / sizeof(u32)); std::memcpy(supported_npad_id_types.data(), data, length); - for (std::size_t i = 0; i < connected_controllers.size(); i++) { - auto& controller = connected_controllers[i]; - if (!controller.is_connected) { - continue; - } - const auto requested_controller = - i <= MAX_NPAD_ID ? MapSettingsTypeToNPad(Settings::values.players[i].type) - : NPadControllerType::Handheld; - if (!IsControllerSupported(requested_controller)) { - const auto is_handheld = requested_controller == NPadControllerType::Handheld; - if (is_handheld) { - controller.type = NPadControllerType::None; - controller.is_connected = false; - AddNewController(requested_controller); - } else { - controller.type = requested_controller; - InitNewlyAddedControler(i); - } - } - } } void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { @@ -504,7 +506,7 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, const std::vector<Vibration>& vibrations) { LOG_DEBUG(Service_HID, "(STUBBED) called"); - if (!can_controllers_vibrate) { + if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { return; } for (std::size_t i = 0; i < controller_ids.size(); i++) { @@ -517,8 +519,6 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, } std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { - // TODO(ogniK): Figure out the best time to signal this event. This event seems that it should - // be signalled at least once, and signaled after a new controller is connected? const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; return styleset_event.readable; } @@ -527,43 +527,43 @@ Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { return last_processed_vibration; } -void Controller_NPad::AddNewController(NPadControllerType controller) { - controller = DecideBestController(controller); - if (controller == NPadControllerType::Handheld) { - connected_controllers[8] = {controller, true}; - InitNewlyAddedControler(8); - return; - } - const auto pos = - std::find_if(connected_controllers.begin(), connected_controllers.end() - 2, - [](const ControllerHolder& holder) { return !holder.is_connected; }); - if (pos == connected_controllers.end() - 2) { - LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); +void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { + UpdateControllerAt(controller, npad_index, true); +} + +void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, + bool connected) { + if (!connected) { + DisconnectNPad(IndexToNPad(npad_index)); return; } - const auto controller_id = std::distance(connected_controllers.begin(), pos); - connected_controllers[controller_id] = {controller, true}; - InitNewlyAddedControler(controller_id); -} -void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) { - controller = DecideBestController(controller); if (controller == NPadControllerType::Handheld) { - connected_controllers[NPadIdToIndex(NPAD_HANDHELD)] = {controller, true}; - InitNewlyAddedControler(NPadIdToIndex(NPAD_HANDHELD)); + Settings::values.players[HANDHELD_INDEX].controller_type = + MapNPadToSettingsType(controller); + Settings::values.players[HANDHELD_INDEX].connected = true; + connected_controllers[HANDHELD_INDEX] = {controller, true}; + InitNewlyAddedController(HANDHELD_INDEX); return; } - connected_controllers[NPadIdToIndex(npad_id)] = {controller, true}; - InitNewlyAddedControler(NPadIdToIndex(npad_id)); -} - -void Controller_NPad::ConnectNPad(u32 npad_id) { - connected_controllers[NPadIdToIndex(npad_id)].is_connected = true; + Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller); + Settings::values.players[npad_index].connected = true; + connected_controllers[npad_index] = {controller, true}; + InitNewlyAddedController(npad_index); } void Controller_NPad::DisconnectNPad(u32 npad_id) { - connected_controllers[NPadIdToIndex(npad_id)].is_connected = false; + const auto npad_index = NPadIdToIndex(npad_id); + connected_controllers[npad_index].is_connected = false; + Settings::values.players[npad_index].connected = false; + + auto& controller = shared_memory_entries[npad_index]; + controller.joy_styles.raw = 0; // Zero out + controller.device_type.raw = 0; + controller.properties.raw = 0; + + styleset_changed_events[npad_index].writable->Signal(); } void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { @@ -599,8 +599,8 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type); - InitNewlyAddedControler(npad_index_1); - InitNewlyAddedControler(npad_index_2); + AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1); + AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2); return true; } @@ -614,11 +614,11 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { case 0: return LedPattern{1, 0, 0, 0}; case 1: - return LedPattern{0, 1, 0, 0}; + return LedPattern{1, 1, 0, 0}; case 2: - return LedPattern{0, 0, 1, 0}; + return LedPattern{1, 1, 1, 0}; case 3: - return LedPattern{0, 0, 0, 1}; + return LedPattern{1, 1, 1, 1}; case 4: return LedPattern{1, 0, 0, 1}; case 5: @@ -628,7 +628,6 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { case 7: return LedPattern{0, 1, 1, 0}; default: - UNIMPLEMENTED_MSG("Unhandled npad_id {}", npad_id); return LedPattern{0, 0, 0, 0}; } } diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 5d4c58a43..75ce5b731 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -118,10 +118,11 @@ public: std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; Vibration GetLastVibration() const; - void AddNewController(NPadControllerType controller); - void AddNewControllerAt(NPadControllerType controller, u32 npad_id); + // Adds a new controller at an index. + void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index); + // Adds a new controller at an index with connection status. + void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); - void ConnectNPad(u32 npad_id); void DisconnectNPad(u32 npad_id); void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; @@ -141,6 +142,8 @@ public: // Specifically for cheat engine and other features. u32 GetAndResetPressState(); + static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type); + static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); static std::size_t NPadIdToIndex(u32 npad_id); static u32 IndexToNPad(std::size_t index); @@ -309,7 +312,7 @@ private: bool is_connected; }; - void InitNewlyAddedControler(std::size_t controller_idx); + void InitNewlyAddedController(std::size_t controller_idx); bool IsControllerSupported(NPadControllerType controller) const; NPadControllerType DecideBestController(NPadControllerType priority) const; void RequestPadStateUpdate(u32 npad_id); diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index e326f8f5c..0df395e85 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -40,9 +40,14 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin cur_entry.sampling_number = last_entry.sampling_number + 1; cur_entry.sampling_number2 = cur_entry.sampling_number; - const auto [x, y, pressed] = touch_device->GetStatus(); + bool pressed = false; + float x, y; + std::tie(x, y, pressed) = touch_device->GetStatus(); auto& touch_entry = cur_entry.states[0]; touch_entry.attribute.raw = 0; + if (!pressed && touch_btn_device) { + std::tie(x, y, pressed) = touch_btn_device->GetStatus(); + } if (pressed && Settings::values.touchscreen.enabled) { touch_entry.x = static_cast<u16>(x * Layout::ScreenUndocked::Width); touch_entry.y = static_cast<u16>(y * Layout::ScreenUndocked::Height); @@ -63,5 +68,10 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin void Controller_Touchscreen::OnLoadInputDevices() { touch_device = Input::CreateDevice<Input::TouchDevice>(Settings::values.touchscreen.device); + if (Settings::values.use_touch_from_button) { + touch_btn_device = Input::CreateDevice<Input::TouchDevice>("engine:touch_from_button"); + } else { + touch_btn_device.reset(); + } } } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index a1d97269e..4d9042adc 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -68,6 +68,7 @@ private: "TouchScreenSharedMemory is an invalid size"); TouchScreenSharedMemory shared_memory{}; std::unique_ptr<Input::TouchDevice> touch_device; + std::unique_ptr<Input::TouchDevice> touch_btn_device; s64_le last_touch{}; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 1e95b7580..33416b5dd 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -38,11 +38,9 @@ namespace Service::HID { // Updating period for each HID device. -// TODO(ogniK): Find actual polling rate of hid -constexpr auto pad_update_ns = std::chrono::nanoseconds{1000000000 / 66}; -[[maybe_unused]] constexpr auto accelerometer_update_ns = - std::chrono::nanoseconds{1000000000 / 100}; -[[maybe_unused]] constexpr auto gyroscope_update_ticks = std::chrono::nanoseconds{1000000000 / 100}; +// HID is polled every 15ms, this value was derived from +// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet +constexpr auto pad_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.6Hz) constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; IAppletResource::IAppletResource(Core::System& system) @@ -845,8 +843,7 @@ void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto can_vibrate{rp.Pop<bool>()}; - applet_resource->GetController<Controller_NPad>(HidController::NPad) - .SetVibrationEnabled(can_vibrate); + Settings::values.vibration_enabled = can_vibrate; LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); @@ -859,8 +856,7 @@ void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push( - applet_resource->GetController<Controller_NPad>(HidController::NPad).IsVibrationEnabled()); + rb.Push(Settings::values.vibration_enabled); } void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 886450be2..58ee1f712 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -5,6 +5,7 @@ #include "common/logging/log.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" +#include "core/file_sys/vfs.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/hle_ipc.h" #include "core/hle/service/ns/errors.h" diff --git a/src/core/settings.cpp b/src/core/settings.cpp index d328fb8b7..28d3f9099 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -13,56 +13,6 @@ namespace Settings { -namespace NativeButton { -const std::array<const char*, NumButtons> mapping = {{ - "button_a", - "button_b", - "button_x", - "button_y", - "button_lstick", - "button_rstick", - "button_l", - "button_r", - "button_zl", - "button_zr", - "button_plus", - "button_minus", - "button_dleft", - "button_dup", - "button_dright", - "button_ddown", - "button_lstick_left", - "button_lstick_up", - "button_lstick_right", - "button_lstick_down", - "button_rstick_left", - "button_rstick_up", - "button_rstick_right", - "button_rstick_down", - "button_sl", - "button_sr", - "button_home", - "button_screenshot", -}}; -} - -namespace NativeAnalog { -const std::array<const char*, NumAnalogs> mapping = {{ - "lstick", - "rstick", -}}; -} - -namespace NativeMouseButton { -const std::array<const char*, NumMouseButtons> mapping = {{ - "left", - "right", - "middle", - "forward", - "back", -}}; -} - Values values = {}; bool configuring_global = true; diff --git a/src/core/settings.h b/src/core/settings.h index bb145f193..80f0d95a7 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -12,340 +12,10 @@ #include <string> #include <vector> #include "common/common_types.h" +#include "input_common/settings.h" namespace Settings { -namespace NativeButton { -enum Values { - A, - B, - X, - Y, - LStick, - RStick, - L, - R, - ZL, - ZR, - Plus, - Minus, - - DLeft, - DUp, - DRight, - DDown, - - LStick_Left, - LStick_Up, - LStick_Right, - LStick_Down, - - RStick_Left, - RStick_Up, - RStick_Right, - RStick_Down, - - SL, - SR, - - Home, - Screenshot, - - NumButtons, -}; - -constexpr int BUTTON_HID_BEGIN = A; -constexpr int BUTTON_NS_BEGIN = Home; - -constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN; -constexpr int BUTTON_NS_END = NumButtons; - -constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN; -constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN; - -extern const std::array<const char*, NumButtons> mapping; - -} // namespace NativeButton - -namespace NativeAnalog { -enum Values { - LStick, - RStick, - - NumAnalogs, -}; - -constexpr int STICK_HID_BEGIN = LStick; -constexpr int STICK_HID_END = NumAnalogs; -constexpr int NUM_STICKS_HID = NumAnalogs; - -extern const std::array<const char*, NumAnalogs> mapping; -} // namespace NativeAnalog - -namespace NativeMouseButton { -enum Values { - Left, - Right, - Middle, - Forward, - Back, - - NumMouseButtons, -}; - -constexpr int MOUSE_HID_BEGIN = Left; -constexpr int MOUSE_HID_END = NumMouseButtons; -constexpr int NUM_MOUSE_HID = NumMouseButtons; - -extern const std::array<const char*, NumMouseButtons> mapping; -} // namespace NativeMouseButton - -namespace NativeKeyboard { -enum Keys { - None, - Error, - - A = 4, - B, - C, - D, - E, - F, - G, - H, - I, - J, - K, - L, - M, - N, - O, - P, - Q, - R, - S, - T, - U, - V, - W, - X, - Y, - Z, - N1, - N2, - N3, - N4, - N5, - N6, - N7, - N8, - N9, - N0, - Enter, - Escape, - Backspace, - Tab, - Space, - Minus, - Equal, - LeftBrace, - RightBrace, - Backslash, - Tilde, - Semicolon, - Apostrophe, - Grave, - Comma, - Dot, - Slash, - CapsLockKey, - - F1, - F2, - F3, - F4, - F5, - F6, - F7, - F8, - F9, - F10, - F11, - F12, - - SystemRequest, - ScrollLockKey, - Pause, - Insert, - Home, - PageUp, - Delete, - End, - PageDown, - Right, - Left, - Down, - Up, - - NumLockKey, - KPSlash, - KPAsterisk, - KPMinus, - KPPlus, - KPEnter, - KP1, - KP2, - KP3, - KP4, - KP5, - KP6, - KP7, - KP8, - KP9, - KP0, - KPDot, - - Key102, - Compose, - Power, - KPEqual, - - F13, - F14, - F15, - F16, - F17, - F18, - F19, - F20, - F21, - F22, - F23, - F24, - - Open, - Help, - Properties, - Front, - Stop, - Repeat, - Undo, - Cut, - Copy, - Paste, - Find, - Mute, - VolumeUp, - VolumeDown, - CapsLockActive, - NumLockActive, - ScrollLockActive, - KPComma, - - KPLeftParenthesis, - KPRightParenthesis, - - LeftControlKey = 0xE0, - LeftShiftKey, - LeftAltKey, - LeftMetaKey, - RightControlKey, - RightShiftKey, - RightAltKey, - RightMetaKey, - - MediaPlayPause, - MediaStopCD, - MediaPrevious, - MediaNext, - MediaEject, - MediaVolumeUp, - MediaVolumeDown, - MediaMute, - MediaWebsite, - MediaBack, - MediaForward, - MediaStop, - MediaFind, - MediaScrollUp, - MediaScrollDown, - MediaEdit, - MediaSleep, - MediaCoffee, - MediaRefresh, - MediaCalculator, - - NumKeyboardKeys, -}; - -static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys."); - -enum Modifiers { - LeftControl, - LeftShift, - LeftAlt, - LeftMeta, - RightControl, - RightShift, - RightAlt, - RightMeta, - CapsLock, - ScrollLock, - NumLock, - - NumKeyboardMods, -}; - -constexpr int KEYBOARD_KEYS_HID_BEGIN = None; -constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys; -constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys; - -constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl; -constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods; -constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; - -} // namespace NativeKeyboard - -using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>; -using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; -using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; -using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; -using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; - -constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; -constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; -constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; -constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; - -enum class ControllerType { - ProController, - DualJoycon, - RightJoycon, - LeftJoycon, -}; - -struct PlayerInput { - bool connected; - ControllerType type; - ButtonsRaw buttons; - AnalogsRaw analogs; - - u32 body_color_right; - u32 button_color_right; - u32 body_color_left; - u32 button_color_left; -}; - -struct TouchscreenInput { - bool enabled; - std::string device; - - u32 finger; - u32 diameter_x; - u32 diameter_y; - u32 rotation_angle; -}; - enum class RendererBackend { OpenGL = 0, Vulkan = 1, @@ -359,7 +29,8 @@ enum class GPUAccuracy : u32 { enum class CPUAccuracy { Accurate = 0, - DebugMode = 1, + Unsafe = 1, + DebugMode = 2, }; extern bool configuring_global; @@ -396,6 +67,11 @@ private: Type local{}; }; +struct TouchFromButtonMap { + std::string name; + std::vector<std::string> buttons; +}; + struct Values { // Audio std::string audio_device_id; @@ -419,6 +95,9 @@ struct Values { bool cpuopt_misc_ir; bool cpuopt_reduce_misalign_checks; + bool cpuopt_unsafe_unfuse_fma; + bool cpuopt_unsafe_reduce_fp_error; + // Renderer Setting<RendererBackend> renderer_backend; bool renderer_debug; @@ -457,6 +136,8 @@ struct Values { // Controls std::array<PlayerInput, 10> players; + bool use_docked_mode; + bool mouse_enabled; std::string mouse_device; MouseButtonsRaw mouse_buttons; @@ -469,14 +150,18 @@ struct Values { ButtonsRaw debug_pad_buttons; AnalogsRaw debug_pad_analogs; + bool vibration_enabled; + std::string motion_device; + std::string touch_device; TouchscreenInput touchscreen; std::atomic_bool is_device_reload_pending{true}; + bool use_touch_from_button; + int touch_from_button_map_index; std::string udp_input_address; u16 udp_input_port; u8 udp_pad_index; - - bool use_docked_mode; + std::vector<TouchFromButtonMap> touch_from_button_maps; // Data Storage bool use_virtual_sd; |