summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt16
-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
16 files changed, 116 insertions, 77 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 00d540f1f..af9f394f1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -136,6 +136,22 @@ if (YUZU_USE_BUNDLED_VCPKG)
endif()
endif()
+ if (MSVC)
+ set(VCPKG_DOWNLOADS_PATH ${PROJECT_SOURCE_DIR}/externals/vcpkg/downloads)
+ set(NASM_VERSION "2.16.01")
+ set(NASM_DESTINATION_PATH ${VCPKG_DOWNLOADS_PATH}/nasm-${NASM_VERSION}-win64.zip)
+ set(NASM_DOWNLOAD_URL "https://github.com/yuzu-emu/ext-windows-bin/raw/master/nasm/nasm-${NASM_VERSION}-win64.zip")
+
+ if (NOT EXISTS ${NASM_DESTINATION_PATH})
+ file(DOWNLOAD ${NASM_DOWNLOAD_URL} ${NASM_DESTINATION_PATH} SHOW_PROGRESS STATUS NASM_STATUS)
+
+ if (NOT NASM_STATUS EQUAL 0)
+ # Warn and not fail since vcpkg is supposed to download this package for us in the first place
+ message(WARNING "External nasm vcpkg package download from ${NASM_DOWNLOAD_URL} failed with status ${NASM_STATUS}")
+ endif()
+ endif()
+ endif()
+
if (YUZU_TESTS)
list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests")
endif()
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 {
class PageInfo {
public:
/// Returns the page pointer
- [[nodiscard]] u8* Pointer() const noexcept {
+ [[nodiscard]] uintptr_t Pointer() const noexcept {
return ExtractPointer(raw.load(std::memory_order_relaxed));
}
@@ -61,7 +61,7 @@ struct PageTable {
}
/// Returns the page pointer and attribute pair, extracted from the same atomic read
- [[nodiscard]] std::pair<u8*, PageType> PointerType() const noexcept {
+ [[nodiscard]] std::pair<uintptr_t, PageType> PointerType() const noexcept {
const uintptr_t non_atomic_raw = raw.load(std::memory_order_relaxed);
return {ExtractPointer(non_atomic_raw), ExtractType(non_atomic_raw)};
}
@@ -73,13 +73,13 @@ struct PageTable {
}
/// Write a page pointer and type pair atomically
- void Store(u8* pointer, PageType type) noexcept {
- raw.store(reinterpret_cast<uintptr_t>(pointer) | static_cast<uintptr_t>(type));
+ void Store(uintptr_t pointer, PageType type) noexcept {
+ raw.store(pointer | static_cast<uintptr_t>(type));
}
/// Unpack a pointer from a page info raw representation
- [[nodiscard]] static u8* ExtractPointer(uintptr_t raw) noexcept {
- return reinterpret_cast<u8*>(raw & (~uintptr_t{0} << ATTRIBUTE_BITS));
+ [[nodiscard]] static uintptr_t ExtractPointer(uintptr_t raw) noexcept {
+ return raw & (~uintptr_t{0} << ATTRIBUTE_BITS);
}
/// 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() {
}
}
-void ARM_Interface::LoadWatchpointArray(const WatchpointArray& wp) {
- watchpoints = &wp;
+void ARM_Interface::LoadWatchpointArray(const WatchpointArray* wp) {
+ watchpoints = wp;
}
const 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:
virtual void SaveContext(ThreadContext64& ctx) const = 0;
virtual void LoadContext(const ThreadContext32& ctx) = 0;
virtual void LoadContext(const ThreadContext64& ctx) = 0;
- void LoadWatchpointArray(const WatchpointArray& wp);
+ void LoadWatchpointArray(const WatchpointArray* wp);
/// Clears the exclusive monitor's state.
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() {
m_kernel.RegisterKernelObject(this);
}
-void KAutoObject::UnregisterWithKernel() {
- m_kernel.UnregisterKernelObject(this);
+void KAutoObject::UnregisterWithKernel(KernelCore& kernel, KAutoObject* self) {
+ kernel.UnregisterKernelObject(self);
}
} // 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:
// If ref count hits zero, destroy the object.
if (cur_ref_count - 1 == 0) {
+ KernelCore& kernel = m_kernel;
this->Destroy();
- this->UnregisterWithKernel();
+ KAutoObject::UnregisterWithKernel(kernel, this);
}
}
private:
void RegisterWithKernel();
- void UnregisterWithKernel();
+ static void UnregisterWithKernel(KernelCore& kernel, KAutoObject* self);
protected:
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) {
void KScheduler::Reload(KThread* thread) {
auto& cpu_core = m_kernel.System().ArmInterface(m_core_id);
+ auto* process = thread->GetOwnerProcess();
cpu_core.LoadContext(thread->GetContext32());
cpu_core.LoadContext(thread->GetContext64());
cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress()));
cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0());
- cpu_core.LoadWatchpointArray(thread->GetOwnerProcess()->GetWatchpoints());
+ cpu_core.LoadWatchpointArray(process ? &process->GetWatchpoints() : nullptr);
cpu_core.ClearExclusiveState();
}
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
case ThreadType::User:
ASSERT(((owner == nullptr) ||
(owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask()));
- ASSERT(((owner == nullptr) ||
+ ASSERT(((owner == nullptr) || (prio > Svc::LowestThreadPriority) ||
(owner->GetPriorityMask() | (1ULL << prio)) == owner->GetPriorityMask()));
break;
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 {
return {};
}
- return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr;
+ return system.DeviceMemory().GetPointer<u8>(paddr + vaddr);
}
[[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const {
@@ -84,7 +84,7 @@ struct Memory::Impl {
return {};
}
- return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr;
+ return system.DeviceMemory().GetPointer<u8>(paddr + vaddr);
}
u8 Read8(const Common::ProcessAddress addr) {
@@ -205,7 +205,8 @@ struct Memory::Impl {
break;
}
case Common::PageType::Memory: {
- u8* mem_ptr = pointer + page_offset + (page_index << YUZU_PAGEBITS);
+ u8* mem_ptr =
+ reinterpret_cast<u8*>(pointer + page_offset + (page_index << YUZU_PAGEBITS));
on_memory(copy_amount, mem_ptr);
break;
}
@@ -447,7 +448,7 @@ struct Memory::Impl {
break;
case Common::PageType::Memory:
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
- nullptr, Common::PageType::DebugMemory);
+ 0, Common::PageType::DebugMemory);
break;
default:
UNREACHABLE();
@@ -465,7 +466,8 @@ struct Memory::Impl {
case Common::PageType::DebugMemory: {
u8* const pointer{GetPointerFromDebugMemory(vaddr & ~YUZU_PAGEMASK)};
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
- pointer - (vaddr & ~YUZU_PAGEMASK), Common::PageType::Memory);
+ reinterpret_cast<uintptr_t>(pointer) - (vaddr & ~YUZU_PAGEMASK),
+ Common::PageType::Memory);
break;
}
default:
@@ -505,7 +507,7 @@ struct Memory::Impl {
case Common::PageType::DebugMemory:
case Common::PageType::Memory:
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
- nullptr, Common::PageType::RasterizerCachedMemory);
+ 0, Common::PageType::RasterizerCachedMemory);
break;
case Common::PageType::RasterizerCachedMemory:
// There can be more than one GPU region mapped per CPU region, so it's common
@@ -533,10 +535,11 @@ struct Memory::Impl {
// pagetable after unmapping a VMA. In that case the underlying VMA will no
// longer exist, and we should just leave the pagetable entry blank.
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
- nullptr, Common::PageType::Unmapped);
+ 0, Common::PageType::Unmapped);
} else {
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
- pointer - (vaddr & ~YUZU_PAGEMASK), Common::PageType::Memory);
+ reinterpret_cast<uintptr_t>(pointer) - (vaddr & ~YUZU_PAGEMASK),
+ Common::PageType::Memory);
}
break;
}
@@ -583,7 +586,7 @@ struct Memory::Impl {
"Mapping memory page without a pointer @ {:016x}", base * YUZU_PAGESIZE);
while (base != end) {
- page_table.pointers[base].Store(nullptr, type);
+ page_table.pointers[base].Store(0, type);
page_table.backing_addr[base] = 0;
page_table.blocks[base] = 0;
base += 1;
@@ -592,7 +595,8 @@ struct Memory::Impl {
auto orig_base = base;
while (base != end) {
auto host_ptr =
- system.DeviceMemory().GetPointer<u8>(target) - (base << YUZU_PAGEBITS);
+ reinterpret_cast<uintptr_t>(system.DeviceMemory().GetPointer<u8>(target)) -
+ (base << YUZU_PAGEBITS);
auto backing = GetInteger(target) - (base << YUZU_PAGEBITS);
page_table.pointers[base].Store(host_ptr, type);
page_table.backing_addr[base] = backing;
@@ -618,8 +622,8 @@ struct Memory::Impl {
// Avoid adding any extra logic to this fast-path block
const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw();
- if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
- return &pointer[vaddr];
+ if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
+ return reinterpret_cast<u8*>(pointer + vaddr);
}
switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) {
case Common::PageType::Unmapped:
@@ -813,7 +817,7 @@ bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const {
return false;
}
const auto [pointer, type] = page_table.pointers[page].PointerType();
- return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory ||
+ return pointer != 0 || type == Common::PageType::RasterizerCachedMemory ||
type == Common::PageType::DebugMemory;
}
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:
explicit QueryCacheBase(VideoCore::RasterizerInterface& rasterizer_,
Core::Memory::Memory& cpu_memory_)
: rasterizer{rasterizer_},
- cpu_memory{cpu_memory_}, streams{{CounterStream{static_cast<QueryCache&>(*this),
+ // Use reinterpret_cast instead of static_cast as workaround for
+ // UBSan bug (https://github.com/llvm/llvm-project/issues/59060)
+ cpu_memory{cpu_memory_}, streams{{CounterStream{reinterpret_cast<QueryCache&>(*this),
VideoCore::QueryType::SamplesPassed}}} {
(void)slot_async_jobs.insert(); // Null value
}
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 {
using namespace Core::Memory;
-RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) : cpu_memory{cpu_memory_} {}
+RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_)
+ : cached_pages(std::make_unique<CachedPages>()), cpu_memory{cpu_memory_} {}
RasterizerAccelerated::~RasterizerAccelerated() = default;
@@ -26,7 +27,7 @@ void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int del
std::atomic_thread_fence(std::memory_order_acquire);
const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE);
for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) {
- std::atomic_uint16_t& count = cached_pages.at(page >> 2).Count(page);
+ std::atomic_uint16_t& count = cached_pages->at(page >> 2).Count(page);
if (delta > 0) {
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:
};
static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!");
- std::array<CacheEntry, 0x2000000> cached_pages;
+ using CachedPages = std::array<CacheEntry, 0x2000000>;
+ std::unique_ptr<CachedPages> cached_pages;
Core::Memory::Memory& cpu_memory;
};
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
}
sets_per_pool = 64;
- if (extensions.extended_dynamic_state3 && is_amd_driver &&
- properties.properties.driverVersion >= VK_MAKE_API_VERSION(0, 2, 0, 270)) {
- LOG_WARNING(Render_Vulkan,
- "AMD drivers after 23.5.2 have broken extendedDynamicState3ColorBlendEquation");
- features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = false;
- features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = false;
- dynamic_state3_blending = false;
- }
if (is_amd_driver) {
// AMD drivers need a higher amount of Sets per Pool in certain circumstances like in XC2.
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 @@
#include <chrono>
#include <string>
+
+#include <QEventLoop>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+
#include <discord_rpc.h>
#include <fmt/format.h>
-#include <httplib.h>
+
#include "common/common_types.h"
#include "common/string_util.h"
#include "core/core.h"
@@ -31,7 +36,7 @@ void DiscordImpl::Pause() {
Discord_ClearPresence();
}
-static std::string GetGameString(const std::string& title) {
+std::string DiscordImpl::GetGameString(const std::string& title) {
// Convert to lowercase
std::string icon_name = Common::ToLower(title);
@@ -56,51 +61,56 @@ static std::string GetGameString(const std::string& title) {
return icon_name;
}
-void DiscordImpl::Update() {
+void DiscordImpl::UpdateGameStatus(bool use_default) {
+ const std::string default_text = "yuzu is an emulator for the Nintendo Switch";
+ const std::string default_image = "yuzu_logo";
+ const std::string url = use_default ? default_image : game_url;
s64 start_time = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
+ DiscordRichPresence presence{};
+
+ presence.largeImageKey = url.c_str();
+ presence.largeImageText = game_title.c_str();
+ presence.smallImageKey = default_image.c_str();
+ presence.smallImageText = default_text.c_str();
+ presence.state = game_title.c_str();
+ presence.details = "Currently in game";
+ presence.startTimestamp = start_time;
+ Discord_UpdatePresence(&presence);
+}
+
+void DiscordImpl::Update() {
const std::string default_text = "yuzu is an emulator for the Nintendo Switch";
const std::string default_image = "yuzu_logo";
- std::string game_cover_url = "https://yuzu-emu.org";
- std::string title;
-
- DiscordRichPresence presence{};
if (system.IsPoweredOn()) {
- system.GetAppLoader().ReadTitle(title);
+ system.GetAppLoader().ReadTitle(game_title);
// Used to format Icon URL for yuzu website game compatibility page
- std::string icon_name = GetGameString(title);
-
- // New Check for game cover
- httplib::Client cli(game_cover_url);
- cli.set_connection_timeout(std::chrono::seconds(3));
- cli.set_read_timeout(std::chrono::seconds(3));
-
- if (auto res = cli.Head(fmt::format("/images/game/boxart/{}.png", icon_name))) {
- if (res->status == 200) {
- game_cover_url += fmt::format("/images/game/boxart/{}.png", icon_name);
- } else {
- game_cover_url = "yuzu_logo";
- }
- } else {
- game_cover_url = "yuzu_logo";
- }
-
- presence.largeImageKey = game_cover_url.c_str();
- presence.largeImageText = title.c_str();
-
- presence.smallImageKey = default_image.c_str();
- presence.smallImageText = default_text.c_str();
- presence.state = title.c_str();
- presence.details = "Currently in game";
- } else {
- presence.largeImageKey = default_image.c_str();
- presence.largeImageText = default_text.c_str();
- presence.details = "Currently not in game";
+ std::string icon_name = GetGameString(game_title);
+ game_url = fmt::format("https://yuzu-emu.org/images/game/boxart/{}.png", icon_name);
+
+ QNetworkAccessManager manager;
+ QNetworkRequest request;
+ request.setUrl(QUrl(QString::fromStdString(game_url)));
+ request.setTransferTimeout(3000);
+ QNetworkReply* reply = manager.head(request);
+ QEventLoop request_event_loop;
+ QObject::connect(reply, &QNetworkReply::finished, &request_event_loop, &QEventLoop::quit);
+ request_event_loop.exec();
+ UpdateGameStatus(reply->error());
+ return;
}
+ s64 start_time = std::chrono::duration_cast<std::chrono::seconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+
+ DiscordRichPresence presence{};
+ presence.largeImageKey = default_image.c_str();
+ presence.largeImageText = default_text.c_str();
+ presence.details = "Currently not in game";
presence.startTimestamp = start_time;
Discord_UpdatePresence(&presence);
}
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:
void Pause() override;
void Update() override;
+private:
+ std::string GetGameString(const std::string& title);
+ void UpdateGameStatus(bool use_default);
+
+ std::string game_url{};
+ std::string game_title{};
+
Core::System& system;
};
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) {
std::vector<u8> icon;
std::string name;
u64 program_id = 0;
- loader->ReadProgramId(program_id);
+ const auto result = loader->ReadProgramId(program_id);
+
+ if (result != Loader::ResultStatus::Success) {
+ continue;
+ }
const PatchManager patch{program_id, system.GetFileSystemController(),
system.GetContentProvider()};