summaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/CMakeLists.txt8
-rw-r--r--src/common/arm64/native_clock.cpp72
-rw-r--r--src/common/arm64/native_clock.h47
-rw-r--r--src/common/common_funcs.h4
-rw-r--r--src/common/elf.h8
-rw-r--r--src/common/fs/fs_paths.h2
-rw-r--r--src/common/fs/path_util.cpp2
-rw-r--r--src/common/fs/path_util.h2
-rw-r--r--src/common/polyfill_thread.h21
-rw-r--r--src/common/settings.cpp5
-rw-r--r--src/common/settings.h5
-rw-r--r--src/common/settings_enums.h2
-rw-r--r--src/common/string_util.cpp5
-rw-r--r--src/common/string_util.h1
-rw-r--r--src/common/wall_clock.cpp8
15 files changed, 181 insertions, 11 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 416203c59..8a1861051 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -189,6 +189,14 @@ if(ARCHITECTURE_x86_64)
target_link_libraries(common PRIVATE xbyak::xbyak)
endif()
+if (ARCHITECTURE_arm64 AND (ANDROID OR LINUX))
+ target_sources(common
+ PRIVATE
+ arm64/native_clock.cpp
+ arm64/native_clock.h
+ )
+endif()
+
if (MSVC)
target_compile_definitions(common PRIVATE
# The standard library doesn't provide any replacement for codecvt yet
diff --git a/src/common/arm64/native_clock.cpp b/src/common/arm64/native_clock.cpp
new file mode 100644
index 000000000..88fdba527
--- /dev/null
+++ b/src/common/arm64/native_clock.cpp
@@ -0,0 +1,72 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/arm64/native_clock.h"
+
+namespace Common::Arm64 {
+
+namespace {
+
+NativeClock::FactorType GetFixedPointFactor(u64 num, u64 den) {
+ return (static_cast<NativeClock::FactorType>(num) << 64) / den;
+}
+
+u64 MultiplyHigh(u64 m, NativeClock::FactorType factor) {
+ return static_cast<u64>((m * factor) >> 64);
+}
+
+} // namespace
+
+NativeClock::NativeClock() {
+ const u64 host_cntfrq = GetHostCNTFRQ();
+ ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq);
+ us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq);
+ ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq);
+ guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq);
+ gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq);
+}
+
+std::chrono::nanoseconds NativeClock::GetTimeNS() const {
+ return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_cntfrq_factor)};
+}
+
+std::chrono::microseconds NativeClock::GetTimeUS() const {
+ return std::chrono::microseconds{MultiplyHigh(GetHostTicksElapsed(), us_cntfrq_factor)};
+}
+
+std::chrono::milliseconds NativeClock::GetTimeMS() const {
+ return std::chrono::milliseconds{MultiplyHigh(GetHostTicksElapsed(), ms_cntfrq_factor)};
+}
+
+u64 NativeClock::GetCNTPCT() const {
+ return MultiplyHigh(GetHostTicksElapsed(), guest_cntfrq_factor);
+}
+
+u64 NativeClock::GetGPUTick() const {
+ return MultiplyHigh(GetHostTicksElapsed(), gputick_cntfrq_factor);
+}
+
+u64 NativeClock::GetHostTicksNow() const {
+ u64 cntvct_el0 = 0;
+ asm volatile("dsb ish\n\t"
+ "mrs %[cntvct_el0], cntvct_el0\n\t"
+ "dsb ish\n\t"
+ : [cntvct_el0] "=r"(cntvct_el0));
+ return cntvct_el0;
+}
+
+u64 NativeClock::GetHostTicksElapsed() const {
+ return GetHostTicksNow();
+}
+
+bool NativeClock::IsNative() const {
+ return true;
+}
+
+u64 NativeClock::GetHostCNTFRQ() {
+ u64 cntfrq_el0 = 0;
+ asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
+ return cntfrq_el0;
+}
+
+} // namespace Common::Arm64
diff --git a/src/common/arm64/native_clock.h b/src/common/arm64/native_clock.h
new file mode 100644
index 000000000..a28b419f2
--- /dev/null
+++ b/src/common/arm64/native_clock.h
@@ -0,0 +1,47 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/wall_clock.h"
+
+namespace Common::Arm64 {
+
+class NativeClock final : public WallClock {
+public:
+ explicit NativeClock();
+
+ std::chrono::nanoseconds GetTimeNS() const override;
+
+ std::chrono::microseconds GetTimeUS() const override;
+
+ std::chrono::milliseconds GetTimeMS() const override;
+
+ u64 GetCNTPCT() const override;
+
+ u64 GetGPUTick() const override;
+
+ u64 GetHostTicksNow() const override;
+
+ u64 GetHostTicksElapsed() const override;
+
+ bool IsNative() const override;
+
+ static u64 GetHostCNTFRQ();
+
+public:
+ using FactorType = unsigned __int128;
+
+ FactorType GetGuestCNTFRQFactor() const {
+ return guest_cntfrq_factor;
+ }
+
+private:
+ FactorType ns_cntfrq_factor;
+ FactorType us_cntfrq_factor;
+ FactorType ms_cntfrq_factor;
+ FactorType guest_cntfrq_factor;
+ FactorType gputick_cntfrq_factor;
+};
+
+} // namespace Common::Arm64
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index 0dad9338a..47d028d48 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -39,8 +39,12 @@
#define Crash() exit(1)
#endif
+#define LTO_NOINLINE __attribute__((noinline))
+
#else // _MSC_VER
+#define LTO_NOINLINE
+
// Locale Cross-Compatibility
#define locale_t _locale_t
diff --git a/src/common/elf.h b/src/common/elf.h
index 14a5e9597..0b728dc54 100644
--- a/src/common/elf.h
+++ b/src/common/elf.h
@@ -211,6 +211,11 @@ struct Elf64_Rela {
Elf64_Sxword r_addend; /* Addend */
};
+/* RELR relocation table entry */
+
+using Elf32_Relr = Elf32_Word;
+using Elf64_Relr = Elf64_Xword;
+
/* How to extract and insert information held in the r_info field. */
static inline u32 Elf32RelSymIndex(Elf32_Word r_info) {
@@ -328,6 +333,9 @@ constexpr u32 ElfDtFiniArray = 26; /* Array with addresses of fini fct */
constexpr u32 ElfDtInitArraySz = 27; /* Size in bytes of DT_INIT_ARRAY */
constexpr u32 ElfDtFiniArraySz = 28; /* Size in bytes of DT_FINI_ARRAY */
constexpr u32 ElfDtSymtabShndx = 34; /* Address of SYMTAB_SHNDX section */
+constexpr u32 ElfDtRelrsz = 35; /* Size of RELR relative relocations */
+constexpr u32 ElfDtRelr = 36; /* Address of RELR relative relocations */
+constexpr u32 ElfDtRelrent = 37; /* Size of one RELR relative relocation */
} // namespace ELF
} // namespace Common
diff --git a/src/common/fs/fs_paths.h b/src/common/fs/fs_paths.h
index 61bac9eba..441c8af97 100644
--- a/src/common/fs/fs_paths.h
+++ b/src/common/fs/fs_paths.h
@@ -18,10 +18,12 @@
#define LOAD_DIR "load"
#define LOG_DIR "log"
#define NAND_DIR "nand"
+#define PLAY_TIME_DIR "play_time"
#define SCREENSHOTS_DIR "screenshots"
#define SDMC_DIR "sdmc"
#define SHADER_DIR "shader"
#define TAS_DIR "tas"
+#define ICONS_DIR "icons"
// yuzu-specific files
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index dce219fcf..0abd81a45 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -124,10 +124,12 @@ public:
GenerateYuzuPath(YuzuPath::LoadDir, yuzu_path / LOAD_DIR);
GenerateYuzuPath(YuzuPath::LogDir, yuzu_path / LOG_DIR);
GenerateYuzuPath(YuzuPath::NANDDir, yuzu_path / NAND_DIR);
+ GenerateYuzuPath(YuzuPath::PlayTimeDir, yuzu_path / PLAY_TIME_DIR);
GenerateYuzuPath(YuzuPath::ScreenshotsDir, yuzu_path / SCREENSHOTS_DIR);
GenerateYuzuPath(YuzuPath::SDMCDir, yuzu_path / SDMC_DIR);
GenerateYuzuPath(YuzuPath::ShaderDir, yuzu_path / SHADER_DIR);
GenerateYuzuPath(YuzuPath::TASDir, yuzu_path / TAS_DIR);
+ GenerateYuzuPath(YuzuPath::IconsDir, yuzu_path / ICONS_DIR);
}
private:
diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h
index ba28964d0..63801c924 100644
--- a/src/common/fs/path_util.h
+++ b/src/common/fs/path_util.h
@@ -20,10 +20,12 @@ enum class YuzuPath {
LoadDir, // Where cheat/mod files are stored.
LogDir, // Where log files are stored.
NANDDir, // Where the emulated NAND is stored.
+ PlayTimeDir, // Where play time data is stored.
ScreenshotsDir, // Where yuzu screenshots are stored.
SDMCDir, // Where the emulated SDMC is stored.
ShaderDir, // Where shaders are stored.
TASDir, // Where TAS scripts are stored.
+ IconsDir, // Where Icons for Windows shortcuts are stored.
};
/**
diff --git a/src/common/polyfill_thread.h b/src/common/polyfill_thread.h
index 41cbb9ed5..12e59a893 100644
--- a/src/common/polyfill_thread.h
+++ b/src/common/polyfill_thread.h
@@ -15,12 +15,13 @@
#include <condition_variable>
#include <stop_token>
#include <thread>
+#include <utility>
namespace Common {
template <typename Condvar, typename Lock, typename Pred>
void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token, Pred&& pred) {
- cv.wait(lk, token, std::move(pred));
+ cv.wait(lk, token, std::forward<Pred>(pred));
}
template <typename Rep, typename Period>
@@ -109,7 +110,7 @@ public:
// Insert the callback.
stop_state_callback ret = ++m_next_callback;
- m_callbacks.emplace(ret, move(f));
+ m_callbacks.emplace(ret, std::move(f));
return ret;
}
@@ -162,7 +163,7 @@ private:
friend class stop_source;
template <typename Callback>
friend class stop_callback;
- stop_token(shared_ptr<polyfill::stop_state> stop_state) : m_stop_state(move(stop_state)) {}
+ stop_token(shared_ptr<polyfill::stop_state> stop_state) : m_stop_state(std::move(stop_state)) {}
private:
shared_ptr<polyfill::stop_state> m_stop_state;
@@ -198,7 +199,7 @@ public:
private:
friend class jthread;
explicit stop_source(shared_ptr<polyfill::stop_state> stop_state)
- : m_stop_state(move(stop_state)) {}
+ : m_stop_state(std::move(stop_state)) {}
private:
shared_ptr<polyfill::stop_state> m_stop_state;
@@ -218,16 +219,16 @@ public:
C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>)
: m_stop_state(st.m_stop_state) {
if (m_stop_state) {
- m_callback = m_stop_state->insert_callback(move(cb));
+ m_callback = m_stop_state->insert_callback(std::move(cb));
}
}
template <typename C>
requires constructible_from<Callback, C>
explicit stop_callback(stop_token&& st,
C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>)
- : m_stop_state(move(st.m_stop_state)) {
+ : m_stop_state(std::move(st.m_stop_state)) {
if (m_stop_state) {
- m_callback = m_stop_state->insert_callback(move(cb));
+ m_callback = m_stop_state->insert_callback(std::move(cb));
}
}
~stop_callback() {
@@ -260,7 +261,7 @@ public:
typename = enable_if_t<!is_same_v<remove_cvref_t<F>, jthread>>>
explicit jthread(F&& f, Args&&... args)
: m_stop_state(make_shared<polyfill::stop_state>()),
- m_thread(make_thread(move(f), move(args)...)) {}
+ m_thread(make_thread(std::forward<F>(f), std::forward<Args>(args)...)) {}
~jthread() {
if (joinable()) {
@@ -317,9 +318,9 @@ private:
template <typename F, typename... Args>
thread make_thread(F&& f, Args&&... args) {
if constexpr (is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>) {
- return thread(move(f), get_stop_token(), move(args)...);
+ return thread(std::forward<F>(f), get_stop_token(), std::forward<Args>(args)...);
} else {
- return thread(move(f), move(args)...);
+ return thread(std::forward<F>(f), std::forward<Args>(args)...);
}
}
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 3fde3cae6..98b43e49c 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -45,6 +45,7 @@ SWITCHABLE(CpuAccuracy, true);
SWITCHABLE(FullscreenMode, true);
SWITCHABLE(GpuAccuracy, true);
SWITCHABLE(Language, true);
+SWITCHABLE(MemoryLayout, true);
SWITCHABLE(NvdecEmulation, false);
SWITCHABLE(Region, true);
SWITCHABLE(RendererBackend, true);
@@ -61,6 +62,10 @@ SWITCHABLE(u32, false);
SWITCHABLE(u8, false);
SWITCHABLE(u8, true);
+// Used in UISettings
+// TODO see if we can move this to uisettings.cpp
+SWITCHABLE(ConfirmStop, true);
+
#undef SETTING
#undef SWITCHABLE
#endif
diff --git a/src/common/settings.h b/src/common/settings.h
index 98ab0ec2e..236e33bee 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -67,6 +67,7 @@ SWITCHABLE(CpuAccuracy, true);
SWITCHABLE(FullscreenMode, true);
SWITCHABLE(GpuAccuracy, true);
SWITCHABLE(Language, true);
+SWITCHABLE(MemoryLayout, true);
SWITCHABLE(NvdecEmulation, false);
SWITCHABLE(Region, true);
SWITCHABLE(RendererBackend, true);
@@ -83,6 +84,10 @@ SWITCHABLE(u32, false);
SWITCHABLE(u8, false);
SWITCHABLE(u8, true);
+// Used in UISettings
+// TODO see if we can move this to uisettings.h
+SWITCHABLE(ConfirmStop, true);
+
#undef SETTING
#undef SWITCHABLE
#endif
diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h
index 815cafe15..11429d7a8 100644
--- a/src/common/settings_enums.h
+++ b/src/common/settings_enums.h
@@ -133,6 +133,8 @@ ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid);
ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb);
+ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never);
+
ENUM(FullscreenMode, Borderless, Exclusive);
ENUM(NvdecEmulation, Off, Cpu, Gpu);
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index feab1653d..4c7aba3f5 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -135,6 +135,11 @@ std::u16string UTF8ToUTF16(std::string_view input) {
return convert.from_bytes(input.data(), input.data() + input.size());
}
+std::u32string UTF8ToUTF32(std::string_view input) {
+ std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
+ return convert.from_bytes(input.data(), input.data() + input.size());
+}
+
#ifdef _WIN32
static std::wstring CPToUTF16(u32 code_page, std::string_view input) {
const auto size =
diff --git a/src/common/string_util.h b/src/common/string_util.h
index c351f1a0c..9da1ca4e9 100644
--- a/src/common/string_util.h
+++ b/src/common/string_util.h
@@ -38,6 +38,7 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
[[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input);
[[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input);
+[[nodiscard]] std::u32string UTF8ToUTF32(std::string_view input);
#ifdef _WIN32
[[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input);
diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp
index 71e15ab4c..caca9a123 100644
--- a/src/common/wall_clock.cpp
+++ b/src/common/wall_clock.cpp
@@ -10,6 +10,10 @@
#include "common/x64/rdtsc.h"
#endif
+#if defined(ARCHITECTURE_arm64) && defined(__linux__)
+#include "common/arm64/native_clock.h"
+#endif
+
namespace Common {
class StandardWallClock final : public WallClock {
@@ -53,7 +57,7 @@ private:
};
std::unique_ptr<WallClock> CreateOptimalClock() {
-#ifdef ARCHITECTURE_x86_64
+#if defined(ARCHITECTURE_x86_64)
const auto& caps = GetCPUCaps();
if (caps.invariant_tsc && caps.tsc_frequency >= std::nano::den) {
@@ -64,6 +68,8 @@ std::unique_ptr<WallClock> CreateOptimalClock() {
// - Is not more precise than 1 GHz (1ns resolution)
return std::make_unique<StandardWallClock>();
}
+#elif defined(ARCHITECTURE_arm64) && defined(__linux__)
+ return std::make_unique<Arm64::NativeClock>();
#else
return std::make_unique<StandardWallClock>();
#endif