diff options
Diffstat (limited to 'src')
30 files changed, 473 insertions, 247 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e30fea268..85926fc8f 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -106,6 +106,7 @@ add_library(common STATIC | |||
| 106 | precompiled_headers.h | 106 | precompiled_headers.h |
| 107 | quaternion.h | 107 | quaternion.h |
| 108 | range_map.h | 108 | range_map.h |
| 109 | range_mutex.h | ||
| 109 | reader_writer_queue.h | 110 | reader_writer_queue.h |
| 110 | ring_buffer.h | 111 | ring_buffer.h |
| 111 | ${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp | 112 | ${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp |
diff --git a/src/common/range_mutex.h b/src/common/range_mutex.h new file mode 100644 index 000000000..d6c949811 --- /dev/null +++ b/src/common/range_mutex.h | |||
| @@ -0,0 +1,93 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <condition_variable> | ||
| 7 | #include <mutex> | ||
| 8 | |||
| 9 | #include "common/intrusive_list.h" | ||
| 10 | |||
| 11 | namespace Common { | ||
| 12 | |||
| 13 | class ScopedRangeLock; | ||
| 14 | |||
| 15 | class RangeMutex { | ||
| 16 | public: | ||
| 17 | explicit RangeMutex() = default; | ||
| 18 | ~RangeMutex() = default; | ||
| 19 | |||
| 20 | private: | ||
| 21 | friend class ScopedRangeLock; | ||
| 22 | |||
| 23 | void Lock(ScopedRangeLock& l); | ||
| 24 | void Unlock(ScopedRangeLock& l); | ||
| 25 | bool HasIntersectionLocked(ScopedRangeLock& l); | ||
| 26 | |||
| 27 | private: | ||
| 28 | std::mutex m_mutex; | ||
| 29 | std::condition_variable m_cv; | ||
| 30 | |||
| 31 | using LockList = Common::IntrusiveListBaseTraits<ScopedRangeLock>::ListType; | ||
| 32 | LockList m_list; | ||
| 33 | }; | ||
| 34 | |||
| 35 | class ScopedRangeLock : public Common::IntrusiveListBaseNode<ScopedRangeLock> { | ||
| 36 | public: | ||
| 37 | explicit ScopedRangeLock(RangeMutex& mutex, u64 address, u64 size) | ||
| 38 | : m_mutex(mutex), m_address(address), m_size(size) { | ||
| 39 | if (m_size > 0) { | ||
| 40 | m_mutex.Lock(*this); | ||
| 41 | } | ||
| 42 | } | ||
| 43 | ~ScopedRangeLock() { | ||
| 44 | if (m_size > 0) { | ||
| 45 | m_mutex.Unlock(*this); | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | u64 GetAddress() const { | ||
| 50 | return m_address; | ||
| 51 | } | ||
| 52 | |||
| 53 | u64 GetSize() const { | ||
| 54 | return m_size; | ||
| 55 | } | ||
| 56 | |||
| 57 | private: | ||
| 58 | RangeMutex& m_mutex; | ||
| 59 | const u64 m_address{}; | ||
| 60 | const u64 m_size{}; | ||
| 61 | }; | ||
| 62 | |||
| 63 | inline void RangeMutex::Lock(ScopedRangeLock& l) { | ||
| 64 | std::unique_lock lk{m_mutex}; | ||
| 65 | m_cv.wait(lk, [&] { return !HasIntersectionLocked(l); }); | ||
| 66 | m_list.push_back(l); | ||
| 67 | } | ||
| 68 | |||
| 69 | inline void RangeMutex::Unlock(ScopedRangeLock& l) { | ||
| 70 | { | ||
| 71 | std::scoped_lock lk{m_mutex}; | ||
| 72 | m_list.erase(m_list.iterator_to(l)); | ||
| 73 | } | ||
| 74 | m_cv.notify_all(); | ||
| 75 | } | ||
| 76 | |||
| 77 | inline bool RangeMutex::HasIntersectionLocked(ScopedRangeLock& l) { | ||
| 78 | const auto cur_begin = l.GetAddress(); | ||
| 79 | const auto cur_last = l.GetAddress() + l.GetSize() - 1; | ||
| 80 | |||
| 81 | for (const auto& other : m_list) { | ||
| 82 | const auto other_begin = other.GetAddress(); | ||
| 83 | const auto other_last = other.GetAddress() + other.GetSize() - 1; | ||
| 84 | |||
| 85 | if (cur_begin <= other_last && other_begin <= cur_last) { | ||
| 86 | return true; | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | return false; | ||
| 91 | } | ||
| 92 | |||
| 93 | } // namespace Common | ||
diff --git a/src/common/settings.h b/src/common/settings.h index 16749ab68..f1b1add56 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -134,12 +134,12 @@ struct Values { | |||
| 134 | Linkage linkage{}; | 134 | Linkage linkage{}; |
| 135 | 135 | ||
| 136 | // Audio | 136 | // Audio |
| 137 | Setting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Category::Audio, | 137 | SwitchableSetting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", |
| 138 | Specialization::RuntimeList}; | 138 | Category::Audio, Specialization::RuntimeList}; |
| 139 | Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio, | 139 | SwitchableSetting<std::string> audio_output_device_id{ |
| 140 | Specialization::RuntimeList}; | 140 | linkage, "auto", "output_device", Category::Audio, Specialization::RuntimeList}; |
| 141 | Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio, | 141 | SwitchableSetting<std::string> audio_input_device_id{ |
| 142 | Specialization::RuntimeList}; | 142 | linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList}; |
| 143 | SwitchableSetting<AudioMode, true> sound_index{ | 143 | SwitchableSetting<AudioMode, true> sound_index{ |
| 144 | linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround, | 144 | linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround, |
| 145 | "sound_index", Category::SystemAudio, Specialization::Default, true, | 145 | "sound_index", Category::SystemAudio, Specialization::Default, true, |
diff --git a/src/core/device_memory_manager.h b/src/core/device_memory_manager.h index ffeed46cc..0568a821b 100644 --- a/src/core/device_memory_manager.h +++ b/src/core/device_memory_manager.h | |||
| @@ -5,11 +5,13 @@ | |||
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <atomic> | 7 | #include <atomic> |
| 8 | #include <bit> | ||
| 8 | #include <deque> | 9 | #include <deque> |
| 9 | #include <memory> | 10 | #include <memory> |
| 10 | #include <mutex> | 11 | #include <mutex> |
| 11 | 12 | ||
| 12 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "common/range_mutex.h" | ||
| 13 | #include "common/scratch_buffer.h" | 15 | #include "common/scratch_buffer.h" |
| 14 | #include "common/virtual_buffer.h" | 16 | #include "common/virtual_buffer.h" |
| 15 | 17 | ||
| @@ -180,31 +182,35 @@ private: | |||
| 180 | } | 182 | } |
| 181 | 183 | ||
| 182 | Common::VirtualBuffer<VAddr> cpu_backing_address; | 184 | Common::VirtualBuffer<VAddr> cpu_backing_address; |
| 183 | static constexpr size_t subentries = 8 / sizeof(u8); | 185 | using CounterType = u8; |
| 186 | using CounterAtomicType = std::atomic_uint8_t; | ||
| 187 | static constexpr size_t subentries = 8 / sizeof(CounterType); | ||
| 184 | static constexpr size_t subentries_mask = subentries - 1; | 188 | static constexpr size_t subentries_mask = subentries - 1; |
| 189 | static constexpr size_t subentries_shift = | ||
| 190 | std::countr_zero(sizeof(u64)) - std::countr_zero(sizeof(CounterType)); | ||
| 185 | class CounterEntry final { | 191 | class CounterEntry final { |
| 186 | public: | 192 | public: |
| 187 | CounterEntry() = default; | 193 | CounterEntry() = default; |
| 188 | 194 | ||
| 189 | std::atomic_uint8_t& Count(std::size_t page) { | 195 | CounterAtomicType& Count(std::size_t page) { |
| 190 | return values[page & subentries_mask]; | 196 | return values[page & subentries_mask]; |
| 191 | } | 197 | } |
| 192 | 198 | ||
| 193 | const std::atomic_uint8_t& Count(std::size_t page) const { | 199 | const CounterAtomicType& Count(std::size_t page) const { |
| 194 | return values[page & subentries_mask]; | 200 | return values[page & subentries_mask]; |
| 195 | } | 201 | } |
| 196 | 202 | ||
| 197 | private: | 203 | private: |
| 198 | std::array<std::atomic_uint8_t, subentries> values{}; | 204 | std::array<CounterAtomicType, subentries> values{}; |
| 199 | }; | 205 | }; |
| 200 | static_assert(sizeof(CounterEntry) == subentries * sizeof(u8), | 206 | static_assert(sizeof(CounterEntry) == subentries * sizeof(CounterType), |
| 201 | "CounterEntry should be 8 bytes!"); | 207 | "CounterEntry should be 8 bytes!"); |
| 202 | 208 | ||
| 203 | static constexpr size_t num_counter_entries = | 209 | static constexpr size_t num_counter_entries = |
| 204 | (1ULL << (device_virtual_bits - page_bits)) / subentries; | 210 | (1ULL << (device_virtual_bits - page_bits)) / subentries; |
| 205 | using CachedPages = std::array<CounterEntry, num_counter_entries>; | 211 | using CachedPages = std::array<CounterEntry, num_counter_entries>; |
| 206 | std::unique_ptr<CachedPages> cached_pages; | 212 | std::unique_ptr<CachedPages> cached_pages; |
| 207 | std::mutex counter_guard; | 213 | Common::RangeMutex counter_guard; |
| 208 | std::mutex mapping_guard; | 214 | std::mutex mapping_guard; |
| 209 | }; | 215 | }; |
| 210 | 216 | ||
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc index eab8a2731..b026f4220 100644 --- a/src/core/device_memory_manager.inc +++ b/src/core/device_memory_manager.inc | |||
| @@ -213,8 +213,8 @@ void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) { | |||
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | template <typename Traits> | 215 | template <typename Traits> |
| 216 | void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, | 216 | void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, Asid asid, |
| 217 | Asid asid, bool track) { | 217 | bool track) { |
| 218 | Core::Memory::Memory* process_memory = registered_processes[asid.id]; | 218 | Core::Memory::Memory* process_memory = registered_processes[asid.id]; |
| 219 | size_t start_page_d = address >> Memory::YUZU_PAGEBITS; | 219 | size_t start_page_d = address >> Memory::YUZU_PAGEBITS; |
| 220 | size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; | 220 | size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; |
| @@ -508,12 +508,7 @@ void DeviceMemoryManager<Traits>::UnregisterProcess(Asid asid) { | |||
| 508 | 508 | ||
| 509 | template <typename Traits> | 509 | template <typename Traits> |
| 510 | void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) { | 510 | void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) { |
| 511 | std::unique_lock<std::mutex> lk(counter_guard, std::defer_lock); | 511 | Common::ScopedRangeLock lk(counter_guard, addr, size); |
| 512 | const auto Lock = [&] { | ||
| 513 | if (!lk) { | ||
| 514 | lk.lock(); | ||
| 515 | } | ||
| 516 | }; | ||
| 517 | u64 uncache_begin = 0; | 512 | u64 uncache_begin = 0; |
| 518 | u64 cache_begin = 0; | 513 | u64 cache_begin = 0; |
| 519 | u64 uncache_bytes = 0; | 514 | u64 uncache_bytes = 0; |
| @@ -524,22 +519,36 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size | |||
| 524 | const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE); | 519 | const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE); |
| 525 | size_t page = addr >> Memory::YUZU_PAGEBITS; | 520 | size_t page = addr >> Memory::YUZU_PAGEBITS; |
| 526 | auto [asid, base_vaddress] = ExtractCPUBacking(page); | 521 | auto [asid, base_vaddress] = ExtractCPUBacking(page); |
| 527 | size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS; | ||
| 528 | auto* memory_device_inter = registered_processes[asid.id]; | 522 | auto* memory_device_inter = registered_processes[asid.id]; |
| 523 | const auto release_pending = [&] { | ||
| 524 | if (uncache_bytes > 0) { | ||
| 525 | MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, | ||
| 526 | uncache_bytes, false); | ||
| 527 | uncache_bytes = 0; | ||
| 528 | } | ||
| 529 | if (cache_bytes > 0) { | ||
| 530 | MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, | ||
| 531 | cache_bytes, true); | ||
| 532 | cache_bytes = 0; | ||
| 533 | } | ||
| 534 | }; | ||
| 529 | for (; page != page_end; ++page) { | 535 | for (; page != page_end; ++page) { |
| 530 | std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page); | 536 | CounterAtomicType& count = cached_pages->at(page >> subentries_shift).Count(page); |
| 537 | auto [asid_2, vpage] = ExtractCPUBacking(page); | ||
| 538 | vpage >>= Memory::YUZU_PAGEBITS; | ||
| 531 | 539 | ||
| 532 | if (delta > 0) { | 540 | if (vpage == 0) [[unlikely]] { |
| 533 | ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<u8>::max(), | 541 | release_pending(); |
| 534 | "Count may overflow!"); | 542 | continue; |
| 535 | } else if (delta < 0) { | 543 | } |
| 536 | ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!"); | 544 | |
| 537 | } else { | 545 | if (asid.id != asid_2.id) [[unlikely]] { |
| 538 | ASSERT_MSG(false, "Delta must be non-zero!"); | 546 | release_pending(); |
| 547 | memory_device_inter = registered_processes[asid_2.id]; | ||
| 539 | } | 548 | } |
| 540 | 549 | ||
| 541 | // Adds or subtracts 1, as count is a unsigned 8-bit value | 550 | // Adds or subtracts 1, as count is a unsigned 8-bit value |
| 542 | count.fetch_add(static_cast<u8>(delta), std::memory_order_release); | 551 | count.fetch_add(static_cast<CounterType>(delta), std::memory_order_release); |
| 543 | 552 | ||
| 544 | // Assume delta is either -1 or 1 | 553 | // Assume delta is either -1 or 1 |
| 545 | if (count.load(std::memory_order::relaxed) == 0) { | 554 | if (count.load(std::memory_order::relaxed) == 0) { |
| @@ -548,7 +557,6 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size | |||
| 548 | } | 557 | } |
| 549 | uncache_bytes += Memory::YUZU_PAGESIZE; | 558 | uncache_bytes += Memory::YUZU_PAGESIZE; |
| 550 | } else if (uncache_bytes > 0) { | 559 | } else if (uncache_bytes > 0) { |
| 551 | Lock(); | ||
| 552 | MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, | 560 | MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, |
| 553 | uncache_bytes, false); | 561 | uncache_bytes, false); |
| 554 | uncache_bytes = 0; | 562 | uncache_bytes = 0; |
| @@ -559,23 +567,12 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size | |||
| 559 | } | 567 | } |
| 560 | cache_bytes += Memory::YUZU_PAGESIZE; | 568 | cache_bytes += Memory::YUZU_PAGESIZE; |
| 561 | } else if (cache_bytes > 0) { | 569 | } else if (cache_bytes > 0) { |
| 562 | Lock(); | 570 | MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, |
| 563 | MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, | 571 | cache_bytes, true); |
| 564 | true); | ||
| 565 | cache_bytes = 0; | 572 | cache_bytes = 0; |
| 566 | } | 573 | } |
| 567 | vpage++; | ||
| 568 | } | ||
| 569 | if (uncache_bytes > 0) { | ||
| 570 | Lock(); | ||
| 571 | MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes, | ||
| 572 | false); | ||
| 573 | } | ||
| 574 | if (cache_bytes > 0) { | ||
| 575 | Lock(); | ||
| 576 | MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, | ||
| 577 | true); | ||
| 578 | } | 574 | } |
| 575 | release_pending(); | ||
| 579 | } | 576 | } |
| 580 | 577 | ||
| 581 | } // namespace Core | 578 | } // namespace Core |
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index 7075ab800..486719cc0 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp | |||
| @@ -202,7 +202,7 @@ void AOC_U::ListAddOnContent(HLERequestContext& ctx) { | |||
| 202 | LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count, | 202 | LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count, |
| 203 | process_id); | 203 | process_id); |
| 204 | 204 | ||
| 205 | const auto current = system.GetApplicationProcessProgramID(); | 205 | const auto current = FileSys::GetBaseTitleID(system.GetApplicationProcessProgramID()); |
| 206 | 206 | ||
| 207 | std::vector<u32> out; | 207 | std::vector<u32> out; |
| 208 | const auto& disabled = Settings::values.disabled_addons[current]; | 208 | const auto& disabled = Settings::values.disabled_addons[current]; |
diff --git a/src/core/hle/service/cmif_serialization.h b/src/core/hle/service/cmif_serialization.h index 9ee26400d..315475e71 100644 --- a/src/core/hle/service/cmif_serialization.h +++ b/src/core/hle/service/cmif_serialization.h | |||
| @@ -122,14 +122,14 @@ struct RequestLayout { | |||
| 122 | u32 domain_interface_count; | 122 | u32 domain_interface_count; |
| 123 | }; | 123 | }; |
| 124 | 124 | ||
| 125 | template <ArgumentType Type1, ArgumentType Type2, typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0> | 125 | template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0> |
| 126 | constexpr u32 GetArgumentRawDataSize() { | 126 | constexpr u32 GetInRawDataSize() { |
| 127 | if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) { | 127 | if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) { |
| 128 | return static_cast<u32>(DataOffset); | 128 | return static_cast<u32>(DataOffset); |
| 129 | } else { | 129 | } else { |
| 130 | using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>; | 130 | using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>; |
| 131 | 131 | ||
| 132 | if constexpr (ArgumentTraits<ArgType>::Type == Type1 || ArgumentTraits<ArgType>::Type == Type2) { | 132 | if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InData || ArgumentTraits<ArgType>::Type == ArgumentType::InProcessId) { |
| 133 | constexpr size_t ArgAlign = alignof(ArgType); | 133 | constexpr size_t ArgAlign = alignof(ArgType); |
| 134 | constexpr size_t ArgSize = sizeof(ArgType); | 134 | constexpr size_t ArgSize = sizeof(ArgType); |
| 135 | 135 | ||
| @@ -138,9 +138,33 @@ constexpr u32 GetArgumentRawDataSize() { | |||
| 138 | constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); | 138 | constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); |
| 139 | constexpr size_t ArgEnd = ArgOffset + ArgSize; | 139 | constexpr size_t ArgEnd = ArgOffset + ArgSize; |
| 140 | 140 | ||
| 141 | return GetArgumentRawDataSize<Type1, Type2, MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>(); | 141 | return GetInRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>(); |
| 142 | } else { | ||
| 143 | return GetInRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>(); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0> | ||
| 149 | constexpr u32 GetOutRawDataSize() { | ||
| 150 | if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) { | ||
| 151 | return static_cast<u32>(DataOffset); | ||
| 152 | } else { | ||
| 153 | using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>; | ||
| 154 | |||
| 155 | if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) { | ||
| 156 | using RawArgType = typename ArgType::Type; | ||
| 157 | constexpr size_t ArgAlign = alignof(RawArgType); | ||
| 158 | constexpr size_t ArgSize = sizeof(RawArgType); | ||
| 159 | |||
| 160 | static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment"); | ||
| 161 | |||
| 162 | constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); | ||
| 163 | constexpr size_t ArgEnd = ArgOffset + ArgSize; | ||
| 164 | |||
| 165 | return GetOutRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>(); | ||
| 142 | } else { | 166 | } else { |
| 143 | return GetArgumentRawDataSize<Type1, Type2, MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>(); | 167 | return GetOutRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>(); |
| 144 | } | 168 | } |
| 145 | } | 169 | } |
| 146 | } | 170 | } |
| @@ -165,7 +189,7 @@ constexpr RequestLayout GetNonDomainReplyInLayout() { | |||
| 165 | return RequestLayout{ | 189 | return RequestLayout{ |
| 166 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(), | 190 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(), |
| 167 | .move_handle_count = 0, | 191 | .move_handle_count = 0, |
| 168 | .cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(), | 192 | .cmif_raw_data_size = GetInRawDataSize<MethodArguments>(), |
| 169 | .domain_interface_count = 0, | 193 | .domain_interface_count = 0, |
| 170 | }; | 194 | }; |
| 171 | } | 195 | } |
| @@ -175,7 +199,7 @@ constexpr RequestLayout GetDomainReplyInLayout() { | |||
| 175 | return RequestLayout{ | 199 | return RequestLayout{ |
| 176 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(), | 200 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(), |
| 177 | .move_handle_count = 0, | 201 | .move_handle_count = 0, |
| 178 | .cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(), | 202 | .cmif_raw_data_size = GetInRawDataSize<MethodArguments>(), |
| 179 | .domain_interface_count = GetArgumentTypeCount<ArgumentType::InInterface, MethodArguments>(), | 203 | .domain_interface_count = GetArgumentTypeCount<ArgumentType::InInterface, MethodArguments>(), |
| 180 | }; | 204 | }; |
| 181 | } | 205 | } |
| @@ -185,7 +209,7 @@ constexpr RequestLayout GetNonDomainReplyOutLayout() { | |||
| 185 | return RequestLayout{ | 209 | return RequestLayout{ |
| 186 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(), | 210 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(), |
| 187 | .move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>() + GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(), | 211 | .move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>() + GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(), |
| 188 | .cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(), | 212 | .cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(), |
| 189 | .domain_interface_count = 0, | 213 | .domain_interface_count = 0, |
| 190 | }; | 214 | }; |
| 191 | } | 215 | } |
| @@ -195,7 +219,7 @@ constexpr RequestLayout GetDomainReplyOutLayout() { | |||
| 195 | return RequestLayout{ | 219 | return RequestLayout{ |
| 196 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(), | 220 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(), |
| 197 | .move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>(), | 221 | .move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>(), |
| 198 | .cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(), | 222 | .cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(), |
| 199 | .domain_interface_count = GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(), | 223 | .domain_interface_count = GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(), |
| 200 | }; | 224 | }; |
| 201 | } | 225 | } |
| @@ -259,7 +283,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE | |||
| 259 | 283 | ||
| 260 | return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); | 284 | return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); |
| 261 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) { | 285 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) { |
| 262 | constexpr size_t BufferSize = sizeof(ArgType); | 286 | constexpr size_t BufferSize = sizeof(typename ArgType::Type); |
| 263 | 287 | ||
| 264 | // Clear the existing data. | 288 | // Clear the existing data. |
| 265 | std::memset(&std::get<ArgIndex>(args), 0, BufferSize); | 289 | std::memset(&std::get<ArgIndex>(args), 0, BufferSize); |
| @@ -300,7 +324,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE | |||
| 300 | 324 | ||
| 301 | return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); | 325 | return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); |
| 302 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) { | 326 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) { |
| 303 | constexpr size_t BufferSize = sizeof(ArgType); | 327 | constexpr size_t BufferSize = sizeof(typename ArgType::Type); |
| 304 | 328 | ||
| 305 | // Clear the existing data. | 329 | // Clear the existing data. |
| 306 | std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize); | 330 | std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize); |
| @@ -337,13 +361,15 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ | |||
| 337 | using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>; | 361 | using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>; |
| 338 | 362 | ||
| 339 | if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) { | 363 | if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) { |
| 340 | constexpr size_t ArgAlign = alignof(ArgType); | 364 | using RawArgType = decltype(std::get<ArgIndex>(args).raw); |
| 341 | constexpr size_t ArgSize = sizeof(ArgType); | 365 | constexpr size_t ArgAlign = alignof(RawArgType); |
| 366 | constexpr size_t ArgSize = sizeof(RawArgType); | ||
| 342 | 367 | ||
| 343 | static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment"); | 368 | static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment"); |
| 344 | static_assert(!RawDataFinished, "All output interface arguments must appear after raw data"); | 369 | static_assert(!RawDataFinished, "All output interface arguments must appear after raw data"); |
| 345 | static_assert(!std::is_pointer_v<ArgType>, "Output raw data must not be a pointer"); | 370 | static_assert(!std::is_pointer_v<ArgType>, "Output raw data must not be a pointer"); |
| 346 | static_assert(std::is_trivially_copyable_v<decltype(std::get<ArgIndex>(args).raw)>, "Output raw data must be trivially copyable"); | 371 | static_assert(!std::is_pointer_v<RawArgType>, "Output raw data must not be a pointer"); |
| 372 | static_assert(std::is_trivially_copyable_v<RawArgType>, "Output raw data must be trivially copyable"); | ||
| 347 | 373 | ||
| 348 | constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); | 374 | constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); |
| 349 | constexpr size_t ArgEnd = ArgOffset + ArgSize; | 375 | constexpr size_t ArgEnd = ArgOffset + ArgSize; |
| @@ -368,7 +394,7 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ | |||
| 368 | 394 | ||
| 369 | return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); | 395 | return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); |
| 370 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) { | 396 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) { |
| 371 | constexpr size_t BufferSize = sizeof(ArgType); | 397 | constexpr size_t BufferSize = sizeof(typename ArgType::Type); |
| 372 | 398 | ||
| 373 | ASSERT(ctx.CanWriteBuffer(OutBufferIndex)); | 399 | ASSERT(ctx.CanWriteBuffer(OutBufferIndex)); |
| 374 | if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) { | 400 | if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) { |
diff --git a/src/core/hle/service/glue/time/time_zone.cpp b/src/core/hle/service/glue/time/time_zone.cpp index 5dc1187cb..98d928697 100644 --- a/src/core/hle/service/glue/time/time_zone.cpp +++ b/src/core/hle/service/glue/time/time_zone.cpp | |||
| @@ -197,32 +197,27 @@ Result TimeZoneService::ToCalendarTimeWithMyRule( | |||
| 197 | 197 | ||
| 198 | Result TimeZoneService::ToPosixTime(Out<u32> out_count, | 198 | Result TimeZoneService::ToPosixTime(Out<u32> out_count, |
| 199 | OutArray<s64, BufferAttr_HipcPointer> out_times, | 199 | OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 200 | Out<u32> out_times_count, | 200 | const Service::PSC::Time::CalendarTime& calendar_time, |
| 201 | Service::PSC::Time::CalendarTime& calendar_time, InRule rule) { | 201 | InRule rule) { |
| 202 | SCOPE_EXIT({ | 202 | SCOPE_EXIT({ |
| 203 | LOG_DEBUG(Service_Time, | 203 | LOG_DEBUG(Service_Time, |
| 204 | "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} " | 204 | "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}", |
| 205 | "out_times_count={}", | 205 | calendar_time, *out_count, out_times[0], out_times[1]); |
| 206 | calendar_time, *out_count, out_times[0], out_times[1], *out_times_count); | ||
| 207 | }); | 206 | }); |
| 208 | 207 | ||
| 209 | R_RETURN( | 208 | R_RETURN(m_wrapped_service->ToPosixTime(out_count, out_times, calendar_time, rule)); |
| 210 | m_wrapped_service->ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule)); | ||
| 211 | } | 209 | } |
| 212 | 210 | ||
| 213 | Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count, | 211 | Result TimeZoneService::ToPosixTimeWithMyRule( |
| 214 | OutArray<s64, BufferAttr_HipcPointer> out_times, | 212 | Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 215 | Out<u32> out_times_count, | 213 | const Service::PSC::Time::CalendarTime& calendar_time) { |
| 216 | Service::PSC::Time::CalendarTime& calendar_time) { | ||
| 217 | SCOPE_EXIT({ | 214 | SCOPE_EXIT({ |
| 218 | LOG_DEBUG(Service_Time, | 215 | LOG_DEBUG(Service_Time, |
| 219 | "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} " | 216 | "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}", |
| 220 | "out_times_count={}", | 217 | calendar_time, *out_count, out_times[0], out_times[1]); |
| 221 | calendar_time, *out_count, out_times[0], out_times[1], *out_times_count); | ||
| 222 | }); | 218 | }); |
| 223 | 219 | ||
| 224 | R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, out_times_count, | 220 | R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, calendar_time)); |
| 225 | calendar_time)); | ||
| 226 | } | 221 | } |
| 227 | 222 | ||
| 228 | } // namespace Service::Glue::Time | 223 | } // namespace Service::Glue::Time |
diff --git a/src/core/hle/service/glue/time/time_zone.h b/src/core/hle/service/glue/time/time_zone.h index bf12adbdc..9c1530966 100644 --- a/src/core/hle/service/glue/time/time_zone.h +++ b/src/core/hle/service/glue/time/time_zone.h | |||
| @@ -68,12 +68,10 @@ public: | |||
| 68 | Out<Service::PSC::Time::CalendarTime> out_calendar_time, | 68 | Out<Service::PSC::Time::CalendarTime> out_calendar_time, |
| 69 | Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time); | 69 | Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time); |
| 70 | Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, | 70 | Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 71 | Out<u32> out_times_count, Service::PSC::Time::CalendarTime& calendar_time, | 71 | const Service::PSC::Time::CalendarTime& calendar_time, InRule rule); |
| 72 | InRule rule); | ||
| 73 | Result ToPosixTimeWithMyRule(Out<u32> out_count, | 72 | Result ToPosixTimeWithMyRule(Out<u32> out_count, |
| 74 | OutArray<s64, BufferAttr_HipcPointer> out_times, | 73 | OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 75 | Out<u32> out_times_count, | 74 | const Service::PSC::Time::CalendarTime& calendar_time); |
| 76 | Service::PSC::Time::CalendarTime& calendar_time); | ||
| 77 | 75 | ||
| 78 | private: | 76 | private: |
| 79 | Core::System& m_system; | 77 | Core::System& m_system; |
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index 09c47b5e3..938b93451 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "core/hle/kernel/k_shared_memory.h" | 8 | #include "core/hle/kernel/k_shared_memory.h" |
| 9 | #include "core/hle/kernel/k_transfer_memory.h" | 9 | #include "core/hle/kernel/k_transfer_memory.h" |
| 10 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/service/cmif_serialization.h" | ||
| 11 | #include "core/hle/service/hid/hid_server.h" | 12 | #include "core/hle/service/hid/hid_server.h" |
| 12 | #include "core/hle/service/ipc_helpers.h" | 13 | #include "core/hle/service/ipc_helpers.h" |
| 13 | #include "core/memory.h" | 14 | #include "core/memory.h" |
| @@ -153,7 +154,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r | |||
| 153 | {104, &IHidServer::DeactivateNpad, "DeactivateNpad"}, | 154 | {104, &IHidServer::DeactivateNpad, "DeactivateNpad"}, |
| 154 | {106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"}, | 155 | {106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"}, |
| 155 | {107, &IHidServer::DisconnectNpad, "DisconnectNpad"}, | 156 | {107, &IHidServer::DisconnectNpad, "DisconnectNpad"}, |
| 156 | {108, &IHidServer::GetPlayerLedPattern, "GetPlayerLedPattern"}, | 157 | {108, C<&IHidServer::GetPlayerLedPattern>, "GetPlayerLedPattern"}, |
| 157 | {109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"}, | 158 | {109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"}, |
| 158 | {120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"}, | 159 | {120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"}, |
| 159 | {121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, | 160 | {121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, |
| @@ -1136,19 +1137,39 @@ void IHidServer::DisconnectNpad(HLERequestContext& ctx) { | |||
| 1136 | rb.Push(ResultSuccess); | 1137 | rb.Push(ResultSuccess); |
| 1137 | } | 1138 | } |
| 1138 | 1139 | ||
| 1139 | void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) { | 1140 | Result IHidServer::GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern, |
| 1140 | IPC::RequestParser rp{ctx}; | 1141 | Core::HID::NpadIdType npad_id) { |
| 1141 | const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()}; | ||
| 1142 | |||
| 1143 | Core::HID::LedPattern pattern{0, 0, 0, 0}; | ||
| 1144 | auto controller = GetResourceManager()->GetNpad(); | ||
| 1145 | const auto result = controller->GetLedPattern(npad_id, pattern); | ||
| 1146 | |||
| 1147 | LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); | 1142 | LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); |
| 1148 | 1143 | ||
| 1149 | IPC::ResponseBuilder rb{ctx, 4}; | 1144 | switch (npad_id) { |
| 1150 | rb.Push(result); | 1145 | case Core::HID::NpadIdType::Player1: |
| 1151 | rb.Push(pattern.raw); | 1146 | *out_led_pattern = Core::HID::LedPattern{1, 0, 0, 0}; |
| 1147 | R_SUCCEED(); | ||
| 1148 | case Core::HID::NpadIdType::Player2: | ||
| 1149 | *out_led_pattern = Core::HID::LedPattern{1, 1, 0, 0}; | ||
| 1150 | R_SUCCEED(); | ||
| 1151 | case Core::HID::NpadIdType::Player3: | ||
| 1152 | *out_led_pattern = Core::HID::LedPattern{1, 1, 1, 0}; | ||
| 1153 | R_SUCCEED(); | ||
| 1154 | case Core::HID::NpadIdType::Player4: | ||
| 1155 | *out_led_pattern = Core::HID::LedPattern{1, 1, 1, 1}; | ||
| 1156 | R_SUCCEED(); | ||
| 1157 | case Core::HID::NpadIdType::Player5: | ||
| 1158 | *out_led_pattern = Core::HID::LedPattern{1, 0, 0, 1}; | ||
| 1159 | R_SUCCEED(); | ||
| 1160 | case Core::HID::NpadIdType::Player6: | ||
| 1161 | *out_led_pattern = Core::HID::LedPattern{1, 0, 1, 0}; | ||
| 1162 | R_SUCCEED(); | ||
| 1163 | case Core::HID::NpadIdType::Player7: | ||
| 1164 | *out_led_pattern = Core::HID::LedPattern{1, 0, 1, 1}; | ||
| 1165 | R_SUCCEED(); | ||
| 1166 | case Core::HID::NpadIdType::Player8: | ||
| 1167 | *out_led_pattern = Core::HID::LedPattern{0, 1, 1, 0}; | ||
| 1168 | R_SUCCEED(); | ||
| 1169 | default: | ||
| 1170 | *out_led_pattern = Core::HID::LedPattern{0, 0, 0, 0}; | ||
| 1171 | R_SUCCEED(); | ||
| 1172 | } | ||
| 1152 | } | 1173 | } |
| 1153 | 1174 | ||
| 1154 | void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { | 1175 | void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/hid/hid_server.h b/src/core/hle/service/hid/hid_server.h index 3a2e0a230..faf775689 100644 --- a/src/core/hle/service/hid/hid_server.h +++ b/src/core/hle/service/hid/hid_server.h | |||
| @@ -3,7 +3,9 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hle/service/cmif_types.h" | ||
| 6 | #include "core/hle/service/service.h" | 7 | #include "core/hle/service/service.h" |
| 8 | #include "hid_core/hid_types.h" | ||
| 7 | 9 | ||
| 8 | namespace Core { | 10 | namespace Core { |
| 9 | class System; | 11 | class System; |
| @@ -66,7 +68,8 @@ private: | |||
| 66 | void DeactivateNpad(HLERequestContext& ctx); | 68 | void DeactivateNpad(HLERequestContext& ctx); |
| 67 | void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx); | 69 | void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx); |
| 68 | void DisconnectNpad(HLERequestContext& ctx); | 70 | void DisconnectNpad(HLERequestContext& ctx); |
| 69 | void GetPlayerLedPattern(HLERequestContext& ctx); | 71 | Result GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern, |
| 72 | Core::HID::NpadIdType npad_id); | ||
| 70 | void ActivateNpadWithRevision(HLERequestContext& ctx); | 73 | void ActivateNpadWithRevision(HLERequestContext& ctx); |
| 71 | void SetNpadJoyHoldType(HLERequestContext& ctx); | 74 | void SetNpadJoyHoldType(HLERequestContext& ctx); |
| 72 | void GetNpadJoyHoldType(HLERequestContext& ctx); | 75 | void GetNpadJoyHoldType(HLERequestContext& ctx); |
diff --git a/src/core/hle/service/nvdrv/core/container.cpp b/src/core/hle/service/nvdrv/core/container.cpp index dc1b4d5be..e89cca6f2 100644 --- a/src/core/hle/service/nvdrv/core/container.cpp +++ b/src/core/hle/service/nvdrv/core/container.cpp | |||
| @@ -83,7 +83,9 @@ SessionId Container::OpenSession(Kernel::KProcess* process) { | |||
| 83 | 83 | ||
| 84 | // Check if this memory block is heap. | 84 | // Check if this memory block is heap. |
| 85 | if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) { | 85 | if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) { |
| 86 | if (svc_mem_info.size > region_size) { | 86 | if (region_start + region_size == svc_mem_info.base_address) { |
| 87 | region_size += svc_mem_info.size; | ||
| 88 | } else if (svc_mem_info.size > region_size) { | ||
| 87 | region_size = svc_mem_info.size; | 89 | region_size = svc_mem_info.size; |
| 88 | region_start = svc_mem_info.base_address; | 90 | region_start = svc_mem_info.base_address; |
| 89 | } | 91 | } |
diff --git a/src/core/hle/service/psc/time/common.h b/src/core/hle/service/psc/time/common.h index 596828b8b..3e13144a0 100644 --- a/src/core/hle/service/psc/time/common.h +++ b/src/core/hle/service/psc/time/common.h | |||
| @@ -189,7 +189,7 @@ struct fmt::formatter<Service::PSC::Time::SteadyClockTimePoint> : fmt::formatter | |||
| 189 | template <typename FormatContext> | 189 | template <typename FormatContext> |
| 190 | auto format(const Service::PSC::Time::SteadyClockTimePoint& time_point, | 190 | auto format(const Service::PSC::Time::SteadyClockTimePoint& time_point, |
| 191 | FormatContext& ctx) const { | 191 | FormatContext& ctx) const { |
| 192 | return fmt::format_to(ctx.out(), "time_point={}", time_point.time_point); | 192 | return fmt::format_to(ctx.out(), "[time_point={}]", time_point.time_point); |
| 193 | } | 193 | } |
| 194 | }; | 194 | }; |
| 195 | 195 | ||
| @@ -197,7 +197,7 @@ template <> | |||
| 197 | struct fmt::formatter<Service::PSC::Time::SystemClockContext> : fmt::formatter<fmt::string_view> { | 197 | struct fmt::formatter<Service::PSC::Time::SystemClockContext> : fmt::formatter<fmt::string_view> { |
| 198 | template <typename FormatContext> | 198 | template <typename FormatContext> |
| 199 | auto format(const Service::PSC::Time::SystemClockContext& context, FormatContext& ctx) const { | 199 | auto format(const Service::PSC::Time::SystemClockContext& context, FormatContext& ctx) const { |
| 200 | return fmt::format_to(ctx.out(), "offset={} steady_time_point={}", context.offset, | 200 | return fmt::format_to(ctx.out(), "[offset={} steady_time_point={}]", context.offset, |
| 201 | context.steady_time_point.time_point); | 201 | context.steady_time_point.time_point); |
| 202 | } | 202 | } |
| 203 | }; | 203 | }; |
| @@ -206,8 +206,9 @@ template <> | |||
| 206 | struct fmt::formatter<Service::PSC::Time::CalendarTime> : fmt::formatter<fmt::string_view> { | 206 | struct fmt::formatter<Service::PSC::Time::CalendarTime> : fmt::formatter<fmt::string_view> { |
| 207 | template <typename FormatContext> | 207 | template <typename FormatContext> |
| 208 | auto format(const Service::PSC::Time::CalendarTime& calendar, FormatContext& ctx) const { | 208 | auto format(const Service::PSC::Time::CalendarTime& calendar, FormatContext& ctx) const { |
| 209 | return fmt::format_to(ctx.out(), "{}/{}/{} {}:{}:{}", calendar.day, calendar.month, | 209 | return fmt::format_to(ctx.out(), "[{:02}/{:02}/{:04} {:02}:{:02}:{:02}]", calendar.day, |
| 210 | calendar.year, calendar.hour, calendar.minute, calendar.second); | 210 | calendar.month, calendar.year, calendar.hour, calendar.minute, |
| 211 | calendar.second); | ||
| 211 | } | 212 | } |
| 212 | }; | 213 | }; |
| 213 | 214 | ||
| @@ -217,7 +218,7 @@ struct fmt::formatter<Service::PSC::Time::CalendarAdditionalInfo> | |||
| 217 | template <typename FormatContext> | 218 | template <typename FormatContext> |
| 218 | auto format(const Service::PSC::Time::CalendarAdditionalInfo& additional, | 219 | auto format(const Service::PSC::Time::CalendarAdditionalInfo& additional, |
| 219 | FormatContext& ctx) const { | 220 | FormatContext& ctx) const { |
| 220 | return fmt::format_to(ctx.out(), "weekday={} yearday={} name={} is_dst={} ut_offset={}", | 221 | return fmt::format_to(ctx.out(), "[weekday={} yearday={} name={} is_dst={} ut_offset={}]", |
| 221 | additional.day_of_week, additional.day_of_year, | 222 | additional.day_of_week, additional.day_of_year, |
| 222 | additional.name.data(), additional.is_dst, additional.ut_offset); | 223 | additional.name.data(), additional.is_dst, additional.ut_offset); |
| 223 | } | 224 | } |
| @@ -227,8 +228,7 @@ template <> | |||
| 227 | struct fmt::formatter<Service::PSC::Time::LocationName> : fmt::formatter<fmt::string_view> { | 228 | struct fmt::formatter<Service::PSC::Time::LocationName> : fmt::formatter<fmt::string_view> { |
| 228 | template <typename FormatContext> | 229 | template <typename FormatContext> |
| 229 | auto format(const Service::PSC::Time::LocationName& name, FormatContext& ctx) const { | 230 | auto format(const Service::PSC::Time::LocationName& name, FormatContext& ctx) const { |
| 230 | std::string_view n{name.data(), name.size()}; | 231 | return formatter<string_view>::format(name.data(), ctx); |
| 231 | return formatter<string_view>::format(n, ctx); | ||
| 232 | } | 232 | } |
| 233 | }; | 233 | }; |
| 234 | 234 | ||
| @@ -236,8 +236,7 @@ template <> | |||
| 236 | struct fmt::formatter<Service::PSC::Time::RuleVersion> : fmt::formatter<fmt::string_view> { | 236 | struct fmt::formatter<Service::PSC::Time::RuleVersion> : fmt::formatter<fmt::string_view> { |
| 237 | template <typename FormatContext> | 237 | template <typename FormatContext> |
| 238 | auto format(const Service::PSC::Time::RuleVersion& version, FormatContext& ctx) const { | 238 | auto format(const Service::PSC::Time::RuleVersion& version, FormatContext& ctx) const { |
| 239 | std::string_view v{version.data(), version.size()}; | 239 | return formatter<string_view>::format(version.data(), ctx); |
| 240 | return formatter<string_view>::format(v, ctx); | ||
| 241 | } | 240 | } |
| 242 | }; | 241 | }; |
| 243 | 242 | ||
| @@ -247,10 +246,11 @@ struct fmt::formatter<Service::PSC::Time::ClockSnapshot> : fmt::formatter<fmt::s | |||
| 247 | auto format(const Service::PSC::Time::ClockSnapshot& snapshot, FormatContext& ctx) const { | 246 | auto format(const Service::PSC::Time::ClockSnapshot& snapshot, FormatContext& ctx) const { |
| 248 | return fmt::format_to( | 247 | return fmt::format_to( |
| 249 | ctx.out(), | 248 | ctx.out(), |
| 250 | "user_context={} network_context={} user_time={} network_time={} user_calendar_time={} " | 249 | "[user_context={} network_context={} user_time={} network_time={} " |
| 250 | "user_calendar_time={} " | ||
| 251 | "network_calendar_time={} user_calendar_additional_time={} " | 251 | "network_calendar_time={} user_calendar_additional_time={} " |
| 252 | "network_calendar_additional_time={} steady_clock_time_point={} location={} " | 252 | "network_calendar_additional_time={} steady_clock_time_point={} location={} " |
| 253 | "is_automatic_correction_enabled={} type={}", | 253 | "is_automatic_correction_enabled={} type={}]", |
| 254 | snapshot.user_context, snapshot.network_context, snapshot.user_time, | 254 | snapshot.user_context, snapshot.network_context, snapshot.user_time, |
| 255 | snapshot.network_time, snapshot.user_calendar_time, snapshot.network_calendar_time, | 255 | snapshot.network_time, snapshot.user_calendar_time, snapshot.network_calendar_time, |
| 256 | snapshot.user_calendar_additional_time, snapshot.network_calendar_additional_time, | 256 | snapshot.user_calendar_additional_time, snapshot.network_calendar_additional_time, |
| @@ -266,7 +266,7 @@ struct fmt::formatter<Service::PSC::Time::ContinuousAdjustmentTimePoint> | |||
| 266 | auto format(const Service::PSC::Time::ContinuousAdjustmentTimePoint& time_point, | 266 | auto format(const Service::PSC::Time::ContinuousAdjustmentTimePoint& time_point, |
| 267 | FormatContext& ctx) const { | 267 | FormatContext& ctx) const { |
| 268 | return fmt::format_to(ctx.out(), | 268 | return fmt::format_to(ctx.out(), |
| 269 | "rtc_offset={} diff_scale={} shift_amount={} lower={} upper={}", | 269 | "[rtc_offset={} diff_scale={} shift_amount={} lower={} upper={}]", |
| 270 | time_point.rtc_offset, time_point.diff_scale, time_point.shift_amount, | 270 | time_point.rtc_offset, time_point.diff_scale, time_point.shift_amount, |
| 271 | time_point.lower, time_point.upper); | 271 | time_point.lower, time_point.upper); |
| 272 | } | 272 | } |
diff --git a/src/core/hle/service/psc/time/service_manager.cpp b/src/core/hle/service/psc/time/service_manager.cpp index ec906b723..4e1643fcb 100644 --- a/src/core/hle/service/psc/time/service_manager.cpp +++ b/src/core/hle/service/psc/time/service_manager.cpp | |||
| @@ -120,11 +120,8 @@ Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& c | |||
| 120 | context, context.steady_time_point.clock_source_id.RawString(), accuracy); | 120 | context, context.steady_time_point.clock_source_id.RawString(), accuracy); |
| 121 | 121 | ||
| 122 | // TODO this is a hack! The network clock should be updated independently, from the ntc service | 122 | // TODO this is a hack! The network clock should be updated independently, from the ntc service |
| 123 | // and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot | 123 | // and maybe elsewhere. We do not do that, so fix the clock to the local clock. |
| 124 | // to avoid it being stuck at 0. | 124 | m_local_system_clock.GetContext(context); |
| 125 | if (context == Service::PSC::Time::SystemClockContext{}) { | ||
| 126 | m_local_system_clock.GetContext(context); | ||
| 127 | } | ||
| 128 | 125 | ||
| 129 | m_network_system_clock.SetContextWriter(m_network_system_context_writer); | 126 | m_network_system_clock.SetContextWriter(m_network_system_context_writer); |
| 130 | m_network_system_clock.Initialize(context, accuracy); | 127 | m_network_system_clock.Initialize(context, accuracy); |
| @@ -138,13 +135,6 @@ Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correctio | |||
| 138 | LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}", | 135 | LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}", |
| 139 | automatic_correction, time_point, time_point.clock_source_id.RawString()); | 136 | automatic_correction, time_point, time_point.clock_source_id.RawString()); |
| 140 | 137 | ||
| 141 | // TODO this is a hack! The user clock should be updated independently, from the ntc service | ||
| 142 | // and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot | ||
| 143 | // to avoid it being stuck at 0. | ||
| 144 | if (time_point == Service::PSC::Time::SteadyClockTimePoint{}) { | ||
| 145 | m_local_system_clock.GetCurrentTimePoint(time_point); | ||
| 146 | } | ||
| 147 | |||
| 148 | m_user_system_clock.SetAutomaticCorrection(automatic_correction); | 138 | m_user_system_clock.SetAutomaticCorrection(automatic_correction); |
| 149 | m_user_system_clock.SetTimePointAndSignal(time_point); | 139 | m_user_system_clock.SetTimePointAndSignal(time_point); |
| 150 | m_user_system_clock.SetInitialized(); | 140 | m_user_system_clock.SetInitialized(); |
diff --git a/src/core/hle/service/psc/time/time_zone.cpp b/src/core/hle/service/psc/time/time_zone.cpp index 82ddba42f..cc855c763 100644 --- a/src/core/hle/service/psc/time/time_zone.cpp +++ b/src/core/hle/service/psc/time/time_zone.cpp | |||
| @@ -140,11 +140,11 @@ Result TimeZone::ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary) | |||
| 140 | R_RETURN(ParseBinaryImpl(out_rule, binary)); | 140 | R_RETURN(ParseBinaryImpl(out_rule, binary)); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count, | 143 | Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count, |
| 144 | CalendarTime& calendar, const Tz::Rule& rule) { | 144 | const CalendarTime& calendar, const Tz::Rule& rule) { |
| 145 | std::scoped_lock l{m_mutex}; | 145 | std::scoped_lock l{m_mutex}; |
| 146 | 146 | ||
| 147 | auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, rule, -1); | 147 | auto res = ToPosixTimeImpl(out_count, out_times, out_times_max_count, calendar, rule, -1); |
| 148 | 148 | ||
| 149 | if (res != ResultSuccess) { | 149 | if (res != ResultSuccess) { |
| 150 | if (res == ResultTimeZoneNotFound) { | 150 | if (res == ResultTimeZoneNotFound) { |
| @@ -158,10 +158,10 @@ Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_t | |||
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, | 160 | Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, |
| 161 | u32 out_times_count, CalendarTime& calendar) { | 161 | size_t out_times_max_count, const CalendarTime& calendar) { |
| 162 | std::scoped_lock l{m_mutex}; | 162 | std::scoped_lock l{m_mutex}; |
| 163 | 163 | ||
| 164 | auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, m_my_rule, -1); | 164 | auto res = ToPosixTimeImpl(out_count, out_times, out_times_max_count, calendar, m_my_rule, -1); |
| 165 | 165 | ||
| 166 | if (res != ResultSuccess) { | 166 | if (res != ResultSuccess) { |
| 167 | if (res == ResultTimeZoneNotFound) { | 167 | if (res == ResultTimeZoneNotFound) { |
| @@ -212,20 +212,23 @@ Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time, | |||
| 212 | R_SUCCEED(); | 212 | R_SUCCEED(); |
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count, | 215 | Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, |
| 216 | CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst) { | 216 | size_t out_times_max_count, const CalendarTime& calendar, |
| 217 | const Tz::Rule& rule, s32 is_dst) { | ||
| 217 | R_TRY(ValidateRule(rule)); | 218 | R_TRY(ValidateRule(rule)); |
| 218 | 219 | ||
| 219 | calendar.month -= 1; | 220 | CalendarTime local_calendar{calendar}; |
| 220 | calendar.year -= 1900; | 221 | |
| 222 | local_calendar.month -= 1; | ||
| 223 | local_calendar.year -= 1900; | ||
| 221 | 224 | ||
| 222 | Tz::CalendarTimeInternal internal{ | 225 | Tz::CalendarTimeInternal internal{ |
| 223 | .tm_sec = calendar.second, | 226 | .tm_sec = local_calendar.second, |
| 224 | .tm_min = calendar.minute, | 227 | .tm_min = local_calendar.minute, |
| 225 | .tm_hour = calendar.hour, | 228 | .tm_hour = local_calendar.hour, |
| 226 | .tm_mday = calendar.day, | 229 | .tm_mday = local_calendar.day, |
| 227 | .tm_mon = calendar.month, | 230 | .tm_mon = local_calendar.month, |
| 228 | .tm_year = calendar.year, | 231 | .tm_year = local_calendar.year, |
| 229 | .tm_wday = 0, | 232 | .tm_wday = 0, |
| 230 | .tm_yday = 0, | 233 | .tm_yday = 0, |
| 231 | .tm_isdst = is_dst, | 234 | .tm_isdst = is_dst, |
| @@ -243,9 +246,9 @@ Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 o | |||
| 243 | R_RETURN(ResultTimeZoneNotFound); | 246 | R_RETURN(ResultTimeZoneNotFound); |
| 244 | } | 247 | } |
| 245 | 248 | ||
| 246 | if (internal.tm_sec != calendar.second || internal.tm_min != calendar.minute || | 249 | if (internal.tm_sec != local_calendar.second || internal.tm_min != local_calendar.minute || |
| 247 | internal.tm_hour != calendar.hour || internal.tm_mday != calendar.day || | 250 | internal.tm_hour != local_calendar.hour || internal.tm_mday != local_calendar.day || |
| 248 | internal.tm_mon != calendar.month || internal.tm_year != calendar.year) { | 251 | internal.tm_mon != local_calendar.month || internal.tm_year != local_calendar.year) { |
| 249 | R_RETURN(ResultTimeZoneNotFound); | 252 | R_RETURN(ResultTimeZoneNotFound); |
| 250 | } | 253 | } |
| 251 | 254 | ||
| @@ -254,7 +257,7 @@ Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 o | |||
| 254 | } | 257 | } |
| 255 | 258 | ||
| 256 | out_times[0] = time; | 259 | out_times[0] = time; |
| 257 | if (out_times_count < 2) { | 260 | if (out_times_max_count < 2) { |
| 258 | out_count = 1; | 261 | out_count = 1; |
| 259 | R_SUCCEED(); | 262 | R_SUCCEED(); |
| 260 | } | 263 | } |
diff --git a/src/core/hle/service/psc/time/time_zone.h b/src/core/hle/service/psc/time/time_zone.h index 6bd8f2fda..6248e45f9 100644 --- a/src/core/hle/service/psc/time/time_zone.h +++ b/src/core/hle/service/psc/time/time_zone.h | |||
| @@ -38,18 +38,18 @@ public: | |||
| 38 | CalendarAdditionalInfo& calendar_additional, s64 time); | 38 | CalendarAdditionalInfo& calendar_additional, s64 time); |
| 39 | Result ParseBinary(LocationName& name, std::span<const u8> binary); | 39 | Result ParseBinary(LocationName& name, std::span<const u8> binary); |
| 40 | Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary); | 40 | Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary); |
| 41 | Result ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count, | 41 | Result ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count, |
| 42 | CalendarTime& calendar, const Tz::Rule& rule); | 42 | const CalendarTime& calendar, const Tz::Rule& rule); |
| 43 | Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, u32 out_times_count, | 43 | Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, |
| 44 | CalendarTime& calendar); | 44 | size_t out_times_max_count, const CalendarTime& calendar); |
| 45 | 45 | ||
| 46 | private: | 46 | private: |
| 47 | Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary); | 47 | Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary); |
| 48 | Result ToCalendarTimeImpl(CalendarTime& out_calendar_time, | 48 | Result ToCalendarTimeImpl(CalendarTime& out_calendar_time, |
| 49 | CalendarAdditionalInfo& out_additional_info, s64 time, | 49 | CalendarAdditionalInfo& out_additional_info, s64 time, |
| 50 | const Tz::Rule& rule); | 50 | const Tz::Rule& rule); |
| 51 | Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count, | 51 | Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, size_t out_times_max_count, |
| 52 | CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst); | 52 | const CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst); |
| 53 | 53 | ||
| 54 | bool m_initialized{}; | 54 | bool m_initialized{}; |
| 55 | std::recursive_mutex m_mutex; | 55 | std::recursive_mutex m_mutex; |
diff --git a/src/core/hle/service/psc/time/time_zone_service.cpp b/src/core/hle/service/psc/time/time_zone_service.cpp index 9376a0324..eb81f5b03 100644 --- a/src/core/hle/service/psc/time/time_zone_service.cpp +++ b/src/core/hle/service/psc/time/time_zone_service.cpp | |||
| @@ -138,32 +138,28 @@ Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_ | |||
| 138 | 138 | ||
| 139 | Result TimeZoneService::ToPosixTime(Out<u32> out_count, | 139 | Result TimeZoneService::ToPosixTime(Out<u32> out_count, |
| 140 | OutArray<s64, BufferAttr_HipcPointer> out_times, | 140 | OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 141 | Out<u32> out_times_count, CalendarTime& calendar_time, | 141 | const CalendarTime& calendar_time, InRule rule) { |
| 142 | InRule rule) { | ||
| 143 | SCOPE_EXIT({ | 142 | SCOPE_EXIT({ |
| 144 | LOG_DEBUG(Service_Time, | 143 | LOG_DEBUG(Service_Time, |
| 145 | "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} " | 144 | "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ", |
| 146 | "out_times_count={}", | 145 | calendar_time, *out_count, out_times[0], out_times[1]); |
| 147 | calendar_time, *out_count, out_times[0], out_times[1], *out_times_count); | ||
| 148 | }); | 146 | }); |
| 149 | 147 | ||
| 150 | R_RETURN( | 148 | R_RETURN( |
| 151 | m_time_zone.ToPosixTime(*out_count, out_times, *out_times_count, calendar_time, *rule)); | 149 | m_time_zone.ToPosixTime(*out_count, out_times, out_times.size(), calendar_time, *rule)); |
| 152 | } | 150 | } |
| 153 | 151 | ||
| 154 | Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count, | 152 | Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count, |
| 155 | OutArray<s64, BufferAttr_HipcPointer> out_times, | 153 | OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 156 | Out<u32> out_times_count, | 154 | const CalendarTime& calendar_time) { |
| 157 | CalendarTime& calendar_time) { | ||
| 158 | SCOPE_EXIT({ | 155 | SCOPE_EXIT({ |
| 159 | LOG_DEBUG(Service_Time, | 156 | LOG_DEBUG(Service_Time, |
| 160 | "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} " | 157 | "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ", |
| 161 | "out_times_count={}", | 158 | calendar_time, *out_count, out_times[0], out_times[1]); |
| 162 | calendar_time, *out_count, out_times[0], out_times[1], *out_times_count); | ||
| 163 | }); | 159 | }); |
| 164 | 160 | ||
| 165 | R_RETURN( | 161 | R_RETURN( |
| 166 | m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, *out_times_count, calendar_time)); | 162 | m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, out_times.size(), calendar_time)); |
| 167 | } | 163 | } |
| 168 | 164 | ||
| 169 | } // namespace Service::PSC::Time | 165 | } // namespace Service::PSC::Time |
diff --git a/src/core/hle/service/psc/time/time_zone_service.h b/src/core/hle/service/psc/time/time_zone_service.h index 084e3f907..6eb9ddc4b 100644 --- a/src/core/hle/service/psc/time/time_zone_service.h +++ b/src/core/hle/service/psc/time/time_zone_service.h | |||
| @@ -50,10 +50,10 @@ public: | |||
| 50 | Result ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time, | 50 | Result ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time, |
| 51 | Out<CalendarAdditionalInfo> out_additional_info, s64 time); | 51 | Out<CalendarAdditionalInfo> out_additional_info, s64 time); |
| 52 | Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, | 52 | Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 53 | Out<u32> out_times_count, CalendarTime& calendar_time, InRule rule); | 53 | const CalendarTime& calendar_time, InRule rule); |
| 54 | Result ToPosixTimeWithMyRule(Out<u32> out_count, | 54 | Result ToPosixTimeWithMyRule(Out<u32> out_count, |
| 55 | OutArray<s64, BufferAttr_HipcPointer> out_times, | 55 | OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 56 | Out<u32> out_times_count, CalendarTime& calendar_time); | 56 | const CalendarTime& calendar_time); |
| 57 | 57 | ||
| 58 | private: | 58 | private: |
| 59 | Core::System& m_system; | 59 | Core::System& m_system; |
diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index 100cb2db4..d3d0fb112 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | namespace Service::Set { | 25 | namespace Service::Set { |
| 26 | 26 | ||
| 27 | namespace { | 27 | namespace { |
| 28 | constexpr u32 SETTINGS_VERSION{2u}; | 28 | constexpr u32 SETTINGS_VERSION{3u}; |
| 29 | constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't'); | 29 | constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't'); |
| 30 | struct SettingsHeader { | 30 | struct SettingsHeader { |
| 31 | u64 magic; | 31 | u64 magic; |
diff --git a/src/core/hle/service/sockets/sockets.h b/src/core/hle/service/sockets/sockets.h index f86af01a4..f3ea31bde 100644 --- a/src/core/hle/service/sockets/sockets.h +++ b/src/core/hle/service/sockets/sockets.h | |||
| @@ -24,6 +24,7 @@ enum class Errno : u32 { | |||
| 24 | CONNRESET = 104, | 24 | CONNRESET = 104, |
| 25 | NOTCONN = 107, | 25 | NOTCONN = 107, |
| 26 | TIMEDOUT = 110, | 26 | TIMEDOUT = 110, |
| 27 | CONNREFUSED = 111, | ||
| 27 | INPROGRESS = 115, | 28 | INPROGRESS = 115, |
| 28 | }; | 29 | }; |
| 29 | 30 | ||
diff --git a/src/core/hle/service/sockets/sockets_translate.cpp b/src/core/hle/service/sockets/sockets_translate.cpp index aed05250c..21bb3e776 100644 --- a/src/core/hle/service/sockets/sockets_translate.cpp +++ b/src/core/hle/service/sockets/sockets_translate.cpp | |||
| @@ -25,6 +25,8 @@ Errno Translate(Network::Errno value) { | |||
| 25 | return Errno::MFILE; | 25 | return Errno::MFILE; |
| 26 | case Network::Errno::PIPE: | 26 | case Network::Errno::PIPE: |
| 27 | return Errno::PIPE; | 27 | return Errno::PIPE; |
| 28 | case Network::Errno::CONNREFUSED: | ||
| 29 | return Errno::CONNREFUSED; | ||
| 28 | case Network::Errno::NOTCONN: | 30 | case Network::Errno::NOTCONN: |
| 29 | return Errno::NOTCONN; | 31 | return Errno::NOTCONN; |
| 30 | case Network::Errno::TIMEDOUT: | 32 | case Network::Errno::TIMEDOUT: |
diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index a983f23ea..7785c1d16 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp | |||
| @@ -693,20 +693,23 @@ std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() { | |||
| 693 | sockaddr_in addr; | 693 | sockaddr_in addr; |
| 694 | socklen_t addrlen = sizeof(addr); | 694 | socklen_t addrlen = sizeof(addr); |
| 695 | 695 | ||
| 696 | std::vector<WSAPOLLFD> host_pollfds{ | 696 | const bool wait_for_accept = !is_non_blocking; |
| 697 | WSAPOLLFD{fd, POLLIN, 0}, | 697 | if (wait_for_accept) { |
| 698 | WSAPOLLFD{GetInterruptSocket(), POLLIN, 0}, | 698 | std::vector<WSAPOLLFD> host_pollfds{ |
| 699 | }; | 699 | WSAPOLLFD{fd, POLLIN, 0}, |
| 700 | 700 | WSAPOLLFD{GetInterruptSocket(), POLLIN, 0}, | |
| 701 | while (true) { | 701 | }; |
| 702 | const int pollres = | 702 | |
| 703 | WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1); | 703 | while (true) { |
| 704 | if (host_pollfds[1].revents != 0) { | 704 | const int pollres = |
| 705 | // Interrupt signaled before a client could be accepted, break | 705 | WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1); |
| 706 | return {AcceptResult{}, Errno::AGAIN}; | 706 | if (host_pollfds[1].revents != 0) { |
| 707 | } | 707 | // Interrupt signaled before a client could be accepted, break |
| 708 | if (pollres > 0) { | 708 | return {AcceptResult{}, Errno::AGAIN}; |
| 709 | break; | 709 | } |
| 710 | if (pollres > 0) { | ||
| 711 | break; | ||
| 712 | } | ||
| 710 | } | 713 | } |
| 711 | } | 714 | } |
| 712 | 715 | ||
| @@ -913,6 +916,7 @@ Errno Socket::SetRcvTimeo(u32 value) { | |||
| 913 | 916 | ||
| 914 | Errno Socket::SetNonBlock(bool enable) { | 917 | Errno Socket::SetNonBlock(bool enable) { |
| 915 | if (EnableNonBlock(fd, enable)) { | 918 | if (EnableNonBlock(fd, enable)) { |
| 919 | is_non_blocking = enable; | ||
| 916 | return Errno::SUCCESS; | 920 | return Errno::SUCCESS; |
| 917 | } | 921 | } |
| 918 | return GetAndLogLastError(); | 922 | return GetAndLogLastError(); |
diff --git a/src/core/internal_network/sockets.h b/src/core/internal_network/sockets.h index 4ba51f62c..3a32dff75 100644 --- a/src/core/internal_network/sockets.h +++ b/src/core/internal_network/sockets.h | |||
| @@ -166,6 +166,9 @@ public: | |||
| 166 | bool IsOpened() const override; | 166 | bool IsOpened() const override; |
| 167 | 167 | ||
| 168 | void HandleProxyPacket(const ProxyPacket& packet) override; | 168 | void HandleProxyPacket(const ProxyPacket& packet) override; |
| 169 | |||
| 170 | private: | ||
| 171 | bool is_non_blocking = false; | ||
| 169 | }; | 172 | }; |
| 170 | 173 | ||
| 171 | std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout); | 174 | std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout); |
diff --git a/src/hid_core/hid_types.h b/src/hid_core/hid_types.h index b310ab72d..ffb5f1926 100644 --- a/src/hid_core/hid_types.h +++ b/src/hid_core/hid_types.h | |||
| @@ -422,7 +422,10 @@ struct NpadPowerInfo { | |||
| 422 | static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); | 422 | static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); |
| 423 | 423 | ||
| 424 | struct LedPattern { | 424 | struct LedPattern { |
| 425 | explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { | 425 | LedPattern() { |
| 426 | raw = 0; | ||
| 427 | } | ||
| 428 | LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { | ||
| 426 | position1.Assign(light1); | 429 | position1.Assign(light1); |
| 427 | position2.Assign(light2); | 430 | position2.Assign(light2); |
| 428 | position3.Assign(light3); | 431 | position3.Assign(light3); |
diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index cde84b1bb..2823be348 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp | |||
| @@ -956,17 +956,6 @@ Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, | |||
| 956 | return ResultSuccess; | 956 | return ResultSuccess; |
| 957 | } | 957 | } |
| 958 | 958 | ||
| 959 | Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const { | ||
| 960 | if (!IsNpadIdValid(npad_id)) { | ||
| 961 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 962 | return ResultInvalidNpadId; | ||
| 963 | } | ||
| 964 | const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); | ||
| 965 | const auto& controller = GetControllerFromNpadIdType(aruid, npad_id).device; | ||
| 966 | pattern = controller->GetLedPattern(); | ||
| 967 | return ResultSuccess; | ||
| 968 | } | ||
| 969 | |||
| 970 | Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, | 959 | Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, |
| 971 | Core::HID::NpadIdType npad_id) const { | 960 | Core::HID::NpadIdType npad_id) const { |
| 972 | std::scoped_lock lock{mutex}; | 961 | std::scoped_lock lock{mutex}; |
diff --git a/src/hid_core/resources/npad/npad.h b/src/hid_core/resources/npad/npad.h index 502cb9b55..3b1a69e7f 100644 --- a/src/hid_core/resources/npad/npad.h +++ b/src/hid_core/resources/npad/npad.h | |||
| @@ -97,8 +97,6 @@ public: | |||
| 97 | Result ResetIsSixAxisSensorDeviceNewlyAssigned( | 97 | Result ResetIsSixAxisSensorDeviceNewlyAssigned( |
| 98 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle); | 98 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle); |
| 99 | 99 | ||
| 100 | Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const; | ||
| 101 | |||
| 102 | Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, | 100 | Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, |
| 103 | Core::HID::NpadIdType npad_id) const; | 101 | Core::HID::NpadIdType npad_id) const; |
| 104 | Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, | 102 | Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 7398ed2ec..a7400adfa 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -1431,7 +1431,8 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DA | |||
| 1431 | } | 1431 | } |
| 1432 | } | 1432 | } |
| 1433 | }; | 1433 | }; |
| 1434 | ForEachSparseImageInRegion(gpu_addr, size_bytes, region_check_gpu); | 1434 | ForEachSparseImageInRegion(channel_state->gpu_memory.GetID(), gpu_addr, size_bytes, |
| 1435 | region_check_gpu); | ||
| 1435 | 1436 | ||
| 1436 | bool can_rescale = info.rescaleable; | 1437 | bool can_rescale = info.rescaleable; |
| 1437 | bool any_rescaled = false; | 1438 | bool any_rescaled = false; |
| @@ -1842,7 +1843,7 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s | |||
| 1842 | if (!storage_id) { | 1843 | if (!storage_id) { |
| 1843 | return; | 1844 | return; |
| 1844 | } | 1845 | } |
| 1845 | auto& gpu_page_table = gpu_page_table_storage[*storage_id]; | 1846 | auto& gpu_page_table = gpu_page_table_storage[*storage_id * 2]; |
| 1846 | ForEachGPUPage(gpu_addr, size, | 1847 | ForEachGPUPage(gpu_addr, size, |
| 1847 | [this, &gpu_page_table, &images, gpu_addr, size, func](u64 page) { | 1848 | [this, &gpu_page_table, &images, gpu_addr, size, func](u64 page) { |
| 1848 | const auto it = gpu_page_table.find(page); | 1849 | const auto it = gpu_page_table.find(page); |
| @@ -1882,41 +1883,48 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s | |||
| 1882 | 1883 | ||
| 1883 | template <class P> | 1884 | template <class P> |
| 1884 | template <typename Func> | 1885 | template <typename Func> |
| 1885 | void TextureCache<P>::ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, Func&& func) { | 1886 | void TextureCache<P>::ForEachSparseImageInRegion(size_t as_id, GPUVAddr gpu_addr, size_t size, |
| 1887 | Func&& func) { | ||
| 1886 | using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type; | 1888 | using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type; |
| 1887 | static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>; | 1889 | static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>; |
| 1888 | boost::container::small_vector<ImageId, 8> images; | 1890 | boost::container::small_vector<ImageId, 8> images; |
| 1889 | ForEachGPUPage(gpu_addr, size, [this, &images, gpu_addr, size, func](u64 page) { | 1891 | auto storage_id = getStorageID(as_id); |
| 1890 | const auto it = sparse_page_table.find(page); | 1892 | if (!storage_id) { |
| 1891 | if (it == sparse_page_table.end()) { | 1893 | return; |
| 1892 | if constexpr (BOOL_BREAK) { | 1894 | } |
| 1893 | return false; | 1895 | auto& sparse_page_table = gpu_page_table_storage[*storage_id * 2 + 1]; |
| 1894 | } else { | 1896 | ForEachGPUPage(gpu_addr, size, |
| 1895 | return; | 1897 | [this, &sparse_page_table, &images, gpu_addr, size, func](u64 page) { |
| 1896 | } | 1898 | const auto it = sparse_page_table.find(page); |
| 1897 | } | 1899 | if (it == sparse_page_table.end()) { |
| 1898 | for (const ImageId image_id : it->second) { | 1900 | if constexpr (BOOL_BREAK) { |
| 1899 | Image& image = slot_images[image_id]; | 1901 | return false; |
| 1900 | if (True(image.flags & ImageFlagBits::Picked)) { | 1902 | } else { |
| 1901 | continue; | 1903 | return; |
| 1902 | } | 1904 | } |
| 1903 | if (!image.OverlapsGPU(gpu_addr, size)) { | 1905 | } |
| 1904 | continue; | 1906 | for (const ImageId image_id : it->second) { |
| 1905 | } | 1907 | Image& image = slot_images[image_id]; |
| 1906 | image.flags |= ImageFlagBits::Picked; | 1908 | if (True(image.flags & ImageFlagBits::Picked)) { |
| 1907 | images.push_back(image_id); | 1909 | continue; |
| 1908 | if constexpr (BOOL_BREAK) { | 1910 | } |
| 1909 | if (func(image_id, image)) { | 1911 | if (!image.OverlapsGPU(gpu_addr, size)) { |
| 1910 | return true; | 1912 | continue; |
| 1911 | } | 1913 | } |
| 1912 | } else { | 1914 | image.flags |= ImageFlagBits::Picked; |
| 1913 | func(image_id, image); | 1915 | images.push_back(image_id); |
| 1914 | } | 1916 | if constexpr (BOOL_BREAK) { |
| 1915 | } | 1917 | if (func(image_id, image)) { |
| 1916 | if constexpr (BOOL_BREAK) { | 1918 | return true; |
| 1917 | return false; | 1919 | } |
| 1918 | } | 1920 | } else { |
| 1919 | }); | 1921 | func(image_id, image); |
| 1922 | } | ||
| 1923 | } | ||
| 1924 | if constexpr (BOOL_BREAK) { | ||
| 1925 | return false; | ||
| 1926 | } | ||
| 1927 | }); | ||
| 1920 | for (const ImageId image_id : images) { | 1928 | for (const ImageId image_id : images) { |
| 1921 | slot_images[image_id].flags &= ~ImageFlagBits::Picked; | 1929 | slot_images[image_id].flags &= ~ImageFlagBits::Picked; |
| 1922 | } | 1930 | } |
| @@ -1988,8 +1996,9 @@ void TextureCache<P>::RegisterImage(ImageId image_id) { | |||
| 1988 | sparse_maps.push_back(map_id); | 1996 | sparse_maps.push_back(map_id); |
| 1989 | }); | 1997 | }); |
| 1990 | sparse_views.emplace(image_id, std::move(sparse_maps)); | 1998 | sparse_views.emplace(image_id, std::move(sparse_maps)); |
| 1991 | ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, | 1999 | ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, image_id](u64 page) { |
| 1992 | [this, image_id](u64 page) { sparse_page_table[page].push_back(image_id); }); | 2000 | (*channel_state->sparse_page_table)[page].push_back(image_id); |
| 2001 | }); | ||
| 1993 | } | 2002 | } |
| 1994 | 2003 | ||
| 1995 | template <class P> | 2004 | template <class P> |
| @@ -2042,7 +2051,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) { | |||
| 2042 | return; | 2051 | return; |
| 2043 | } | 2052 | } |
| 2044 | ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) { | 2053 | ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) { |
| 2045 | clear_page_table(page, sparse_page_table); | 2054 | clear_page_table(page, (*channel_state->sparse_page_table)); |
| 2046 | }); | 2055 | }); |
| 2047 | auto it = sparse_views.find(image_id); | 2056 | auto it = sparse_views.find(image_id); |
| 2048 | ASSERT(it != sparse_views.end()); | 2057 | ASSERT(it != sparse_views.end()); |
| @@ -2496,13 +2505,15 @@ void TextureCache<P>::CreateChannel(struct Tegra::Control::ChannelState& channel | |||
| 2496 | const auto it = channel_map.find(channel.bind_id); | 2505 | const auto it = channel_map.find(channel.bind_id); |
| 2497 | auto* this_state = &channel_storage[it->second]; | 2506 | auto* this_state = &channel_storage[it->second]; |
| 2498 | const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()]; | 2507 | const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()]; |
| 2499 | this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id]; | 2508 | this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id * 2]; |
| 2509 | this_state->sparse_page_table = &gpu_page_table_storage[this_as_ref.storage_id * 2 + 1]; | ||
| 2500 | } | 2510 | } |
| 2501 | 2511 | ||
| 2502 | /// Bind a channel for execution. | 2512 | /// Bind a channel for execution. |
| 2503 | template <class P> | 2513 | template <class P> |
| 2504 | void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) { | 2514 | void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) { |
| 2505 | gpu_page_table_storage.emplace_back(); | 2515 | gpu_page_table_storage.emplace_back(); |
| 2516 | gpu_page_table_storage.emplace_back(); | ||
| 2506 | } | 2517 | } |
| 2507 | 2518 | ||
| 2508 | } // namespace VideoCommon | 2519 | } // namespace VideoCommon |
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 8699d40d4..f9aebb293 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -86,6 +86,7 @@ public: | |||
| 86 | std::unordered_map<TSCEntry, SamplerId> samplers; | 86 | std::unordered_map<TSCEntry, SamplerId> samplers; |
| 87 | 87 | ||
| 88 | TextureCacheGPUMap* gpu_page_table; | 88 | TextureCacheGPUMap* gpu_page_table; |
| 89 | TextureCacheGPUMap* sparse_page_table; | ||
| 89 | }; | 90 | }; |
| 90 | 91 | ||
| 91 | template <class P> | 92 | template <class P> |
| @@ -357,7 +358,7 @@ private: | |||
| 357 | void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func); | 358 | void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func); |
| 358 | 359 | ||
| 359 | template <typename Func> | 360 | template <typename Func> |
| 360 | void ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, Func&& func); | 361 | void ForEachSparseImageInRegion(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func); |
| 361 | 362 | ||
| 362 | /// Iterates over all the images in a region calling func | 363 | /// Iterates over all the images in a region calling func |
| 363 | template <typename Func> | 364 | template <typename Func> |
| @@ -431,7 +432,6 @@ private: | |||
| 431 | std::unordered_map<RenderTargets, FramebufferId> framebuffers; | 432 | std::unordered_map<RenderTargets, FramebufferId> framebuffers; |
| 432 | 433 | ||
| 433 | std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table; | 434 | std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table; |
| 434 | std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>> sparse_page_table; | ||
| 435 | std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views; | 435 | std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views; |
| 436 | 436 | ||
| 437 | DAddr virtual_invalid_space{}; | 437 | DAddr virtual_invalid_space{}; |
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index 9b6ef47a7..c235b0fca 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | #include <vector> | 6 | #include <vector> |
| 7 | #include <QComboBox> | 7 | #include <QComboBox> |
| 8 | #include <QPushButton> | ||
| 8 | 9 | ||
| 9 | #include "audio_core/sink/sink.h" | 10 | #include "audio_core/sink/sink.h" |
| 10 | #include "audio_core/sink/sink_details.h" | 11 | #include "audio_core/sink/sink_details.h" |
| @@ -67,19 +68,99 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) { | |||
| 67 | 68 | ||
| 68 | hold.emplace(std::pair{setting->Id(), widget}); | 69 | hold.emplace(std::pair{setting->Id(), widget}); |
| 69 | 70 | ||
| 71 | auto global_sink_match = [this] { | ||
| 72 | return static_cast<Settings::AudioEngine>(sink_combo_box->currentIndex()) == | ||
| 73 | Settings::values.sink_id.GetValue(true); | ||
| 74 | }; | ||
| 70 | if (setting->Id() == Settings::values.sink_id.Id()) { | 75 | if (setting->Id() == Settings::values.sink_id.Id()) { |
| 71 | // TODO (lat9nq): Let the system manage sink_id | 76 | // TODO (lat9nq): Let the system manage sink_id |
| 72 | sink_combo_box = widget->combobox; | 77 | sink_combo_box = widget->combobox; |
| 73 | InitializeAudioSinkComboBox(); | 78 | InitializeAudioSinkComboBox(); |
| 74 | 79 | ||
| 75 | connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, | 80 | if (Settings::IsConfiguringGlobal()) { |
| 76 | &ConfigureAudio::UpdateAudioDevices); | 81 | connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, |
| 82 | &ConfigureAudio::UpdateAudioDevices); | ||
| 83 | } else { | ||
| 84 | restore_sink_button = ConfigurationShared::Widget::CreateRestoreGlobalButton( | ||
| 85 | Settings::values.sink_id.UsingGlobal(), widget); | ||
| 86 | widget->layout()->addWidget(restore_sink_button); | ||
| 87 | connect(restore_sink_button, &QAbstractButton::clicked, [this](bool) { | ||
| 88 | Settings::values.sink_id.SetGlobal(true); | ||
| 89 | const int sink_index = static_cast<int>(Settings::values.sink_id.GetValue()); | ||
| 90 | sink_combo_box->setCurrentIndex(sink_index); | ||
| 91 | ConfigureAudio::UpdateAudioDevices(sink_index); | ||
| 92 | Settings::values.audio_output_device_id.SetGlobal(true); | ||
| 93 | Settings::values.audio_input_device_id.SetGlobal(true); | ||
| 94 | restore_sink_button->setVisible(false); | ||
| 95 | }); | ||
| 96 | connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), | ||
| 97 | [this, global_sink_match](const int slot) { | ||
| 98 | Settings::values.sink_id.SetGlobal(false); | ||
| 99 | Settings::values.audio_output_device_id.SetGlobal(false); | ||
| 100 | Settings::values.audio_input_device_id.SetGlobal(false); | ||
| 101 | |||
| 102 | restore_sink_button->setVisible(true); | ||
| 103 | restore_sink_button->setEnabled(true); | ||
| 104 | output_device_combo_box->setCurrentIndex(0); | ||
| 105 | restore_output_device_button->setVisible(true); | ||
| 106 | restore_output_device_button->setEnabled(global_sink_match()); | ||
| 107 | input_device_combo_box->setCurrentIndex(0); | ||
| 108 | restore_input_device_button->setVisible(true); | ||
| 109 | restore_input_device_button->setEnabled(global_sink_match()); | ||
| 110 | ConfigureAudio::UpdateAudioDevices(slot); | ||
| 111 | }); | ||
| 112 | } | ||
| 77 | } else if (setting->Id() == Settings::values.audio_output_device_id.Id()) { | 113 | } else if (setting->Id() == Settings::values.audio_output_device_id.Id()) { |
| 78 | // Keep track of output (and input) device comboboxes to populate them with system | 114 | // Keep track of output (and input) device comboboxes to populate them with system |
| 79 | // devices, which are determined at run time | 115 | // devices, which are determined at run time |
| 80 | output_device_combo_box = widget->combobox; | 116 | output_device_combo_box = widget->combobox; |
| 117 | |||
| 118 | if (!Settings::IsConfiguringGlobal()) { | ||
| 119 | restore_output_device_button = | ||
| 120 | ConfigurationShared::Widget::CreateRestoreGlobalButton( | ||
| 121 | Settings::values.audio_output_device_id.UsingGlobal(), widget); | ||
| 122 | restore_output_device_button->setEnabled(global_sink_match()); | ||
| 123 | restore_output_device_button->setVisible( | ||
| 124 | !Settings::values.audio_output_device_id.UsingGlobal()); | ||
| 125 | widget->layout()->addWidget(restore_output_device_button); | ||
| 126 | connect(restore_output_device_button, &QAbstractButton::clicked, [this](bool) { | ||
| 127 | Settings::values.audio_output_device_id.SetGlobal(true); | ||
| 128 | SetOutputDevicesFromDeviceID(); | ||
| 129 | restore_output_device_button->setVisible(false); | ||
| 130 | }); | ||
| 131 | connect(output_device_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), | ||
| 132 | [this, global_sink_match](int) { | ||
| 133 | if (updating_devices) { | ||
| 134 | return; | ||
| 135 | } | ||
| 136 | Settings::values.audio_output_device_id.SetGlobal(false); | ||
| 137 | restore_output_device_button->setVisible(true); | ||
| 138 | restore_output_device_button->setEnabled(global_sink_match()); | ||
| 139 | }); | ||
| 140 | } | ||
| 81 | } else if (setting->Id() == Settings::values.audio_input_device_id.Id()) { | 141 | } else if (setting->Id() == Settings::values.audio_input_device_id.Id()) { |
| 82 | input_device_combo_box = widget->combobox; | 142 | input_device_combo_box = widget->combobox; |
| 143 | |||
| 144 | if (!Settings::IsConfiguringGlobal()) { | ||
| 145 | restore_input_device_button = | ||
| 146 | ConfigurationShared::Widget::CreateRestoreGlobalButton( | ||
| 147 | Settings::values.audio_input_device_id.UsingGlobal(), widget); | ||
| 148 | widget->layout()->addWidget(restore_input_device_button); | ||
| 149 | connect(restore_input_device_button, &QAbstractButton::clicked, [this](bool) { | ||
| 150 | Settings::values.audio_input_device_id.SetGlobal(true); | ||
| 151 | SetInputDevicesFromDeviceID(); | ||
| 152 | restore_input_device_button->setVisible(false); | ||
| 153 | }); | ||
| 154 | connect(input_device_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), | ||
| 155 | [this, global_sink_match](int) { | ||
| 156 | if (updating_devices) { | ||
| 157 | return; | ||
| 158 | } | ||
| 159 | Settings::values.audio_input_device_id.SetGlobal(false); | ||
| 160 | restore_input_device_button->setVisible(true); | ||
| 161 | restore_input_device_button->setEnabled(global_sink_match()); | ||
| 162 | }); | ||
| 163 | } | ||
| 83 | } | 164 | } |
| 84 | } | 165 | } |
| 85 | 166 | ||
| @@ -89,16 +170,13 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) { | |||
| 89 | } | 170 | } |
| 90 | 171 | ||
| 91 | void ConfigureAudio::SetConfiguration() { | 172 | void ConfigureAudio::SetConfiguration() { |
| 92 | if (!Settings::IsConfiguringGlobal()) { | ||
| 93 | return; | ||
| 94 | } | ||
| 95 | |||
| 96 | SetOutputSinkFromSinkID(); | 173 | SetOutputSinkFromSinkID(); |
| 97 | 174 | ||
| 98 | // The device list cannot be pre-populated (nor listed) until the output sink is known. | 175 | // The device list cannot be pre-populated (nor listed) until the output sink is known. |
| 99 | UpdateAudioDevices(sink_combo_box->currentIndex()); | 176 | UpdateAudioDevices(sink_combo_box->currentIndex()); |
| 100 | 177 | ||
| 101 | SetAudioDevicesFromDeviceID(); | 178 | SetOutputDevicesFromDeviceID(); |
| 179 | SetInputDevicesFromDeviceID(); | ||
| 102 | } | 180 | } |
| 103 | 181 | ||
| 104 | void ConfigureAudio::SetOutputSinkFromSinkID() { | 182 | void ConfigureAudio::SetOutputSinkFromSinkID() { |
| @@ -116,8 +194,8 @@ void ConfigureAudio::SetOutputSinkFromSinkID() { | |||
| 116 | sink_combo_box->setCurrentIndex(new_sink_index); | 194 | sink_combo_box->setCurrentIndex(new_sink_index); |
| 117 | } | 195 | } |
| 118 | 196 | ||
| 119 | void ConfigureAudio::SetAudioDevicesFromDeviceID() { | 197 | void ConfigureAudio::SetOutputDevicesFromDeviceID() { |
| 120 | int new_device_index = -1; | 198 | int new_device_index = 0; |
| 121 | 199 | ||
| 122 | const QString output_device_id = | 200 | const QString output_device_id = |
| 123 | QString::fromStdString(Settings::values.audio_output_device_id.GetValue()); | 201 | QString::fromStdString(Settings::values.audio_output_device_id.GetValue()); |
| @@ -129,8 +207,10 @@ void ConfigureAudio::SetAudioDevicesFromDeviceID() { | |||
| 129 | } | 207 | } |
| 130 | 208 | ||
| 131 | output_device_combo_box->setCurrentIndex(new_device_index); | 209 | output_device_combo_box->setCurrentIndex(new_device_index); |
| 210 | } | ||
| 132 | 211 | ||
| 133 | new_device_index = -1; | 212 | void ConfigureAudio::SetInputDevicesFromDeviceID() { |
| 213 | int new_device_index = 0; | ||
| 134 | const QString input_device_id = | 214 | const QString input_device_id = |
| 135 | QString::fromStdString(Settings::values.audio_input_device_id.GetValue()); | 215 | QString::fromStdString(Settings::values.audio_input_device_id.GetValue()); |
| 136 | for (int index = 0; index < input_device_combo_box->count(); index++) { | 216 | for (int index = 0; index < input_device_combo_box->count(); index++) { |
| @@ -149,15 +229,12 @@ void ConfigureAudio::ApplyConfiguration() { | |||
| 149 | apply_func(is_powered_on); | 229 | apply_func(is_powered_on); |
| 150 | } | 230 | } |
| 151 | 231 | ||
| 152 | if (Settings::IsConfiguringGlobal()) { | 232 | Settings::values.sink_id.LoadString( |
| 153 | Settings::values.sink_id.LoadString( | 233 | sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString()); |
| 154 | sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString()); | 234 | Settings::values.audio_output_device_id.SetValue( |
| 155 | Settings::values.audio_output_device_id.SetValue( | 235 | output_device_combo_box->itemText(output_device_combo_box->currentIndex()).toStdString()); |
| 156 | output_device_combo_box->itemText(output_device_combo_box->currentIndex()) | 236 | Settings::values.audio_input_device_id.SetValue( |
| 157 | .toStdString()); | 237 | input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString()); |
| 158 | Settings::values.audio_input_device_id.SetValue( | ||
| 159 | input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString()); | ||
| 160 | } | ||
| 161 | } | 238 | } |
| 162 | 239 | ||
| 163 | void ConfigureAudio::changeEvent(QEvent* event) { | 240 | void ConfigureAudio::changeEvent(QEvent* event) { |
| @@ -169,6 +246,7 @@ void ConfigureAudio::changeEvent(QEvent* event) { | |||
| 169 | } | 246 | } |
| 170 | 247 | ||
| 171 | void ConfigureAudio::UpdateAudioDevices(int sink_index) { | 248 | void ConfigureAudio::UpdateAudioDevices(int sink_index) { |
| 249 | updating_devices = true; | ||
| 172 | output_device_combo_box->clear(); | 250 | output_device_combo_box->clear(); |
| 173 | output_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); | 251 | output_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); |
| 174 | 252 | ||
| @@ -183,6 +261,7 @@ void ConfigureAudio::UpdateAudioDevices(int sink_index) { | |||
| 183 | for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) { | 261 | for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) { |
| 184 | input_device_combo_box->addItem(QString::fromStdString(device)); | 262 | input_device_combo_box->addItem(QString::fromStdString(device)); |
| 185 | } | 263 | } |
| 264 | updating_devices = false; | ||
| 186 | } | 265 | } |
| 187 | 266 | ||
| 188 | void ConfigureAudio::InitializeAudioSinkComboBox() { | 267 | void ConfigureAudio::InitializeAudioSinkComboBox() { |
diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h index 82d7f6524..32a2fa5f0 100644 --- a/src/yuzu/configuration/configure_audio.h +++ b/src/yuzu/configuration/configure_audio.h | |||
| @@ -45,7 +45,8 @@ private: | |||
| 45 | void UpdateAudioDevices(int sink_index); | 45 | void UpdateAudioDevices(int sink_index); |
| 46 | 46 | ||
| 47 | void SetOutputSinkFromSinkID(); | 47 | void SetOutputSinkFromSinkID(); |
| 48 | void SetAudioDevicesFromDeviceID(); | 48 | void SetOutputDevicesFromDeviceID(); |
| 49 | void SetInputDevicesFromDeviceID(); | ||
| 49 | 50 | ||
| 50 | void Setup(const ConfigurationShared::Builder& builder); | 51 | void Setup(const ConfigurationShared::Builder& builder); |
| 51 | 52 | ||
| @@ -55,7 +56,11 @@ private: | |||
| 55 | 56 | ||
| 56 | std::vector<std::function<void(bool)>> apply_funcs{}; | 57 | std::vector<std::function<void(bool)>> apply_funcs{}; |
| 57 | 58 | ||
| 59 | bool updating_devices = false; | ||
| 58 | QComboBox* sink_combo_box; | 60 | QComboBox* sink_combo_box; |
| 61 | QPushButton* restore_sink_button; | ||
| 59 | QComboBox* output_device_combo_box; | 62 | QComboBox* output_device_combo_box; |
| 63 | QPushButton* restore_output_device_button; | ||
| 60 | QComboBox* input_device_combo_box; | 64 | QComboBox* input_device_combo_box; |
| 65 | QPushButton* restore_input_device_button; | ||
| 61 | }; | 66 | }; |