diff options
Diffstat (limited to 'src/core')
50 files changed, 492 insertions, 399 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index e598c0e2b..42277e2cd 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -146,7 +146,7 @@ struct System::Impl { | |||
| 146 | ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) { | 146 | ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) { |
| 147 | LOG_DEBUG(HW_Memory, "initialized OK"); | 147 | LOG_DEBUG(HW_Memory, "initialized OK"); |
| 148 | 148 | ||
| 149 | device_memory = std::make_unique<Core::DeviceMemory>(system); | 149 | device_memory = std::make_unique<Core::DeviceMemory>(); |
| 150 | 150 | ||
| 151 | is_multicore = Settings::values.use_multi_core.GetValue(); | 151 | is_multicore = Settings::values.use_multi_core.GetValue(); |
| 152 | is_async_gpu = is_multicore || Settings::values.use_asynchronous_gpu_emulation.GetValue(); | 152 | is_async_gpu = is_multicore || Settings::values.use_asynchronous_gpu_emulation.GetValue(); |
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index b5feb3f24..71af26ec5 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -23,7 +23,7 @@ std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callbac | |||
| 23 | struct CoreTiming::Event { | 23 | struct CoreTiming::Event { |
| 24 | u64 time; | 24 | u64 time; |
| 25 | u64 fifo_order; | 25 | u64 fifo_order; |
| 26 | u64 userdata; | 26 | std::uintptr_t user_data; |
| 27 | std::weak_ptr<EventType> type; | 27 | std::weak_ptr<EventType> type; |
| 28 | 28 | ||
| 29 | // Sort by time, unless the times are the same, in which case sort by | 29 | // Sort by time, unless the times are the same, in which case sort by |
| @@ -58,7 +58,7 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) { | |||
| 58 | event_fifo_id = 0; | 58 | event_fifo_id = 0; |
| 59 | shutting_down = false; | 59 | shutting_down = false; |
| 60 | ticks = 0; | 60 | ticks = 0; |
| 61 | const auto empty_timed_callback = [](u64, std::chrono::nanoseconds) {}; | 61 | const auto empty_timed_callback = [](std::uintptr_t, std::chrono::nanoseconds) {}; |
| 62 | ev_lost = CreateEvent("_lost_event", empty_timed_callback); | 62 | ev_lost = CreateEvent("_lost_event", empty_timed_callback); |
| 63 | if (is_multicore) { | 63 | if (is_multicore) { |
| 64 | timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); | 64 | timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); |
| @@ -107,22 +107,24 @@ bool CoreTiming::HasPendingEvents() const { | |||
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future, | 109 | void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future, |
| 110 | const std::shared_ptr<EventType>& event_type, u64 userdata) { | 110 | const std::shared_ptr<EventType>& event_type, |
| 111 | std::uintptr_t user_data) { | ||
| 111 | { | 112 | { |
| 112 | std::scoped_lock scope{basic_lock}; | 113 | std::scoped_lock scope{basic_lock}; |
| 113 | const u64 timeout = static_cast<u64>((GetGlobalTimeNs() + ns_into_future).count()); | 114 | const u64 timeout = static_cast<u64>((GetGlobalTimeNs() + ns_into_future).count()); |
| 114 | 115 | ||
| 115 | event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type}); | 116 | event_queue.emplace_back(Event{timeout, event_fifo_id++, user_data, event_type}); |
| 116 | 117 | ||
| 117 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | 118 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); |
| 118 | } | 119 | } |
| 119 | event.Set(); | 120 | event.Set(); |
| 120 | } | 121 | } |
| 121 | 122 | ||
| 122 | void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata) { | 123 | void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, |
| 124 | std::uintptr_t user_data) { | ||
| 123 | std::scoped_lock scope{basic_lock}; | 125 | std::scoped_lock scope{basic_lock}; |
| 124 | const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { | 126 | const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { |
| 125 | return e.type.lock().get() == event_type.get() && e.userdata == userdata; | 127 | return e.type.lock().get() == event_type.get() && e.user_data == user_data; |
| 126 | }); | 128 | }); |
| 127 | 129 | ||
| 128 | // Removing random items breaks the invariant so we have to re-establish it. | 130 | // Removing random items breaks the invariant so we have to re-establish it. |
| @@ -197,7 +199,7 @@ std::optional<s64> CoreTiming::Advance() { | |||
| 197 | 199 | ||
| 198 | if (const auto event_type{evt.type.lock()}) { | 200 | if (const auto event_type{evt.type.lock()}) { |
| 199 | event_type->callback( | 201 | event_type->callback( |
| 200 | evt.userdata, std::chrono::nanoseconds{static_cast<s64>(global_timer - evt.time)}); | 202 | evt.user_data, std::chrono::nanoseconds{static_cast<s64>(global_timer - evt.time)}); |
| 201 | } | 203 | } |
| 202 | 204 | ||
| 203 | basic_lock.lock(); | 205 | basic_lock.lock(); |
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 120c74e46..b0b6036e4 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -22,7 +22,8 @@ | |||
| 22 | namespace Core::Timing { | 22 | namespace Core::Timing { |
| 23 | 23 | ||
| 24 | /// A callback that may be scheduled for a particular core timing event. | 24 | /// A callback that may be scheduled for a particular core timing event. |
| 25 | using TimedCallback = std::function<void(u64 userdata, std::chrono::nanoseconds ns_late)>; | 25 | using TimedCallback = |
| 26 | std::function<void(std::uintptr_t user_data, std::chrono::nanoseconds ns_late)>; | ||
| 26 | 27 | ||
| 27 | /// Contains the characteristics of a particular event. | 28 | /// Contains the characteristics of a particular event. |
| 28 | struct EventType { | 29 | struct EventType { |
| @@ -94,9 +95,9 @@ public: | |||
| 94 | 95 | ||
| 95 | /// Schedules an event in core timing | 96 | /// Schedules an event in core timing |
| 96 | void ScheduleEvent(std::chrono::nanoseconds ns_into_future, | 97 | void ScheduleEvent(std::chrono::nanoseconds ns_into_future, |
| 97 | const std::shared_ptr<EventType>& event_type, u64 userdata = 0); | 98 | const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data = 0); |
| 98 | 99 | ||
| 99 | void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata); | 100 | void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data); |
| 100 | 101 | ||
| 101 | /// We only permit one event of each type in the queue at a time. | 102 | /// We only permit one event of each type in the queue at a time. |
| 102 | void RemoveEvent(const std::shared_ptr<EventType>& event_type); | 103 | void RemoveEvent(const std::shared_ptr<EventType>& event_type); |
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 32afcf3ae..358943429 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp | |||
| @@ -52,15 +52,15 @@ void CpuManager::Shutdown() { | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | std::function<void(void*)> CpuManager::GetGuestThreadStartFunc() { | 54 | std::function<void(void*)> CpuManager::GetGuestThreadStartFunc() { |
| 55 | return std::function<void(void*)>(GuestThreadFunction); | 55 | return GuestThreadFunction; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | std::function<void(void*)> CpuManager::GetIdleThreadStartFunc() { | 58 | std::function<void(void*)> CpuManager::GetIdleThreadStartFunc() { |
| 59 | return std::function<void(void*)>(IdleThreadFunction); | 59 | return IdleThreadFunction; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | std::function<void(void*)> CpuManager::GetSuspendThreadStartFunc() { | 62 | std::function<void(void*)> CpuManager::GetSuspendThreadStartFunc() { |
| 63 | return std::function<void(void*)>(SuspendThreadFunction); | 63 | return SuspendThreadFunction; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | void CpuManager::GuestThreadFunction(void* cpu_manager_) { | 66 | void CpuManager::GuestThreadFunction(void* cpu_manager_) { |
diff --git a/src/core/device_memory.cpp b/src/core/device_memory.cpp index 51097ced3..0c4b440ed 100644 --- a/src/core/device_memory.cpp +++ b/src/core/device_memory.cpp | |||
| @@ -2,14 +2,11 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/device_memory.h" | 5 | #include "core/device_memory.h" |
| 7 | #include "core/memory.h" | ||
| 8 | 6 | ||
| 9 | namespace Core { | 7 | namespace Core { |
| 10 | 8 | ||
| 11 | DeviceMemory::DeviceMemory(System& system) : buffer{DramMemoryMap::Size}, system{system} {} | 9 | DeviceMemory::DeviceMemory() : buffer{DramMemoryMap::Size} {} |
| 12 | |||
| 13 | DeviceMemory::~DeviceMemory() = default; | 10 | DeviceMemory::~DeviceMemory() = default; |
| 14 | 11 | ||
| 15 | } // namespace Core | 12 | } // namespace Core |
diff --git a/src/core/device_memory.h b/src/core/device_memory.h index 9efa088d0..5b1ae28f3 100644 --- a/src/core/device_memory.h +++ b/src/core/device_memory.h | |||
| @@ -4,14 +4,11 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/assert.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/common_funcs.h" | ||
| 9 | #include "common/virtual_buffer.h" | 8 | #include "common/virtual_buffer.h" |
| 10 | 9 | ||
| 11 | namespace Core { | 10 | namespace Core { |
| 12 | 11 | ||
| 13 | class System; | ||
| 14 | |||
| 15 | namespace DramMemoryMap { | 12 | namespace DramMemoryMap { |
| 16 | enum : u64 { | 13 | enum : u64 { |
| 17 | Base = 0x80000000ULL, | 14 | Base = 0x80000000ULL, |
| @@ -26,7 +23,7 @@ enum : u64 { | |||
| 26 | 23 | ||
| 27 | class DeviceMemory : NonCopyable { | 24 | class DeviceMemory : NonCopyable { |
| 28 | public: | 25 | public: |
| 29 | explicit DeviceMemory(Core::System& system); | 26 | explicit DeviceMemory(); |
| 30 | ~DeviceMemory(); | 27 | ~DeviceMemory(); |
| 31 | 28 | ||
| 32 | template <typename T> | 29 | template <typename T> |
| @@ -45,7 +42,6 @@ public: | |||
| 45 | 42 | ||
| 46 | private: | 43 | private: |
| 47 | Common::VirtualBuffer<u8> buffer; | 44 | Common::VirtualBuffer<u8> buffer; |
| 48 | Core::System& system; | ||
| 49 | }; | 45 | }; |
| 50 | 46 | ||
| 51 | } // namespace Core | 47 | } // namespace Core |
diff --git a/src/core/file_sys/mode.h b/src/core/file_sys/mode.h index c95205668..2b4f21073 100644 --- a/src/core/file_sys/mode.h +++ b/src/core/file_sys/mode.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_funcs.h" | ||
| 7 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 8 | 9 | ||
| 9 | namespace FileSys { | 10 | namespace FileSys { |
| @@ -11,13 +12,11 @@ namespace FileSys { | |||
| 11 | enum class Mode : u32 { | 12 | enum class Mode : u32 { |
| 12 | Read = 1, | 13 | Read = 1, |
| 13 | Write = 2, | 14 | Write = 2, |
| 14 | ReadWrite = 3, | 15 | ReadWrite = Read | Write, |
| 15 | Append = 4, | 16 | Append = 4, |
| 16 | WriteAppend = 6, | 17 | WriteAppend = Write | Append, |
| 17 | }; | 18 | }; |
| 18 | 19 | ||
| 19 | inline u32 operator&(Mode lhs, Mode rhs) { | 20 | DECLARE_ENUM_FLAG_OPERATORS(Mode) |
| 20 | return static_cast<u32>(lhs) & static_cast<u32>(rhs); | ||
| 21 | } | ||
| 22 | 21 | ||
| 23 | } // namespace FileSys | 22 | } // namespace FileSys |
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index c47ff863e..729dbb5f4 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp | |||
| @@ -288,8 +288,8 @@ std::optional<std::vector<Core::Memory::CheatEntry>> ReadCheatFileFromFolder( | |||
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | Core::Memory::TextCheatParser parser; | 290 | Core::Memory::TextCheatParser parser; |
| 291 | return parser.Parse( | 291 | return parser.Parse(system, |
| 292 | system, std::string_view(reinterpret_cast<const char* const>(data.data()), data.size())); | 292 | std::string_view(reinterpret_cast<const char*>(data.data()), data.size())); |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | } // Anonymous namespace | 295 | } // Anonymous namespace |
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 37351c561..f831487dd 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp | |||
| @@ -344,15 +344,18 @@ VirtualFile RegisteredCache::GetFileAtID(NcaID id) const { | |||
| 344 | 344 | ||
| 345 | static std::optional<NcaID> CheckMapForContentRecord(const std::map<u64, CNMT>& map, u64 title_id, | 345 | static std::optional<NcaID> CheckMapForContentRecord(const std::map<u64, CNMT>& map, u64 title_id, |
| 346 | ContentRecordType type) { | 346 | ContentRecordType type) { |
| 347 | if (map.find(title_id) == map.end()) | 347 | const auto cmnt_iter = map.find(title_id); |
| 348 | return {}; | 348 | if (cmnt_iter == map.cend()) { |
| 349 | 349 | return std::nullopt; | |
| 350 | const auto& cnmt = map.at(title_id); | 350 | } |
| 351 | 351 | ||
| 352 | const auto iter = std::find_if(cnmt.GetContentRecords().begin(), cnmt.GetContentRecords().end(), | 352 | const auto& cnmt = cmnt_iter->second; |
| 353 | const auto& content_records = cnmt.GetContentRecords(); | ||
| 354 | const auto iter = std::find_if(content_records.cbegin(), content_records.cend(), | ||
| 353 | [type](const ContentRecord& rec) { return rec.type == type; }); | 355 | [type](const ContentRecord& rec) { return rec.type == type; }); |
| 354 | if (iter == cnmt.GetContentRecords().end()) | 356 | if (iter == content_records.cend()) { |
| 355 | return {}; | 357 | return std::nullopt; |
| 358 | } | ||
| 356 | 359 | ||
| 357 | return std::make_optional(iter->nca_id); | 360 | return std::make_optional(iter->nca_id); |
| 358 | } | 361 | } |
| @@ -467,14 +470,16 @@ VirtualFile RegisteredCache::GetEntryUnparsed(u64 title_id, ContentRecordType ty | |||
| 467 | 470 | ||
| 468 | std::optional<u32> RegisteredCache::GetEntryVersion(u64 title_id) const { | 471 | std::optional<u32> RegisteredCache::GetEntryVersion(u64 title_id) const { |
| 469 | const auto meta_iter = meta.find(title_id); | 472 | const auto meta_iter = meta.find(title_id); |
| 470 | if (meta_iter != meta.end()) | 473 | if (meta_iter != meta.cend()) { |
| 471 | return meta_iter->second.GetTitleVersion(); | 474 | return meta_iter->second.GetTitleVersion(); |
| 475 | } | ||
| 472 | 476 | ||
| 473 | const auto yuzu_meta_iter = yuzu_meta.find(title_id); | 477 | const auto yuzu_meta_iter = yuzu_meta.find(title_id); |
| 474 | if (yuzu_meta_iter != yuzu_meta.end()) | 478 | if (yuzu_meta_iter != yuzu_meta.cend()) { |
| 475 | return yuzu_meta_iter->second.GetTitleVersion(); | 479 | return yuzu_meta_iter->second.GetTitleVersion(); |
| 480 | } | ||
| 476 | 481 | ||
| 477 | return {}; | 482 | return std::nullopt; |
| 478 | } | 483 | } |
| 479 | 484 | ||
| 480 | VirtualFile RegisteredCache::GetEntryRaw(u64 title_id, ContentRecordType type) const { | 485 | VirtualFile RegisteredCache::GetEntryRaw(u64 title_id, ContentRecordType type) const { |
| @@ -547,56 +552,6 @@ InstallResult RegisteredCache::InstallEntry(const XCI& xci, bool overwrite_if_ex | |||
| 547 | return InstallEntry(*xci.GetSecurePartitionNSP(), overwrite_if_exists, copy); | 552 | return InstallEntry(*xci.GetSecurePartitionNSP(), overwrite_if_exists, copy); |
| 548 | } | 553 | } |
| 549 | 554 | ||
| 550 | bool RegisteredCache::RemoveExistingEntry(u64 title_id) { | ||
| 551 | const auto delete_nca = [this](const NcaID& id) { | ||
| 552 | const auto path = GetRelativePathFromNcaID(id, false, true, false); | ||
| 553 | |||
| 554 | if (dir->GetFileRelative(path) == nullptr) { | ||
| 555 | return false; | ||
| 556 | } | ||
| 557 | |||
| 558 | Core::Crypto::SHA256Hash hash{}; | ||
| 559 | mbedtls_sha256_ret(id.data(), id.size(), hash.data(), 0); | ||
| 560 | const auto dirname = fmt::format("000000{:02X}", hash[0]); | ||
| 561 | |||
| 562 | const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname); | ||
| 563 | |||
| 564 | const auto res = dir2->DeleteFile(fmt::format("{}.nca", Common::HexToString(id, false))); | ||
| 565 | |||
| 566 | return res; | ||
| 567 | }; | ||
| 568 | |||
| 569 | // If an entry exists in the registered cache, remove it | ||
| 570 | if (HasEntry(title_id, ContentRecordType::Meta)) { | ||
| 571 | LOG_INFO(Loader, | ||
| 572 | "Previously installed entry (v{}) for title_id={:016X} detected! " | ||
| 573 | "Attempting to remove...", | ||
| 574 | GetEntryVersion(title_id).value_or(0), title_id); | ||
| 575 | // Get all the ncas associated with the current CNMT and delete them | ||
| 576 | const auto meta_old_id = | ||
| 577 | GetNcaIDFromMetadata(title_id, ContentRecordType::Meta).value_or(NcaID{}); | ||
| 578 | const auto program_id = | ||
| 579 | GetNcaIDFromMetadata(title_id, ContentRecordType::Program).value_or(NcaID{}); | ||
| 580 | const auto data_id = | ||
| 581 | GetNcaIDFromMetadata(title_id, ContentRecordType::Data).value_or(NcaID{}); | ||
| 582 | const auto control_id = | ||
| 583 | GetNcaIDFromMetadata(title_id, ContentRecordType::Control).value_or(NcaID{}); | ||
| 584 | const auto html_id = | ||
| 585 | GetNcaIDFromMetadata(title_id, ContentRecordType::HtmlDocument).value_or(NcaID{}); | ||
| 586 | const auto legal_id = | ||
| 587 | GetNcaIDFromMetadata(title_id, ContentRecordType::LegalInformation).value_or(NcaID{}); | ||
| 588 | |||
| 589 | delete_nca(meta_old_id); | ||
| 590 | delete_nca(program_id); | ||
| 591 | delete_nca(data_id); | ||
| 592 | delete_nca(control_id); | ||
| 593 | delete_nca(html_id); | ||
| 594 | delete_nca(legal_id); | ||
| 595 | return true; | ||
| 596 | } | ||
| 597 | return false; | ||
| 598 | } | ||
| 599 | |||
| 600 | InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_exists, | 555 | InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_exists, |
| 601 | const VfsCopyFunction& copy) { | 556 | const VfsCopyFunction& copy) { |
| 602 | const auto ncas = nsp.GetNCAsCollapsed(); | 557 | const auto ncas = nsp.GetNCAsCollapsed(); |
| @@ -692,6 +647,57 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type, | |||
| 692 | return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id); | 647 | return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id); |
| 693 | } | 648 | } |
| 694 | 649 | ||
| 650 | bool RegisteredCache::RemoveExistingEntry(u64 title_id) const { | ||
| 651 | const auto delete_nca = [this](const NcaID& id) { | ||
| 652 | const auto path = GetRelativePathFromNcaID(id, false, true, false); | ||
| 653 | |||
| 654 | const bool isFile = dir->GetFileRelative(path) != nullptr; | ||
| 655 | const bool isDir = dir->GetDirectoryRelative(path) != nullptr; | ||
| 656 | |||
| 657 | if (isFile) { | ||
| 658 | return dir->DeleteFile(path); | ||
| 659 | } else if (isDir) { | ||
| 660 | return dir->DeleteSubdirectoryRecursive(path); | ||
| 661 | } | ||
| 662 | |||
| 663 | return false; | ||
| 664 | }; | ||
| 665 | |||
| 666 | // If an entry exists in the registered cache, remove it | ||
| 667 | if (HasEntry(title_id, ContentRecordType::Meta)) { | ||
| 668 | LOG_INFO(Loader, | ||
| 669 | "Previously installed entry (v{}) for title_id={:016X} detected! " | ||
| 670 | "Attempting to remove...", | ||
| 671 | GetEntryVersion(title_id).value_or(0), title_id); | ||
| 672 | |||
| 673 | // Get all the ncas associated with the current CNMT and delete them | ||
| 674 | const auto meta_old_id = | ||
| 675 | GetNcaIDFromMetadata(title_id, ContentRecordType::Meta).value_or(NcaID{}); | ||
| 676 | const auto program_id = | ||
| 677 | GetNcaIDFromMetadata(title_id, ContentRecordType::Program).value_or(NcaID{}); | ||
| 678 | const auto data_id = | ||
| 679 | GetNcaIDFromMetadata(title_id, ContentRecordType::Data).value_or(NcaID{}); | ||
| 680 | const auto control_id = | ||
| 681 | GetNcaIDFromMetadata(title_id, ContentRecordType::Control).value_or(NcaID{}); | ||
| 682 | const auto html_id = | ||
| 683 | GetNcaIDFromMetadata(title_id, ContentRecordType::HtmlDocument).value_or(NcaID{}); | ||
| 684 | const auto legal_id = | ||
| 685 | GetNcaIDFromMetadata(title_id, ContentRecordType::LegalInformation).value_or(NcaID{}); | ||
| 686 | |||
| 687 | const auto deleted_meta = delete_nca(meta_old_id); | ||
| 688 | const auto deleted_program = delete_nca(program_id); | ||
| 689 | const auto deleted_data = delete_nca(data_id); | ||
| 690 | const auto deleted_control = delete_nca(control_id); | ||
| 691 | const auto deleted_html = delete_nca(html_id); | ||
| 692 | const auto deleted_legal = delete_nca(legal_id); | ||
| 693 | |||
| 694 | return deleted_meta && (deleted_meta || deleted_program || deleted_data || | ||
| 695 | deleted_control || deleted_html || deleted_legal); | ||
| 696 | } | ||
| 697 | |||
| 698 | return false; | ||
| 699 | } | ||
| 700 | |||
| 695 | InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy, | 701 | InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy, |
| 696 | bool overwrite_if_exists, | 702 | bool overwrite_if_exists, |
| 697 | std::optional<NcaID> override_id) { | 703 | std::optional<NcaID> override_id) { |
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index 29cf0d40c..ec1d54f27 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h | |||
| @@ -155,9 +155,6 @@ public: | |||
| 155 | std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {}, | 155 | std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {}, |
| 156 | std::optional<u64> title_id = {}) const override; | 156 | std::optional<u64> title_id = {}) const override; |
| 157 | 157 | ||
| 158 | // Removes an existing entry based on title id | ||
| 159 | bool RemoveExistingEntry(u64 title_id); | ||
| 160 | |||
| 161 | // Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure | 158 | // Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure |
| 162 | // there is a meta NCA and all of them are accessible. | 159 | // there is a meta NCA and all of them are accessible. |
| 163 | InstallResult InstallEntry(const XCI& xci, bool overwrite_if_exists = false, | 160 | InstallResult InstallEntry(const XCI& xci, bool overwrite_if_exists = false, |
| @@ -172,6 +169,9 @@ public: | |||
| 172 | InstallResult InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists = false, | 169 | InstallResult InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists = false, |
| 173 | const VfsCopyFunction& copy = &VfsRawCopy); | 170 | const VfsCopyFunction& copy = &VfsRawCopy); |
| 174 | 171 | ||
| 172 | // Removes an existing entry based on title id | ||
| 173 | bool RemoveExistingEntry(u64 title_id) const; | ||
| 174 | |||
| 175 | private: | 175 | private: |
| 176 | template <typename T> | 176 | template <typename T> |
| 177 | void IterateAllMetadata(std::vector<T>& out, | 177 | void IterateAllMetadata(std::vector<T>& out, |
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index adfd2c1a4..ba4efee3a 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp | |||
| @@ -17,23 +17,23 @@ constexpr char SAVE_DATA_SIZE_FILENAME[] = ".yuzu_save_size"; | |||
| 17 | 17 | ||
| 18 | namespace { | 18 | namespace { |
| 19 | 19 | ||
| 20 | void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) { | 20 | void PrintSaveDataAttributeWarnings(SaveDataAttribute meta) { |
| 21 | if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) { | 21 | if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) { |
| 22 | if (meta.zero_1 != 0) { | 22 | if (meta.zero_1 != 0) { |
| 23 | LOG_WARNING(Service_FS, | 23 | LOG_WARNING(Service_FS, |
| 24 | "Possibly incorrect SaveDataDescriptor, type is " | 24 | "Possibly incorrect SaveDataAttribute, type is " |
| 25 | "SystemSaveData||SaveData but offset 0x28 is non-zero ({:016X}).", | 25 | "SystemSaveData||SaveData but offset 0x28 is non-zero ({:016X}).", |
| 26 | meta.zero_1); | 26 | meta.zero_1); |
| 27 | } | 27 | } |
| 28 | if (meta.zero_2 != 0) { | 28 | if (meta.zero_2 != 0) { |
| 29 | LOG_WARNING(Service_FS, | 29 | LOG_WARNING(Service_FS, |
| 30 | "Possibly incorrect SaveDataDescriptor, type is " | 30 | "Possibly incorrect SaveDataAttribute, type is " |
| 31 | "SystemSaveData||SaveData but offset 0x30 is non-zero ({:016X}).", | 31 | "SystemSaveData||SaveData but offset 0x30 is non-zero ({:016X}).", |
| 32 | meta.zero_2); | 32 | meta.zero_2); |
| 33 | } | 33 | } |
| 34 | if (meta.zero_3 != 0) { | 34 | if (meta.zero_3 != 0) { |
| 35 | LOG_WARNING(Service_FS, | 35 | LOG_WARNING(Service_FS, |
| 36 | "Possibly incorrect SaveDataDescriptor, type is " | 36 | "Possibly incorrect SaveDataAttribute, type is " |
| 37 | "SystemSaveData||SaveData but offset 0x38 is non-zero ({:016X}).", | 37 | "SystemSaveData||SaveData but offset 0x38 is non-zero ({:016X}).", |
| 38 | meta.zero_3); | 38 | meta.zero_3); |
| 39 | } | 39 | } |
| @@ -41,33 +41,32 @@ void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) { | |||
| 41 | 41 | ||
| 42 | if (meta.type == SaveDataType::SystemSaveData && meta.title_id != 0) { | 42 | if (meta.type == SaveDataType::SystemSaveData && meta.title_id != 0) { |
| 43 | LOG_WARNING(Service_FS, | 43 | LOG_WARNING(Service_FS, |
| 44 | "Possibly incorrect SaveDataDescriptor, type is SystemSaveData but title_id is " | 44 | "Possibly incorrect SaveDataAttribute, type is SystemSaveData but title_id is " |
| 45 | "non-zero ({:016X}).", | 45 | "non-zero ({:016X}).", |
| 46 | meta.title_id); | 46 | meta.title_id); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | if (meta.type == SaveDataType::DeviceSaveData && meta.user_id != u128{0, 0}) { | 49 | if (meta.type == SaveDataType::DeviceSaveData && meta.user_id != u128{0, 0}) { |
| 50 | LOG_WARNING(Service_FS, | 50 | LOG_WARNING(Service_FS, |
| 51 | "Possibly incorrect SaveDataDescriptor, type is DeviceSaveData but user_id is " | 51 | "Possibly incorrect SaveDataAttribute, type is DeviceSaveData but user_id is " |
| 52 | "non-zero ({:016X}{:016X})", | 52 | "non-zero ({:016X}{:016X})", |
| 53 | meta.user_id[1], meta.user_id[0]); | 53 | meta.user_id[1], meta.user_id[0]); |
| 54 | } | 54 | } |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataDescriptor& desc) { | 57 | bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataAttribute& attr) { |
| 58 | return desc.type == SaveDataType::CacheStorage || desc.type == SaveDataType::TemporaryStorage || | 58 | return attr.type == SaveDataType::CacheStorage || attr.type == SaveDataType::TemporaryStorage || |
| 59 | (space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User | 59 | (space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User |
| 60 | (desc.type == SaveDataType::SaveData || desc.type == SaveDataType::DeviceSaveData) && | 60 | (attr.type == SaveDataType::SaveData || attr.type == SaveDataType::DeviceSaveData) && |
| 61 | desc.title_id == 0 && desc.save_id == 0); | 61 | attr.title_id == 0 && attr.save_id == 0); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | } // Anonymous namespace | 64 | } // Anonymous namespace |
| 65 | 65 | ||
| 66 | std::string SaveDataDescriptor::DebugInfo() const { | 66 | std::string SaveDataAttribute::DebugInfo() const { |
| 67 | return fmt::format("[type={:02X}, title_id={:016X}, user_id={:016X}{:016X}, " | 67 | return fmt::format("[title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}, type={:02X}, " |
| 68 | "save_id={:016X}, " | ||
| 69 | "rank={}, index={}]", | 68 | "rank={}, index={}]", |
| 70 | static_cast<u8>(type), title_id, user_id[1], user_id[0], save_id, | 69 | title_id, user_id[1], user_id[0], save_id, static_cast<u8>(type), |
| 71 | static_cast<u8>(rank), index); | 70 | static_cast<u8>(rank), index); |
| 72 | } | 71 | } |
| 73 | 72 | ||
| @@ -80,8 +79,8 @@ SaveDataFactory::SaveDataFactory(VirtualDir save_directory) : dir(std::move(save | |||
| 80 | SaveDataFactory::~SaveDataFactory() = default; | 79 | SaveDataFactory::~SaveDataFactory() = default; |
| 81 | 80 | ||
| 82 | ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space, | 81 | ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space, |
| 83 | const SaveDataDescriptor& meta) const { | 82 | const SaveDataAttribute& meta) const { |
| 84 | PrintSaveDataDescriptorWarnings(meta); | 83 | PrintSaveDataAttributeWarnings(meta); |
| 85 | 84 | ||
| 86 | const auto save_directory = | 85 | const auto save_directory = |
| 87 | GetFullPath(space, meta.type, meta.title_id, meta.user_id, meta.save_id); | 86 | GetFullPath(space, meta.type, meta.title_id, meta.user_id, meta.save_id); |
| @@ -98,7 +97,7 @@ ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space, | |||
| 98 | } | 97 | } |
| 99 | 98 | ||
| 100 | ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, | 99 | ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, |
| 101 | const SaveDataDescriptor& meta) const { | 100 | const SaveDataAttribute& meta) const { |
| 102 | 101 | ||
| 103 | const auto save_directory = | 102 | const auto save_directory = |
| 104 | GetFullPath(space, meta.type, meta.title_id, meta.user_id, meta.save_id); | 103 | GetFullPath(space, meta.type, meta.title_id, meta.user_id, meta.save_id); |
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h index 991e57aa1..6625bbbd8 100644 --- a/src/core/file_sys/savedata_factory.h +++ b/src/core/file_sys/savedata_factory.h | |||
| @@ -21,6 +21,7 @@ enum class SaveDataSpaceId : u8 { | |||
| 21 | TemporaryStorage = 3, | 21 | TemporaryStorage = 3, |
| 22 | SdCardUser = 4, | 22 | SdCardUser = 4, |
| 23 | ProperSystem = 100, | 23 | ProperSystem = 100, |
| 24 | SafeMode = 101, | ||
| 24 | }; | 25 | }; |
| 25 | 26 | ||
| 26 | enum class SaveDataType : u8 { | 27 | enum class SaveDataType : u8 { |
| @@ -30,28 +31,50 @@ enum class SaveDataType : u8 { | |||
| 30 | DeviceSaveData = 3, | 31 | DeviceSaveData = 3, |
| 31 | TemporaryStorage = 4, | 32 | TemporaryStorage = 4, |
| 32 | CacheStorage = 5, | 33 | CacheStorage = 5, |
| 34 | SystemBcat = 6, | ||
| 33 | }; | 35 | }; |
| 34 | 36 | ||
| 35 | enum class SaveDataRank : u8 { | 37 | enum class SaveDataRank : u8 { |
| 36 | Primary, | 38 | Primary = 0, |
| 37 | Secondary, | 39 | Secondary = 1, |
| 38 | }; | 40 | }; |
| 39 | 41 | ||
| 40 | struct SaveDataDescriptor { | 42 | enum class SaveDataFlags : u32 { |
| 41 | u64_le title_id; | 43 | None = (0 << 0), |
| 44 | KeepAfterResettingSystemSaveData = (1 << 0), | ||
| 45 | KeepAfterRefurbishment = (1 << 1), | ||
| 46 | KeepAfterResettingSystemSaveDataWithoutUserSaveData = (1 << 2), | ||
| 47 | NeedsSecureDelete = (1 << 3), | ||
| 48 | }; | ||
| 49 | |||
| 50 | struct SaveDataAttribute { | ||
| 51 | u64 title_id; | ||
| 42 | u128 user_id; | 52 | u128 user_id; |
| 43 | u64_le save_id; | 53 | u64 save_id; |
| 44 | SaveDataType type; | 54 | SaveDataType type; |
| 45 | SaveDataRank rank; | 55 | SaveDataRank rank; |
| 46 | u16_le index; | 56 | u16 index; |
| 47 | INSERT_PADDING_BYTES(4); | 57 | INSERT_PADDING_BYTES(4); |
| 48 | u64_le zero_1; | 58 | u64 zero_1; |
| 49 | u64_le zero_2; | 59 | u64 zero_2; |
| 50 | u64_le zero_3; | 60 | u64 zero_3; |
| 51 | 61 | ||
| 52 | std::string DebugInfo() const; | 62 | std::string DebugInfo() const; |
| 53 | }; | 63 | }; |
| 54 | static_assert(sizeof(SaveDataDescriptor) == 0x40, "SaveDataDescriptor has incorrect size."); | 64 | static_assert(sizeof(SaveDataAttribute) == 0x40, "SaveDataAttribute has incorrect size."); |
| 65 | |||
| 66 | struct SaveDataExtraData { | ||
| 67 | SaveDataAttribute attr; | ||
| 68 | u64 owner_id; | ||
| 69 | s64 timestamp; | ||
| 70 | SaveDataFlags flags; | ||
| 71 | INSERT_PADDING_BYTES(4); | ||
| 72 | s64 available_size; | ||
| 73 | s64 journal_size; | ||
| 74 | s64 commit_id; | ||
| 75 | std::array<u8, 0x190> unused; | ||
| 76 | }; | ||
| 77 | static_assert(sizeof(SaveDataExtraData) == 0x200, "SaveDataExtraData has incorrect size."); | ||
| 55 | 78 | ||
| 56 | struct SaveDataSize { | 79 | struct SaveDataSize { |
| 57 | u64 normal; | 80 | u64 normal; |
| @@ -64,8 +87,8 @@ public: | |||
| 64 | explicit SaveDataFactory(VirtualDir dir); | 87 | explicit SaveDataFactory(VirtualDir dir); |
| 65 | ~SaveDataFactory(); | 88 | ~SaveDataFactory(); |
| 66 | 89 | ||
| 67 | ResultVal<VirtualDir> Create(SaveDataSpaceId space, const SaveDataDescriptor& meta) const; | 90 | ResultVal<VirtualDir> Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const; |
| 68 | ResultVal<VirtualDir> Open(SaveDataSpaceId space, const SaveDataDescriptor& meta) const; | 91 | ResultVal<VirtualDir> Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const; |
| 69 | 92 | ||
| 70 | VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; | 93 | VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; |
| 71 | 94 | ||
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index 96ce5957c..0db0091f6 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp | |||
| @@ -18,20 +18,22 @@ static std::string ModeFlagsToString(Mode mode) { | |||
| 18 | std::string mode_str; | 18 | std::string mode_str; |
| 19 | 19 | ||
| 20 | // Calculate the correct open mode for the file. | 20 | // Calculate the correct open mode for the file. |
| 21 | if (mode & Mode::Read && mode & Mode::Write) { | 21 | if (True(mode & Mode::Read) && True(mode & Mode::Write)) { |
| 22 | if (mode & Mode::Append) | 22 | if (True(mode & Mode::Append)) { |
| 23 | mode_str = "a+"; | 23 | mode_str = "a+"; |
| 24 | else | 24 | } else { |
| 25 | mode_str = "r+"; | 25 | mode_str = "r+"; |
| 26 | } | ||
| 26 | } else { | 27 | } else { |
| 27 | if (mode & Mode::Read) | 28 | if (True(mode & Mode::Read)) { |
| 28 | mode_str = "r"; | 29 | mode_str = "r"; |
| 29 | else if (mode & Mode::Append) | 30 | } else if (True(mode & Mode::Append)) { |
| 30 | mode_str = "a"; | 31 | mode_str = "a"; |
| 31 | else if (mode & Mode::Write) | 32 | } else if (True(mode & Mode::Write)) { |
| 32 | mode_str = "w"; | 33 | mode_str = "w"; |
| 33 | else | 34 | } else { |
| 34 | UNREACHABLE_MSG("Invalid file open mode: {:02X}", static_cast<u8>(mode)); | 35 | UNREACHABLE_MSG("Invalid file open mode: {:02X}", static_cast<u8>(mode)); |
| 36 | } | ||
| 35 | } | 37 | } |
| 36 | 38 | ||
| 37 | mode_str += "b"; | 39 | mode_str += "b"; |
| @@ -73,8 +75,9 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { | |||
| 73 | } | 75 | } |
| 74 | } | 76 | } |
| 75 | 77 | ||
| 76 | if (!FileUtil::Exists(path) && (perms & Mode::WriteAppend) != 0) | 78 | if (!FileUtil::Exists(path) && True(perms & Mode::WriteAppend)) { |
| 77 | FileUtil::CreateEmptyFile(path); | 79 | FileUtil::CreateEmptyFile(path); |
| 80 | } | ||
| 78 | 81 | ||
| 79 | auto backing = std::make_shared<FileUtil::IOFile>(path, ModeFlagsToString(perms).c_str()); | 82 | auto backing = std::make_shared<FileUtil::IOFile>(path, ModeFlagsToString(perms).c_str()); |
| 80 | cache[path] = backing; | 83 | cache[path] = backing; |
| @@ -247,11 +250,11 @@ std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() const { | |||
| 247 | } | 250 | } |
| 248 | 251 | ||
| 249 | bool RealVfsFile::IsWritable() const { | 252 | bool RealVfsFile::IsWritable() const { |
| 250 | return (perms & Mode::WriteAppend) != 0; | 253 | return True(perms & Mode::WriteAppend); |
| 251 | } | 254 | } |
| 252 | 255 | ||
| 253 | bool RealVfsFile::IsReadable() const { | 256 | bool RealVfsFile::IsReadable() const { |
| 254 | return (perms & Mode::ReadWrite) != 0; | 257 | return True(perms & Mode::ReadWrite); |
| 255 | } | 258 | } |
| 256 | 259 | ||
| 257 | std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { | 260 | std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { |
| @@ -319,8 +322,9 @@ RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& | |||
| 319 | path_components(FileUtil::SplitPathComponents(path)), | 322 | path_components(FileUtil::SplitPathComponents(path)), |
| 320 | parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), | 323 | parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), |
| 321 | perms(perms_) { | 324 | perms(perms_) { |
| 322 | if (!FileUtil::Exists(path) && perms & Mode::WriteAppend) | 325 | if (!FileUtil::Exists(path) && True(perms & Mode::WriteAppend)) { |
| 323 | FileUtil::CreateDir(path); | 326 | FileUtil::CreateDir(path); |
| 327 | } | ||
| 324 | } | 328 | } |
| 325 | 329 | ||
| 326 | RealVfsDirectory::~RealVfsDirectory() = default; | 330 | RealVfsDirectory::~RealVfsDirectory() = default; |
| @@ -371,11 +375,11 @@ std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories() | |||
| 371 | } | 375 | } |
| 372 | 376 | ||
| 373 | bool RealVfsDirectory::IsWritable() const { | 377 | bool RealVfsDirectory::IsWritable() const { |
| 374 | return (perms & Mode::WriteAppend) != 0; | 378 | return True(perms & Mode::WriteAppend); |
| 375 | } | 379 | } |
| 376 | 380 | ||
| 377 | bool RealVfsDirectory::IsReadable() const { | 381 | bool RealVfsDirectory::IsReadable() const { |
| 378 | return (perms & Mode::ReadWrite) != 0; | 382 | return True(perms & Mode::ReadWrite); |
| 379 | } | 383 | } |
| 380 | 384 | ||
| 381 | std::string RealVfsDirectory::GetName() const { | 385 | std::string RealVfsDirectory::GetName() const { |
diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp index 86e06ccb9..81413c684 100644 --- a/src/core/file_sys/xts_archive.cpp +++ b/src/core/file_sys/xts_archive.cpp | |||
| @@ -70,14 +70,18 @@ NAX::NAX(VirtualFile file_, std::array<u8, 0x10> nca_id) | |||
| 70 | NAX::~NAX() = default; | 70 | NAX::~NAX() = default; |
| 71 | 71 | ||
| 72 | Loader::ResultStatus NAX::Parse(std::string_view path) { | 72 | Loader::ResultStatus NAX::Parse(std::string_view path) { |
| 73 | if (file->ReadObject(header.get()) != sizeof(NAXHeader)) | 73 | if (file == nullptr) { |
| 74 | return Loader::ResultStatus::ErrorNullFile; | ||
| 75 | } | ||
| 76 | if (file->ReadObject(header.get()) != sizeof(NAXHeader)) { | ||
| 74 | return Loader::ResultStatus::ErrorBadNAXHeader; | 77 | return Loader::ResultStatus::ErrorBadNAXHeader; |
| 75 | 78 | } | |
| 76 | if (header->magic != Common::MakeMagic('N', 'A', 'X', '0')) | 79 | if (header->magic != Common::MakeMagic('N', 'A', 'X', '0')) { |
| 77 | return Loader::ResultStatus::ErrorBadNAXHeader; | 80 | return Loader::ResultStatus::ErrorBadNAXHeader; |
| 78 | 81 | } | |
| 79 | if (file->GetSize() < NAX_HEADER_PADDING_SIZE + header->file_size) | 82 | if (file->GetSize() < NAX_HEADER_PADDING_SIZE + header->file_size) { |
| 80 | return Loader::ResultStatus::ErrorIncorrectNAXFileSize; | 83 | return Loader::ResultStatus::ErrorIncorrectNAXFileSize; |
| 84 | } | ||
| 81 | 85 | ||
| 82 | keys.DeriveSDSeedLazy(); | 86 | keys.DeriveSDSeedLazy(); |
| 83 | std::array<Core::Crypto::Key256, 2> sd_keys{}; | 87 | std::array<Core::Crypto::Key256, 2> sd_keys{}; |
diff --git a/src/core/hardware_interrupt_manager.cpp b/src/core/hardware_interrupt_manager.cpp index efc1030c1..645f26e91 100644 --- a/src/core/hardware_interrupt_manager.cpp +++ b/src/core/hardware_interrupt_manager.cpp | |||
| @@ -11,8 +11,8 @@ | |||
| 11 | namespace Core::Hardware { | 11 | namespace Core::Hardware { |
| 12 | 12 | ||
| 13 | InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) { | 13 | InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) { |
| 14 | gpu_interrupt_event = | 14 | gpu_interrupt_event = Core::Timing::CreateEvent( |
| 15 | Core::Timing::CreateEvent("GPUInterrupt", [this](u64 message, std::chrono::nanoseconds) { | 15 | "GPUInterrupt", [this](std::uintptr_t message, std::chrono::nanoseconds) { |
| 16 | auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv"); | 16 | auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv"); |
| 17 | const u32 syncpt = static_cast<u32>(message >> 32); | 17 | const u32 syncpt = static_cast<u32>(message >> 32); |
| 18 | const u32 value = static_cast<u32>(message); | 18 | const u32 value = static_cast<u32>(message); |
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index b31673928..f3277b766 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <vector> | 13 | #include <vector> |
| 14 | #include <boost/container/small_vector.hpp> | 14 | #include <boost/container/small_vector.hpp> |
| 15 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 16 | #include "common/concepts.h" | ||
| 16 | #include "common/swap.h" | 17 | #include "common/swap.h" |
| 17 | #include "core/hle/ipc.h" | 18 | #include "core/hle/ipc.h" |
| 18 | #include "core/hle/kernel/object.h" | 19 | #include "core/hle/kernel/object.h" |
| @@ -193,23 +194,24 @@ public: | |||
| 193 | 194 | ||
| 194 | /* Helper function to write a buffer using the appropriate buffer descriptor | 195 | /* Helper function to write a buffer using the appropriate buffer descriptor |
| 195 | * | 196 | * |
| 196 | * @tparam ContiguousContainer an arbitrary container that satisfies the | 197 | * @tparam T an arbitrary container that satisfies the |
| 197 | * ContiguousContainer concept in the C++ standard library. | 198 | * ContiguousContainer concept in the C++ standard library or a trivially copyable type. |
| 198 | * | 199 | * |
| 199 | * @param container The container to write the data of into a buffer. | 200 | * @param data The container/data to write into a buffer. |
| 200 | * @param buffer_index The buffer in particular to write to. | 201 | * @param buffer_index The buffer in particular to write to. |
| 201 | */ | 202 | */ |
| 202 | template <typename ContiguousContainer, | 203 | template <typename T, typename = std::enable_if_t<!std::is_pointer_v<T>>> |
| 203 | typename = std::enable_if_t<!std::is_pointer_v<ContiguousContainer>>> | 204 | std::size_t WriteBuffer(const T& data, std::size_t buffer_index = 0) const { |
| 204 | std::size_t WriteBuffer(const ContiguousContainer& container, | 205 | if constexpr (Common::IsSTLContainer<T>) { |
| 205 | std::size_t buffer_index = 0) const { | 206 | using ContiguousType = typename T::value_type; |
| 206 | using ContiguousType = typename ContiguousContainer::value_type; | 207 | static_assert(std::is_trivially_copyable_v<ContiguousType>, |
| 207 | 208 | "Container to WriteBuffer must contain trivially copyable objects"); | |
| 208 | static_assert(std::is_trivially_copyable_v<ContiguousType>, | 209 | return WriteBuffer(std::data(data), std::size(data) * sizeof(ContiguousType), |
| 209 | "Container to WriteBuffer must contain trivially copyable objects"); | 210 | buffer_index); |
| 210 | 211 | } else { | |
| 211 | return WriteBuffer(std::data(container), std::size(container) * sizeof(ContiguousType), | 212 | static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable"); |
| 212 | buffer_index); | 213 | return WriteBuffer(&data, sizeof(T), buffer_index); |
| 214 | } | ||
| 213 | } | 215 | } |
| 214 | 216 | ||
| 215 | /// Helper function to get the size of the input buffer | 217 | /// Helper function to get the size of the input buffer |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 8dd4a2637..cabe8d418 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -145,7 +145,7 @@ struct KernelCore::Impl { | |||
| 145 | 145 | ||
| 146 | void InitializePreemption(KernelCore& kernel) { | 146 | void InitializePreemption(KernelCore& kernel) { |
| 147 | preemption_event = Core::Timing::CreateEvent( | 147 | preemption_event = Core::Timing::CreateEvent( |
| 148 | "PreemptionCallback", [this, &kernel](u64, std::chrono::nanoseconds) { | 148 | "PreemptionCallback", [this, &kernel](std::uintptr_t, std::chrono::nanoseconds) { |
| 149 | { | 149 | { |
| 150 | SchedulerLock lock(kernel); | 150 | SchedulerLock lock(kernel); |
| 151 | global_scheduler.PreemptThreads(); | 151 | global_scheduler.PreemptThreads(); |
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index af22f4c33..7e6391c6c 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp | |||
| @@ -33,8 +33,10 @@ ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kern | |||
| 33 | std::string name) { | 33 | std::string name) { |
| 34 | std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)}; | 34 | std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)}; |
| 35 | 35 | ||
| 36 | session->request_event = Core::Timing::CreateEvent( | 36 | session->request_event = |
| 37 | name, [session](u64, std::chrono::nanoseconds) { session->CompleteSyncRequest(); }); | 37 | Core::Timing::CreateEvent(name, [session](std::uintptr_t, std::chrono::nanoseconds) { |
| 38 | session->CompleteSyncRequest(); | ||
| 39 | }); | ||
| 38 | session->name = std::move(name); | 40 | session->name = std::move(name); |
| 39 | session->parent = std::move(parent); | 41 | session->parent = std::move(parent); |
| 40 | 42 | ||
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp index 88b01b751..95f2446c9 100644 --- a/src/core/hle/kernel/time_manager.cpp +++ b/src/core/hle/kernel/time_manager.cpp | |||
| @@ -16,14 +16,14 @@ namespace Kernel { | |||
| 16 | 16 | ||
| 17 | TimeManager::TimeManager(Core::System& system_) : system{system_} { | 17 | TimeManager::TimeManager(Core::System& system_) : system{system_} { |
| 18 | time_manager_event_type = Core::Timing::CreateEvent( | 18 | time_manager_event_type = Core::Timing::CreateEvent( |
| 19 | "Kernel::TimeManagerCallback", [this](u64 thread_handle, std::chrono::nanoseconds) { | 19 | "Kernel::TimeManagerCallback", |
| 20 | SchedulerLock lock(system.Kernel()); | 20 | [this](std::uintptr_t thread_handle, std::chrono::nanoseconds) { |
| 21 | Handle proper_handle = static_cast<Handle>(thread_handle); | 21 | const SchedulerLock lock(system.Kernel()); |
| 22 | const auto proper_handle = static_cast<Handle>(thread_handle); | ||
| 22 | if (cancelled_events[proper_handle]) { | 23 | if (cancelled_events[proper_handle]) { |
| 23 | return; | 24 | return; |
| 24 | } | 25 | } |
| 25 | std::shared_ptr<Thread> thread = | 26 | auto thread = this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle); |
| 26 | this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle); | ||
| 27 | thread->OnWakeUp(); | 27 | thread->OnWakeUp(); |
| 28 | }); | 28 | }); |
| 29 | } | 29 | } |
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 8ac856ec3..63e4aeca0 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -286,9 +286,7 @@ protected: | |||
| 286 | ProfileBase profile_base{}; | 286 | ProfileBase profile_base{}; |
| 287 | ProfileData data{}; | 287 | ProfileData data{}; |
| 288 | if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) { | 288 | if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) { |
| 289 | std::array<u8, sizeof(ProfileData)> raw_data; | 289 | ctx.WriteBuffer(data); |
| 290 | std::memcpy(raw_data.data(), &data, sizeof(ProfileData)); | ||
| 291 | ctx.WriteBuffer(raw_data); | ||
| 292 | IPC::ResponseBuilder rb{ctx, 16}; | 290 | IPC::ResponseBuilder rb{ctx, 16}; |
| 293 | rb.Push(RESULT_SUCCESS); | 291 | rb.Push(RESULT_SUCCESS); |
| 294 | rb.PushRaw(profile_base); | 292 | rb.PushRaw(profile_base); |
| @@ -333,7 +331,7 @@ protected: | |||
| 333 | std::vector<u8> buffer(size); | 331 | std::vector<u8> buffer(size); |
| 334 | image.ReadBytes(buffer.data(), buffer.size()); | 332 | image.ReadBytes(buffer.data(), buffer.size()); |
| 335 | 333 | ||
| 336 | ctx.WriteBuffer(buffer.data(), buffer.size()); | 334 | ctx.WriteBuffer(buffer); |
| 337 | rb.Push<u32>(size); | 335 | rb.Push<u32>(size); |
| 338 | } | 336 | } |
| 339 | 337 | ||
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index eb8c81645..a98d57b5c 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp | |||
| @@ -58,7 +58,7 @@ ProfileManager::~ProfileManager() { | |||
| 58 | /// internal management of the users profiles | 58 | /// internal management of the users profiles |
| 59 | std::optional<std::size_t> ProfileManager::AddToProfiles(const ProfileInfo& profile) { | 59 | std::optional<std::size_t> ProfileManager::AddToProfiles(const ProfileInfo& profile) { |
| 60 | if (user_count >= MAX_USERS) { | 60 | if (user_count >= MAX_USERS) { |
| 61 | return {}; | 61 | return std::nullopt; |
| 62 | } | 62 | } |
| 63 | profiles[user_count] = profile; | 63 | profiles[user_count] = profile; |
| 64 | return user_count++; | 64 | return user_count++; |
| @@ -101,13 +101,14 @@ ResultCode ProfileManager::CreateNewUser(UUID uuid, const ProfileUsername& usern | |||
| 101 | [&uuid](const ProfileInfo& profile) { return uuid == profile.user_uuid; })) { | 101 | [&uuid](const ProfileInfo& profile) { return uuid == profile.user_uuid; })) { |
| 102 | return ERROR_USER_ALREADY_EXISTS; | 102 | return ERROR_USER_ALREADY_EXISTS; |
| 103 | } | 103 | } |
| 104 | ProfileInfo profile; | 104 | |
| 105 | profile.user_uuid = uuid; | 105 | return AddUser({ |
| 106 | profile.username = username; | 106 | .user_uuid = uuid, |
| 107 | profile.data = {}; | 107 | .username = username, |
| 108 | profile.creation_time = 0x0; | 108 | .creation_time = 0, |
| 109 | profile.is_open = false; | 109 | .data = {}, |
| 110 | return AddUser(profile); | 110 | .is_open = false, |
| 111 | }); | ||
| 111 | } | 112 | } |
| 112 | 113 | ||
| 113 | /// Creates a new user on the system. This function allows a much simpler method of registration | 114 | /// Creates a new user on the system. This function allows a much simpler method of registration |
| @@ -126,7 +127,7 @@ ResultCode ProfileManager::CreateNewUser(UUID uuid, const std::string& username) | |||
| 126 | 127 | ||
| 127 | std::optional<UUID> ProfileManager::GetUser(std::size_t index) const { | 128 | std::optional<UUID> ProfileManager::GetUser(std::size_t index) const { |
| 128 | if (index >= MAX_USERS) { | 129 | if (index >= MAX_USERS) { |
| 129 | return {}; | 130 | return std::nullopt; |
| 130 | } | 131 | } |
| 131 | 132 | ||
| 132 | return profiles[index].user_uuid; | 133 | return profiles[index].user_uuid; |
| @@ -135,13 +136,13 @@ std::optional<UUID> ProfileManager::GetUser(std::size_t index) const { | |||
| 135 | /// Returns a users profile index based on their user id. | 136 | /// Returns a users profile index based on their user id. |
| 136 | std::optional<std::size_t> ProfileManager::GetUserIndex(const UUID& uuid) const { | 137 | std::optional<std::size_t> ProfileManager::GetUserIndex(const UUID& uuid) const { |
| 137 | if (!uuid) { | 138 | if (!uuid) { |
| 138 | return {}; | 139 | return std::nullopt; |
| 139 | } | 140 | } |
| 140 | 141 | ||
| 141 | const auto iter = std::find_if(profiles.begin(), profiles.end(), | 142 | const auto iter = std::find_if(profiles.begin(), profiles.end(), |
| 142 | [&uuid](const ProfileInfo& p) { return p.user_uuid == uuid; }); | 143 | [&uuid](const ProfileInfo& p) { return p.user_uuid == uuid; }); |
| 143 | if (iter == profiles.end()) { | 144 | if (iter == profiles.end()) { |
| 144 | return {}; | 145 | return std::nullopt; |
| 145 | } | 146 | } |
| 146 | 147 | ||
| 147 | return static_cast<std::size_t>(std::distance(profiles.begin(), iter)); | 148 | return static_cast<std::size_t>(std::distance(profiles.begin(), iter)); |
| @@ -339,7 +340,13 @@ void ProfileManager::ParseUserSaveFile() { | |||
| 339 | continue; | 340 | continue; |
| 340 | } | 341 | } |
| 341 | 342 | ||
| 342 | AddUser({user.uuid, user.username, user.timestamp, user.extra_data, false}); | 343 | AddUser({ |
| 344 | .user_uuid = user.uuid, | ||
| 345 | .username = user.username, | ||
| 346 | .creation_time = user.timestamp, | ||
| 347 | .data = user.extra_data, | ||
| 348 | .is_open = false, | ||
| 349 | }); | ||
| 343 | } | 350 | } |
| 344 | 351 | ||
| 345 | std::stable_partition(profiles.begin(), profiles.end(), | 352 | std::stable_partition(profiles.begin(), profiles.end(), |
| @@ -350,11 +357,13 @@ void ProfileManager::WriteUserSaveFile() { | |||
| 350 | ProfileDataRaw raw{}; | 357 | ProfileDataRaw raw{}; |
| 351 | 358 | ||
| 352 | for (std::size_t i = 0; i < MAX_USERS; ++i) { | 359 | for (std::size_t i = 0; i < MAX_USERS; ++i) { |
| 353 | raw.users[i].username = profiles[i].username; | 360 | raw.users[i] = { |
| 354 | raw.users[i].uuid2 = profiles[i].user_uuid; | 361 | .uuid = profiles[i].user_uuid, |
| 355 | raw.users[i].uuid = profiles[i].user_uuid; | 362 | .uuid2 = profiles[i].user_uuid, |
| 356 | raw.users[i].timestamp = profiles[i].creation_time; | 363 | .timestamp = profiles[i].creation_time, |
| 357 | raw.users[i].extra_data = profiles[i].data; | 364 | .username = profiles[i].username, |
| 365 | .extra_data = profiles[i].data, | ||
| 366 | }; | ||
| 358 | } | 367 | } |
| 359 | 368 | ||
| 360 | const auto raw_path = | 369 | const auto raw_path = |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index ceed20609..55a1edf1a 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -1342,12 +1342,12 @@ void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) { | |||
| 1342 | 1342 | ||
| 1343 | LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]); | 1343 | LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]); |
| 1344 | 1344 | ||
| 1345 | FileSys::SaveDataDescriptor descriptor{}; | 1345 | FileSys::SaveDataAttribute attribute{}; |
| 1346 | descriptor.title_id = system.CurrentProcess()->GetTitleID(); | 1346 | attribute.title_id = system.CurrentProcess()->GetTitleID(); |
| 1347 | descriptor.user_id = user_id; | 1347 | attribute.user_id = user_id; |
| 1348 | descriptor.type = FileSys::SaveDataType::SaveData; | 1348 | attribute.type = FileSys::SaveDataType::SaveData; |
| 1349 | const auto res = system.GetFileSystemController().CreateSaveData( | 1349 | const auto res = system.GetFileSystemController().CreateSaveData( |
| 1350 | FileSys::SaveDataSpaceId::NandUser, descriptor); | 1350 | FileSys::SaveDataSpaceId::NandUser, attribute); |
| 1351 | 1351 | ||
| 1352 | IPC::ResponseBuilder rb{ctx, 4}; | 1352 | IPC::ResponseBuilder rb{ctx, 4}; |
| 1353 | rb.Push(res.Code()); | 1353 | rb.Push(res.Code()); |
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 106e89743..dd80dd1dc 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -71,7 +71,7 @@ public: | |||
| 71 | 71 | ||
| 72 | stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate, | 72 | stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate, |
| 73 | audio_params.channel_count, std::move(unique_name), | 73 | audio_params.channel_count, std::move(unique_name), |
| 74 | [=]() { buffer_event.writable->Signal(); }); | 74 | [this] { buffer_event.writable->Signal(); }); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | private: | 77 | private: |
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index d19513cbb..f1d81602c 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp | |||
| @@ -92,7 +92,7 @@ private: | |||
| 92 | if (performance) { | 92 | if (performance) { |
| 93 | rb.Push<u64>(*performance); | 93 | rb.Push<u64>(*performance); |
| 94 | } | 94 | } |
| 95 | ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16)); | 95 | ctx.WriteBuffer(samples); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | bool DecodeOpusData(u32& consumed, u32& sample_count, const std::vector<u8>& input, | 98 | bool DecodeOpusData(u32& consumed, u32& sample_count, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp index 603b64d4f..db0e06ca1 100644 --- a/src/core/hle/service/bcat/module.cpp +++ b/src/core/hle/service/bcat/module.cpp | |||
| @@ -112,7 +112,7 @@ private: | |||
| 112 | void GetImpl(Kernel::HLERequestContext& ctx) { | 112 | void GetImpl(Kernel::HLERequestContext& ctx) { |
| 113 | LOG_DEBUG(Service_BCAT, "called"); | 113 | LOG_DEBUG(Service_BCAT, "called"); |
| 114 | 114 | ||
| 115 | ctx.WriteBuffer(&impl, sizeof(DeliveryCacheProgressImpl)); | 115 | ctx.WriteBuffer(impl); |
| 116 | 116 | ||
| 117 | IPC::ResponseBuilder rb{ctx, 2}; | 117 | IPC::ResponseBuilder rb{ctx, 2}; |
| 118 | rb.Push(RESULT_SUCCESS); | 118 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp index a41c73c48..c2737a365 100644 --- a/src/core/hle/service/es/es.cpp +++ b/src/core/hle/service/es/es.cpp | |||
| @@ -160,7 +160,7 @@ private: | |||
| 160 | return; | 160 | return; |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | ctx.WriteBuffer(key.data(), key.size()); | 163 | ctx.WriteBuffer(key); |
| 164 | 164 | ||
| 165 | IPC::ResponseBuilder rb{ctx, 2}; | 165 | IPC::ResponseBuilder rb{ctx, 2}; |
| 166 | rb.Push(RESULT_SUCCESS); | 166 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index c66124998..4490f8e4c 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -311,7 +311,7 @@ ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFS( | |||
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | ResultVal<FileSys::VirtualDir> FileSystemController::CreateSaveData( | 313 | ResultVal<FileSys::VirtualDir> FileSystemController::CreateSaveData( |
| 314 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataDescriptor& save_struct) const { | 314 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const { |
| 315 | LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", | 315 | LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", |
| 316 | static_cast<u8>(space), save_struct.DebugInfo()); | 316 | static_cast<u8>(space), save_struct.DebugInfo()); |
| 317 | 317 | ||
| @@ -323,15 +323,15 @@ ResultVal<FileSys::VirtualDir> FileSystemController::CreateSaveData( | |||
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveData( | 325 | ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveData( |
| 326 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataDescriptor& descriptor) const { | 326 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& attribute) const { |
| 327 | LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", | 327 | LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", |
| 328 | static_cast<u8>(space), descriptor.DebugInfo()); | 328 | static_cast<u8>(space), attribute.DebugInfo()); |
| 329 | 329 | ||
| 330 | if (save_data_factory == nullptr) { | 330 | if (save_data_factory == nullptr) { |
| 331 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 331 | return FileSys::ERROR_ENTITY_NOT_FOUND; |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | return save_data_factory->Open(space, descriptor); | 334 | return save_data_factory->Open(space, attribute); |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveDataSpace( | 337 | ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveDataSpace( |
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 1b0a6a949..6dbbf0b2b 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h | |||
| @@ -31,7 +31,7 @@ enum class SaveDataSpaceId : u8; | |||
| 31 | enum class SaveDataType : u8; | 31 | enum class SaveDataType : u8; |
| 32 | enum class StorageId : u8; | 32 | enum class StorageId : u8; |
| 33 | 33 | ||
| 34 | struct SaveDataDescriptor; | 34 | struct SaveDataAttribute; |
| 35 | struct SaveDataSize; | 35 | struct SaveDataSize; |
| 36 | } // namespace FileSys | 36 | } // namespace FileSys |
| 37 | 37 | ||
| @@ -69,9 +69,9 @@ public: | |||
| 69 | ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id, | 69 | ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id, |
| 70 | FileSys::ContentRecordType type) const; | 70 | FileSys::ContentRecordType type) const; |
| 71 | ResultVal<FileSys::VirtualDir> CreateSaveData( | 71 | ResultVal<FileSys::VirtualDir> CreateSaveData( |
| 72 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataDescriptor& save_struct) const; | 72 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const; |
| 73 | ResultVal<FileSys::VirtualDir> OpenSaveData( | 73 | ResultVal<FileSys::VirtualDir> OpenSaveData( |
| 74 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataDescriptor& save_struct) const; | 74 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const; |
| 75 | ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) const; | 75 | ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) const; |
| 76 | ResultVal<FileSys::VirtualDir> OpenSDMC() const; | 76 | ResultVal<FileSys::VirtualDir> OpenSDMC() const; |
| 77 | ResultVal<FileSys::VirtualDir> OpenBISPartition(FileSys::BisPartitionId id) const; | 77 | ResultVal<FileSys::VirtualDir> OpenBISPartition(FileSys::BisPartitionId id) const; |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 20c331b77..26fd87f58 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -696,8 +696,8 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter) | |||
| 696 | {67, nullptr, "FindSaveDataWithFilter"}, | 696 | {67, nullptr, "FindSaveDataWithFilter"}, |
| 697 | {68, nullptr, "OpenSaveDataInfoReaderBySaveDataFilter"}, | 697 | {68, nullptr, "OpenSaveDataInfoReaderBySaveDataFilter"}, |
| 698 | {69, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataAttribute"}, | 698 | {69, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataAttribute"}, |
| 699 | {70, nullptr, "WriteSaveDataFileSystemExtraDataBySaveDataAttribute"}, | 699 | {70, &FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute, "WriteSaveDataFileSystemExtraDataBySaveDataAttribute"}, |
| 700 | {71, nullptr, "ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute"}, | 700 | {71, &FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute, "ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute"}, |
| 701 | {80, nullptr, "OpenSaveDataMetaFile"}, | 701 | {80, nullptr, "OpenSaveDataMetaFile"}, |
| 702 | {81, nullptr, "OpenSaveDataTransferManager"}, | 702 | {81, nullptr, "OpenSaveDataTransferManager"}, |
| 703 | {82, nullptr, "OpenSaveDataTransferManagerVersion2"}, | 703 | {82, nullptr, "OpenSaveDataTransferManagerVersion2"}, |
| @@ -812,7 +812,7 @@ void FSP_SRV::OpenSdCardFileSystem(Kernel::HLERequestContext& ctx) { | |||
| 812 | void FSP_SRV::CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx) { | 812 | void FSP_SRV::CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx) { |
| 813 | IPC::RequestParser rp{ctx}; | 813 | IPC::RequestParser rp{ctx}; |
| 814 | 814 | ||
| 815 | auto save_struct = rp.PopRaw<FileSys::SaveDataDescriptor>(); | 815 | auto save_struct = rp.PopRaw<FileSys::SaveDataAttribute>(); |
| 816 | [[maybe_unused]] auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>(); | 816 | [[maybe_unused]] auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>(); |
| 817 | u128 uid = rp.PopRaw<u128>(); | 817 | u128 uid = rp.PopRaw<u128>(); |
| 818 | 818 | ||
| @@ -826,17 +826,18 @@ void FSP_SRV::CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx) { | |||
| 826 | } | 826 | } |
| 827 | 827 | ||
| 828 | void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) { | 828 | void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) { |
| 829 | LOG_INFO(Service_FS, "called."); | 829 | IPC::RequestParser rp{ctx}; |
| 830 | 830 | ||
| 831 | struct Parameters { | 831 | struct Parameters { |
| 832 | FileSys::SaveDataSpaceId save_data_space_id; | 832 | FileSys::SaveDataSpaceId space_id; |
| 833 | FileSys::SaveDataDescriptor descriptor; | 833 | FileSys::SaveDataAttribute attribute; |
| 834 | }; | 834 | }; |
| 835 | 835 | ||
| 836 | IPC::RequestParser rp{ctx}; | ||
| 837 | const auto parameters = rp.PopRaw<Parameters>(); | 836 | const auto parameters = rp.PopRaw<Parameters>(); |
| 838 | 837 | ||
| 839 | auto dir = fsc.OpenSaveData(parameters.save_data_space_id, parameters.descriptor); | 838 | LOG_INFO(Service_FS, "called."); |
| 839 | |||
| 840 | auto dir = fsc.OpenSaveData(parameters.space_id, parameters.attribute); | ||
| 840 | if (dir.Failed()) { | 841 | if (dir.Failed()) { |
| 841 | IPC::ResponseBuilder rb{ctx, 2, 0, 0}; | 842 | IPC::ResponseBuilder rb{ctx, 2, 0, 0}; |
| 842 | rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); | 843 | rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); |
| @@ -844,13 +845,18 @@ void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) { | |||
| 844 | } | 845 | } |
| 845 | 846 | ||
| 846 | FileSys::StorageId id; | 847 | FileSys::StorageId id; |
| 847 | if (parameters.save_data_space_id == FileSys::SaveDataSpaceId::NandUser) { | 848 | |
| 849 | switch (parameters.space_id) { | ||
| 850 | case FileSys::SaveDataSpaceId::NandUser: | ||
| 848 | id = FileSys::StorageId::NandUser; | 851 | id = FileSys::StorageId::NandUser; |
| 849 | } else if (parameters.save_data_space_id == FileSys::SaveDataSpaceId::SdCardSystem || | 852 | break; |
| 850 | parameters.save_data_space_id == FileSys::SaveDataSpaceId::SdCardUser) { | 853 | case FileSys::SaveDataSpaceId::SdCardSystem: |
| 854 | case FileSys::SaveDataSpaceId::SdCardUser: | ||
| 851 | id = FileSys::StorageId::SdCard; | 855 | id = FileSys::StorageId::SdCard; |
| 852 | } else { | 856 | break; |
| 857 | case FileSys::SaveDataSpaceId::NandSystem: | ||
| 853 | id = FileSys::StorageId::NandSystem; | 858 | id = FileSys::StorageId::NandSystem; |
| 859 | break; | ||
| 854 | } | 860 | } |
| 855 | 861 | ||
| 856 | auto filesystem = | 862 | auto filesystem = |
| @@ -876,22 +882,31 @@ void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& | |||
| 876 | rb.PushIpcInterface<ISaveDataInfoReader>(std::make_shared<ISaveDataInfoReader>(space, fsc)); | 882 | rb.PushIpcInterface<ISaveDataInfoReader>(std::make_shared<ISaveDataInfoReader>(space, fsc)); |
| 877 | } | 883 | } |
| 878 | 884 | ||
| 879 | void FSP_SRV::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { | 885 | void FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute(Kernel::HLERequestContext& ctx) { |
| 880 | IPC::RequestParser rp{ctx}; | 886 | LOG_WARNING(Service_FS, "(STUBBED) called."); |
| 881 | log_mode = rp.PopEnum<LogMode>(); | ||
| 882 | |||
| 883 | LOG_DEBUG(Service_FS, "called, log_mode={:08X}", static_cast<u32>(log_mode)); | ||
| 884 | 887 | ||
| 885 | IPC::ResponseBuilder rb{ctx, 2}; | 888 | IPC::ResponseBuilder rb{ctx, 2}; |
| 886 | rb.Push(RESULT_SUCCESS); | 889 | rb.Push(RESULT_SUCCESS); |
| 887 | } | 890 | } |
| 888 | 891 | ||
| 889 | void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { | 892 | void FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute( |
| 890 | LOG_DEBUG(Service_FS, "called"); | 893 | Kernel::HLERequestContext& ctx) { |
| 894 | IPC::RequestParser rp{ctx}; | ||
| 895 | |||
| 896 | struct Parameters { | ||
| 897 | FileSys::SaveDataSpaceId space_id; | ||
| 898 | FileSys::SaveDataAttribute attribute; | ||
| 899 | }; | ||
| 900 | |||
| 901 | const auto parameters = rp.PopRaw<Parameters>(); | ||
| 902 | // Stub this to None for now, backend needs an impl to read/write the SaveDataExtraData | ||
| 903 | constexpr auto flags = static_cast<u32>(FileSys::SaveDataFlags::None); | ||
| 904 | |||
| 905 | LOG_WARNING(Service_FS, "(STUBBED) called, flags={}", flags); | ||
| 891 | 906 | ||
| 892 | IPC::ResponseBuilder rb{ctx, 3}; | 907 | IPC::ResponseBuilder rb{ctx, 3}; |
| 893 | rb.Push(RESULT_SUCCESS); | 908 | rb.Push(RESULT_SUCCESS); |
| 894 | rb.PushEnum(log_mode); | 909 | rb.Push(flags); |
| 895 | } | 910 | } |
| 896 | 911 | ||
| 897 | void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { | 912 | void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { |
| @@ -966,6 +981,24 @@ void FSP_SRV::OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ct | |||
| 966 | rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); | 981 | rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); |
| 967 | } | 982 | } |
| 968 | 983 | ||
| 984 | void FSP_SRV::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { | ||
| 985 | IPC::RequestParser rp{ctx}; | ||
| 986 | log_mode = rp.PopEnum<LogMode>(); | ||
| 987 | |||
| 988 | LOG_DEBUG(Service_FS, "called, log_mode={:08X}", static_cast<u32>(log_mode)); | ||
| 989 | |||
| 990 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 991 | rb.Push(RESULT_SUCCESS); | ||
| 992 | } | ||
| 993 | |||
| 994 | void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { | ||
| 995 | LOG_DEBUG(Service_FS, "called"); | ||
| 996 | |||
| 997 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 998 | rb.Push(RESULT_SUCCESS); | ||
| 999 | rb.PushEnum(log_mode); | ||
| 1000 | } | ||
| 1001 | |||
| 969 | void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) { | 1002 | void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) { |
| 970 | const auto raw = ctx.ReadBuffer(); | 1003 | const auto raw = ctx.ReadBuffer(); |
| 971 | auto log = Common::StringFromFixedZeroTerminatedBuffer( | 1004 | auto log = Common::StringFromFixedZeroTerminatedBuffer( |
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index dfb3e395b..4964e874e 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h | |||
| @@ -43,11 +43,13 @@ private: | |||
| 43 | void OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx); | 43 | void OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx); |
| 44 | void OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx); | 44 | void OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx); |
| 45 | void OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx); | 45 | void OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx); |
| 46 | void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); | 46 | void WriteSaveDataFileSystemExtraDataBySaveDataAttribute(Kernel::HLERequestContext& ctx); |
| 47 | void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); | 47 | void ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(Kernel::HLERequestContext& ctx); |
| 48 | void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); | 48 | void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); |
| 49 | void OpenDataStorageByDataId(Kernel::HLERequestContext& ctx); | 49 | void OpenDataStorageByDataId(Kernel::HLERequestContext& ctx); |
| 50 | void OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); | 50 | void OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); |
| 51 | void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); | ||
| 52 | void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); | ||
| 51 | void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx); | 53 | void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx); |
| 52 | void GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx); | 54 | void GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx); |
| 53 | void OpenMultiCommitManager(Kernel::HLERequestContext& ctx); | 55 | void OpenMultiCommitManager(Kernel::HLERequestContext& ctx); |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 680290cbd..1e95b7580 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -77,8 +77,9 @@ IAppletResource::IAppletResource(Core::System& system) | |||
| 77 | 77 | ||
| 78 | // Register update callbacks | 78 | // Register update callbacks |
| 79 | pad_update_event = Core::Timing::CreateEvent( | 79 | pad_update_event = Core::Timing::CreateEvent( |
| 80 | "HID::UpdatePadCallback", [this](u64 userdata, std::chrono::nanoseconds ns_late) { | 80 | "HID::UpdatePadCallback", |
| 81 | UpdateControllers(userdata, ns_late); | 81 | [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { |
| 82 | UpdateControllers(user_data, ns_late); | ||
| 82 | }); | 83 | }); |
| 83 | 84 | ||
| 84 | // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) | 85 | // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) |
| @@ -108,7 +109,8 @@ void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) { | |||
| 108 | rb.PushCopyObjects(shared_mem); | 109 | rb.PushCopyObjects(shared_mem); |
| 109 | } | 110 | } |
| 110 | 111 | ||
| 111 | void IAppletResource::UpdateControllers(u64 userdata, std::chrono::nanoseconds ns_late) { | 112 | void IAppletResource::UpdateControllers(std::uintptr_t user_data, |
| 113 | std::chrono::nanoseconds ns_late) { | ||
| 112 | auto& core_timing = system.CoreTiming(); | 114 | auto& core_timing = system.CoreTiming(); |
| 113 | 115 | ||
| 114 | const bool should_reload = Settings::values.is_device_reload_pending.exchange(false); | 116 | const bool should_reload = Settings::values.is_device_reload_pending.exchange(false); |
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index c6f0a2584..efb07547f 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -64,7 +64,7 @@ private: | |||
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); | 66 | void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); |
| 67 | void UpdateControllers(u64 userdata, std::chrono::nanoseconds ns_late); | 67 | void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
| 68 | 68 | ||
| 69 | std::shared_ptr<Kernel::SharedMemory> shared_mem; | 69 | std::shared_ptr<Kernel::SharedMemory> shared_mem; |
| 70 | 70 | ||
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 64a526b9e..d8cd10e31 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp | |||
| @@ -310,7 +310,7 @@ public: | |||
| 310 | 310 | ||
| 311 | ResultVal<VAddr> MapProcessCodeMemory(Kernel::Process* process, VAddr baseAddress, | 311 | ResultVal<VAddr> MapProcessCodeMemory(Kernel::Process* process, VAddr baseAddress, |
| 312 | u64 size) const { | 312 | u64 size) const { |
| 313 | for (int retry{}; retry < MAXIMUM_MAP_RETRIES; retry++) { | 313 | for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { |
| 314 | auto& page_table{process->PageTable()}; | 314 | auto& page_table{process->PageTable()}; |
| 315 | const VAddr addr{GetRandomMapRegion(page_table, size)}; | 315 | const VAddr addr{GetRandomMapRegion(page_table, size)}; |
| 316 | const ResultCode result{page_table.MapProcessCodeMemory(addr, baseAddress, size)}; | 316 | const ResultCode result{page_table.MapProcessCodeMemory(addr, baseAddress, size)}; |
| @@ -331,8 +331,7 @@ public: | |||
| 331 | 331 | ||
| 332 | ResultVal<VAddr> MapNro(Kernel::Process* process, VAddr nro_addr, std::size_t nro_size, | 332 | ResultVal<VAddr> MapNro(Kernel::Process* process, VAddr nro_addr, std::size_t nro_size, |
| 333 | VAddr bss_addr, std::size_t bss_size, std::size_t size) const { | 333 | VAddr bss_addr, std::size_t bss_size, std::size_t size) const { |
| 334 | 334 | for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { | |
| 335 | for (int retry{}; retry < MAXIMUM_MAP_RETRIES; retry++) { | ||
| 336 | auto& page_table{process->PageTable()}; | 335 | auto& page_table{process->PageTable()}; |
| 337 | VAddr addr{}; | 336 | VAddr addr{}; |
| 338 | 337 | ||
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index 4b79eb81d..5e2d769a4 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp | |||
| @@ -127,7 +127,7 @@ private: | |||
| 127 | const u32 array_size = rp.Pop<u32>(); | 127 | const u32 array_size = rp.Pop<u32>(); |
| 128 | LOG_DEBUG(Service_NFP, "called, array_size={}", array_size); | 128 | LOG_DEBUG(Service_NFP, "called, array_size={}", array_size); |
| 129 | 129 | ||
| 130 | ctx.WriteBuffer(&device_handle, sizeof(device_handle)); | 130 | ctx.WriteBuffer(device_handle); |
| 131 | 131 | ||
| 132 | IPC::ResponseBuilder rb{ctx, 3}; | 132 | IPC::ResponseBuilder rb{ctx, 3}; |
| 133 | rb.Push(RESULT_SUCCESS); | 133 | rb.Push(RESULT_SUCCESS); |
| @@ -220,7 +220,7 @@ private: | |||
| 220 | 220 | ||
| 221 | tag_info.protocol = 1; // TODO(ogniK): Figure out actual values | 221 | tag_info.protocol = 1; // TODO(ogniK): Figure out actual values |
| 222 | tag_info.tag_type = 2; | 222 | tag_info.tag_type = 2; |
| 223 | ctx.WriteBuffer(&tag_info, sizeof(TagInfo)); | 223 | ctx.WriteBuffer(tag_info); |
| 224 | rb.Push(RESULT_SUCCESS); | 224 | rb.Push(RESULT_SUCCESS); |
| 225 | } | 225 | } |
| 226 | 226 | ||
| @@ -237,7 +237,7 @@ private: | |||
| 237 | 237 | ||
| 238 | IPC::ResponseBuilder rb{ctx, 2}; | 238 | IPC::ResponseBuilder rb{ctx, 2}; |
| 239 | auto amiibo = nfp_interface.GetAmiiboBuffer(); | 239 | auto amiibo = nfp_interface.GetAmiiboBuffer(); |
| 240 | ctx.WriteBuffer(&amiibo.model_info, sizeof(amiibo.model_info)); | 240 | ctx.WriteBuffer(amiibo.model_info); |
| 241 | rb.Push(RESULT_SUCCESS); | 241 | rb.Push(RESULT_SUCCESS); |
| 242 | } | 242 | } |
| 243 | 243 | ||
| @@ -283,7 +283,7 @@ private: | |||
| 283 | 283 | ||
| 284 | CommonInfo common_info{}; | 284 | CommonInfo common_info{}; |
| 285 | common_info.application_area_size = 0; | 285 | common_info.application_area_size = 0; |
| 286 | ctx.WriteBuffer(&common_info, sizeof(CommonInfo)); | 286 | ctx.WriteBuffer(common_info); |
| 287 | 287 | ||
| 288 | IPC::ResponseBuilder rb{ctx, 2}; | 288 | IPC::ResponseBuilder rb{ctx, 2}; |
| 289 | rb.Push(RESULT_SUCCESS); | 289 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index deaf0808b..88fbfa9b0 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp | |||
| @@ -60,24 +60,24 @@ void NVDRV::IoctlBase(Kernel::HLERequestContext& ctx, IoctlVersion version) { | |||
| 60 | 60 | ||
| 61 | if (ctrl.must_delay) { | 61 | if (ctrl.must_delay) { |
| 62 | ctrl.fresh_call = false; | 62 | ctrl.fresh_call = false; |
| 63 | ctx.SleepClientThread("NVServices::DelayedResponse", ctrl.timeout, | 63 | ctx.SleepClientThread( |
| 64 | [=](std::shared_ptr<Kernel::Thread> thread, | 64 | "NVServices::DelayedResponse", ctrl.timeout, |
| 65 | Kernel::HLERequestContext& ctx, | 65 | [=, this](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx_, |
| 66 | Kernel::ThreadWakeupReason reason) { | 66 | Kernel::ThreadWakeupReason reason) { |
| 67 | IoctlCtrl ctrl2{ctrl}; | 67 | IoctlCtrl ctrl2{ctrl}; |
| 68 | std::vector<u8> tmp_output = output; | 68 | std::vector<u8> tmp_output = output; |
| 69 | std::vector<u8> tmp_output2 = output2; | 69 | std::vector<u8> tmp_output2 = output2; |
| 70 | u32 result = nvdrv->Ioctl(fd, command, input, input2, tmp_output, | 70 | const u32 ioctl_result = nvdrv->Ioctl(fd, command, input, input2, tmp_output, |
| 71 | tmp_output2, ctrl2, version); | 71 | tmp_output2, ctrl2, version); |
| 72 | ctx.WriteBuffer(tmp_output, 0); | 72 | ctx_.WriteBuffer(tmp_output, 0); |
| 73 | if (version == IoctlVersion::Version3) { | 73 | if (version == IoctlVersion::Version3) { |
| 74 | ctx.WriteBuffer(tmp_output2, 1); | 74 | ctx_.WriteBuffer(tmp_output2, 1); |
| 75 | } | 75 | } |
| 76 | IPC::ResponseBuilder rb{ctx, 3}; | 76 | IPC::ResponseBuilder rb{ctx_, 3}; |
| 77 | rb.Push(RESULT_SUCCESS); | 77 | rb.Push(RESULT_SUCCESS); |
| 78 | rb.Push(result); | 78 | rb.Push(ioctl_result); |
| 79 | }, | 79 | }, |
| 80 | nvdrv->GetEventWriteable(ctrl.event_id)); | 80 | nvdrv->GetEventWriteable(ctrl.event_id)); |
| 81 | } else { | 81 | } else { |
| 82 | ctx.WriteBuffer(output); | 82 | ctx.WriteBuffer(output); |
| 83 | if (version == IoctlVersion::Version3) { | 83 | if (version == IoctlVersion::Version3) { |
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index e561bf654..f644a460d 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp | |||
| @@ -67,7 +67,7 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) { | |||
| 67 | 67 | ||
| 68 | // Schedule the screen composition events | 68 | // Schedule the screen composition events |
| 69 | composition_event = Core::Timing::CreateEvent( | 69 | composition_event = Core::Timing::CreateEvent( |
| 70 | "ScreenComposition", [this](u64, std::chrono::nanoseconds ns_late) { | 70 | "ScreenComposition", [this](std::uintptr_t, std::chrono::nanoseconds ns_late) { |
| 71 | const auto guard = Lock(); | 71 | const auto guard = Lock(); |
| 72 | Compose(); | 72 | Compose(); |
| 73 | 73 | ||
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index 34fe2fd82..e64777668 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp | |||
| @@ -106,7 +106,7 @@ void GetKeyCodeMapImpl(Kernel::HLERequestContext& ctx) { | |||
| 106 | 106 | ||
| 107 | IPC::ResponseBuilder rb{ctx, 2}; | 107 | IPC::ResponseBuilder rb{ctx, 2}; |
| 108 | rb.Push(RESULT_SUCCESS); | 108 | rb.Push(RESULT_SUCCESS); |
| 109 | ctx.WriteBuffer(&layout, sizeof(KeyboardLayout)); | 109 | ctx.WriteBuffer(layout); |
| 110 | } | 110 | } |
| 111 | } // Anonymous namespace | 111 | } // Anonymous namespace |
| 112 | 112 | ||
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index b06d2f103..b526a94fe 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <type_traits> | 9 | #include <type_traits> |
| 10 | #include <unordered_map> | 10 | #include <unordered_map> |
| 11 | 11 | ||
| 12 | #include "common/concepts.h" | ||
| 12 | #include "core/hle/kernel/client_port.h" | 13 | #include "core/hle/kernel/client_port.h" |
| 13 | #include "core/hle/kernel/object.h" | 14 | #include "core/hle/kernel/object.h" |
| 14 | #include "core/hle/kernel/server_port.h" | 15 | #include "core/hle/kernel/server_port.h" |
| @@ -56,10 +57,8 @@ public: | |||
| 56 | ResultVal<std::shared_ptr<Kernel::ClientPort>> GetServicePort(const std::string& name); | 57 | ResultVal<std::shared_ptr<Kernel::ClientPort>> GetServicePort(const std::string& name); |
| 57 | ResultVal<std::shared_ptr<Kernel::ClientSession>> ConnectToService(const std::string& name); | 58 | ResultVal<std::shared_ptr<Kernel::ClientSession>> ConnectToService(const std::string& name); |
| 58 | 59 | ||
| 59 | template <typename T> | 60 | template <Common::IsBaseOf<Kernel::SessionRequestHandler> T> |
| 60 | std::shared_ptr<T> GetService(const std::string& service_name) const { | 61 | std::shared_ptr<T> GetService(const std::string& service_name) const { |
| 61 | static_assert(std::is_base_of_v<Kernel::SessionRequestHandler, T>, | ||
| 62 | "Not a base of ServiceFrameworkBase"); | ||
| 63 | auto service = registered_services.find(service_name); | 62 | auto service = registered_services.find(service_name); |
| 64 | if (service == registered_services.end()) { | 63 | if (service == registered_services.end()) { |
| 65 | LOG_DEBUG(Service, "Can't find service: {}", service_name); | 64 | LOG_DEBUG(Service, "Can't find service: {}", service_name); |
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 13e4b3818..ee4fa4b48 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp | |||
| @@ -290,7 +290,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { | |||
| 290 | 290 | ||
| 291 | IPC::ResponseBuilder rb{ctx, 2}; | 291 | IPC::ResponseBuilder rb{ctx, 2}; |
| 292 | rb.Push(RESULT_SUCCESS); | 292 | rb.Push(RESULT_SUCCESS); |
| 293 | ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot)); | 293 | ctx.WriteBuffer(clock_snapshot); |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) { | 296 | void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) { |
| @@ -313,7 +313,7 @@ void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLEReques | |||
| 313 | 313 | ||
| 314 | IPC::ResponseBuilder rb{ctx, 2}; | 314 | IPC::ResponseBuilder rb{ctx, 2}; |
| 315 | rb.Push(RESULT_SUCCESS); | 315 | rb.Push(RESULT_SUCCESS); |
| 316 | ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot)); | 316 | ctx.WriteBuffer(clock_snapshot); |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser( | 319 | void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser( |
diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp index db57ae069..ff3a10b3e 100644 --- a/src/core/hle/service/time/time_zone_service.cpp +++ b/src/core/hle/service/time/time_zone_service.cpp | |||
| @@ -142,7 +142,7 @@ void ITimeZoneService::ToPosixTime(Kernel::HLERequestContext& ctx) { | |||
| 142 | IPC::ResponseBuilder rb{ctx, 3}; | 142 | IPC::ResponseBuilder rb{ctx, 3}; |
| 143 | rb.Push(RESULT_SUCCESS); | 143 | rb.Push(RESULT_SUCCESS); |
| 144 | rb.PushRaw<u32>(1); // Number of times we're returning | 144 | rb.PushRaw<u32>(1); // Number of times we're returning |
| 145 | ctx.WriteBuffer(&posix_time, sizeof(s64)); | 145 | ctx.WriteBuffer(posix_time); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) { | 148 | void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) { |
| @@ -164,7 +164,7 @@ void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) { | |||
| 164 | IPC::ResponseBuilder rb{ctx, 3}; | 164 | IPC::ResponseBuilder rb{ctx, 3}; |
| 165 | rb.Push(RESULT_SUCCESS); | 165 | rb.Push(RESULT_SUCCESS); |
| 166 | rb.PushRaw<u32>(1); // Number of times we're returning | 166 | rb.PushRaw<u32>(1); // Number of times we're returning |
| 167 | ctx.WriteBuffer(&posix_time, sizeof(s64)); | 167 | ctx.WriteBuffer(posix_time); |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | } // namespace Service::Time | 170 | } // namespace Service::Time |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 825d11a3f..988d253f9 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -548,8 +548,8 @@ private: | |||
| 548 | // Wait the current thread until a buffer becomes available | 548 | // Wait the current thread until a buffer becomes available |
| 549 | ctx.SleepClientThread( | 549 | ctx.SleepClientThread( |
| 550 | "IHOSBinderDriver::DequeueBuffer", UINT64_MAX, | 550 | "IHOSBinderDriver::DequeueBuffer", UINT64_MAX, |
| 551 | [=](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx, | 551 | [=, this](std::shared_ptr<Kernel::Thread> thread, |
| 552 | Kernel::ThreadWakeupReason reason) { | 552 | Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { |
| 553 | // Repeat TransactParcel DequeueBuffer when a buffer is available | 553 | // Repeat TransactParcel DequeueBuffer when a buffer is available |
| 554 | const auto guard = nv_flinger->Lock(); | 554 | const auto guard = nv_flinger->Lock(); |
| 555 | auto& buffer_queue = nv_flinger->FindBufferQueue(id); | 555 | auto& buffer_queue = nv_flinger->FindBufferQueue(id); |
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index ced41b1fe..eeebdf02e 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp | |||
| @@ -188,11 +188,11 @@ CheatEngine::~CheatEngine() { | |||
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | void CheatEngine::Initialize() { | 190 | void CheatEngine::Initialize() { |
| 191 | event = Core::Timing::CreateEvent("CheatEngine::FrameCallback::" + | 191 | event = Core::Timing::CreateEvent( |
| 192 | Common::HexToString(metadata.main_nso_build_id), | 192 | "CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id), |
| 193 | [this](u64 userdata, std::chrono::nanoseconds ns_late) { | 193 | [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { |
| 194 | FrameCallback(userdata, ns_late); | 194 | FrameCallback(user_data, ns_late); |
| 195 | }); | 195 | }); |
| 196 | core_timing.ScheduleEvent(CHEAT_ENGINE_NS, event); | 196 | core_timing.ScheduleEvent(CHEAT_ENGINE_NS, event); |
| 197 | 197 | ||
| 198 | metadata.process_id = system.CurrentProcess()->GetProcessID(); | 198 | metadata.process_id = system.CurrentProcess()->GetProcessID(); |
| @@ -219,7 +219,7 @@ void CheatEngine::Reload(std::vector<CheatEntry> cheats) { | |||
| 219 | 219 | ||
| 220 | MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70)); | 220 | MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70)); |
| 221 | 221 | ||
| 222 | void CheatEngine::FrameCallback(u64, std::chrono::nanoseconds ns_late) { | 222 | void CheatEngine::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) { |
| 223 | if (is_pending_reload.exchange(false)) { | 223 | if (is_pending_reload.exchange(false)) { |
| 224 | vm.LoadProgram(cheats); | 224 | vm.LoadProgram(cheats); |
| 225 | } | 225 | } |
diff --git a/src/core/memory/cheat_engine.h b/src/core/memory/cheat_engine.h index d4068cf84..fa039a831 100644 --- a/src/core/memory/cheat_engine.h +++ b/src/core/memory/cheat_engine.h | |||
| @@ -72,7 +72,7 @@ public: | |||
| 72 | void Reload(std::vector<CheatEntry> cheats); | 72 | void Reload(std::vector<CheatEntry> cheats); |
| 73 | 73 | ||
| 74 | private: | 74 | private: |
| 75 | void FrameCallback(u64 userdata, std::chrono::nanoseconds ns_late); | 75 | void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
| 76 | 76 | ||
| 77 | DmntCheatVm vm; | 77 | DmntCheatVm vm; |
| 78 | CheatProcessMetadata metadata; | 78 | CheatProcessMetadata metadata; |
diff --git a/src/core/memory/dmnt_cheat_vm.cpp b/src/core/memory/dmnt_cheat_vm.cpp index 2e7da23fe..48be80c12 100644 --- a/src/core/memory/dmnt_cheat_vm.cpp +++ b/src/core/memory/dmnt_cheat_vm.cpp | |||
| @@ -313,30 +313,32 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 313 | 313 | ||
| 314 | switch (opcode_type) { | 314 | switch (opcode_type) { |
| 315 | case CheatVmOpcodeType::StoreStatic: { | 315 | case CheatVmOpcodeType::StoreStatic: { |
| 316 | StoreStaticOpcode store_static{}; | ||
| 317 | // 0TMR00AA AAAAAAAA YYYYYYYY (YYYYYYYY) | 316 | // 0TMR00AA AAAAAAAA YYYYYYYY (YYYYYYYY) |
| 318 | // Read additional words. | 317 | // Read additional words. |
| 319 | const u32 second_dword = GetNextDword(); | 318 | const u32 second_dword = GetNextDword(); |
| 320 | store_static.bit_width = (first_dword >> 24) & 0xF; | 319 | const u32 bit_width = (first_dword >> 24) & 0xF; |
| 321 | store_static.mem_type = static_cast<MemoryAccessType>((first_dword >> 20) & 0xF); | 320 | |
| 322 | store_static.offset_register = ((first_dword >> 16) & 0xF); | 321 | opcode.opcode = StoreStaticOpcode{ |
| 323 | store_static.rel_address = | 322 | .bit_width = bit_width, |
| 324 | (static_cast<u64>(first_dword & 0xFF) << 32ul) | static_cast<u64>(second_dword); | 323 | .mem_type = static_cast<MemoryAccessType>((first_dword >> 20) & 0xF), |
| 325 | store_static.value = GetNextVmInt(store_static.bit_width); | 324 | .offset_register = (first_dword >> 16) & 0xF, |
| 326 | opcode.opcode = store_static; | 325 | .rel_address = (static_cast<u64>(first_dword & 0xFF) << 32) | second_dword, |
| 326 | .value = GetNextVmInt(bit_width), | ||
| 327 | }; | ||
| 327 | } break; | 328 | } break; |
| 328 | case CheatVmOpcodeType::BeginConditionalBlock: { | 329 | case CheatVmOpcodeType::BeginConditionalBlock: { |
| 329 | BeginConditionalOpcode begin_cond{}; | ||
| 330 | // 1TMC00AA AAAAAAAA YYYYYYYY (YYYYYYYY) | 330 | // 1TMC00AA AAAAAAAA YYYYYYYY (YYYYYYYY) |
| 331 | // Read additional words. | 331 | // Read additional words. |
| 332 | const u32 second_dword = GetNextDword(); | 332 | const u32 second_dword = GetNextDword(); |
| 333 | begin_cond.bit_width = (first_dword >> 24) & 0xF; | 333 | const u32 bit_width = (first_dword >> 24) & 0xF; |
| 334 | begin_cond.mem_type = static_cast<MemoryAccessType>((first_dword >> 20) & 0xF); | 334 | |
| 335 | begin_cond.cond_type = static_cast<ConditionalComparisonType>((first_dword >> 16) & 0xF); | 335 | opcode.opcode = BeginConditionalOpcode{ |
| 336 | begin_cond.rel_address = | 336 | .bit_width = bit_width, |
| 337 | (static_cast<u64>(first_dword & 0xFF) << 32ul) | static_cast<u64>(second_dword); | 337 | .mem_type = static_cast<MemoryAccessType>((first_dword >> 20) & 0xF), |
| 338 | begin_cond.value = GetNextVmInt(begin_cond.bit_width); | 338 | .cond_type = static_cast<ConditionalComparisonType>((first_dword >> 16) & 0xF), |
| 339 | opcode.opcode = begin_cond; | 339 | .rel_address = (static_cast<u64>(first_dword & 0xFF) << 32) | second_dword, |
| 340 | .value = GetNextVmInt(bit_width), | ||
| 341 | }; | ||
| 340 | } break; | 342 | } break; |
| 341 | case CheatVmOpcodeType::EndConditionalBlock: { | 343 | case CheatVmOpcodeType::EndConditionalBlock: { |
| 342 | // 20000000 | 344 | // 20000000 |
| @@ -344,12 +346,14 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 344 | opcode.opcode = EndConditionalOpcode{}; | 346 | opcode.opcode = EndConditionalOpcode{}; |
| 345 | } break; | 347 | } break; |
| 346 | case CheatVmOpcodeType::ControlLoop: { | 348 | case CheatVmOpcodeType::ControlLoop: { |
| 347 | ControlLoopOpcode ctrl_loop{}; | ||
| 348 | // 300R0000 VVVVVVVV | 349 | // 300R0000 VVVVVVVV |
| 349 | // 310R0000 | 350 | // 310R0000 |
| 350 | // Parse register, whether loop start or loop end. | 351 | // Parse register, whether loop start or loop end. |
| 351 | ctrl_loop.start_loop = ((first_dword >> 24) & 0xF) == 0; | 352 | ControlLoopOpcode ctrl_loop{ |
| 352 | ctrl_loop.reg_index = ((first_dword >> 20) & 0xF); | 353 | .start_loop = ((first_dword >> 24) & 0xF) == 0, |
| 354 | .reg_index = (first_dword >> 20) & 0xF, | ||
| 355 | .num_iters = 0, | ||
| 356 | }; | ||
| 353 | 357 | ||
| 354 | // Read number of iters if loop start. | 358 | // Read number of iters if loop start. |
| 355 | if (ctrl_loop.start_loop) { | 359 | if (ctrl_loop.start_loop) { |
| @@ -358,66 +362,65 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 358 | opcode.opcode = ctrl_loop; | 362 | opcode.opcode = ctrl_loop; |
| 359 | } break; | 363 | } break; |
| 360 | case CheatVmOpcodeType::LoadRegisterStatic: { | 364 | case CheatVmOpcodeType::LoadRegisterStatic: { |
| 361 | LoadRegisterStaticOpcode ldr_static{}; | ||
| 362 | // 400R0000 VVVVVVVV VVVVVVVV | 365 | // 400R0000 VVVVVVVV VVVVVVVV |
| 363 | // Read additional words. | 366 | // Read additional words. |
| 364 | ldr_static.reg_index = ((first_dword >> 16) & 0xF); | 367 | opcode.opcode = LoadRegisterStaticOpcode{ |
| 365 | ldr_static.value = | 368 | .reg_index = (first_dword >> 16) & 0xF, |
| 366 | (static_cast<u64>(GetNextDword()) << 32ul) | static_cast<u64>(GetNextDword()); | 369 | .value = (static_cast<u64>(GetNextDword()) << 32) | GetNextDword(), |
| 367 | opcode.opcode = ldr_static; | 370 | }; |
| 368 | } break; | 371 | } break; |
| 369 | case CheatVmOpcodeType::LoadRegisterMemory: { | 372 | case CheatVmOpcodeType::LoadRegisterMemory: { |
| 370 | LoadRegisterMemoryOpcode ldr_memory{}; | ||
| 371 | // 5TMRI0AA AAAAAAAA | 373 | // 5TMRI0AA AAAAAAAA |
| 372 | // Read additional words. | 374 | // Read additional words. |
| 373 | const u32 second_dword = GetNextDword(); | 375 | const u32 second_dword = GetNextDword(); |
| 374 | ldr_memory.bit_width = (first_dword >> 24) & 0xF; | 376 | opcode.opcode = LoadRegisterMemoryOpcode{ |
| 375 | ldr_memory.mem_type = static_cast<MemoryAccessType>((first_dword >> 20) & 0xF); | 377 | .bit_width = (first_dword >> 24) & 0xF, |
| 376 | ldr_memory.reg_index = ((first_dword >> 16) & 0xF); | 378 | .mem_type = static_cast<MemoryAccessType>((first_dword >> 20) & 0xF), |
| 377 | ldr_memory.load_from_reg = ((first_dword >> 12) & 0xF) != 0; | 379 | .reg_index = ((first_dword >> 16) & 0xF), |
| 378 | ldr_memory.rel_address = | 380 | .load_from_reg = ((first_dword >> 12) & 0xF) != 0, |
| 379 | (static_cast<u64>(first_dword & 0xFF) << 32ul) | static_cast<u64>(second_dword); | 381 | .rel_address = (static_cast<u64>(first_dword & 0xFF) << 32) | second_dword, |
| 380 | opcode.opcode = ldr_memory; | 382 | }; |
| 381 | } break; | 383 | } break; |
| 382 | case CheatVmOpcodeType::StoreStaticToAddress: { | 384 | case CheatVmOpcodeType::StoreStaticToAddress: { |
| 383 | StoreStaticToAddressOpcode str_static{}; | ||
| 384 | // 6T0RIor0 VVVVVVVV VVVVVVVV | 385 | // 6T0RIor0 VVVVVVVV VVVVVVVV |
| 385 | // Read additional words. | 386 | // Read additional words. |
| 386 | str_static.bit_width = (first_dword >> 24) & 0xF; | 387 | opcode.opcode = StoreStaticToAddressOpcode{ |
| 387 | str_static.reg_index = ((first_dword >> 16) & 0xF); | 388 | .bit_width = (first_dword >> 24) & 0xF, |
| 388 | str_static.increment_reg = ((first_dword >> 12) & 0xF) != 0; | 389 | .reg_index = (first_dword >> 16) & 0xF, |
| 389 | str_static.add_offset_reg = ((first_dword >> 8) & 0xF) != 0; | 390 | .increment_reg = ((first_dword >> 12) & 0xF) != 0, |
| 390 | str_static.offset_reg_index = ((first_dword >> 4) & 0xF); | 391 | .add_offset_reg = ((first_dword >> 8) & 0xF) != 0, |
| 391 | str_static.value = | 392 | .offset_reg_index = (first_dword >> 4) & 0xF, |
| 392 | (static_cast<u64>(GetNextDword()) << 32ul) | static_cast<u64>(GetNextDword()); | 393 | .value = (static_cast<u64>(GetNextDword()) << 32) | GetNextDword(), |
| 393 | opcode.opcode = str_static; | 394 | }; |
| 394 | } break; | 395 | } break; |
| 395 | case CheatVmOpcodeType::PerformArithmeticStatic: { | 396 | case CheatVmOpcodeType::PerformArithmeticStatic: { |
| 396 | PerformArithmeticStaticOpcode perform_math_static{}; | ||
| 397 | // 7T0RC000 VVVVVVVV | 397 | // 7T0RC000 VVVVVVVV |
| 398 | // Read additional words. | 398 | // Read additional words. |
| 399 | perform_math_static.bit_width = (first_dword >> 24) & 0xF; | 399 | opcode.opcode = PerformArithmeticStaticOpcode{ |
| 400 | perform_math_static.reg_index = ((first_dword >> 16) & 0xF); | 400 | .bit_width = (first_dword >> 24) & 0xF, |
| 401 | perform_math_static.math_type = | 401 | .reg_index = ((first_dword >> 16) & 0xF), |
| 402 | static_cast<RegisterArithmeticType>((first_dword >> 12) & 0xF); | 402 | .math_type = static_cast<RegisterArithmeticType>((first_dword >> 12) & 0xF), |
| 403 | perform_math_static.value = GetNextDword(); | 403 | .value = GetNextDword(), |
| 404 | opcode.opcode = perform_math_static; | 404 | }; |
| 405 | } break; | 405 | } break; |
| 406 | case CheatVmOpcodeType::BeginKeypressConditionalBlock: { | 406 | case CheatVmOpcodeType::BeginKeypressConditionalBlock: { |
| 407 | BeginKeypressConditionalOpcode begin_keypress_cond{}; | ||
| 408 | // 8kkkkkkk | 407 | // 8kkkkkkk |
| 409 | // Just parse the mask. | 408 | // Just parse the mask. |
| 410 | begin_keypress_cond.key_mask = first_dword & 0x0FFFFFFF; | 409 | opcode.opcode = BeginKeypressConditionalOpcode{ |
| 411 | opcode.opcode = begin_keypress_cond; | 410 | .key_mask = first_dword & 0x0FFFFFFF, |
| 411 | }; | ||
| 412 | } break; | 412 | } break; |
| 413 | case CheatVmOpcodeType::PerformArithmeticRegister: { | 413 | case CheatVmOpcodeType::PerformArithmeticRegister: { |
| 414 | PerformArithmeticRegisterOpcode perform_math_reg{}; | ||
| 415 | // 9TCRSIs0 (VVVVVVVV (VVVVVVVV)) | 414 | // 9TCRSIs0 (VVVVVVVV (VVVVVVVV)) |
| 416 | perform_math_reg.bit_width = (first_dword >> 24) & 0xF; | 415 | PerformArithmeticRegisterOpcode perform_math_reg{ |
| 417 | perform_math_reg.math_type = static_cast<RegisterArithmeticType>((first_dword >> 20) & 0xF); | 416 | .bit_width = (first_dword >> 24) & 0xF, |
| 418 | perform_math_reg.dst_reg_index = ((first_dword >> 16) & 0xF); | 417 | .math_type = static_cast<RegisterArithmeticType>((first_dword >> 20) & 0xF), |
| 419 | perform_math_reg.src_reg_1_index = ((first_dword >> 12) & 0xF); | 418 | .dst_reg_index = (first_dword >> 16) & 0xF, |
| 420 | perform_math_reg.has_immediate = ((first_dword >> 8) & 0xF) != 0; | 419 | .src_reg_1_index = (first_dword >> 12) & 0xF, |
| 420 | .src_reg_2_index = 0, | ||
| 421 | .has_immediate = ((first_dword >> 8) & 0xF) != 0, | ||
| 422 | .value = {}, | ||
| 423 | }; | ||
| 421 | if (perform_math_reg.has_immediate) { | 424 | if (perform_math_reg.has_immediate) { |
| 422 | perform_math_reg.src_reg_2_index = 0; | 425 | perform_math_reg.src_reg_2_index = 0; |
| 423 | perform_math_reg.value = GetNextVmInt(perform_math_reg.bit_width); | 426 | perform_math_reg.value = GetNextVmInt(perform_math_reg.bit_width); |
| @@ -427,7 +430,6 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 427 | opcode.opcode = perform_math_reg; | 430 | opcode.opcode = perform_math_reg; |
| 428 | } break; | 431 | } break; |
| 429 | case CheatVmOpcodeType::StoreRegisterToAddress: { | 432 | case CheatVmOpcodeType::StoreRegisterToAddress: { |
| 430 | StoreRegisterToAddressOpcode str_register{}; | ||
| 431 | // ATSRIOxa (aaaaaaaa) | 433 | // ATSRIOxa (aaaaaaaa) |
| 432 | // A = opcode 10 | 434 | // A = opcode 10 |
| 433 | // T = bit width | 435 | // T = bit width |
| @@ -439,20 +441,23 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 439 | // Relative Address | 441 | // Relative Address |
| 440 | // x = offset register (for offset type 1), memory type (for offset type 3) | 442 | // x = offset register (for offset type 1), memory type (for offset type 3) |
| 441 | // a = relative address (for offset type 2+3) | 443 | // a = relative address (for offset type 2+3) |
| 442 | str_register.bit_width = (first_dword >> 24) & 0xF; | 444 | StoreRegisterToAddressOpcode str_register{ |
| 443 | str_register.str_reg_index = ((first_dword >> 20) & 0xF); | 445 | .bit_width = (first_dword >> 24) & 0xF, |
| 444 | str_register.addr_reg_index = ((first_dword >> 16) & 0xF); | 446 | .str_reg_index = (first_dword >> 20) & 0xF, |
| 445 | str_register.increment_reg = ((first_dword >> 12) & 0xF) != 0; | 447 | .addr_reg_index = (first_dword >> 16) & 0xF, |
| 446 | str_register.ofs_type = static_cast<StoreRegisterOffsetType>(((first_dword >> 8) & 0xF)); | 448 | .increment_reg = ((first_dword >> 12) & 0xF) != 0, |
| 447 | str_register.ofs_reg_index = ((first_dword >> 4) & 0xF); | 449 | .ofs_type = static_cast<StoreRegisterOffsetType>(((first_dword >> 8) & 0xF)), |
| 450 | .mem_type = MemoryAccessType::MainNso, | ||
| 451 | .ofs_reg_index = (first_dword >> 4) & 0xF, | ||
| 452 | .rel_address = 0, | ||
| 453 | }; | ||
| 448 | switch (str_register.ofs_type) { | 454 | switch (str_register.ofs_type) { |
| 449 | case StoreRegisterOffsetType::None: | 455 | case StoreRegisterOffsetType::None: |
| 450 | case StoreRegisterOffsetType::Reg: | 456 | case StoreRegisterOffsetType::Reg: |
| 451 | // Nothing more to do | 457 | // Nothing more to do |
| 452 | break; | 458 | break; |
| 453 | case StoreRegisterOffsetType::Imm: | 459 | case StoreRegisterOffsetType::Imm: |
| 454 | str_register.rel_address = | 460 | str_register.rel_address = (static_cast<u64>(first_dword & 0xF) << 32) | GetNextDword(); |
| 455 | ((static_cast<u64>(first_dword & 0xF) << 32ul) | static_cast<u64>(GetNextDword())); | ||
| 456 | break; | 461 | break; |
| 457 | case StoreRegisterOffsetType::MemReg: | 462 | case StoreRegisterOffsetType::MemReg: |
| 458 | str_register.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF); | 463 | str_register.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF); |
| @@ -460,8 +465,7 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 460 | case StoreRegisterOffsetType::MemImm: | 465 | case StoreRegisterOffsetType::MemImm: |
| 461 | case StoreRegisterOffsetType::MemImmReg: | 466 | case StoreRegisterOffsetType::MemImmReg: |
| 462 | str_register.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF); | 467 | str_register.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF); |
| 463 | str_register.rel_address = | 468 | str_register.rel_address = (static_cast<u64>(first_dword & 0xF) << 32) | GetNextDword(); |
| 464 | ((static_cast<u64>(first_dword & 0xF) << 32ul) | static_cast<u64>(GetNextDword())); | ||
| 465 | break; | 469 | break; |
| 466 | default: | 470 | default: |
| 467 | str_register.ofs_type = StoreRegisterOffsetType::None; | 471 | str_register.ofs_type = StoreRegisterOffsetType::None; |
| @@ -470,7 +474,6 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 470 | opcode.opcode = str_register; | 474 | opcode.opcode = str_register; |
| 471 | } break; | 475 | } break; |
| 472 | case CheatVmOpcodeType::BeginRegisterConditionalBlock: { | 476 | case CheatVmOpcodeType::BeginRegisterConditionalBlock: { |
| 473 | BeginRegisterConditionalOpcode begin_reg_cond{}; | ||
| 474 | // C0TcSX## | 477 | // C0TcSX## |
| 475 | // C0TcS0Ma aaaaaaaa | 478 | // C0TcS0Ma aaaaaaaa |
| 476 | // C0TcS1Mr | 479 | // C0TcS1Mr |
| @@ -492,11 +495,19 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 492 | // r = offset register. | 495 | // r = offset register. |
| 493 | // X = other register. | 496 | // X = other register. |
| 494 | // V = value. | 497 | // V = value. |
| 495 | begin_reg_cond.bit_width = (first_dword >> 20) & 0xF; | 498 | |
| 496 | begin_reg_cond.cond_type = | 499 | BeginRegisterConditionalOpcode begin_reg_cond{ |
| 497 | static_cast<ConditionalComparisonType>((first_dword >> 16) & 0xF); | 500 | .bit_width = (first_dword >> 20) & 0xF, |
| 498 | begin_reg_cond.val_reg_index = ((first_dword >> 12) & 0xF); | 501 | .cond_type = static_cast<ConditionalComparisonType>((first_dword >> 16) & 0xF), |
| 499 | begin_reg_cond.comp_type = static_cast<CompareRegisterValueType>((first_dword >> 8) & 0xF); | 502 | .val_reg_index = (first_dword >> 12) & 0xF, |
| 503 | .comp_type = static_cast<CompareRegisterValueType>((first_dword >> 8) & 0xF), | ||
| 504 | .mem_type = MemoryAccessType::MainNso, | ||
| 505 | .addr_reg_index = 0, | ||
| 506 | .other_reg_index = 0, | ||
| 507 | .ofs_reg_index = 0, | ||
| 508 | .rel_address = 0, | ||
| 509 | .value = {}, | ||
| 510 | }; | ||
| 500 | 511 | ||
| 501 | switch (begin_reg_cond.comp_type) { | 512 | switch (begin_reg_cond.comp_type) { |
| 502 | case CompareRegisterValueType::StaticValue: | 513 | case CompareRegisterValueType::StaticValue: |
| @@ -508,26 +519,25 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 508 | case CompareRegisterValueType::MemoryRelAddr: | 519 | case CompareRegisterValueType::MemoryRelAddr: |
| 509 | begin_reg_cond.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF); | 520 | begin_reg_cond.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF); |
| 510 | begin_reg_cond.rel_address = | 521 | begin_reg_cond.rel_address = |
| 511 | ((static_cast<u64>(first_dword & 0xF) << 32ul) | static_cast<u64>(GetNextDword())); | 522 | (static_cast<u64>(first_dword & 0xF) << 32) | GetNextDword(); |
| 512 | break; | 523 | break; |
| 513 | case CompareRegisterValueType::MemoryOfsReg: | 524 | case CompareRegisterValueType::MemoryOfsReg: |
| 514 | begin_reg_cond.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF); | 525 | begin_reg_cond.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF); |
| 515 | begin_reg_cond.ofs_reg_index = (first_dword & 0xF); | 526 | begin_reg_cond.ofs_reg_index = (first_dword & 0xF); |
| 516 | break; | 527 | break; |
| 517 | case CompareRegisterValueType::RegisterRelAddr: | 528 | case CompareRegisterValueType::RegisterRelAddr: |
| 518 | begin_reg_cond.addr_reg_index = ((first_dword >> 4) & 0xF); | 529 | begin_reg_cond.addr_reg_index = (first_dword >> 4) & 0xF; |
| 519 | begin_reg_cond.rel_address = | 530 | begin_reg_cond.rel_address = |
| 520 | ((static_cast<u64>(first_dword & 0xF) << 32ul) | static_cast<u64>(GetNextDword())); | 531 | (static_cast<u64>(first_dword & 0xF) << 32) | GetNextDword(); |
| 521 | break; | 532 | break; |
| 522 | case CompareRegisterValueType::RegisterOfsReg: | 533 | case CompareRegisterValueType::RegisterOfsReg: |
| 523 | begin_reg_cond.addr_reg_index = ((first_dword >> 4) & 0xF); | 534 | begin_reg_cond.addr_reg_index = (first_dword >> 4) & 0xF; |
| 524 | begin_reg_cond.ofs_reg_index = (first_dword & 0xF); | 535 | begin_reg_cond.ofs_reg_index = first_dword & 0xF; |
| 525 | break; | 536 | break; |
| 526 | } | 537 | } |
| 527 | opcode.opcode = begin_reg_cond; | 538 | opcode.opcode = begin_reg_cond; |
| 528 | } break; | 539 | } break; |
| 529 | case CheatVmOpcodeType::SaveRestoreRegister: { | 540 | case CheatVmOpcodeType::SaveRestoreRegister: { |
| 530 | SaveRestoreRegisterOpcode save_restore_reg{}; | ||
| 531 | // C10D0Sx0 | 541 | // C10D0Sx0 |
| 532 | // C1 = opcode 0xC1 | 542 | // C1 = opcode 0xC1 |
| 533 | // D = destination index. | 543 | // D = destination index. |
| @@ -535,36 +545,37 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 535 | // x = 3 if clearing reg, 2 if clearing saved value, 1 if saving a register, 0 if restoring | 545 | // x = 3 if clearing reg, 2 if clearing saved value, 1 if saving a register, 0 if restoring |
| 536 | // a register. | 546 | // a register. |
| 537 | // NOTE: If we add more save slots later, current encoding is backwards compatible. | 547 | // NOTE: If we add more save slots later, current encoding is backwards compatible. |
| 538 | save_restore_reg.dst_index = (first_dword >> 16) & 0xF; | 548 | opcode.opcode = SaveRestoreRegisterOpcode{ |
| 539 | save_restore_reg.src_index = (first_dword >> 8) & 0xF; | 549 | .dst_index = (first_dword >> 16) & 0xF, |
| 540 | save_restore_reg.op_type = static_cast<SaveRestoreRegisterOpType>((first_dword >> 4) & 0xF); | 550 | .src_index = (first_dword >> 8) & 0xF, |
| 541 | opcode.opcode = save_restore_reg; | 551 | .op_type = static_cast<SaveRestoreRegisterOpType>((first_dword >> 4) & 0xF), |
| 552 | }; | ||
| 542 | } break; | 553 | } break; |
| 543 | case CheatVmOpcodeType::SaveRestoreRegisterMask: { | 554 | case CheatVmOpcodeType::SaveRestoreRegisterMask: { |
| 544 | SaveRestoreRegisterMaskOpcode save_restore_regmask{}; | ||
| 545 | // C2x0XXXX | 555 | // C2x0XXXX |
| 546 | // C2 = opcode 0xC2 | 556 | // C2 = opcode 0xC2 |
| 547 | // x = 3 if clearing reg, 2 if clearing saved value, 1 if saving, 0 if restoring. | 557 | // x = 3 if clearing reg, 2 if clearing saved value, 1 if saving, 0 if restoring. |
| 548 | // X = 16-bit bitmask, bit i --> save or restore register i. | 558 | // X = 16-bit bitmask, bit i --> save or restore register i. |
| 549 | save_restore_regmask.op_type = | 559 | SaveRestoreRegisterMaskOpcode save_restore_regmask{ |
| 550 | static_cast<SaveRestoreRegisterOpType>((first_dword >> 20) & 0xF); | 560 | .op_type = static_cast<SaveRestoreRegisterOpType>((first_dword >> 20) & 0xF), |
| 561 | .should_operate = {}, | ||
| 562 | }; | ||
| 551 | for (std::size_t i = 0; i < NumRegisters; i++) { | 563 | for (std::size_t i = 0; i < NumRegisters; i++) { |
| 552 | save_restore_regmask.should_operate[i] = (first_dword & (1u << i)) != 0; | 564 | save_restore_regmask.should_operate[i] = (first_dword & (1U << i)) != 0; |
| 553 | } | 565 | } |
| 554 | opcode.opcode = save_restore_regmask; | 566 | opcode.opcode = save_restore_regmask; |
| 555 | } break; | 567 | } break; |
| 556 | case CheatVmOpcodeType::ReadWriteStaticRegister: { | 568 | case CheatVmOpcodeType::ReadWriteStaticRegister: { |
| 557 | ReadWriteStaticRegisterOpcode rw_static_reg{}; | ||
| 558 | // C3000XXx | 569 | // C3000XXx |
| 559 | // C3 = opcode 0xC3. | 570 | // C3 = opcode 0xC3. |
| 560 | // XX = static register index. | 571 | // XX = static register index. |
| 561 | // x = register index. | 572 | // x = register index. |
| 562 | rw_static_reg.static_idx = ((first_dword >> 4) & 0xFF); | 573 | opcode.opcode = ReadWriteStaticRegisterOpcode{ |
| 563 | rw_static_reg.idx = (first_dword & 0xF); | 574 | .static_idx = (first_dword >> 4) & 0xFF, |
| 564 | opcode.opcode = rw_static_reg; | 575 | .idx = first_dword & 0xF, |
| 576 | }; | ||
| 565 | } break; | 577 | } break; |
| 566 | case CheatVmOpcodeType::DebugLog: { | 578 | case CheatVmOpcodeType::DebugLog: { |
| 567 | DebugLogOpcode debug_log{}; | ||
| 568 | // FFFTIX## | 579 | // FFFTIX## |
| 569 | // FFFTI0Ma aaaaaaaa | 580 | // FFFTI0Ma aaaaaaaa |
| 570 | // FFFTI1Mr | 581 | // FFFTI1Mr |
| @@ -583,31 +594,36 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) { | |||
| 583 | // a = relative address. | 594 | // a = relative address. |
| 584 | // r = offset register. | 595 | // r = offset register. |
| 585 | // X = value register. | 596 | // X = value register. |
| 586 | debug_log.bit_width = (first_dword >> 16) & 0xF; | 597 | DebugLogOpcode debug_log{ |
| 587 | debug_log.log_id = ((first_dword >> 12) & 0xF); | 598 | .bit_width = (first_dword >> 16) & 0xF, |
| 588 | debug_log.val_type = static_cast<DebugLogValueType>((first_dword >> 8) & 0xF); | 599 | .log_id = (first_dword >> 12) & 0xF, |
| 600 | .val_type = static_cast<DebugLogValueType>((first_dword >> 8) & 0xF), | ||
| 601 | .mem_type = MemoryAccessType::MainNso, | ||
| 602 | .addr_reg_index = 0, | ||
| 603 | .val_reg_index = 0, | ||
| 604 | .ofs_reg_index = 0, | ||
| 605 | .rel_address = 0, | ||
| 606 | }; | ||
| 589 | 607 | ||
| 590 | switch (debug_log.val_type) { | 608 | switch (debug_log.val_type) { |
| 591 | case DebugLogValueType::RegisterValue: | 609 | case DebugLogValueType::RegisterValue: |
| 592 | debug_log.val_reg_index = ((first_dword >> 4) & 0xF); | 610 | debug_log.val_reg_index = (first_dword >> 4) & 0xF; |
| 593 | break; | 611 | break; |
| 594 | case DebugLogValueType::MemoryRelAddr: | 612 | case DebugLogValueType::MemoryRelAddr: |
| 595 | debug_log.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF); | 613 | debug_log.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF); |
| 596 | debug_log.rel_address = | 614 | debug_log.rel_address = (static_cast<u64>(first_dword & 0xF) << 32) | GetNextDword(); |
| 597 | ((static_cast<u64>(first_dword & 0xF) << 32ul) | static_cast<u64>(GetNextDword())); | ||
| 598 | break; | 615 | break; |
| 599 | case DebugLogValueType::MemoryOfsReg: | 616 | case DebugLogValueType::MemoryOfsReg: |
| 600 | debug_log.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF); | 617 | debug_log.mem_type = static_cast<MemoryAccessType>((first_dword >> 4) & 0xF); |
| 601 | debug_log.ofs_reg_index = (first_dword & 0xF); | 618 | debug_log.ofs_reg_index = first_dword & 0xF; |
| 602 | break; | 619 | break; |
| 603 | case DebugLogValueType::RegisterRelAddr: | 620 | case DebugLogValueType::RegisterRelAddr: |
| 604 | debug_log.addr_reg_index = ((first_dword >> 4) & 0xF); | 621 | debug_log.addr_reg_index = (first_dword >> 4) & 0xF; |
| 605 | debug_log.rel_address = | 622 | debug_log.rel_address = (static_cast<u64>(first_dword & 0xF) << 32) | GetNextDword(); |
| 606 | ((static_cast<u64>(first_dword & 0xF) << 32ul) | static_cast<u64>(GetNextDword())); | ||
| 607 | break; | 623 | break; |
| 608 | case DebugLogValueType::RegisterOfsReg: | 624 | case DebugLogValueType::RegisterOfsReg: |
| 609 | debug_log.addr_reg_index = ((first_dword >> 4) & 0xF); | 625 | debug_log.addr_reg_index = (first_dword >> 4) & 0xF; |
| 610 | debug_log.ofs_reg_index = (first_dword & 0xF); | 626 | debug_log.ofs_reg_index = first_dword & 0xF; |
| 611 | break; | 627 | break; |
| 612 | } | 628 | } |
| 613 | opcode.opcode = debug_log; | 629 | opcode.opcode = debug_log; |
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 29339ead7..b899ac884 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp | |||
| @@ -74,15 +74,16 @@ void PerfStats::EndGameFrame() { | |||
| 74 | game_frames += 1; | 74 | game_frames += 1; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | double PerfStats::GetMeanFrametime() { | 77 | double PerfStats::GetMeanFrametime() const { |
| 78 | std::lock_guard lock{object_mutex}; | 78 | std::lock_guard lock{object_mutex}; |
| 79 | 79 | ||
| 80 | if (current_index <= IgnoreFrames) { | 80 | if (current_index <= IgnoreFrames) { |
| 81 | return 0; | 81 | return 0; |
| 82 | } | 82 | } |
| 83 | |||
| 83 | const double sum = std::accumulate(perf_history.begin() + IgnoreFrames, | 84 | const double sum = std::accumulate(perf_history.begin() + IgnoreFrames, |
| 84 | perf_history.begin() + current_index, 0.0); | 85 | perf_history.begin() + current_index, 0.0); |
| 85 | return sum / (current_index - IgnoreFrames); | 86 | return sum / static_cast<double>(current_index - IgnoreFrames); |
| 86 | } | 87 | } |
| 87 | 88 | ||
| 88 | PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us) { | 89 | PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us) { |
| @@ -94,12 +95,13 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us | |||
| 94 | 95 | ||
| 95 | const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval; | 96 | const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval; |
| 96 | 97 | ||
| 97 | PerfStatsResults results{}; | 98 | const PerfStatsResults results{ |
| 98 | results.system_fps = static_cast<double>(system_frames) / interval; | 99 | .system_fps = static_cast<double>(system_frames) / interval, |
| 99 | results.game_fps = static_cast<double>(game_frames) / interval; | 100 | .game_fps = static_cast<double>(game_frames) / interval, |
| 100 | results.frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() / | 101 | .frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() / |
| 101 | static_cast<double>(system_frames); | 102 | static_cast<double>(system_frames), |
| 102 | results.emulation_speed = system_us_per_second.count() / 1'000'000.0; | 103 | .emulation_speed = system_us_per_second.count() / 1'000'000.0, |
| 104 | }; | ||
| 103 | 105 | ||
| 104 | // Reset counters | 106 | // Reset counters |
| 105 | reset_point = now; | 107 | reset_point = now; |
| @@ -111,7 +113,7 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us | |||
| 111 | return results; | 113 | return results; |
| 112 | } | 114 | } |
| 113 | 115 | ||
| 114 | double PerfStats::GetLastFrameTimeScale() { | 116 | double PerfStats::GetLastFrameTimeScale() const { |
| 115 | std::lock_guard lock{object_mutex}; | 117 | std::lock_guard lock{object_mutex}; |
| 116 | 118 | ||
| 117 | constexpr double FRAME_LENGTH = 1.0 / 60; | 119 | constexpr double FRAME_LENGTH = 1.0 / 60; |
diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h index d9a64f072..69256b960 100644 --- a/src/core/perf_stats.h +++ b/src/core/perf_stats.h | |||
| @@ -30,7 +30,6 @@ struct PerfStatsResults { | |||
| 30 | class PerfStats { | 30 | class PerfStats { |
| 31 | public: | 31 | public: |
| 32 | explicit PerfStats(u64 title_id); | 32 | explicit PerfStats(u64 title_id); |
| 33 | |||
| 34 | ~PerfStats(); | 33 | ~PerfStats(); |
| 35 | 34 | ||
| 36 | using Clock = std::chrono::high_resolution_clock; | 35 | using Clock = std::chrono::high_resolution_clock; |
| @@ -42,18 +41,18 @@ public: | |||
| 42 | PerfStatsResults GetAndResetStats(std::chrono::microseconds current_system_time_us); | 41 | PerfStatsResults GetAndResetStats(std::chrono::microseconds current_system_time_us); |
| 43 | 42 | ||
| 44 | /** | 43 | /** |
| 45 | * Returns the Arthimetic Mean of all frametime values stored in the performance history. | 44 | * Returns the arithmetic mean of all frametime values stored in the performance history. |
| 46 | */ | 45 | */ |
| 47 | double GetMeanFrametime(); | 46 | double GetMeanFrametime() const; |
| 48 | 47 | ||
| 49 | /** | 48 | /** |
| 50 | * Gets the ratio between walltime and the emulated time of the previous system frame. This is | 49 | * Gets the ratio between walltime and the emulated time of the previous system frame. This is |
| 51 | * useful for scaling inputs or outputs moving between the two time domains. | 50 | * useful for scaling inputs or outputs moving between the two time domains. |
| 52 | */ | 51 | */ |
| 53 | double GetLastFrameTimeScale(); | 52 | double GetLastFrameTimeScale() const; |
| 54 | 53 | ||
| 55 | private: | 54 | private: |
| 56 | std::mutex object_mutex{}; | 55 | mutable std::mutex object_mutex; |
| 57 | 56 | ||
| 58 | /// Title ID for the game that is running. 0 if there is no game running yet | 57 | /// Title ID for the game that is running. 0 if there is no game running yet |
| 59 | u64 title_id{0}; | 58 | u64 title_id{0}; |
| @@ -61,7 +60,7 @@ private: | |||
| 61 | std::size_t current_index{0}; | 60 | std::size_t current_index{0}; |
| 62 | /// Stores an hour of historical frametime data useful for processing and tracking performance | 61 | /// Stores an hour of historical frametime data useful for processing and tracking performance |
| 63 | /// regressions with code changes. | 62 | /// regressions with code changes. |
| 64 | std::array<double, 216000> perf_history = {}; | 63 | std::array<double, 216000> perf_history{}; |
| 65 | 64 | ||
| 66 | /// Point when the cumulative counters were reset | 65 | /// Point when the cumulative counters were reset |
| 67 | Clock::time_point reset_point = Clock::now(); | 66 | Clock::time_point reset_point = Clock::now(); |
diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 44252dd81..416b2d866 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp | |||
| @@ -173,7 +173,6 @@ void RestoreGlobalState() { | |||
| 173 | values.use_assembly_shaders.SetGlobal(true); | 173 | values.use_assembly_shaders.SetGlobal(true); |
| 174 | values.use_asynchronous_shaders.SetGlobal(true); | 174 | values.use_asynchronous_shaders.SetGlobal(true); |
| 175 | values.use_fast_gpu_time.SetGlobal(true); | 175 | values.use_fast_gpu_time.SetGlobal(true); |
| 176 | values.force_30fps_mode.SetGlobal(true); | ||
| 177 | values.bg_red.SetGlobal(true); | 176 | values.bg_red.SetGlobal(true); |
| 178 | values.bg_green.SetGlobal(true); | 177 | values.bg_green.SetGlobal(true); |
| 179 | values.bg_blue.SetGlobal(true); | 178 | values.bg_blue.SetGlobal(true); |
diff --git a/src/core/settings.h b/src/core/settings.h index 386233fdf..bb145f193 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -435,7 +435,6 @@ struct Values { | |||
| 435 | Setting<bool> use_vsync; | 435 | Setting<bool> use_vsync; |
| 436 | Setting<bool> use_assembly_shaders; | 436 | Setting<bool> use_assembly_shaders; |
| 437 | Setting<bool> use_asynchronous_shaders; | 437 | Setting<bool> use_asynchronous_shaders; |
| 438 | Setting<bool> force_30fps_mode; | ||
| 439 | Setting<bool> use_fast_gpu_time; | 438 | Setting<bool> use_fast_gpu_time; |
| 440 | 439 | ||
| 441 | Setting<float> bg_red; | 440 | Setting<float> bg_red; |
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp index 27b894b51..2003e096f 100644 --- a/src/core/tools/freezer.cpp +++ b/src/core/tools/freezer.cpp | |||
| @@ -55,10 +55,11 @@ void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 v | |||
| 55 | 55 | ||
| 56 | Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_) | 56 | Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_) |
| 57 | : core_timing{core_timing_}, memory{memory_} { | 57 | : core_timing{core_timing_}, memory{memory_} { |
| 58 | event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback", | 58 | event = Core::Timing::CreateEvent( |
| 59 | [this](u64 userdata, std::chrono::nanoseconds ns_late) { | 59 | "MemoryFreezer::FrameCallback", |
| 60 | FrameCallback(userdata, ns_late); | 60 | [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { |
| 61 | }); | 61 | FrameCallback(user_data, ns_late); |
| 62 | }); | ||
| 62 | core_timing.ScheduleEvent(memory_freezer_ns, event); | 63 | core_timing.ScheduleEvent(memory_freezer_ns, event); |
| 63 | } | 64 | } |
| 64 | 65 | ||
| @@ -159,7 +160,7 @@ std::vector<Freezer::Entry> Freezer::GetEntries() const { | |||
| 159 | return entries; | 160 | return entries; |
| 160 | } | 161 | } |
| 161 | 162 | ||
| 162 | void Freezer::FrameCallback(u64, std::chrono::nanoseconds ns_late) { | 163 | void Freezer::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) { |
| 163 | if (!IsActive()) { | 164 | if (!IsActive()) { |
| 164 | LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events."); | 165 | LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events."); |
| 165 | return; | 166 | return; |
diff --git a/src/core/tools/freezer.h b/src/core/tools/freezer.h index 8438783d5..2b2326bc4 100644 --- a/src/core/tools/freezer.h +++ b/src/core/tools/freezer.h | |||
| @@ -73,7 +73,7 @@ public: | |||
| 73 | std::vector<Entry> GetEntries() const; | 73 | std::vector<Entry> GetEntries() const; |
| 74 | 74 | ||
| 75 | private: | 75 | private: |
| 76 | void FrameCallback(u64 userdata, std::chrono::nanoseconds ns_late); | 76 | void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
| 77 | void FillEntryReads(); | 77 | void FillEntryReads(); |
| 78 | 78 | ||
| 79 | std::atomic_bool active{false}; | 79 | std::atomic_bool active{false}; |