summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/page_table.h12
-rw-r--r--src/core/arm/arm_interface.cpp4
-rw-r--r--src/core/arm/arm_interface.h2
-rw-r--r--src/core/hle/kernel/k_auto_object.cpp4
-rw-r--r--src/core/hle/kernel/k_auto_object.h5
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp3
-rw-r--r--src/core/hle/kernel/k_thread.cpp2
-rw-r--r--src/core/memory.cpp30
-rw-r--r--src/video_core/query_cache.h4
-rw-r--r--src/video_core/rasterizer_accelerated.cpp5
-rw-r--r--src/video_core/rasterizer_accelerated.h3
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp8
-rw-r--r--src/yuzu/discord_impl.cpp82
-rw-r--r--src/yuzu/discord_impl.h7
-rw-r--r--src/yuzu/game_list_worker.cpp6
15 files changed, 100 insertions, 77 deletions
diff --git a/src/common/page_table.h b/src/common/page_table.h
index fec8378f3..e653d52ad 100644
--- a/src/common/page_table.h
+++ b/src/common/page_table.h
@@ -51,7 +51,7 @@ struct PageTable {
51 class PageInfo { 51 class PageInfo {
52 public: 52 public:
53 /// Returns the page pointer 53 /// Returns the page pointer
54 [[nodiscard]] u8* Pointer() const noexcept { 54 [[nodiscard]] uintptr_t Pointer() const noexcept {
55 return ExtractPointer(raw.load(std::memory_order_relaxed)); 55 return ExtractPointer(raw.load(std::memory_order_relaxed));
56 } 56 }
57 57
@@ -61,7 +61,7 @@ struct PageTable {
61 } 61 }
62 62
63 /// Returns the page pointer and attribute pair, extracted from the same atomic read 63 /// Returns the page pointer and attribute pair, extracted from the same atomic read
64 [[nodiscard]] std::pair<u8*, PageType> PointerType() const noexcept { 64 [[nodiscard]] std::pair<uintptr_t, PageType> PointerType() const noexcept {
65 const uintptr_t non_atomic_raw = raw.load(std::memory_order_relaxed); 65 const uintptr_t non_atomic_raw = raw.load(std::memory_order_relaxed);
66 return {ExtractPointer(non_atomic_raw), ExtractType(non_atomic_raw)}; 66 return {ExtractPointer(non_atomic_raw), ExtractType(non_atomic_raw)};
67 } 67 }
@@ -73,13 +73,13 @@ struct PageTable {
73 } 73 }
74 74
75 /// Write a page pointer and type pair atomically 75 /// Write a page pointer and type pair atomically
76 void Store(u8* pointer, PageType type) noexcept { 76 void Store(uintptr_t pointer, PageType type) noexcept {
77 raw.store(reinterpret_cast<uintptr_t>(pointer) | static_cast<uintptr_t>(type)); 77 raw.store(pointer | static_cast<uintptr_t>(type));
78 } 78 }
79 79
80 /// Unpack a pointer from a page info raw representation 80 /// Unpack a pointer from a page info raw representation
81 [[nodiscard]] static u8* ExtractPointer(uintptr_t raw) noexcept { 81 [[nodiscard]] static uintptr_t ExtractPointer(uintptr_t raw) noexcept {
82 return reinterpret_cast<u8*>(raw & (~uintptr_t{0} << ATTRIBUTE_BITS)); 82 return raw & (~uintptr_t{0} << ATTRIBUTE_BITS);
83 } 83 }
84 84
85 /// Unpack a page type from a page info raw representation 85 /// Unpack a page type from a page info raw representation
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index aa0eb9791..0c012f094 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -217,8 +217,8 @@ void ARM_Interface::Run() {
217 } 217 }
218} 218}
219 219
220void ARM_Interface::LoadWatchpointArray(const WatchpointArray& wp) { 220void ARM_Interface::LoadWatchpointArray(const WatchpointArray* wp) {
221 watchpoints = &wp; 221 watchpoints = wp;
222} 222}
223 223
224const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint( 224const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint(
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index d5f2fa09a..3d866ff6f 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -186,7 +186,7 @@ public:
186 virtual void SaveContext(ThreadContext64& ctx) const = 0; 186 virtual void SaveContext(ThreadContext64& ctx) const = 0;
187 virtual void LoadContext(const ThreadContext32& ctx) = 0; 187 virtual void LoadContext(const ThreadContext32& ctx) = 0;
188 virtual void LoadContext(const ThreadContext64& ctx) = 0; 188 virtual void LoadContext(const ThreadContext64& ctx) = 0;
189 void LoadWatchpointArray(const WatchpointArray& wp); 189 void LoadWatchpointArray(const WatchpointArray* wp);
190 190
191 /// Clears the exclusive monitor's state. 191 /// Clears the exclusive monitor's state.
192 virtual void ClearExclusiveState() = 0; 192 virtual void ClearExclusiveState() = 0;
diff --git a/src/core/hle/kernel/k_auto_object.cpp b/src/core/hle/kernel/k_auto_object.cpp
index 0ae42c95c..9cd7a9fd5 100644
--- a/src/core/hle/kernel/k_auto_object.cpp
+++ b/src/core/hle/kernel/k_auto_object.cpp
@@ -15,8 +15,8 @@ void KAutoObject::RegisterWithKernel() {
15 m_kernel.RegisterKernelObject(this); 15 m_kernel.RegisterKernelObject(this);
16} 16}
17 17
18void KAutoObject::UnregisterWithKernel() { 18void KAutoObject::UnregisterWithKernel(KernelCore& kernel, KAutoObject* self) {
19 m_kernel.UnregisterKernelObject(this); 19 kernel.UnregisterKernelObject(self);
20} 20}
21 21
22} // namespace Kernel 22} // namespace Kernel
diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h
index f384b1568..8d4e0df44 100644
--- a/src/core/hle/kernel/k_auto_object.h
+++ b/src/core/hle/kernel/k_auto_object.h
@@ -159,14 +159,15 @@ public:
159 159
160 // If ref count hits zero, destroy the object. 160 // If ref count hits zero, destroy the object.
161 if (cur_ref_count - 1 == 0) { 161 if (cur_ref_count - 1 == 0) {
162 KernelCore& kernel = m_kernel;
162 this->Destroy(); 163 this->Destroy();
163 this->UnregisterWithKernel(); 164 KAutoObject::UnregisterWithKernel(kernel, this);
164 } 165 }
165 } 166 }
166 167
167private: 168private:
168 void RegisterWithKernel(); 169 void RegisterWithKernel();
169 void UnregisterWithKernel(); 170 static void UnregisterWithKernel(KernelCore& kernel, KAutoObject* self);
170 171
171protected: 172protected:
172 KernelCore& m_kernel; 173 KernelCore& m_kernel;
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 75ce5a23c..d8143c650 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -510,11 +510,12 @@ void KScheduler::Unload(KThread* thread) {
510 510
511void KScheduler::Reload(KThread* thread) { 511void KScheduler::Reload(KThread* thread) {
512 auto& cpu_core = m_kernel.System().ArmInterface(m_core_id); 512 auto& cpu_core = m_kernel.System().ArmInterface(m_core_id);
513 auto* process = thread->GetOwnerProcess();
513 cpu_core.LoadContext(thread->GetContext32()); 514 cpu_core.LoadContext(thread->GetContext32());
514 cpu_core.LoadContext(thread->GetContext64()); 515 cpu_core.LoadContext(thread->GetContext64());
515 cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress())); 516 cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress()));
516 cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0()); 517 cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0());
517 cpu_core.LoadWatchpointArray(thread->GetOwnerProcess()->GetWatchpoints()); 518 cpu_core.LoadWatchpointArray(process ? &process->GetWatchpoints() : nullptr);
518 cpu_core.ClearExclusiveState(); 519 cpu_core.ClearExclusiveState();
519} 520}
520 521
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index d88909889..7df8fd7f7 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -129,7 +129,7 @@ Result KThread::Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress
129 case ThreadType::User: 129 case ThreadType::User:
130 ASSERT(((owner == nullptr) || 130 ASSERT(((owner == nullptr) ||
131 (owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask())); 131 (owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask()));
132 ASSERT(((owner == nullptr) || 132 ASSERT(((owner == nullptr) || (prio > Svc::LowestThreadPriority) ||
133 (owner->GetPriorityMask() | (1ULL << prio)) == owner->GetPriorityMask())); 133 (owner->GetPriorityMask() | (1ULL << prio)) == owner->GetPriorityMask()));
134 break; 134 break;
135 case ThreadType::Kernel: 135 case ThreadType::Kernel:
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 179685b72..513bc4edb 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -73,7 +73,7 @@ struct Memory::Impl {
73 return {}; 73 return {};
74 } 74 }
75 75
76 return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr; 76 return system.DeviceMemory().GetPointer<u8>(paddr + vaddr);
77 } 77 }
78 78
79 [[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const { 79 [[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const {
@@ -84,7 +84,7 @@ struct Memory::Impl {
84 return {}; 84 return {};
85 } 85 }
86 86
87 return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr; 87 return system.DeviceMemory().GetPointer<u8>(paddr + vaddr);
88 } 88 }
89 89
90 u8 Read8(const Common::ProcessAddress addr) { 90 u8 Read8(const Common::ProcessAddress addr) {
@@ -205,7 +205,8 @@ struct Memory::Impl {
205 break; 205 break;
206 } 206 }
207 case Common::PageType::Memory: { 207 case Common::PageType::Memory: {
208 u8* mem_ptr = pointer + page_offset + (page_index << YUZU_PAGEBITS); 208 u8* mem_ptr =
209 reinterpret_cast<u8*>(pointer + page_offset + (page_index << YUZU_PAGEBITS));
209 on_memory(copy_amount, mem_ptr); 210 on_memory(copy_amount, mem_ptr);
210 break; 211 break;
211 } 212 }
@@ -447,7 +448,7 @@ struct Memory::Impl {
447 break; 448 break;
448 case Common::PageType::Memory: 449 case Common::PageType::Memory:
449 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( 450 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
450 nullptr, Common::PageType::DebugMemory); 451 0, Common::PageType::DebugMemory);
451 break; 452 break;
452 default: 453 default:
453 UNREACHABLE(); 454 UNREACHABLE();
@@ -465,7 +466,8 @@ struct Memory::Impl {
465 case Common::PageType::DebugMemory: { 466 case Common::PageType::DebugMemory: {
466 u8* const pointer{GetPointerFromDebugMemory(vaddr & ~YUZU_PAGEMASK)}; 467 u8* const pointer{GetPointerFromDebugMemory(vaddr & ~YUZU_PAGEMASK)};
467 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( 468 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
468 pointer - (vaddr & ~YUZU_PAGEMASK), Common::PageType::Memory); 469 reinterpret_cast<uintptr_t>(pointer) - (vaddr & ~YUZU_PAGEMASK),
470 Common::PageType::Memory);
469 break; 471 break;
470 } 472 }
471 default: 473 default:
@@ -505,7 +507,7 @@ struct Memory::Impl {
505 case Common::PageType::DebugMemory: 507 case Common::PageType::DebugMemory:
506 case Common::PageType::Memory: 508 case Common::PageType::Memory:
507 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( 509 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
508 nullptr, Common::PageType::RasterizerCachedMemory); 510 0, Common::PageType::RasterizerCachedMemory);
509 break; 511 break;
510 case Common::PageType::RasterizerCachedMemory: 512 case Common::PageType::RasterizerCachedMemory:
511 // There can be more than one GPU region mapped per CPU region, so it's common 513 // There can be more than one GPU region mapped per CPU region, so it's common
@@ -533,10 +535,11 @@ struct Memory::Impl {
533 // pagetable after unmapping a VMA. In that case the underlying VMA will no 535 // pagetable after unmapping a VMA. In that case the underlying VMA will no
534 // longer exist, and we should just leave the pagetable entry blank. 536 // longer exist, and we should just leave the pagetable entry blank.
535 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( 537 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
536 nullptr, Common::PageType::Unmapped); 538 0, Common::PageType::Unmapped);
537 } else { 539 } else {
538 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( 540 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
539 pointer - (vaddr & ~YUZU_PAGEMASK), Common::PageType::Memory); 541 reinterpret_cast<uintptr_t>(pointer) - (vaddr & ~YUZU_PAGEMASK),
542 Common::PageType::Memory);
540 } 543 }
541 break; 544 break;
542 } 545 }
@@ -583,7 +586,7 @@ struct Memory::Impl {
583 "Mapping memory page without a pointer @ {:016x}", base * YUZU_PAGESIZE); 586 "Mapping memory page without a pointer @ {:016x}", base * YUZU_PAGESIZE);
584 587
585 while (base != end) { 588 while (base != end) {
586 page_table.pointers[base].Store(nullptr, type); 589 page_table.pointers[base].Store(0, type);
587 page_table.backing_addr[base] = 0; 590 page_table.backing_addr[base] = 0;
588 page_table.blocks[base] = 0; 591 page_table.blocks[base] = 0;
589 base += 1; 592 base += 1;
@@ -592,7 +595,8 @@ struct Memory::Impl {
592 auto orig_base = base; 595 auto orig_base = base;
593 while (base != end) { 596 while (base != end) {
594 auto host_ptr = 597 auto host_ptr =
595 system.DeviceMemory().GetPointer<u8>(target) - (base << YUZU_PAGEBITS); 598 reinterpret_cast<uintptr_t>(system.DeviceMemory().GetPointer<u8>(target)) -
599 (base << YUZU_PAGEBITS);
596 auto backing = GetInteger(target) - (base << YUZU_PAGEBITS); 600 auto backing = GetInteger(target) - (base << YUZU_PAGEBITS);
597 page_table.pointers[base].Store(host_ptr, type); 601 page_table.pointers[base].Store(host_ptr, type);
598 page_table.backing_addr[base] = backing; 602 page_table.backing_addr[base] = backing;
@@ -618,8 +622,8 @@ struct Memory::Impl {
618 622
619 // Avoid adding any extra logic to this fast-path block 623 // Avoid adding any extra logic to this fast-path block
620 const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw(); 624 const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw();
621 if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { 625 if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
622 return &pointer[vaddr]; 626 return reinterpret_cast<u8*>(pointer + vaddr);
623 } 627 }
624 switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) { 628 switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) {
625 case Common::PageType::Unmapped: 629 case Common::PageType::Unmapped:
@@ -813,7 +817,7 @@ bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const {
813 return false; 817 return false;
814 } 818 }
815 const auto [pointer, type] = page_table.pointers[page].PointerType(); 819 const auto [pointer, type] = page_table.pointers[page].PointerType();
816 return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory || 820 return pointer != 0 || type == Common::PageType::RasterizerCachedMemory ||
817 type == Common::PageType::DebugMemory; 821 type == Common::PageType::DebugMemory;
818} 822}
819 823
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h
index 1528cc1dd..7047e2e63 100644
--- a/src/video_core/query_cache.h
+++ b/src/video_core/query_cache.h
@@ -103,7 +103,9 @@ public:
103 explicit QueryCacheBase(VideoCore::RasterizerInterface& rasterizer_, 103 explicit QueryCacheBase(VideoCore::RasterizerInterface& rasterizer_,
104 Core::Memory::Memory& cpu_memory_) 104 Core::Memory::Memory& cpu_memory_)
105 : rasterizer{rasterizer_}, 105 : rasterizer{rasterizer_},
106 cpu_memory{cpu_memory_}, streams{{CounterStream{static_cast<QueryCache&>(*this), 106 // Use reinterpret_cast instead of static_cast as workaround for
107 // UBSan bug (https://github.com/llvm/llvm-project/issues/59060)
108 cpu_memory{cpu_memory_}, streams{{CounterStream{reinterpret_cast<QueryCache&>(*this),
107 VideoCore::QueryType::SamplesPassed}}} { 109 VideoCore::QueryType::SamplesPassed}}} {
108 (void)slot_async_jobs.insert(); // Null value 110 (void)slot_async_jobs.insert(); // Null value
109 } 111 }
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp
index 4a197d65d..f200a650f 100644
--- a/src/video_core/rasterizer_accelerated.cpp
+++ b/src/video_core/rasterizer_accelerated.cpp
@@ -13,7 +13,8 @@ namespace VideoCore {
13 13
14using namespace Core::Memory; 14using namespace Core::Memory;
15 15
16RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) : cpu_memory{cpu_memory_} {} 16RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_)
17 : cached_pages(std::make_unique<CachedPages>()), cpu_memory{cpu_memory_} {}
17 18
18RasterizerAccelerated::~RasterizerAccelerated() = default; 19RasterizerAccelerated::~RasterizerAccelerated() = default;
19 20
@@ -26,7 +27,7 @@ void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int del
26 std::atomic_thread_fence(std::memory_order_acquire); 27 std::atomic_thread_fence(std::memory_order_acquire);
27 const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE); 28 const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE);
28 for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) { 29 for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) {
29 std::atomic_uint16_t& count = cached_pages.at(page >> 2).Count(page); 30 std::atomic_uint16_t& count = cached_pages->at(page >> 2).Count(page);
30 31
31 if (delta > 0) { 32 if (delta > 0) {
32 ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!"); 33 ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!");
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h
index 7118b8aff..e6c0ea87a 100644
--- a/src/video_core/rasterizer_accelerated.h
+++ b/src/video_core/rasterizer_accelerated.h
@@ -41,7 +41,8 @@ private:
41 }; 41 };
42 static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!"); 42 static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!");
43 43
44 std::array<CacheEntry, 0x2000000> cached_pages; 44 using CachedPages = std::array<CacheEntry, 0x2000000>;
45 std::unique_ptr<CachedPages> cached_pages;
45 Core::Memory::Memory& cpu_memory; 46 Core::Memory::Memory& cpu_memory;
46}; 47};
47 48
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index e04852e01..9c6fbb918 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -554,14 +554,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
554 } 554 }
555 555
556 sets_per_pool = 64; 556 sets_per_pool = 64;
557 if (extensions.extended_dynamic_state3 && is_amd_driver &&
558 properties.properties.driverVersion >= VK_MAKE_API_VERSION(0, 2, 0, 270)) {
559 LOG_WARNING(Render_Vulkan,
560 "AMD drivers after 23.5.2 have broken extendedDynamicState3ColorBlendEquation");
561 features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = false;
562 features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = false;
563 dynamic_state3_blending = false;
564 }
565 if (is_amd_driver) { 557 if (is_amd_driver) {
566 // AMD drivers need a higher amount of Sets per Pool in certain circumstances like in XC2. 558 // AMD drivers need a higher amount of Sets per Pool in certain circumstances like in XC2.
567 sets_per_pool = 96; 559 sets_per_pool = 96;
diff --git a/src/yuzu/discord_impl.cpp b/src/yuzu/discord_impl.cpp
index ac2fc1bcb..57b50abd0 100644
--- a/src/yuzu/discord_impl.cpp
+++ b/src/yuzu/discord_impl.cpp
@@ -3,9 +3,14 @@
3 3
4#include <chrono> 4#include <chrono>
5#include <string> 5#include <string>
6
7#include <QEventLoop>
8#include <QNetworkAccessManager>
9#include <QNetworkReply>
10
6#include <discord_rpc.h> 11#include <discord_rpc.h>
7#include <fmt/format.h> 12#include <fmt/format.h>
8#include <httplib.h> 13
9#include "common/common_types.h" 14#include "common/common_types.h"
10#include "common/string_util.h" 15#include "common/string_util.h"
11#include "core/core.h" 16#include "core/core.h"
@@ -31,7 +36,7 @@ void DiscordImpl::Pause() {
31 Discord_ClearPresence(); 36 Discord_ClearPresence();
32} 37}
33 38
34static std::string GetGameString(const std::string& title) { 39std::string DiscordImpl::GetGameString(const std::string& title) {
35 // Convert to lowercase 40 // Convert to lowercase
36 std::string icon_name = Common::ToLower(title); 41 std::string icon_name = Common::ToLower(title);
37 42
@@ -56,51 +61,56 @@ static std::string GetGameString(const std::string& title) {
56 return icon_name; 61 return icon_name;
57} 62}
58 63
59void DiscordImpl::Update() { 64void DiscordImpl::UpdateGameStatus(bool use_default) {
65 const std::string default_text = "yuzu is an emulator for the Nintendo Switch";
66 const std::string default_image = "yuzu_logo";
67 const std::string url = use_default ? default_image : game_url;
60 s64 start_time = std::chrono::duration_cast<std::chrono::seconds>( 68 s64 start_time = std::chrono::duration_cast<std::chrono::seconds>(
61 std::chrono::system_clock::now().time_since_epoch()) 69 std::chrono::system_clock::now().time_since_epoch())
62 .count(); 70 .count();
71 DiscordRichPresence presence{};
72
73 presence.largeImageKey = url.c_str();
74 presence.largeImageText = game_title.c_str();
75 presence.smallImageKey = default_image.c_str();
76 presence.smallImageText = default_text.c_str();
77 presence.state = game_title.c_str();
78 presence.details = "Currently in game";
79 presence.startTimestamp = start_time;
80 Discord_UpdatePresence(&presence);
81}
82
83void DiscordImpl::Update() {
63 const std::string default_text = "yuzu is an emulator for the Nintendo Switch"; 84 const std::string default_text = "yuzu is an emulator for the Nintendo Switch";
64 const std::string default_image = "yuzu_logo"; 85 const std::string default_image = "yuzu_logo";
65 std::string game_cover_url = "https://yuzu-emu.org";
66 std::string title;
67
68 DiscordRichPresence presence{};
69 86
70 if (system.IsPoweredOn()) { 87 if (system.IsPoweredOn()) {
71 system.GetAppLoader().ReadTitle(title); 88 system.GetAppLoader().ReadTitle(game_title);
72 89
73 // Used to format Icon URL for yuzu website game compatibility page 90 // Used to format Icon URL for yuzu website game compatibility page
74 std::string icon_name = GetGameString(title); 91 std::string icon_name = GetGameString(game_title);
75 92 game_url = fmt::format("https://yuzu-emu.org/images/game/boxart/{}.png", icon_name);
76 // New Check for game cover 93
77 httplib::Client cli(game_cover_url); 94 QNetworkAccessManager manager;
78 cli.set_connection_timeout(std::chrono::seconds(3)); 95 QNetworkRequest request;
79 cli.set_read_timeout(std::chrono::seconds(3)); 96 request.setUrl(QUrl(QString::fromStdString(game_url)));
80 97 request.setTransferTimeout(3000);
81 if (auto res = cli.Head(fmt::format("/images/game/boxart/{}.png", icon_name))) { 98 QNetworkReply* reply = manager.head(request);
82 if (res->status == 200) { 99 QEventLoop request_event_loop;
83 game_cover_url += fmt::format("/images/game/boxart/{}.png", icon_name); 100 QObject::connect(reply, &QNetworkReply::finished, &request_event_loop, &QEventLoop::quit);
84 } else { 101 request_event_loop.exec();
85 game_cover_url = "yuzu_logo"; 102 UpdateGameStatus(reply->error());
86 } 103 return;
87 } else {
88 game_cover_url = "yuzu_logo";
89 }
90
91 presence.largeImageKey = game_cover_url.c_str();
92 presence.largeImageText = title.c_str();
93
94 presence.smallImageKey = default_image.c_str();
95 presence.smallImageText = default_text.c_str();
96 presence.state = title.c_str();
97 presence.details = "Currently in game";
98 } else {
99 presence.largeImageKey = default_image.c_str();
100 presence.largeImageText = default_text.c_str();
101 presence.details = "Currently not in game";
102 } 104 }
103 105
106 s64 start_time = std::chrono::duration_cast<std::chrono::seconds>(
107 std::chrono::system_clock::now().time_since_epoch())
108 .count();
109
110 DiscordRichPresence presence{};
111 presence.largeImageKey = default_image.c_str();
112 presence.largeImageText = default_text.c_str();
113 presence.details = "Currently not in game";
104 presence.startTimestamp = start_time; 114 presence.startTimestamp = start_time;
105 Discord_UpdatePresence(&presence); 115 Discord_UpdatePresence(&presence);
106} 116}
diff --git a/src/yuzu/discord_impl.h b/src/yuzu/discord_impl.h
index 84710b9c6..eb6cf9ae0 100644
--- a/src/yuzu/discord_impl.h
+++ b/src/yuzu/discord_impl.h
@@ -19,6 +19,13 @@ public:
19 void Pause() override; 19 void Pause() override;
20 void Update() override; 20 void Update() override;
21 21
22private:
23 std::string GetGameString(const std::string& title);
24 void UpdateGameStatus(bool use_default);
25
26 std::string game_url{};
27 std::string game_title{};
28
22 Core::System& system; 29 Core::System& system;
23}; 30};
24 31
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index 5c910c9e0..9404365b4 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -265,7 +265,11 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
265 std::vector<u8> icon; 265 std::vector<u8> icon;
266 std::string name; 266 std::string name;
267 u64 program_id = 0; 267 u64 program_id = 0;
268 loader->ReadProgramId(program_id); 268 const auto result = loader->ReadProgramId(program_id);
269
270 if (result != Loader::ResultStatus::Success) {
271 continue;
272 }
269 273
270 const PatchManager patch{program_id, system.GetFileSystemController(), 274 const PatchManager patch{program_id, system.GetFileSystemController(),
271 system.GetContentProvider()}; 275 system.GetContentProvider()};