mirror of
https://github.com/PabloMK7/citra.git
synced 2024-12-28 02:26:13 +00:00
misc: fix issues pointed out by msvc (#7316)
* do not move constant variables
* applet_manager: avoid possible use after move
* use constant references where pointed out by msvc
* extra_hid: initialize response
* ValidateSaveState: passing slot separately is not necessary
* common: mark HashCombine as nodiscard
* cityhash: remove use of using namespace std
* Prefix all size_t with std::
done automatically by executing regex replace `([^:0-9a-zA-Z_])size_t([^0-9a-zA-Z_])` -> `$1std::size_t$2`
based on 7d8f115
* shared_memory.cpp: fix log error format
* fix compiling with pch off
This commit is contained in:
parent
6069fac76d
commit
c8c2beaeff
|
@ -81,8 +81,8 @@ jstring Java_org_citra_citra_1emu_model_GameInfo_getTitle(JNIEnv* env, jobject o
|
||||||
Loader::SMDH::TitleLanguage language = Loader::SMDH::TitleLanguage::English;
|
Loader::SMDH::TitleLanguage language = Loader::SMDH::TitleLanguage::English;
|
||||||
|
|
||||||
// Get the title from SMDH in UTF-16 format
|
// Get the title from SMDH in UTF-16 format
|
||||||
std::u16string title{
|
std::u16string title{reinterpret_cast<char16_t*>(
|
||||||
reinterpret_cast<char16_t*>(smdh->titles[static_cast<size_t>(language)].long_title.data())};
|
smdh->titles[static_cast<std::size_t>(language)].long_title.data())};
|
||||||
|
|
||||||
return ToJString(env, Common::UTF16ToUTF8(title).data());
|
return ToJString(env, Common::UTF16ToUTF8(title).data());
|
||||||
}
|
}
|
||||||
|
@ -93,8 +93,8 @@ jstring Java_org_citra_citra_1emu_model_GameInfo_getCompany(JNIEnv* env, jobject
|
||||||
|
|
||||||
// Get the Publisher's name from SMDH in UTF-16 format
|
// Get the Publisher's name from SMDH in UTF-16 format
|
||||||
char16_t* publisher;
|
char16_t* publisher;
|
||||||
publisher =
|
publisher = reinterpret_cast<char16_t*>(
|
||||||
reinterpret_cast<char16_t*>(smdh->titles[static_cast<size_t>(language)].publisher.data());
|
smdh->titles[static_cast<std::size_t>(language)].publisher.data());
|
||||||
|
|
||||||
return ToJString(env, Common::UTF16ToUTF8(publisher).data());
|
return ToJString(env, Common::UTF16ToUTF8(publisher).data());
|
||||||
}
|
}
|
||||||
|
|
|
@ -661,8 +661,8 @@ void Java_org_citra_citra_1emu_NativeLibrary_removeAmiibo([[maybe_unused]] JNIEn
|
||||||
JNIEXPORT jobject JNICALL Java_org_citra_citra_1emu_utils_CiaInstallWorker_installCIA(
|
JNIEXPORT jobject JNICALL Java_org_citra_citra_1emu_utils_CiaInstallWorker_installCIA(
|
||||||
JNIEnv* env, jobject jobj, jstring jpath) {
|
JNIEnv* env, jobject jobj, jstring jpath) {
|
||||||
std::string path = GetJString(env, jpath);
|
std::string path = GetJString(env, jpath);
|
||||||
Service::AM::InstallStatus res =
|
Service::AM::InstallStatus res = Service::AM::InstallCIA(
|
||||||
Service::AM::InstallCIA(path, [env, jobj](size_t total_bytes_read, size_t file_size) {
|
path, [env, jobj](std::size_t total_bytes_read, std::size_t file_size) {
|
||||||
env->CallVoidMethod(jobj, IDCache::GetCiaInstallHelperSetProgress(),
|
env->CallVoidMethod(jobj, IDCache::GetCiaInstallHelperSetProgress(),
|
||||||
static_cast<jint>(file_size), static_cast<jint>(total_bytes_read));
|
static_cast<jint>(file_size), static_cast<jint>(total_bytes_read));
|
||||||
});
|
});
|
||||||
|
|
|
@ -148,7 +148,7 @@ ALsizei OpenALSink::Impl::Callback(void* impl_, void* buffer, ALsizei buffer_siz
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t num_frames = buffer_size_in_bytes / (2 * sizeof(s16));
|
const std::size_t num_frames = buffer_size_in_bytes / (2 * sizeof(s16));
|
||||||
impl->cb(reinterpret_cast<s16*>(buffer), num_frames);
|
impl->cb(reinterpret_cast<s16*>(buffer), num_frames);
|
||||||
|
|
||||||
return buffer_size_in_bytes;
|
return buffer_size_in_bytes;
|
||||||
|
|
|
@ -83,7 +83,7 @@ void SDL2Sink::Impl::Callback(void* impl_, u8* buffer, int buffer_size_in_bytes)
|
||||||
if (!impl || !impl->cb)
|
if (!impl || !impl->cb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const size_t num_frames = buffer_size_in_bytes / (2 * sizeof(s16));
|
const std::size_t num_frames = buffer_size_in_bytes / (2 * sizeof(s16));
|
||||||
|
|
||||||
impl->cb(reinterpret_cast<s16*>(buffer), num_frames);
|
impl->cb(reinterpret_cast<s16*>(buffer), num_frames);
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,7 +236,7 @@ void Config::ReadValues() {
|
||||||
std::string offset_string =
|
std::string offset_string =
|
||||||
sdl2_config->GetString("System", "init_time_offset", default_init_time_offset);
|
sdl2_config->GetString("System", "init_time_offset", default_init_time_offset);
|
||||||
|
|
||||||
size_t sep_index = offset_string.find(' ');
|
std::size_t sep_index = offset_string.find(' ');
|
||||||
|
|
||||||
if (sep_index == std::string::npos) {
|
if (sep_index == std::string::npos) {
|
||||||
LOG_ERROR(Config, "Failed to parse init_time_offset. Using 0 00:00:00");
|
LOG_ERROR(Config, "Failed to parse init_time_offset. Using 0 00:00:00");
|
||||||
|
|
|
@ -25,7 +25,7 @@ bool QtImageInterface::DecodePNG(std::vector<u8>& dst, u32& width, u32& height,
|
||||||
image = image.convertToFormat(QImage::Format_RGBA8888);
|
image = image.convertToFormat(QImage::Format_RGBA8888);
|
||||||
|
|
||||||
// Write RGBA8 to vector
|
// Write RGBA8 to vector
|
||||||
const size_t image_size = width * height * 4;
|
const std::size_t image_size = width * height * 4;
|
||||||
dst.resize(image_size);
|
dst.resize(image_size);
|
||||||
std::memcpy(dst.data(), image.constBits(), image_size);
|
std::memcpy(dst.data(), image.constBits(), image_size);
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace Common {
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
static std::string GetCPUString() {
|
static std::string GetCPUString() {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
size_t buf_len = sizeof(buf);
|
std::size_t buf_len = sizeof(buf);
|
||||||
if (sysctlbyname("machdep.cpu.brand_string", &buf, &buf_len, NULL, 0) == -1) {
|
if (sysctlbyname("machdep.cpu.brand_string", &buf, &buf_len, NULL, 0) == -1) {
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,15 +63,15 @@ struct ABIFrameInfo {
|
||||||
};
|
};
|
||||||
|
|
||||||
inline ABIFrameInfo ABI_CalculateFrameSize(std::bitset<64> regs, std::size_t frame_size) {
|
inline ABIFrameInfo ABI_CalculateFrameSize(std::bitset<64> regs, std::size_t frame_size) {
|
||||||
const size_t gprs_count = (regs & ABI_ALL_GPRS).count();
|
const std::size_t gprs_count = (regs & ABI_ALL_GPRS).count();
|
||||||
const size_t fprs_count = (regs & ABI_ALL_FPRS).count();
|
const std::size_t fprs_count = (regs & ABI_ALL_FPRS).count();
|
||||||
|
|
||||||
const size_t gprs_size = (gprs_count + 1) / 2 * 16;
|
const std::size_t gprs_size = (gprs_count + 1) / 2 * 16;
|
||||||
const size_t fprs_size = fprs_count * 16;
|
const std::size_t fprs_size = fprs_count * 16;
|
||||||
|
|
||||||
size_t total_size = 0;
|
std::size_t total_size = 0;
|
||||||
total_size += gprs_size;
|
total_size += gprs_size;
|
||||||
const size_t fprs_base_subtraction = total_size;
|
const std::size_t fprs_base_subtraction = total_size;
|
||||||
total_size += fprs_size;
|
total_size += fprs_size;
|
||||||
total_size += frame_size;
|
total_size += frame_size;
|
||||||
|
|
||||||
|
@ -100,11 +100,11 @@ inline void ABI_PushRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gprs.empty()) {
|
if (!gprs.empty()) {
|
||||||
for (size_t i = 0; i < gprs.size() - 1; i += 2) {
|
for (std::size_t i = 0; i < gprs.size() - 1; i += 2) {
|
||||||
code.STP(gprs[i], gprs[i + 1], SP, i * sizeof(u64));
|
code.STP(gprs[i], gprs[i + 1], SP, i * sizeof(u64));
|
||||||
}
|
}
|
||||||
if (gprs.size() % 2 == 1) {
|
if (gprs.size() % 2 == 1) {
|
||||||
const size_t i = gprs.size() - 1;
|
const std::size_t i = gprs.size() - 1;
|
||||||
code.STR(gprs[i], SP, i * sizeof(u64));
|
code.STR(gprs[i], SP, i * sizeof(u64));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,11 +121,11 @@ inline void ABI_PushRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fprs.empty()) {
|
if (!fprs.empty()) {
|
||||||
for (size_t i = 0; i < fprs.size() - 1; i += 2) {
|
for (std::size_t i = 0; i < fprs.size() - 1; i += 2) {
|
||||||
code.STP(fprs[i], fprs[i + 1], SP, frame_info.fprs_offset + i * (sizeof(u64) * 2));
|
code.STP(fprs[i], fprs[i + 1], SP, frame_info.fprs_offset + i * (sizeof(u64) * 2));
|
||||||
}
|
}
|
||||||
if (fprs.size() % 2 == 1) {
|
if (fprs.size() % 2 == 1) {
|
||||||
const size_t i = fprs.size() - 1;
|
const std::size_t i = fprs.size() - 1;
|
||||||
code.STR(fprs[i], SP, frame_info.fprs_offset + i * (sizeof(u64) * 2));
|
code.STR(fprs[i], SP, frame_info.fprs_offset + i * (sizeof(u64) * 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,11 +159,11 @@ inline void ABI_PopRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gprs.empty()) {
|
if (!gprs.empty()) {
|
||||||
for (size_t i = 0; i < gprs.size() - 1; i += 2) {
|
for (std::size_t i = 0; i < gprs.size() - 1; i += 2) {
|
||||||
code.LDP(gprs[i], gprs[i + 1], SP, i * sizeof(u64));
|
code.LDP(gprs[i], gprs[i + 1], SP, i * sizeof(u64));
|
||||||
}
|
}
|
||||||
if (gprs.size() % 2 == 1) {
|
if (gprs.size() % 2 == 1) {
|
||||||
const size_t i = gprs.size() - 1;
|
const std::size_t i = gprs.size() - 1;
|
||||||
code.LDR(gprs[i], SP, i * sizeof(u64));
|
code.LDR(gprs[i], SP, i * sizeof(u64));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,11 +180,11 @@ inline void ABI_PopRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fprs.empty()) {
|
if (!fprs.empty()) {
|
||||||
for (size_t i = 0; i < fprs.size() - 1; i += 2) {
|
for (std::size_t i = 0; i < fprs.size() - 1; i += 2) {
|
||||||
code.LDP(fprs[i], fprs[i + 1], SP, frame_info.fprs_offset + i * (sizeof(u64) * 2));
|
code.LDP(fprs[i], fprs[i + 1], SP, frame_info.fprs_offset + i * (sizeof(u64) * 2));
|
||||||
}
|
}
|
||||||
if (fprs.size() % 2 == 1) {
|
if (fprs.size() % 2 == 1) {
|
||||||
const size_t i = fprs.size() - 1;
|
const std::size_t i = fprs.size() - 1;
|
||||||
code.LDR(fprs[i], SP, frame_info.fprs_offset + i * (sizeof(u64) * 2));
|
code.LDR(fprs[i], SP, frame_info.fprs_offset + i * (sizeof(u64) * 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,10 @@
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
constexpr size_t DefaultCapacity = 0x1000;
|
constexpr std::size_t DefaultCapacity = 0x1000;
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename T, size_t Capacity = detail::DefaultCapacity>
|
template <typename T, std::size_t Capacity = detail::DefaultCapacity>
|
||||||
class SPSCQueue {
|
class SPSCQueue {
|
||||||
static_assert((Capacity & (Capacity - 1)) == 0, "Capacity must be a power of two.");
|
static_assert((Capacity & (Capacity - 1)) == 0, "Capacity must be a power of two.");
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ private:
|
||||||
|
|
||||||
template <PushMode Mode, typename... Args>
|
template <PushMode Mode, typename... Args>
|
||||||
bool Emplace(Args&&... args) {
|
bool Emplace(Args&&... args) {
|
||||||
const size_t write_index = m_write_index.load(std::memory_order::relaxed);
|
const std::size_t write_index = m_write_index.load(std::memory_order::relaxed);
|
||||||
|
|
||||||
if constexpr (Mode == PushMode::Try) {
|
if constexpr (Mode == PushMode::Try) {
|
||||||
// Check if we have free slots to write to.
|
// Check if we have free slots to write to.
|
||||||
|
@ -92,7 +92,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the position to write to.
|
// Determine the position to write to.
|
||||||
const size_t pos = write_index % Capacity;
|
const std::size_t pos = write_index % Capacity;
|
||||||
|
|
||||||
// Emplace into the queue.
|
// Emplace into the queue.
|
||||||
new (std::addressof(m_data[pos])) T(std::forward<Args>(args)...);
|
new (std::addressof(m_data[pos])) T(std::forward<Args>(args)...);
|
||||||
|
@ -109,7 +109,7 @@ private:
|
||||||
|
|
||||||
template <PopMode Mode>
|
template <PopMode Mode>
|
||||||
bool Pop(T& t, [[maybe_unused]] std::stop_token stop_token = {}) {
|
bool Pop(T& t, [[maybe_unused]] std::stop_token stop_token = {}) {
|
||||||
const size_t read_index = m_read_index.load(std::memory_order::relaxed);
|
const std::size_t read_index = m_read_index.load(std::memory_order::relaxed);
|
||||||
|
|
||||||
if constexpr (Mode == PopMode::Try) {
|
if constexpr (Mode == PopMode::Try) {
|
||||||
// Check if the queue is empty.
|
// Check if the queue is empty.
|
||||||
|
@ -136,7 +136,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the position to read from.
|
// Determine the position to read from.
|
||||||
const size_t pos = read_index % Capacity;
|
const std::size_t pos = read_index % Capacity;
|
||||||
|
|
||||||
// Pop the data off the queue, moving it.
|
// Pop the data off the queue, moving it.
|
||||||
t = std::move(m_data[pos]);
|
t = std::move(m_data[pos]);
|
||||||
|
@ -162,7 +162,7 @@ private:
|
||||||
std::mutex consumer_cv_mutex;
|
std::mutex consumer_cv_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, size_t Capacity = detail::DefaultCapacity>
|
template <typename T, std::size_t Capacity = detail::DefaultCapacity>
|
||||||
class MPSCQueue {
|
class MPSCQueue {
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
|
@ -202,7 +202,7 @@ private:
|
||||||
std::mutex write_mutex;
|
std::mutex write_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, size_t Capacity = detail::DefaultCapacity>
|
template <typename T, std::size_t Capacity = detail::DefaultCapacity>
|
||||||
class MPMCQueue {
|
class MPMCQueue {
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
|
|
|
@ -40,11 +40,9 @@
|
||||||
#define WORDS_BIGENDIAN 1
|
#define WORDS_BIGENDIAN 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
typedef std::uint8_t uint8;
|
||||||
|
typedef std::uint32_t uint32;
|
||||||
typedef uint8_t uint8;
|
typedef std::uint64_t uint64;
|
||||||
typedef uint32_t uint32;
|
|
||||||
typedef uint64_t uint64;
|
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
|
@ -152,19 +150,19 @@ static uint64 HashLen17to32(const char* s, std::size_t len) {
|
||||||
|
|
||||||
// Return a 16-byte hash for 48 bytes. Quick and dirty.
|
// Return a 16-byte hash for 48 bytes. Quick and dirty.
|
||||||
// Callers do best to use "random-looking" values for a and b.
|
// Callers do best to use "random-looking" values for a and b.
|
||||||
static pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w, uint64 x, uint64 y, uint64 z, uint64 a,
|
static std::pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w, uint64 x, uint64 y, uint64 z,
|
||||||
uint64 b) {
|
uint64 a, uint64 b) {
|
||||||
a += w;
|
a += w;
|
||||||
b = Rotate(b + a + z, 21);
|
b = Rotate(b + a + z, 21);
|
||||||
uint64 c = a;
|
uint64 c = a;
|
||||||
a += x;
|
a += x;
|
||||||
a += y;
|
a += y;
|
||||||
b += Rotate(a, 44);
|
b += Rotate(a, 44);
|
||||||
return make_pair(a + z, b + c);
|
return std::make_pair(a + z, b + c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
|
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
|
||||||
static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, uint64 a, uint64 b) {
|
static std::pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, uint64 a, uint64 b) {
|
||||||
return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a,
|
return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a,
|
||||||
b);
|
b);
|
||||||
}
|
}
|
||||||
|
@ -207,8 +205,8 @@ uint64 CityHash64(const char* s, std::size_t len) {
|
||||||
uint64 x = Fetch64(s + len - 40);
|
uint64 x = Fetch64(s + len - 40);
|
||||||
uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
|
uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
|
||||||
uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
|
uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
|
||||||
pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
|
std::pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
|
||||||
pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
|
std::pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
|
||||||
x = x * k1 + Fetch64(s);
|
x = x * k1 + Fetch64(s);
|
||||||
|
|
||||||
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
|
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
|
||||||
|
@ -276,7 +274,7 @@ uint128 CityHash128WithSeed(const char* s, std::size_t len, uint128 seed) {
|
||||||
|
|
||||||
// We expect len >= 128 to be the common case. Keep 56 bytes of state:
|
// We expect len >= 128 to be the common case. Keep 56 bytes of state:
|
||||||
// v, w, x, y, and z.
|
// v, w, x, y, and z.
|
||||||
pair<uint64, uint64> v, w;
|
std::pair<uint64, uint64> v, w;
|
||||||
uint64 x = Uint128Low64(seed);
|
uint64 x = Uint128Low64(seed);
|
||||||
uint64 y = Uint128High64(seed);
|
uint64 y = Uint128High64(seed);
|
||||||
uint64 z = len * k1;
|
uint64 z = len * k1;
|
||||||
|
|
|
@ -38,7 +38,7 @@ bool DynamicLibrary::Load(std::string_view filename) {
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
DWORD error_message_id = GetLastError();
|
DWORD error_message_id = GetLastError();
|
||||||
LPSTR message_buffer = nullptr;
|
LPSTR message_buffer = nullptr;
|
||||||
size_t size =
|
std::size_t size =
|
||||||
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
nullptr, error_message_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
nullptr, error_message_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
|
|
@ -1159,7 +1159,7 @@ std::size_t IOFile::ReadImpl(void* data, std::size_t length, std::size_t data_si
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static std::size_t pread(int fd, void* buf, size_t count, uint64_t offset) {
|
static std::size_t pread(int fd, void* buf, std::size_t count, uint64_t offset) {
|
||||||
long unsigned int read_bytes = 0;
|
long unsigned int read_bytes = 0;
|
||||||
OVERLAPPED overlapped = {0};
|
OVERLAPPED overlapped = {0};
|
||||||
HANDLE file = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
HANDLE file = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
||||||
|
|
|
@ -37,7 +37,7 @@ static inline u64 ComputeStructHash64(const T& data) noexcept {
|
||||||
* Combines the seed parameter with the provided hash, producing a new unique hash
|
* Combines the seed parameter with the provided hash, producing a new unique hash
|
||||||
* Implementation from: http://boost.sourceforge.net/doc/html/boost/hash_combine.html
|
* Implementation from: http://boost.sourceforge.net/doc/html/boost/hash_combine.html
|
||||||
*/
|
*/
|
||||||
inline u64 HashCombine(const u64 seed, const u64 hash) {
|
[[nodiscard]] inline u64 HashCombine(const u64 seed, const u64 hash) {
|
||||||
return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2));
|
return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred&& pred) {
|
||||||
namespace std {
|
namespace std {
|
||||||
namespace polyfill {
|
namespace polyfill {
|
||||||
|
|
||||||
using stop_state_callback = size_t;
|
using stop_state_callback = std::size_t;
|
||||||
|
|
||||||
class stop_state {
|
class stop_state {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -31,9 +31,9 @@ template <class T>
|
||||||
class SlotVector {
|
class SlotVector {
|
||||||
public:
|
public:
|
||||||
~SlotVector() noexcept {
|
~SlotVector() noexcept {
|
||||||
size_t index = 0;
|
std::size_t index = 0;
|
||||||
for (u64 bits : stored_bitset) {
|
for (u64 bits : stored_bitset) {
|
||||||
for (size_t bit = 0; bits; ++bit, bits >>= 1) {
|
for (std::size_t bit = 0; bits; ++bit, bits >>= 1) {
|
||||||
if ((bits & 1) != 0) {
|
if ((bits & 1) != 0) {
|
||||||
values[index + bit].object.~T();
|
values[index + bit].object.~T();
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ public:
|
||||||
ResetStorageBit(id.index);
|
ResetStorageBit(id.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const noexcept {
|
std::size_t size() const noexcept {
|
||||||
return values_capacity - free_list.size();
|
return values_capacity - free_list.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,12 +126,12 @@ private:
|
||||||
return free_index;
|
return free_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reserve(size_t new_capacity) noexcept {
|
void Reserve(std::size_t new_capacity) noexcept {
|
||||||
Entry* const new_values = new Entry[new_capacity];
|
Entry* const new_values = new Entry[new_capacity];
|
||||||
size_t index = 0;
|
std::size_t index = 0;
|
||||||
for (u64 bits : stored_bitset) {
|
for (u64 bits : stored_bitset) {
|
||||||
for (size_t bit = 0; bits; ++bit, bits >>= 1) {
|
for (std::size_t bit = 0; bits; ++bit, bits >>= 1) {
|
||||||
const size_t i = index + bit;
|
const std::size_t i = index + bit;
|
||||||
if ((bits & 1) == 0) {
|
if ((bits & 1) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ private:
|
||||||
|
|
||||||
stored_bitset.resize((new_capacity + 63) / 64);
|
stored_bitset.resize((new_capacity + 63) / 64);
|
||||||
|
|
||||||
const size_t old_free_size = free_list.size();
|
const std::size_t old_free_size = free_list.size();
|
||||||
free_list.resize(old_free_size + (new_capacity - values_capacity));
|
free_list.resize(old_free_size + (new_capacity - values_capacity));
|
||||||
std::iota(free_list.begin() + old_free_size, free_list.end(),
|
std::iota(free_list.begin() + old_free_size, free_list.end(),
|
||||||
static_cast<u32>(values_capacity));
|
static_cast<u32>(values_capacity));
|
||||||
|
@ -155,7 +155,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry* values = nullptr;
|
Entry* values = nullptr;
|
||||||
size_t values_capacity = 0;
|
std::size_t values_capacity = 0;
|
||||||
|
|
||||||
std::vector<u64> stored_bitset;
|
std::vector<u64> stored_bitset;
|
||||||
std::vector<u32> free_list;
|
std::vector<u32> free_list;
|
||||||
|
@ -165,7 +165,7 @@ private:
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct std::hash<Common::SlotId> {
|
struct std::hash<Common::SlotId> {
|
||||||
size_t operator()(const Common::SlotId& id) const noexcept {
|
std::size_t operator()(const Common::SlotId& id) const noexcept {
|
||||||
return std::hash<u32>{}(id.index);
|
return std::hash<u32>{}(id.index);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,23 +23,23 @@ namespace Common {
|
||||||
|
|
||||||
// a cache which evicts the least recently used item when it is full
|
// a cache which evicts the least recently used item when it is full
|
||||||
// the cache elements are statically allocated.
|
// the cache elements are statically allocated.
|
||||||
template <class Key, class Value, size_t Size>
|
template <class Key, class Value, std::size_t Size>
|
||||||
class StaticLRUCache {
|
class StaticLRUCache {
|
||||||
public:
|
public:
|
||||||
using key_type = Key;
|
using key_type = Key;
|
||||||
using value_type = Value;
|
using value_type = Value;
|
||||||
using list_type = std::list<std::pair<Key, size_t>>;
|
using list_type = std::list<std::pair<Key, std::size_t>>;
|
||||||
using array_type = std::array<Value, Size>;
|
using array_type = std::array<Value, Size>;
|
||||||
|
|
||||||
StaticLRUCache() = default;
|
StaticLRUCache() = default;
|
||||||
|
|
||||||
~StaticLRUCache() = default;
|
~StaticLRUCache() = default;
|
||||||
|
|
||||||
size_t size() const {
|
std::size_t size() const {
|
||||||
return m_list.size();
|
return m_list.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_t capacity() const {
|
constexpr std::size_t capacity() const {
|
||||||
return m_array.size();
|
return m_array.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ public:
|
||||||
// lookup value in the cache
|
// lookup value in the cache
|
||||||
auto i = find(key);
|
auto i = find(key);
|
||||||
if (i == m_list.cend()) {
|
if (i == m_list.cend()) {
|
||||||
size_t next_index = size();
|
std::size_t next_index = size();
|
||||||
// insert item into the cache, but first check if it is full
|
// insert item into the cache, but first check if it is full
|
||||||
if (next_index >= capacity()) {
|
if (next_index >= capacity()) {
|
||||||
// cache is full, evict the least recently used item
|
// cache is full, evict the least recently used item
|
||||||
|
@ -97,10 +97,10 @@ private:
|
||||||
[&key](const auto& el) { return el.first == key; });
|
[&key](const auto& el) { return el.first == key; });
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t evict() {
|
std::size_t evict() {
|
||||||
// evict item from the end of most recently used list
|
// evict item from the end of most recently used list
|
||||||
typename list_type::iterator i = --m_list.end();
|
typename list_type::iterator i = --m_list.end();
|
||||||
size_t evicted_index = i->second;
|
std::size_t evicted_index = i->second;
|
||||||
m_list.erase(i);
|
m_list.erase(i);
|
||||||
return evicted_index;
|
return evicted_index;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
template <size_t N>
|
template <std::size_t N>
|
||||||
struct StringLiteral {
|
struct StringLiteral {
|
||||||
constexpr StringLiteral(const char (&str)[N]) {
|
constexpr StringLiteral(const char (&str)[N]) {
|
||||||
std::copy_n(str, N, value);
|
std::copy_n(str, N, value);
|
||||||
|
|
|
@ -101,7 +101,7 @@ void SetCurrentThreadName(const char* name) {
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
// Linux limits thread names to 15 characters and will outright reject any
|
// Linux limits thread names to 15 characters and will outright reject any
|
||||||
// attempt to set a longer name with ERANGE.
|
// attempt to set a longer name with ERANGE.
|
||||||
std::string truncated(name, std::min(strlen(name), static_cast<size_t>(15)));
|
std::string truncated(name, std::min(strlen(name), static_cast<std::size_t>(15)));
|
||||||
if (int e = pthread_setname_np(pthread_self(), truncated.c_str())) {
|
if (int e = pthread_setname_np(pthread_self(), truncated.c_str())) {
|
||||||
errno = e;
|
errno = e;
|
||||||
LOG_ERROR(Common, "Failed to set thread name to '{}': {}", truncated, GetLastErrorMsg());
|
LOG_ERROR(Common, "Failed to set thread name to '{}': {}", truncated, GetLastErrorMsg());
|
||||||
|
|
|
@ -25,7 +25,7 @@ class StatefulThreadWorker {
|
||||||
static constexpr bool with_state = !std::is_same_v<StateType, void>;
|
static constexpr bool with_state = !std::is_same_v<StateType, void>;
|
||||||
|
|
||||||
struct DummyCallable {
|
struct DummyCallable {
|
||||||
int operator()(size_t) const noexcept {
|
int operator()(std::size_t) const noexcept {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -33,12 +33,13 @@ class StatefulThreadWorker {
|
||||||
using Task =
|
using Task =
|
||||||
std::conditional_t<with_state, UniqueFunction<void, StateType*>, UniqueFunction<void>>;
|
std::conditional_t<with_state, UniqueFunction<void, StateType*>, UniqueFunction<void>>;
|
||||||
using StateMaker =
|
using StateMaker =
|
||||||
std::conditional_t<with_state, std::function<StateType(size_t)>, DummyCallable>;
|
std::conditional_t<with_state, std::function<StateType(std::size_t)>, DummyCallable>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit StatefulThreadWorker(size_t num_workers, std::string_view name, StateMaker func = {})
|
explicit StatefulThreadWorker(std::size_t num_workers, std::string_view name,
|
||||||
|
StateMaker func = {})
|
||||||
: workers_queued{num_workers}, thread_name{name} {
|
: workers_queued{num_workers}, thread_name{name} {
|
||||||
const auto lambda = [this, func](std::stop_token stop_token, size_t index) {
|
const auto lambda = [this, func](std::stop_token stop_token, std::size_t index) {
|
||||||
Common::SetCurrentThreadName(thread_name.data());
|
Common::SetCurrentThreadName(thread_name.data());
|
||||||
{
|
{
|
||||||
[[maybe_unused]] std::conditional_t<with_state, StateType, int> state{func(index)};
|
[[maybe_unused]] std::conditional_t<with_state, StateType, int> state{func(index)};
|
||||||
|
@ -69,7 +70,7 @@ public:
|
||||||
wait_condition.notify_all();
|
wait_condition.notify_all();
|
||||||
};
|
};
|
||||||
threads.reserve(num_workers);
|
threads.reserve(num_workers);
|
||||||
for (size_t i = 0; i < num_workers; ++i) {
|
for (std::size_t i = 0; i < num_workers; ++i) {
|
||||||
threads.emplace_back(lambda, i);
|
threads.emplace_back(lambda, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,10 +111,10 @@ private:
|
||||||
std::mutex queue_mutex;
|
std::mutex queue_mutex;
|
||||||
std::condition_variable_any condition;
|
std::condition_variable_any condition;
|
||||||
std::condition_variable wait_condition;
|
std::condition_variable wait_condition;
|
||||||
std::atomic<size_t> work_scheduled{};
|
std::atomic<std::size_t> work_scheduled{};
|
||||||
std::atomic<size_t> work_done{};
|
std::atomic<std::size_t> work_done{};
|
||||||
std::atomic<size_t> workers_stopped{};
|
std::atomic<std::size_t> workers_stopped{};
|
||||||
std::atomic<size_t> workers_queued{};
|
std::atomic<std::size_t> workers_queued{};
|
||||||
std::string_view thread_name;
|
std::string_view thread_name;
|
||||||
std::vector<std::jthread> threads;
|
std::vector<std::jthread> threads;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,8 +13,8 @@ namespace {
|
||||||
template <Common::StringLiteral haystack, Common::StringLiteral needle>
|
template <Common::StringLiteral haystack, Common::StringLiteral needle>
|
||||||
constexpr u32 GetMatchingBitsFromStringLiteral() {
|
constexpr u32 GetMatchingBitsFromStringLiteral() {
|
||||||
u32 result = 0;
|
u32 result = 0;
|
||||||
for (size_t i = 0; i < haystack.strlen; i++) {
|
for (std::size_t i = 0; i < haystack.strlen; i++) {
|
||||||
for (size_t a = 0; a < needle.strlen; a++) {
|
for (std::size_t a = 0; a < needle.strlen; a++) {
|
||||||
if (haystack.value[i] == needle.value[a]) {
|
if (haystack.value[i] == needle.value[a]) {
|
||||||
result |= 1 << (haystack.strlen - 1 - i);
|
result |= 1 << (haystack.strlen - 1 - i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1073,7 +1073,7 @@ std::vector<FormatInfo> ListFormats() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.push_back({current->name, ToStdString(current->long_name), std::move(extensions),
|
out.push_back({current->name, ToStdString(current->long_name), extensions,
|
||||||
std::move(supported_video_codecs), std::move(supported_audio_codecs),
|
std::move(supported_video_codecs), std::move(supported_audio_codecs),
|
||||||
GetOptionList(current->priv_class, true)});
|
GetOptionList(current->priv_class, true)});
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,9 +57,9 @@ static bool LZSS_Decompress(std::span<const u8> compressed, std::span<u8> decomp
|
||||||
u32 buffer_top_and_bottom;
|
u32 buffer_top_and_bottom;
|
||||||
std::memcpy(&buffer_top_and_bottom, footer, sizeof(u32));
|
std::memcpy(&buffer_top_and_bottom, footer, sizeof(u32));
|
||||||
|
|
||||||
size_t out = decompressed.size();
|
std::size_t out = decompressed.size();
|
||||||
size_t index = compressed.size() - ((buffer_top_and_bottom >> 24) & 0xFF);
|
std::size_t index = compressed.size() - ((buffer_top_and_bottom >> 24) & 0xFF);
|
||||||
size_t stop_index = compressed.size() - (buffer_top_and_bottom & 0xFFFFFF);
|
std::size_t stop_index = compressed.size() - (buffer_top_and_bottom & 0xFFFFFF);
|
||||||
|
|
||||||
std::memset(decompressed.data(), 0, decompressed.size());
|
std::memset(decompressed.data(), 0, decompressed.size());
|
||||||
std::memcpy(decompressed.data(), compressed.data(), compressed.size());
|
std::memcpy(decompressed.data(), compressed.data(), compressed.size());
|
||||||
|
|
|
@ -131,7 +131,7 @@ public:
|
||||||
return m_offset;
|
return m_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Seek(size_t offset) {
|
bool Seek(std::size_t offset) {
|
||||||
if (offset > m_size)
|
if (offset > m_size)
|
||||||
return false;
|
return false;
|
||||||
m_offset = offset;
|
m_offset = offset;
|
||||||
|
@ -242,7 +242,7 @@ private:
|
||||||
if (m_target_relative_offset + length > m_target.size())
|
if (m_target_relative_offset + length > m_target.size())
|
||||||
return false;
|
return false;
|
||||||
// Byte by byte copy.
|
// Byte by byte copy.
|
||||||
for (size_t i = 0; i < length; ++i)
|
for (std::size_t i = 0; i < length; ++i)
|
||||||
m_target.data()[m_target.Tell() + i] = m_target.data()[m_target_relative_offset++];
|
m_target.data()[m_target.Tell() + i] = m_target.data()[m_target_relative_offset++];
|
||||||
m_target.Seek(m_target.Tell() + length);
|
m_target.Seek(m_target.Tell() + length);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -357,7 +357,7 @@ void FileSys::Plugin3GXLoader::MapBootloader(Kernel::Process& process, Kernel::K
|
||||||
// Write bootloader
|
// Write bootloader
|
||||||
kernel.memory.WriteBlock(
|
kernel.memory.WriteBlock(
|
||||||
process, _3GX_exe_load_addr - bootloader_memory_size, bootloader.data(),
|
process, _3GX_exe_load_addr - bootloader_memory_size, bootloader.data(),
|
||||||
std::min<size_t>(bootloader.size() * sizeof(u32), bootloader_memory_size));
|
std::min<std::size_t>(bootloader.size() * sizeof(u32), bootloader_memory_size));
|
||||||
|
|
||||||
game_instructions[0] = 0xE51FF004; // ldr pc, [pc, #-4]
|
game_instructions[0] = 0xE51FF004; // ldr pc, [pc, #-4]
|
||||||
game_instructions[1] = _3GX_exe_load_addr - bootloader_memory_size;
|
game_instructions[1] = _3GX_exe_load_addr - bootloader_memory_size;
|
||||||
|
|
|
@ -72,7 +72,7 @@ private:
|
||||||
Kernel::Process& process, Kernel::KernelSystem& kernel,
|
Kernel::Process& process, Kernel::KernelSystem& kernel,
|
||||||
Service::PLGLDR::PLG_LDR& plg_ldr);
|
Service::PLGLDR::PLG_LDR& plg_ldr);
|
||||||
|
|
||||||
static constexpr size_t bootloader_memory_size = 0x1000;
|
static constexpr std::size_t bootloader_memory_size = 0x1000;
|
||||||
static void MapBootloader(Kernel::Process& process, Kernel::KernelSystem& kernel,
|
static void MapBootloader(Kernel::Process& process, Kernel::KernelSystem& kernel,
|
||||||
u32 memory_offset, std::span<const u32> exe_load_func,
|
u32 memory_offset, std::span<const u32> exe_load_func,
|
||||||
const u32_le* exe_load_args, u32 checksum_size, u32 exe_checksum,
|
const u32_le* exe_load_args, u32 checksum_size, u32 exe_checksum,
|
||||||
|
|
|
@ -16,7 +16,7 @@ std::size_t DirectRomFSReader::ReadFile(std::size_t offset, std::size_t length,
|
||||||
return 0; // Crypto++ does not like zero size buffer
|
return 0; // Crypto++ does not like zero size buffer
|
||||||
|
|
||||||
const auto segments = BreakupRead(offset, length);
|
const auto segments = BreakupRead(offset, length);
|
||||||
size_t read_progress = 0;
|
std::size_t read_progress = 0;
|
||||||
|
|
||||||
// Skip cache if the read is too big
|
// Skip cache if the read is too big
|
||||||
if (segments.size() == 1 && segments[0].second > cache_line_size) {
|
if (segments.size() == 1 && segments[0].second > cache_line_size) {
|
||||||
|
@ -33,8 +33,8 @@ std::size_t DirectRomFSReader::ReadFile(std::size_t offset, std::size_t length,
|
||||||
// TODO(PabloMK7): Make cache thread safe, read the comment in CacheReady function.
|
// TODO(PabloMK7): Make cache thread safe, read the comment in CacheReady function.
|
||||||
// std::unique_lock<std::shared_mutex> read_guard(cache_mutex);
|
// std::unique_lock<std::shared_mutex> read_guard(cache_mutex);
|
||||||
for (const auto& seg : segments) {
|
for (const auto& seg : segments) {
|
||||||
size_t read_size = cache_line_size;
|
std::size_t read_size = cache_line_size;
|
||||||
size_t page = OffsetToPage(seg.first);
|
std::size_t page = OffsetToPage(seg.first);
|
||||||
// Check if segment is in cache
|
// Check if segment is in cache
|
||||||
auto cache_entry = cache.request(page);
|
auto cache_entry = cache.request(page);
|
||||||
if (!cache_entry.first) {
|
if (!cache_entry.first) {
|
||||||
|
@ -51,7 +51,7 @@ std::size_t DirectRomFSReader::ReadFile(std::size_t offset, std::size_t length,
|
||||||
LOG_TRACE(Service_FS, "RomFS Cache HIT: page={}, length={}, into={}", page, seg.second,
|
LOG_TRACE(Service_FS, "RomFS Cache HIT: page={}, length={}, into={}", page, seg.second,
|
||||||
(seg.first - page));
|
(seg.first - page));
|
||||||
}
|
}
|
||||||
size_t copy_amount =
|
std::size_t copy_amount =
|
||||||
(read_size > (seg.first - page))
|
(read_size > (seg.first - page))
|
||||||
? std::min((seg.first - page) + seg.second, read_size) - (seg.first - page)
|
? std::min((seg.first - page) + seg.second, read_size) - (seg.first - page)
|
||||||
: 0;
|
: 0;
|
||||||
|
@ -98,10 +98,10 @@ std::vector<std::pair<std::size_t, std::size_t>> DirectRomFSReader::BreakupRead(
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t curr_offset = offset;
|
std::size_t curr_offset = offset;
|
||||||
while (length) {
|
while (length) {
|
||||||
size_t next_page = OffsetToPage(curr_offset + cache_line_size);
|
std::size_t next_page = OffsetToPage(curr_offset + cache_line_size);
|
||||||
size_t curr_page_len = std::min(length, next_page - curr_offset);
|
std::size_t curr_page_len = std::min(length, next_page - curr_offset);
|
||||||
ret.push_back(std::make_pair(curr_offset, curr_page_len));
|
ret.push_back(std::make_pair(curr_offset, curr_page_len));
|
||||||
curr_offset = next_page;
|
curr_offset = next_page;
|
||||||
length -= curr_page_len;
|
length -= curr_page_len;
|
||||||
|
|
|
@ -67,8 +67,8 @@ private:
|
||||||
u64 data_size;
|
u64 data_size;
|
||||||
|
|
||||||
// Total cache size: 128KB
|
// Total cache size: 128KB
|
||||||
static constexpr size_t cache_line_size = (1 << 13); // About 8KB
|
static constexpr std::size_t cache_line_size = (1 << 13); // About 8KB
|
||||||
static constexpr size_t cache_line_count = 16;
|
static constexpr std::size_t cache_line_count = 16;
|
||||||
|
|
||||||
Common::StaticLRUCache<std::size_t, std::array<u8, cache_line_size>, cache_line_count> cache;
|
Common::StaticLRUCache<std::size_t, std::array<u8, cache_line_size>, cache_line_count> cache;
|
||||||
// TODO(PabloMK7): Make cache thread safe, read the comment in CacheReady function.
|
// TODO(PabloMK7): Make cache thread safe, read the comment in CacheReady function.
|
||||||
|
|
|
@ -22,22 +22,22 @@ std::shared_ptr<ResourceLimit> ResourceLimit::Create(KernelSystem& kernel, std::
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 ResourceLimit::GetCurrentValue(ResourceLimitType type) const {
|
s32 ResourceLimit::GetCurrentValue(ResourceLimitType type) const {
|
||||||
const auto index = static_cast<size_t>(type);
|
const auto index = static_cast<std::size_t>(type);
|
||||||
return m_current_values[index];
|
return m_current_values[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 ResourceLimit::GetLimitValue(ResourceLimitType type) const {
|
s32 ResourceLimit::GetLimitValue(ResourceLimitType type) const {
|
||||||
const auto index = static_cast<size_t>(type);
|
const auto index = static_cast<std::size_t>(type);
|
||||||
return m_limit_values[index];
|
return m_limit_values[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceLimit::SetLimitValue(ResourceLimitType type, s32 value) {
|
void ResourceLimit::SetLimitValue(ResourceLimitType type, s32 value) {
|
||||||
const auto index = static_cast<size_t>(type);
|
const auto index = static_cast<std::size_t>(type);
|
||||||
m_limit_values[index] = value;
|
m_limit_values[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceLimit::Reserve(ResourceLimitType type, s32 amount) {
|
bool ResourceLimit::Reserve(ResourceLimitType type, s32 amount) {
|
||||||
const auto index = static_cast<size_t>(type);
|
const auto index = static_cast<std::size_t>(type);
|
||||||
const s32 limit = m_limit_values[index];
|
const s32 limit = m_limit_values[index];
|
||||||
const s32 new_value = m_current_values[index] + amount;
|
const s32 new_value = m_current_values[index] + amount;
|
||||||
if (new_value > limit) {
|
if (new_value > limit) {
|
||||||
|
@ -50,7 +50,7 @@ bool ResourceLimit::Reserve(ResourceLimitType type, s32 amount) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceLimit::Release(ResourceLimitType type, s32 amount) {
|
bool ResourceLimit::Release(ResourceLimitType type, s32 amount) {
|
||||||
const auto index = static_cast<size_t>(type);
|
const auto index = static_cast<std::size_t>(type);
|
||||||
const s32 value = m_current_values[index];
|
const s32 value = m_current_values[index];
|
||||||
if (amount > value) {
|
if (amount > value) {
|
||||||
LOG_ERROR(Kernel, "Amount {} exceeds current value {} for resource type {}", amount, value,
|
LOG_ERROR(Kernel, "Amount {} exceeds current value {} for resource type {}", amount, value,
|
||||||
|
|
|
@ -68,7 +68,7 @@ public:
|
||||||
bool Release(ResourceLimitType type, s32 amount);
|
bool Release(ResourceLimitType type, s32 amount);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using ResourceArray = std::array<s32, static_cast<size_t>(ResourceLimitType::Max)>;
|
using ResourceArray = std::array<s32, static_cast<std::size_t>(ResourceLimitType::Max)>;
|
||||||
ResourceArray m_limit_values{};
|
ResourceArray m_limit_values{};
|
||||||
ResourceArray m_current_values{};
|
ResourceArray m_current_values{};
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
|
|
@ -127,7 +127,7 @@ Result SharedMemory::Map(Process& target_process, VAddr address, MemoryPermissio
|
||||||
|
|
||||||
// Heap-backed memory blocks can not be mapped with other_permissions = DontCare
|
// Heap-backed memory blocks can not be mapped with other_permissions = DontCare
|
||||||
if (base_address != 0 && other_permissions == MemoryPermission::DontCare) {
|
if (base_address != 0 && other_permissions == MemoryPermission::DontCare) {
|
||||||
LOG_ERROR(Kernel, "cannot map id={}, address=0x{08X} name={}, permissions don't match",
|
LOG_ERROR(Kernel, "cannot map id={}, address=0x{:08X} name={}, permissions don't match",
|
||||||
GetObjectId(), address, name);
|
GetObjectId(), address, name);
|
||||||
return ResultInvalidCombination;
|
return ResultInvalidCombination;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1686,8 +1686,8 @@ Result SVC::AcceptSession(Handle* out_server_session, Handle server_port_handle)
|
||||||
return current_process->handle_table.Create(out_server_session, std::move(session));
|
return current_process->handle_table.Create(out_server_session, std::move(session));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CopyStringPart(char* out, const char* in, size_t offset, size_t max_length) {
|
static void CopyStringPart(char* out, const char* in, std::size_t offset, std::size_t max_length) {
|
||||||
size_t str_size = strlen(in);
|
std::size_t str_size = strlen(in);
|
||||||
if (offset < str_size) {
|
if (offset < str_size) {
|
||||||
strncpy(out, in + offset, max_length - 1);
|
strncpy(out, in + offset, max_length - 1);
|
||||||
out[max_length - 1] = '\0';
|
out[max_length - 1] = '\0';
|
||||||
|
|
|
@ -244,7 +244,7 @@ void Thread::WakeAfterDelay(s64 nanoseconds, bool thread_safe_mode) {
|
||||||
// Don't schedule a wakeup if the thread wants to wait forever
|
// Don't schedule a wakeup if the thread wants to wait forever
|
||||||
if (nanoseconds == -1)
|
if (nanoseconds == -1)
|
||||||
return;
|
return;
|
||||||
size_t core = thread_safe_mode ? core_id : std::numeric_limits<std::size_t>::max();
|
std::size_t core = thread_safe_mode ? core_id : std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
thread_manager.kernel.timing.ScheduleEvent(nsToCycles(nanoseconds),
|
thread_manager.kernel.timing.ScheduleEvent(nsToCycles(nanoseconds),
|
||||||
thread_manager.ThreadWakeupEventType, thread_id,
|
thread_manager.ThreadWakeupEventType, thread_id,
|
||||||
|
|
|
@ -713,6 +713,7 @@ Result AppletManager::SendDspSleep(AppletId from_applet_id,
|
||||||
.signal = SignalType::DspSleep,
|
.signal = SignalType::DspSleep,
|
||||||
.object = std::move(object),
|
.object = std::move(object),
|
||||||
});
|
});
|
||||||
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sys_lib_slot = GetAppletSlotFromPos(AppletPos::SysLibrary);
|
auto sys_lib_slot = GetAppletSlotFromPos(AppletPos::SysLibrary);
|
||||||
|
@ -728,6 +729,7 @@ Result AppletManager::SendDspSleep(AppletId from_applet_id,
|
||||||
.signal = SignalType::DspSleep,
|
.signal = SignalType::DspSleep,
|
||||||
.object = std::move(object),
|
.object = std::move(object),
|
||||||
});
|
});
|
||||||
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
|
|
|
@ -399,8 +399,8 @@ Result OnlineService::GetNsDataHeaderInfo(const u32 ns_data_id, const NsDataHead
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<size_t> OnlineService::ReadNsData(const u32 ns_data_id, const u64 offset, const u32 size,
|
ResultVal<std::size_t> OnlineService::ReadNsData(const u32 ns_data_id, const u64 offset,
|
||||||
Kernel::MappedBuffer& buffer) {
|
const u32 size, Kernel::MappedBuffer& buffer) {
|
||||||
std::optional<NsDataEntry> entry = GetNsDataEntryFromId(ns_data_id);
|
std::optional<NsDataEntry> entry = GetNsDataEntryFromId(ns_data_id);
|
||||||
if (!entry.has_value()) {
|
if (!entry.has_value()) {
|
||||||
LOG_WARNING(Service_BOSS, "Failed to find NsData entry for ID {:#010X}", ns_data_id);
|
LOG_WARNING(Service_BOSS, "Failed to find NsData entry for ID {:#010X}", ns_data_id);
|
||||||
|
|
|
@ -36,11 +36,11 @@ constexpr u32 BOSS_EXTDATA_HEADER_LENGTH = 0x18;
|
||||||
constexpr u32 BOSS_S_ENTRY_SIZE = 0xC00;
|
constexpr u32 BOSS_S_ENTRY_SIZE = 0xC00;
|
||||||
constexpr u32 BOSS_SAVE_HEADER_SIZE = 4;
|
constexpr u32 BOSS_SAVE_HEADER_SIZE = 4;
|
||||||
|
|
||||||
constexpr size_t TASK_ID_SIZE = 8;
|
constexpr std::size_t TASK_ID_SIZE = 8;
|
||||||
constexpr size_t URL_SIZE = 0x200;
|
constexpr std::size_t URL_SIZE = 0x200;
|
||||||
constexpr size_t HEADERS_SIZE = 0x360;
|
constexpr std::size_t HEADERS_SIZE = 0x360;
|
||||||
constexpr size_t CERTIDLIST_SIZE = 3;
|
constexpr std::size_t CERTIDLIST_SIZE = 3;
|
||||||
constexpr size_t TASKIDLIST_SIZE = 0x400;
|
constexpr std::size_t TASKIDLIST_SIZE = 0x400;
|
||||||
|
|
||||||
constexpr std::array<u8, 8> boss_system_savedata_id{
|
constexpr std::array<u8, 8> boss_system_savedata_id{
|
||||||
0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x01, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x01, 0x00,
|
||||||
|
@ -188,8 +188,8 @@ public:
|
||||||
std::optional<NsDataEntry> GetNsDataEntryFromId(const u32 ns_data_id);
|
std::optional<NsDataEntry> GetNsDataEntryFromId(const u32 ns_data_id);
|
||||||
Result GetNsDataHeaderInfo(const u32 ns_data_id, const NsDataHeaderInfoType type,
|
Result GetNsDataHeaderInfo(const u32 ns_data_id, const NsDataHeaderInfoType type,
|
||||||
const u32 size, Kernel::MappedBuffer& buffer);
|
const u32 size, Kernel::MappedBuffer& buffer);
|
||||||
ResultVal<size_t> ReadNsData(const u32 ns_data_id, const u64 offset, const u32 size,
|
ResultVal<std::size_t> ReadNsData(const u32 ns_data_id, const u64 offset, const u32 size,
|
||||||
Kernel::MappedBuffer& buffer);
|
Kernel::MappedBuffer& buffer);
|
||||||
Result SendProperty(const u16 id, const u32 size, Kernel::MappedBuffer& buffer);
|
Result SendProperty(const u16 id, const u32 size, Kernel::MappedBuffer& buffer);
|
||||||
Result ReceiveProperty(const u16 id, const u32 size, Kernel::MappedBuffer& buffer);
|
Result ReceiveProperty(const u16 id, const u32 size, Kernel::MappedBuffer& buffer);
|
||||||
|
|
||||||
|
|
|
@ -649,7 +649,7 @@ void Module::Interface::ReadData(Kernel::HLERequestContext& ctx) {
|
||||||
buffer = {};
|
buffer = {};
|
||||||
}
|
}
|
||||||
dest_buffer.Write(buffer.data(), 0,
|
dest_buffer.Write(buffer.data(), 0,
|
||||||
std::min(static_cast<size_t>(dest_buffer_size), buffer.size()));
|
std::min(static_cast<std::size_t>(dest_buffer_size), buffer.size()));
|
||||||
|
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushMappedBuffer(param_buffer);
|
rb.PushMappedBuffer(param_buffer);
|
||||||
|
|
|
@ -384,7 +384,7 @@ ResultVal<void*> Module::GetConfigBlockPointer(u32 block_id, u32 size, AccessFla
|
||||||
"Config block 0x{:X} with flags {} and size {} was not found, creating "
|
"Config block 0x{:X} with flags {} and size {} was not found, creating "
|
||||||
"from defaults.",
|
"from defaults.",
|
||||||
block_id, accesss_flag, size);
|
block_id, accesss_flag, size);
|
||||||
auto default_block = GetDefaultConfigBlock(static_cast<ConfigBlockID>(block_id));
|
const auto& default_block = GetDefaultConfigBlock(static_cast<ConfigBlockID>(block_id));
|
||||||
auto result = CreateConfigBlock(block_id, static_cast<u16>(default_block.data.size()),
|
auto result = CreateConfigBlock(block_id, static_cast<u16>(default_block.data.size()),
|
||||||
default_block.access_flags, default_block.data.data());
|
default_block.access_flags, default_block.data.data());
|
||||||
if (!result.IsSuccess()) {
|
if (!result.IsSuccess()) {
|
||||||
|
|
|
@ -107,7 +107,7 @@ void File::Read(Kernel::HLERequestContext& ctx) {
|
||||||
Result ret{0};
|
Result ret{0};
|
||||||
Kernel::MappedBuffer* buffer;
|
Kernel::MappedBuffer* buffer;
|
||||||
std::unique_ptr<u8*> data;
|
std::unique_ptr<u8*> data;
|
||||||
size_t read_size;
|
std::size_t read_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto async_data = std::make_shared<AsyncData>();
|
auto async_data = std::make_shared<AsyncData>();
|
||||||
|
|
|
@ -112,9 +112,9 @@ static URLInfo SplitUrl(const std::string& url) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t WriteHeaders(httplib::Stream& stream,
|
static std::size_t WriteHeaders(httplib::Stream& stream,
|
||||||
std::span<const Context::RequestHeader> headers) {
|
std::span<const Context::RequestHeader> headers) {
|
||||||
size_t write_len = 0;
|
std::size_t write_len = 0;
|
||||||
for (const auto& header : headers) {
|
for (const auto& header : headers) {
|
||||||
auto len = stream.write_format("%s: %s\r\n", header.name.c_str(), header.value.c_str());
|
auto len = stream.write_format("%s: %s\r\n", header.name.c_str(), header.value.c_str());
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
|
@ -130,8 +130,8 @@ static size_t WriteHeaders(httplib::Stream& stream,
|
||||||
return write_len;
|
return write_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t HandleHeaderWrite(std::vector<Context::RequestHeader>& pending_headers,
|
static std::size_t HandleHeaderWrite(std::vector<Context::RequestHeader>& pending_headers,
|
||||||
httplib::Stream& strm, httplib::Headers& httplib_headers) {
|
httplib::Stream& strm, httplib::Headers& httplib_headers) {
|
||||||
std::vector<Context::RequestHeader> final_headers;
|
std::vector<Context::RequestHeader> final_headers;
|
||||||
std::vector<Context::RequestHeader>::iterator it_pending_headers;
|
std::vector<Context::RequestHeader>::iterator it_pending_headers;
|
||||||
httplib::Headers::iterator it_httplib_headers;
|
httplib::Headers::iterator it_httplib_headers;
|
||||||
|
@ -508,7 +508,7 @@ void HTTP_C::ReceiveDataImpl(Kernel::HLERequestContext& ctx, bool timeout) {
|
||||||
}
|
}
|
||||||
Context& http_context = GetContext(async_data->context_handle);
|
Context& http_context = GetContext(async_data->context_handle);
|
||||||
|
|
||||||
const size_t remaining_data =
|
const std::size_t remaining_data =
|
||||||
http_context.response.body.size() - http_context.current_copied_data;
|
http_context.response.body.size() - http_context.current_copied_data;
|
||||||
|
|
||||||
if (async_data->buffer_size >= remaining_data) {
|
if (async_data->buffer_size >= remaining_data) {
|
||||||
|
|
|
@ -217,7 +217,7 @@ public:
|
||||||
std::future<void> request_future;
|
std::future<void> request_future;
|
||||||
std::atomic<u64> current_download_size_bytes;
|
std::atomic<u64> current_download_size_bytes;
|
||||||
std::atomic<u64> total_download_size_bytes;
|
std::atomic<u64> total_download_size_bytes;
|
||||||
size_t current_copied_data;
|
std::size_t current_copied_data;
|
||||||
bool uses_default_client_cert{};
|
bool uses_default_client_cert{};
|
||||||
httplib::Response response;
|
httplib::Response response;
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,7 @@ void ExtraHID::SendHIDStatus() {
|
||||||
float x, y;
|
float x, y;
|
||||||
std::tie(x, y) = c_stick->GetStatus();
|
std::tie(x, y) = c_stick->GetStatus();
|
||||||
|
|
||||||
ExtraHIDResponse response;
|
ExtraHIDResponse response{};
|
||||||
response.c_stick.header.Assign(static_cast<u8>(ResponseID::PollHID));
|
response.c_stick.header.Assign(static_cast<u8>(ResponseID::PollHID));
|
||||||
response.c_stick.c_stick_x.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * x));
|
response.c_stick.c_stick_x.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * x));
|
||||||
response.c_stick.c_stick_y.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * y));
|
response.c_stick.c_stick_y.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * y));
|
||||||
|
|
|
@ -1102,7 +1102,7 @@ void SOC_U::SendToOther(Kernel::HLERequestContext& ctx) {
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
std::vector<u8> input_buff(len);
|
std::vector<u8> input_buff(len);
|
||||||
input_mapped_buff.Read(input_buff.data(), 0,
|
input_mapped_buff.Read(input_buff.data(), 0,
|
||||||
std::min(input_mapped_buff.GetSize(), static_cast<size_t>(len)));
|
std::min(input_mapped_buff.GetSize(), static_cast<std::size_t>(len)));
|
||||||
|
|
||||||
s32 ret = -1;
|
s32 ret = -1;
|
||||||
if (addr_len > 0) {
|
if (addr_len > 0) {
|
||||||
|
@ -1853,7 +1853,7 @@ void SOC_U::GetSockOpt(Kernel::HLERequestContext& ctx) {
|
||||||
if (err == SOCKET_ERROR_VALUE) {
|
if (err == SOCKET_ERROR_VALUE) {
|
||||||
err = TranslateError(GET_ERRNO);
|
err = TranslateError(GET_ERRNO);
|
||||||
} else {
|
} else {
|
||||||
platform_data.resize(static_cast<size_t>(platform_data_size));
|
platform_data.resize(static_cast<std::size_t>(platform_data_size));
|
||||||
TranslateSockOptDataFromPlatform(optval, platform_data, level_opt.first,
|
TranslateSockOptDataFromPlatform(optval, platform_data, level_opt.first,
|
||||||
level_opt.second);
|
level_opt.second);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ class AppLoader_THREEDSX final : public AppLoader {
|
||||||
public:
|
public:
|
||||||
AppLoader_THREEDSX(Core::System& system_, FileUtil::IOFile&& file, const std::string& filename,
|
AppLoader_THREEDSX(Core::System& system_, FileUtil::IOFile&& file, const std::string& filename,
|
||||||
const std::string& filepath)
|
const std::string& filepath)
|
||||||
: AppLoader(system_, std::move(file)), filename(std::move(filename)), filepath(filepath) {}
|
: AppLoader(system_, std::move(file)), filename(filename), filepath(filepath) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the type of the file
|
* Returns the type of the file
|
||||||
|
|
|
@ -48,8 +48,8 @@ static std::string GetSaveStatePath(u64 program_id, u64 movie_id, u32 slot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ValidateSaveState(const CSTHeader& header, SaveStateInfo& info, u64 program_id,
|
static bool ValidateSaveState(const CSTHeader& header, SaveStateInfo& info, u64 program_id,
|
||||||
u64 movie_id, u32 slot) {
|
u64 movie_id) {
|
||||||
const auto path = GetSaveStatePath(program_id, movie_id, slot);
|
const auto path = GetSaveStatePath(program_id, movie_id, info.slot);
|
||||||
if (header.filetype != header_magic_bytes) {
|
if (header.filetype != header_magic_bytes) {
|
||||||
LOG_WARNING(Core, "Invalid save state file {}", path);
|
LOG_WARNING(Core, "Invalid save state file {}", path);
|
||||||
return false;
|
return false;
|
||||||
|
@ -112,7 +112,7 @@ std::vector<SaveStateInfo> ListSaveStates(u64 program_id, u64 movie_id) {
|
||||||
LOG_ERROR(Core, "Could not read from file {}", path);
|
LOG_ERROR(Core, "Could not read from file {}", path);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!ValidateSaveState(header, info, program_id, movie_id, slot)) {
|
if (!ValidateSaveState(header, info, program_id, movie_id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +185,8 @@ void System::LoadState(u32 slot) {
|
||||||
|
|
||||||
// validate header
|
// validate header
|
||||||
SaveStateInfo info;
|
SaveStateInfo info;
|
||||||
if (!ValidateSaveState(header, info, title_id, movie_id, slot)) {
|
info.slot = slot;
|
||||||
|
if (!ValidateSaveState(header, info, title_id, movie_id)) {
|
||||||
throw std::runtime_error("Invalid savestate");
|
throw std::runtime_error("Invalid savestate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,7 +207,7 @@ void CustomTexManager::PrepareDumping(u64 title_id) {
|
||||||
void CustomTexManager::PreloadTextures(const std::atomic_bool& stop_run,
|
void CustomTexManager::PreloadTextures(const std::atomic_bool& stop_run,
|
||||||
const VideoCore::DiskResourceLoadCallback& callback) {
|
const VideoCore::DiskResourceLoadCallback& callback) {
|
||||||
u64 size_sum = 0;
|
u64 size_sum = 0;
|
||||||
size_t preloaded = 0;
|
std::size_t preloaded = 0;
|
||||||
const u64 sys_mem = Common::GetMemInfo().total_physical_memory;
|
const u64 sys_mem = Common::GetMemInfo().total_physical_memory;
|
||||||
const u64 recommended_min_mem = 2_GiB;
|
const u64 recommended_min_mem = 2_GiB;
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ bool CustomTexManager::ReadConfig(u64 title_id, bool options_only) {
|
||||||
|
|
||||||
const auto& textures = json["textures"];
|
const auto& textures = json["textures"];
|
||||||
for (const auto& material : textures.items()) {
|
for (const auto& material : textures.items()) {
|
||||||
size_t idx{};
|
std::size_t idx{};
|
||||||
const u64 hash = std::stoull(material.key(), &idx, 16);
|
const u64 hash = std::stoull(material.key(), &idx, 16);
|
||||||
if (!idx) {
|
if (!idx) {
|
||||||
LOG_ERROR(Render, "Key {} is invalid, skipping", material.key());
|
LOG_ERROR(Render, "Key {} is invalid, skipping", material.key());
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "common/logging/log.h"
|
||||||
#include "core/hle/service/gsp/gsp_command.h"
|
#include "core/hle/service/gsp/gsp_command.h"
|
||||||
|
|
||||||
namespace VideoCore {
|
namespace VideoCore {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_funcs.h"
|
||||||
#include "common/vector_math.h"
|
#include "common/vector_math.h"
|
||||||
#include "video_core/pica_types.h"
|
#include "video_core/pica_types.h"
|
||||||
|
|
||||||
|
|
|
@ -398,7 +398,7 @@ void PicaCore::SubmitImmediate(u32 value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_t IMMEDIATE_MODE_INDEX = 0xF;
|
constexpr std::size_t IMMEDIATE_MODE_INDEX = 0xF;
|
||||||
|
|
||||||
auto& setup = regs.internal.pipeline.vs_default_attributes_setup;
|
auto& setup = regs.internal.pipeline.vs_default_attributes_setup;
|
||||||
if (setup.index > IMMEDIATE_MODE_INDEX) {
|
if (setup.index > IMMEDIATE_MODE_INDEX) {
|
||||||
|
|
|
@ -53,7 +53,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
union Regs {
|
union Regs {
|
||||||
static constexpr size_t NUM_REGS = 0x732;
|
static constexpr std::size_t NUM_REGS = 0x732;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u32 hardware_id;
|
u32 hardware_id;
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "common/assert.h"
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
|
||||||
namespace Pica {
|
namespace Pica {
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include "common/assert.h"
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/math_util.h"
|
#include "common/math_util.h"
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
#include "common/bit_set.h"
|
#include "common/bit_set.h"
|
||||||
#include "common/hash.h"
|
#include "common/hash.h"
|
||||||
|
#include "common/logging/log.h"
|
||||||
#include "video_core/pica/regs_shader.h"
|
#include "video_core/pica/regs_shader.h"
|
||||||
#include "video_core/pica/shader_setup.h"
|
#include "video_core/pica/shader_setup.h"
|
||||||
|
|
||||||
|
|
|
@ -21,15 +21,15 @@ struct Uniforms {
|
||||||
std::array<bool, 16> b;
|
std::array<bool, 16> b;
|
||||||
std::array<Common::Vec4<u8>, 4> i;
|
std::array<Common::Vec4<u8>, 4> i;
|
||||||
|
|
||||||
static size_t GetFloatUniformOffset(u32 index) {
|
static std::size_t GetFloatUniformOffset(u32 index) {
|
||||||
return offsetof(Uniforms, f) + index * sizeof(Common::Vec4<f24>);
|
return offsetof(Uniforms, f) + index * sizeof(Common::Vec4<f24>);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t GetBoolUniformOffset(u32 index) {
|
static std::size_t GetBoolUniformOffset(u32 index) {
|
||||||
return offsetof(Uniforms, b) + index * sizeof(bool);
|
return offsetof(Uniforms, b) + index * sizeof(bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t GetIntUniformOffset(u32 index) {
|
static std::size_t GetIntUniformOffset(u32 index) {
|
||||||
return offsetof(Uniforms, i) + index * sizeof(Common::Vec4<u8>);
|
return offsetof(Uniforms, i) + index * sizeof(Common::Vec4<u8>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
#include "common/bit_set.h"
|
#include "common/bit_set.h"
|
||||||
#include "video_core/pica/regs_shader.h"
|
#include "video_core/pica/regs_shader.h"
|
||||||
#include "video_core/pica/shader_unit.h"
|
#include "video_core/pica/shader_unit.h"
|
||||||
|
|
|
@ -33,15 +33,15 @@ struct ShaderUnit {
|
||||||
|
|
||||||
void WriteOutput(const ShaderRegs& config, AttributeBuffer& output);
|
void WriteOutput(const ShaderRegs& config, AttributeBuffer& output);
|
||||||
|
|
||||||
static constexpr size_t InputOffset(s32 register_index) {
|
static constexpr std::size_t InputOffset(s32 register_index) {
|
||||||
return offsetof(ShaderUnit, input) + register_index * sizeof(Common::Vec4<f24>);
|
return offsetof(ShaderUnit, input) + register_index * sizeof(Common::Vec4<f24>);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr size_t OutputOffset(s32 register_index) {
|
static constexpr std::size_t OutputOffset(s32 register_index) {
|
||||||
return offsetof(ShaderUnit, output) + register_index * sizeof(Common::Vec4<f24>);
|
return offsetof(ShaderUnit, output) + register_index * sizeof(Common::Vec4<f24>);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr size_t TemporaryOffset(s32 register_index) {
|
static constexpr std::size_t TemporaryOffset(s32 register_index) {
|
||||||
return offsetof(ShaderUnit, temporary) + register_index * sizeof(Common::Vec4<f24>);
|
return offsetof(ShaderUnit, temporary) + register_index * sizeof(Common::Vec4<f24>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -710,7 +710,7 @@ void RasterizerAccelerated::SyncCombinerColor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerAccelerated::SyncTevConstColor(
|
void RasterizerAccelerated::SyncTevConstColor(
|
||||||
const size_t stage_index, const Pica::TexturingRegs::TevStageConfig& tev_stage) {
|
const std::size_t stage_index, const Pica::TexturingRegs::TevStageConfig& tev_stage) {
|
||||||
const auto const_color = ColorRGBA8(tev_stage.const_color);
|
const auto const_color = ColorRGBA8(tev_stage.const_color);
|
||||||
|
|
||||||
if (const_color == fs_uniform_block_data.data.const_color[stage_index]) {
|
if (const_color == fs_uniform_block_data.data.const_color[stage_index]) {
|
||||||
|
|
|
@ -777,7 +777,7 @@ typename RasterizerCache<T>::SurfaceRect_Tuple RasterizerCache<T>::GetTexCopySur
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
void RasterizerCache<T>::ForEachSurfaceInRegion(PAddr addr, size_t size, Func&& func) {
|
void RasterizerCache<T>::ForEachSurfaceInRegion(PAddr addr, std::size_t size, Func&& func) {
|
||||||
using FuncReturn = typename std::invoke_result<Func, SurfaceId, Surface&>::type;
|
using FuncReturn = typename std::invoke_result<Func, SurfaceId, Surface&>::type;
|
||||||
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
||||||
boost::container::small_vector<SurfaceId, 8> surfaces;
|
boost::container::small_vector<SurfaceId, 8> surfaces;
|
||||||
|
|
|
@ -139,7 +139,7 @@ public:
|
||||||
private:
|
private:
|
||||||
/// Iterate over all page indices in a range
|
/// Iterate over all page indices in a range
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
void ForEachPage(PAddr addr, size_t size, Func&& func) {
|
void ForEachPage(PAddr addr, std::size_t size, Func&& func) {
|
||||||
static constexpr bool RETURNS_BOOL = std::is_same_v<std::invoke_result<Func, u64>, bool>;
|
static constexpr bool RETURNS_BOOL = std::is_same_v<std::invoke_result<Func, u64>, bool>;
|
||||||
const u64 page_end = (addr + size - 1) >> CITRA_PAGEBITS;
|
const u64 page_end = (addr + size - 1) >> CITRA_PAGEBITS;
|
||||||
for (u64 page = addr >> CITRA_PAGEBITS; page <= page_end; ++page) {
|
for (u64 page = addr >> CITRA_PAGEBITS; page <= page_end; ++page) {
|
||||||
|
@ -155,7 +155,7 @@ private:
|
||||||
|
|
||||||
/// Iterates over all the surfaces in a region calling func
|
/// Iterates over all the surfaces in a region calling func
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
void ForEachSurfaceInRegion(PAddr addr, size_t size, Func&& func);
|
void ForEachSurfaceInRegion(PAddr addr, std::size_t size, Func&& func);
|
||||||
|
|
||||||
/// Get the best surface match (and its match type) for the given flags
|
/// Get the best surface match (and its match type) for the given flags
|
||||||
template <MatchFlags find_flags>
|
template <MatchFlags find_flags>
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
/// Returns true if the surface contains a custom material with a normal map.
|
/// Returns true if the surface contains a custom material with a normal map.
|
||||||
bool HasNormalMap() const noexcept;
|
bool HasNormalMap() const noexcept;
|
||||||
|
|
||||||
bool Overlaps(PAddr overlap_addr, size_t overlap_size) const noexcept {
|
bool Overlaps(PAddr overlap_addr, std::size_t overlap_size) const noexcept {
|
||||||
const PAddr overlap_end = overlap_addr + static_cast<PAddr>(overlap_size);
|
const PAddr overlap_end = overlap_addr + static_cast<PAddr>(overlap_size);
|
||||||
return addr < overlap_end && overlap_addr < end;
|
return addr < overlap_end && overlap_addr < end;
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,7 +310,7 @@ void RendererOpenGL::InitOpenGLObjects() {
|
||||||
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
|
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
|
||||||
Settings::values.bg_blue.GetValue(), 0.0f);
|
Settings::values.bg_blue.GetValue(), 0.0f);
|
||||||
|
|
||||||
for (size_t i = 0; i < samplers.size(); i++) {
|
for (std::size_t i = 0; i < samplers.size(); i++) {
|
||||||
samplers[i].Create();
|
samplers[i].Create();
|
||||||
glSamplerParameteri(samplers[i].handle, GL_TEXTURE_MIN_FILTER,
|
glSamplerParameteri(samplers[i].handle, GL_TEXTURE_MIN_FILTER,
|
||||||
i == 0 ? GL_NEAREST : GL_LINEAR);
|
i == 0 ? GL_NEAREST : GL_LINEAR);
|
||||||
|
|
|
@ -78,12 +78,12 @@ void SwBlitter::TextureCopy(const Pica::DisplayTransferConfig& config) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t contiguous_input_size =
|
const std::size_t contiguous_input_size =
|
||||||
config.texture_copy.size / input_width * (input_width + input_gap);
|
config.texture_copy.size / input_width * (input_width + input_gap);
|
||||||
rasterizer->FlushRegion(config.GetPhysicalInputAddress(),
|
rasterizer->FlushRegion(config.GetPhysicalInputAddress(),
|
||||||
static_cast<u32>(contiguous_input_size));
|
static_cast<u32>(contiguous_input_size));
|
||||||
|
|
||||||
const size_t contiguous_output_size =
|
const std::size_t contiguous_output_size =
|
||||||
config.texture_copy.size / output_width * (output_width + output_gap);
|
config.texture_copy.size / output_width * (output_width + output_gap);
|
||||||
|
|
||||||
// Only need to flush output if it has a gap
|
// Only need to flush output if it has a gap
|
||||||
|
@ -329,7 +329,7 @@ void SwBlitter::MemoryFill(const Pica::MemoryFillConfig& config) {
|
||||||
// Fill with 32-bit values
|
// Fill with 32-bit values
|
||||||
if (end > start) {
|
if (end > start) {
|
||||||
const u32 value = config.value_32bit;
|
const u32 value = config.value_32bit;
|
||||||
const size_t len = (end - start) / sizeof(u32);
|
const std::size_t len = (end - start) / sizeof(u32);
|
||||||
for (std::size_t i = 0; i < len; ++i) {
|
for (std::size_t i = 0; i < len; ++i) {
|
||||||
std::memcpy(&start[i * sizeof(u32)], &value, sizeof(u32));
|
std::memcpy(&start[i * sizeof(u32)], &value, sizeof(u32));
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ private:
|
||||||
Memory::MemorySystem& memory;
|
Memory::MemorySystem& memory;
|
||||||
Pica::PicaCore& pica;
|
Pica::PicaCore& pica;
|
||||||
Pica::RegsInternal& regs;
|
Pica::RegsInternal& regs;
|
||||||
size_t num_sw_threads;
|
std::size_t num_sw_threads;
|
||||||
Common::ThreadWorker sw_workers;
|
Common::ThreadWorker sw_workers;
|
||||||
Framebuffer fb;
|
Framebuffer fb;
|
||||||
};
|
};
|
||||||
|
|
|
@ -691,7 +691,7 @@ void Instance::CollectToolingInfo() {
|
||||||
|
|
||||||
bool Instance::SetMoltenVkConfig() {
|
bool Instance::SetMoltenVkConfig() {
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
size_t mvk_config_size = sizeof(MVKConfiguration);
|
std::size_t mvk_config_size = sizeof(MVKConfiguration);
|
||||||
MVKConfiguration mvk_config{};
|
MVKConfiguration mvk_config{};
|
||||||
|
|
||||||
const auto _vkGetMoltenVKConfigurationMVK =
|
const auto _vkGetMoltenVKConfigurationMVK =
|
||||||
|
|
|
@ -543,7 +543,7 @@ void PipelineCache::BindTexelBuffer(u32 binding, vk::BufferView buffer_view) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipelineCache::SetBufferOffset(u32 binding, size_t offset) {
|
void PipelineCache::SetBufferOffset(u32 binding, std::size_t offset) {
|
||||||
if (offsets[binding] != static_cast<u32>(offset)) {
|
if (offsets[binding] != static_cast<u32>(offset)) {
|
||||||
offsets[binding] = static_cast<u32>(offset);
|
offsets[binding] = static_cast<u32>(offset);
|
||||||
set_dirty[0] = true;
|
set_dirty[0] = true;
|
||||||
|
|
|
@ -79,7 +79,7 @@ public:
|
||||||
void BindTexelBuffer(u32 binding, vk::BufferView buffer_view);
|
void BindTexelBuffer(u32 binding, vk::BufferView buffer_view);
|
||||||
|
|
||||||
/// Sets the dynamic offset for the uniform buffer at binding
|
/// Sets the dynamic offset for the uniform buffer at binding
|
||||||
void SetBufferOffset(u32 binding, size_t offset);
|
void SetBufferOffset(u32 binding, std::size_t offset);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Builds the rasterizer pipeline layout
|
/// Builds the rasterizer pipeline layout
|
||||||
|
|
|
@ -63,7 +63,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback(
|
||||||
|
|
||||||
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags,
|
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags,
|
||||||
VkDebugReportObjectTypeEXT objectType,
|
VkDebugReportObjectTypeEXT objectType,
|
||||||
uint64_t object, size_t location,
|
uint64_t object, std::size_t location,
|
||||||
int32_t messageCode,
|
int32_t messageCode,
|
||||||
const char* pLayerPrefix,
|
const char* pLayerPrefix,
|
||||||
const char* pMessage, void* pUserData) {
|
const char* pMessage, void* pUserData) {
|
||||||
|
|
|
@ -235,7 +235,7 @@ void RasterizerVulkan::SetupVertexArray() {
|
||||||
if (aligned_stride == loader.byte_count) {
|
if (aligned_stride == loader.byte_count) {
|
||||||
std::memcpy(dst_ptr, src_ptr, data_size);
|
std::memcpy(dst_ptr, src_ptr, data_size);
|
||||||
} else {
|
} else {
|
||||||
for (size_t vertex = 0; vertex < vertex_num; vertex++) {
|
for (std::size_t vertex = 0; vertex < vertex_num; vertex++) {
|
||||||
std::memcpy(dst_ptr + vertex * aligned_stride, src_ptr + vertex * loader.byte_count,
|
std::memcpy(dst_ptr + vertex * aligned_stride, src_ptr + vertex * loader.byte_count,
|
||||||
loader.byte_count);
|
loader.byte_count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,8 @@ struct RenderPass {
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderpassCache {
|
class RenderpassCache {
|
||||||
static constexpr size_t MAX_COLOR_FORMATS = 13;
|
static constexpr std::size_t MAX_COLOR_FORMATS = 13;
|
||||||
static constexpr size_t MAX_DEPTH_FORMATS = 4;
|
static constexpr std::size_t MAX_DEPTH_FORMATS = 4;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit RenderpassCache(const Instance& instance, Scheduler& scheduler);
|
explicit RenderpassCache(const Instance& instance, Scheduler& scheduler);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
ResourcePool::ResourcePool(MasterSemaphore* master_semaphore_, size_t grow_step_)
|
ResourcePool::ResourcePool(MasterSemaphore* master_semaphore_, std::size_t grow_step_)
|
||||||
: master_semaphore{master_semaphore_}, grow_step{grow_step_} {}
|
: master_semaphore{master_semaphore_}, grow_step{grow_step_} {}
|
||||||
|
|
||||||
std::size_t ResourcePool::CommitResource() {
|
std::size_t ResourcePool::CommitResource() {
|
||||||
|
@ -57,12 +57,12 @@ std::size_t ResourcePool::ManageOverflow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourcePool::Grow() {
|
void ResourcePool::Grow() {
|
||||||
const size_t old_capacity = ticks.size();
|
const std::size_t old_capacity = ticks.size();
|
||||||
ticks.resize(old_capacity + grow_step);
|
ticks.resize(old_capacity + grow_step);
|
||||||
Allocate(old_capacity, old_capacity + grow_step);
|
Allocate(old_capacity, old_capacity + grow_step);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_t COMMAND_BUFFER_POOL_SIZE = 4;
|
constexpr std::size_t COMMAND_BUFFER_POOL_SIZE = 4;
|
||||||
|
|
||||||
struct CommandPool::Pool {
|
struct CommandPool::Pool {
|
||||||
vk::CommandPool handle;
|
vk::CommandPool handle;
|
||||||
|
|
|
@ -119,9 +119,9 @@ u32 UnpackDepthStencil(const VideoCore::StagingData& data, vk::Format dest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::container::small_vector<vk::ImageMemoryBarrier, 3> MakeInitBarriers(
|
boost::container::small_vector<vk::ImageMemoryBarrier, 3> MakeInitBarriers(
|
||||||
vk::ImageAspectFlags aspect, std::span<const vk::Image> images, size_t num_images) {
|
vk::ImageAspectFlags aspect, std::span<const vk::Image> images, std::size_t num_images) {
|
||||||
boost::container::small_vector<vk::ImageMemoryBarrier, 3> barriers;
|
boost::container::small_vector<vk::ImageMemoryBarrier, 3> barriers;
|
||||||
for (size_t i = 0; i < num_images; i++) {
|
for (std::size_t i = 0; i < num_images; i++) {
|
||||||
barriers.push_back(vk::ImageMemoryBarrier{
|
barriers.push_back(vk::ImageMemoryBarrier{
|
||||||
.srcAccessMask = vk::AccessFlagBits::eNone,
|
.srcAccessMask = vk::AccessFlagBits::eNone,
|
||||||
.dstAccessMask = vk::AccessFlagBits::eNone,
|
.dstAccessMask = vk::AccessFlagBits::eNone,
|
||||||
|
|
|
@ -12,7 +12,7 @@ using ProcTexCombiner = TexturingRegs::ProcTexCombiner;
|
||||||
using ProcTexFilter = TexturingRegs::ProcTexFilter;
|
using ProcTexFilter = TexturingRegs::ProcTexFilter;
|
||||||
using TextureType = Pica::TexturingRegs::TextureConfig::TextureType;
|
using TextureType = Pica::TexturingRegs::TextureConfig::TextureType;
|
||||||
|
|
||||||
constexpr static size_t RESERVE_SIZE = 8 * 1024 * 1024;
|
constexpr static std::size_t RESERVE_SIZE = 8 * 1024 * 1024;
|
||||||
|
|
||||||
enum class Semantic : u32 {
|
enum class Semantic : u32 {
|
||||||
Position,
|
Position,
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace Pica {
|
namespace Pica {
|
||||||
|
|
|
@ -968,7 +968,7 @@ void JitShader::Compile(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>* program_
|
||||||
protect();
|
protect();
|
||||||
invalidate_all();
|
invalidate_all();
|
||||||
|
|
||||||
const size_t code_size =
|
const std::size_t code_size =
|
||||||
current_address() - reinterpret_cast<uintptr_t>(oaknut::CodeBlock::ptr());
|
current_address() - reinterpret_cast<uintptr_t>(oaknut::CodeBlock::ptr());
|
||||||
|
|
||||||
ASSERT_MSG(code_size <= MAX_SHADER_SIZE, "Compiled a shader that exceeds the allocated size!");
|
ASSERT_MSG(code_size <= MAX_SHADER_SIZE, "Compiled a shader that exceeds the allocated size!");
|
||||||
|
|
Loading…
Reference in a new issue