Compare commits

...
Author SHA1 Message Date
nmzik f100f785da libs: fill controller and broadcast status outputs 2026-09-19 05:16:16 +04:00
nmzik ba1854bbdc net: start pool IDs at 1 2026-09-19 04:59:28 +04:00
nmzik ea6aae8577 shader: V_MAD_I16 2026-09-19 04:43:48 +04:00
nmzik 5b7d3343cf shader: V_CMP_NLT_F16 2026-09-18 12:25:13 +04:00
nmzik 394e638905 shader: V_MUL_LO_U16 2026-09-18 11:21:57 +04:00
nmzik c2b7b0b58c Revert "BC7-RGBA32_UINT views (Vulkan validation)"
This reverts commit 165234b159.
2026-09-18 11:12:36 +04:00
nmzik 1d2f59dfa4 ajm: reject invalid batch storage 2026-09-18 09:11:55 +04:00
nmzikandBlackCAT 007d7ea2eb audio: infer stereo RAW AAC layout from channel-pair packets
Co-authored-by: BlackCAT <52720489+psnwd@users.noreply.github.com>
2026-09-18 09:11:55 +04:00
nmzikandshadowbeat070 95d3d9d3ad shader: fix packed integer negation
Co-authored-by: shadowbeat070 <70843316+shadowbeat070@users.noreply.github.com>
2026-09-18 09:11:55 +04:00
bfc8cd0e0b shader: DPP8 moves
Co-authored-by: foufouadi <attar.foued@gmail.com>
Co-authored-by: fxpw <fxpw@outlook.com>
2026-09-18 09:11:55 +04:00
165234b159 BC7-RGBA32_UINT views (Vulkan validation)
Co-authored-by: Techx3 <56268269+Techx3@users.noreply.github.com>
Co-authored-by: shadowbeat070 <70843316+shadowbeat070@users.noreply.github.com>
Co-authored-by: SueryRD <the.ai.tester2@gmail.com>
Co-authored-by: BlackCAT <52720489+psnwd@users.noreply.github.com>
2026-09-18 09:11:55 +04:00
nmzik 6493674726 shader: dual-source blending (Vulkan) 2026-09-18 09:11:55 +04:00
nmzik cbedf5707f UDP P2P sockets 2026-09-18 09:11:55 +04:00
nmzik 57c5b206ca fix network errno 2026-09-18 09:11:55 +04:00
nmzik 87b4417aca fix initial NP sign-in callback 2026-09-18 09:11:55 +04:00
nmzik 104530eafc fix Windows build (#680)
fix Windows Vulkan barrier macro
2026-09-17 21:32:54 +04:00
nmzik 6cfde37e98 avoid extra allocations 2026-09-17 20:35:36 +04:00
nmzik c5cebc1d19 remove unused helpers and the -64 suffix 2026-09-17 20:35:36 +04:00
nmzik 697b18b366 replace ByteBuffer with std::vector 2026-09-17 20:35:36 +04:00
nmzik 5b2935e36c remove the extra virtual memory layer 2026-09-17 20:35:36 +04:00
nmzik 5dc644edb4 clean up graphics helpers 2026-09-17 20:35:36 +04:00
nmzik 1211958b4e clean up runtime helpers 2026-09-17 20:35:36 +04:00
nmzik 218e7200bb clean up launcher helpers 2026-09-17 20:35:36 +04:00
nmzik 2bf78a94e0 remove string wrappers 2026-09-17 20:35:36 +04:00
nmzikandSaadi cc8e02380f remove magic_enum wrappers
Co-authored-by: Saadi <cosxmos@gmail.com>
2026-09-17 20:35:36 +04:00
nmzik c66d977c1d shader: encode SNORM16 formatted stores for skinning buffers 2026-09-17 17:40:05 +04:00
nmzik 4b77686566 shader: V_CMP_NGT_F16 2026-09-17 16:56:32 +04:00
c0sxm0s a6144f794b launcher: report cheat file save failures (#669)
PatchesDialog::Save silently ignored QSaveFile failures, leaving the
status label showing the old "Loaded N cheat(s)" text so the user could
not tell that their selection was not saved. Report the failure in the
status label and the log instead.
2026-09-17 16:13:35 +04:00
Mininaut bab1c3614c libc: treat negative dynamic printf precision as omitted (#625) 2026-09-17 15:18:04 +04:00
c0sxm0s de1545e19a launcher: wire cancel->reject in C++; document glslang for Windows (#663)
uic from Qt 6.12.0 crashes (0xC0000005) on any non-empty <connections>
block in .ui files. Move the cancel_button -> reject connection from
configuration_edit_dialog.ui into configurationEditDialog.cpp, matching
how the other buttons are already connected there.

Also document the glslang (glslangValidator) requirement for Windows
builds; CMake requires it via find_program(... REQUIRED).
2026-09-17 15:13:20 +04:00
Komaryandnmzik ce629e0391 input: add gyroscope and motion sensor support (#634)
input: add controller motion sensor support

Co-authored-by: nmzik <Nmzik@mail.ru>
2026-09-17 12:28:12 +04:00
110 changed files with 2576 additions and 2740 deletions

No files matched your search

+1
View File
@@ -137,6 +137,7 @@ the Vulkan/SPIR-V validation rules.
- Visual Studio 2022 or Build Tools 2022 with the **Desktop development with C++** workload and
**C++ Clang tools for Windows** component
- Qt 6 for MSVC 2022 64-bit, including Concurrent, Network, and Widgets
- [glslang](https://github.com/KhronosGroup/glslang/releases) (`glslangValidator`) on `PATH`
The Microsoft C++ compiler (`cl.exe`) is not supported; use `clang-cl`.
-166
View File
@@ -1,166 +0,0 @@
#ifndef KYTY_COMMON_BYTEBUFFER_H_
#define KYTY_COMMON_BYTEBUFFER_H_
#include "common/assert.h"
#include "common/common.h"
#include <algorithm>
#include <cstddef> // IWYU pragma: export
#include <cstring>
#include <utility>
#include <vector>
namespace Common {
using Byte = std::byte;
class ByteBuffer {
public:
using DataType = std::vector<Byte>;
static constexpr uint32_t INVALID_INDEX = static_cast<uint32_t>(-1);
using iterator = DataType::iterator;
using const_iterator = DataType::const_iterator;
ByteBuffer() = default;
ByteBuffer(const ByteBuffer&) = default;
ByteBuffer(ByteBuffer&&) = default;
ByteBuffer& operator=(const ByteBuffer&) = default;
ByteBuffer& operator=(ByteBuffer&&) = default;
explicit ByteBuffer(uint32_t size): m_data(size) {}
ByteBuffer(std::initializer_list<uint8_t> list) {
for (const uint8_t& e: list) {
m_data.emplace_back(static_cast<Byte>(e));
}
}
explicit ByteBuffer(const void* buf, uint32_t size)
: ByteBuffer(size) // @suppress("Ambiguous problem")
{
EXIT_IF(buf == nullptr && size != 0);
if (size != 0) {
std::memcpy(m_data.data(), buf, size);
}
}
[[nodiscard]] uint32_t Size() const { return static_cast<uint32_t>(m_data.size()); }
[[nodiscard]] bool IsEmpty() const { return m_data.empty(); }
void Clear() { m_data.clear(); }
void Add(const Byte& val) { m_data.push_back(val); }
void Add(Byte&& val) { m_data.push_back(std::move(val)); }
void Add(const Byte* val, uint32_t num) {
EXIT_IF(val == nullptr && num != 0);
m_data.insert(m_data.end(), val, val + num);
}
void Add(const ByteBuffer& v) {
if (this == &v) {
const ByteBuffer copy(v);
Add(copy.GetDataConst(), copy.Size());
return;
}
Add(v.GetDataConst(), v.Size());
}
void InsertAt(uint32_t index, const Byte& val) {
EXIT_IF(index > Size());
m_data.insert(m_data.begin() + index, val);
}
void InsertAt(uint32_t index, Byte&& val) {
EXIT_IF(index > Size());
m_data.insert(m_data.begin() + index, std::move(val));
}
[[nodiscard]] uint32_t Find(const Byte& t) const {
const auto it = std::find(m_data.begin(), m_data.end(), t);
return (it == m_data.end() ? INVALID_INDEX
: static_cast<uint32_t>(std::distance(m_data.begin(), it)));
}
[[nodiscard]] bool Contains(const Byte& t) const { return Find(t) != INVALID_INDEX; }
bool Remove(const Byte& t) {
const auto it = std::find(m_data.begin(), m_data.end(), t);
if (it == m_data.end()) {
return false;
}
m_data.erase(it);
return true;
}
bool RemoveAt(uint32_t index, uint32_t count = 1) {
if (index >= Size() || count == 0) {
return false;
}
const uint32_t erase_count = std::min(count, Size() - index);
m_data.erase(m_data.begin() + index, m_data.begin() + index + erase_count);
return true;
}
[[nodiscard]] bool IndexValid(uint32_t index) const { return index < Size(); }
Byte& operator[](uint32_t index) {
EXIT_IF(index >= Size());
return m_data[index];
}
const Byte& operator[](uint32_t index) const {
EXIT_IF(index >= Size());
return m_data[index];
}
[[nodiscard]] const Byte& At(uint32_t index) const {
EXIT_IF(index >= Size());
return m_data[index];
}
Byte* GetData() { return m_data.data(); }
[[nodiscard]] const Byte* GetData() const { return m_data.data(); }
[[nodiscard]] const Byte* GetDataConst() const { return m_data.data(); }
void Sort() {
std::sort(m_data.begin(), m_data.end(), [](Byte a, Byte b) {
return std::to_integer<uint8_t>(a) < std::to_integer<uint8_t>(b);
});
}
template <typename OP>
void Sort(OP&& comp_func) {
std::sort(m_data.begin(), m_data.end(), std::forward<OP>(comp_func));
}
bool operator==(const ByteBuffer& s) const { return m_data == s.m_data; }
bool operator!=(const ByteBuffer& s) const { return !(*this == s); }
iterator begin() { return m_data.begin(); } // NOLINT(readability-identifier-naming)
iterator end() { return m_data.end(); } // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator begin() const {
return m_data.begin();
} // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator end() const {
return m_data.end();
} // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator cbegin() const {
return m_data.cbegin();
} // NOLINT(readability-identifier-naming)
[[nodiscard]] const_iterator cend() const {
return m_data.cend();
} // NOLINT(readability-identifier-naming)
private:
DataType m_data;
};
} // namespace Common
#endif /* KYTY_COMMON_BYTEBUFFER_H_ */
-4
View File
@@ -24,8 +24,4 @@ std::string Debug::GetLinker() {
#endif
}
std::string Debug::GetBitness() {
return "64";
}
} // namespace Common
-1
View File
@@ -10,7 +10,6 @@ namespace Common {
namespace Debug {
std::string GetCompiler();
std::string GetLinker();
std::string GetBitness();
} // namespace Debug
} // namespace Common
+13 -28
View File
@@ -136,10 +136,6 @@ bool File::OpenInMem(void* buf, uint32_t buf_size) {
return true;
}
bool File::OpenInMem(ByteBuffer& buf) {
return OpenInMem(buf.GetData(), buf.Size());
}
bool File::CreateInMem() {
EXIT_IF(m_p->f != nullptr);
@@ -251,8 +247,8 @@ void File::Printf(const char* format, ...) {
bool File::IsDirectoryExisting(const std::filesystem::path& path) {
auto path_str = PathToGenericString(path);
return SysFileIsDirectoryExisting(
Common::EndsWith(path_str, "/") ? Common::RemoveLast(path_str, 1) : path_str);
return SysFileIsDirectoryExisting(path_str.ends_with("/") ? Common::RemoveLast(path_str, 1)
: path_str);
}
bool File::IsFileExisting(const std::filesystem::path& name) {
@@ -263,14 +259,14 @@ bool File::CreateDirectory(
const std::filesystem::path& path) // @suppress("Member declaration not found")
{
auto path_str = PathToGenericString(path);
return SysFileCreateDirectory(Common::EndsWith(path_str, "/") ? Common::RemoveLast(path_str, 1)
: path_str);
return SysFileCreateDirectory(path_str.ends_with("/") ? Common::RemoveLast(path_str, 1)
: path_str);
}
bool File::DeleteDirectory(const std::filesystem::path& path) {
auto path_str = PathToGenericString(path);
return SysFileDeleteDirectory(Common::EndsWith(path_str, "/") ? Common::RemoveLast(path_str, 1)
: path_str);
return SysFileDeleteDirectory(path_str.ends_with("/") ? Common::RemoveLast(path_str, 1)
: path_str);
}
bool File::CreateDirectories(const std::filesystem::path& path) {
@@ -283,7 +279,7 @@ bool File::CreateDirectories(const std::filesystem::path& path) {
for (uint32_t si = 0; si < list.size(); si++) {
const std::string& s = list[si];
if (si != 0 || Common::StartsWith(real_path, "/")) {
if (si != 0 || real_path.starts_with("/")) {
p += "/";
}
@@ -313,7 +309,7 @@ bool File::DeleteDirectories(const std::filesystem::path& path) {
for (uint32_t si = 0; si < list.size(); si++) {
const std::string& s = list[si];
if (si != 0 || Common::StartsWith(real_path, "/")) {
if (si != 0 || real_path.starts_with("/")) {
p += "/";
}
@@ -345,7 +341,7 @@ bool File::Flush() {
return SysFileFlush(*m_p->f);
}
ByteBuffer File::ReadWholeBuffer() {
std::vector<std::byte> File::ReadWholeBuffer() {
EXIT_IF(IsInvalid());
EXIT_IF(Tell() != 0);
@@ -353,25 +349,14 @@ ByteBuffer File::ReadWholeBuffer() {
EXIT_IF((s >> 32u) != 0);
ByteBuffer buf(s);
const auto read_size = static_cast<uint32_t>(s);
std::vector<std::byte> buf(read_size);
Read(buf.GetData(), s);
Read(buf.data(), read_size);
return buf;
}
ByteBuffer File::Read(uint32_t size) {
ByteBuffer buf(size);
uint32_t b = 0;
Read(buf.GetData(), size, &b);
buf.RemoveAt(b, size - b);
return buf;
}
void File::Write(const ByteBuffer& buf, uint32_t* bytes_written) {
Write(buf.GetDataConst(), buf.Size(), bytes_written);
}
DateTime File::GetLastAccessTimeUTC(const std::filesystem::path& name) {
SysTimeStruct t {};
SysFileToSystemTimeUtc(SysFileGetLastAccessTimeUtc(name), t);
@@ -478,7 +463,7 @@ std::vector<File::FindInfo> File::FindFiles(const std::filesystem::path& path) {
auto path_str = PathToGenericString(path);
uint32_t len = static_cast<uint32_t>(path_str.size());
if (!Common::EndsWith(path_str, "/") && !Common::EndsWith(path_str, "\\")) {
if (!path_str.ends_with("/") && !path_str.ends_with("\\")) {
len++;
}
+4 -7
View File
@@ -1,10 +1,10 @@
#ifndef KYTY_COMMON_FILE_H_
#define KYTY_COMMON_FILE_H_
#include "common/byteBuffer.h"
#include "common/common.h"
#include "common/dateTime.h"
#include <cstddef>
#include <filesystem>
#include <memory>
#include <string>
@@ -51,7 +51,6 @@ public:
bool Create(const std::filesystem::path& name);
bool Open(const std::filesystem::path& name, Mode mode);
bool OpenInMem(void* buf, uint32_t buf_size);
bool OpenInMem(ByteBuffer& buf); // NOLINT(google-runtime-references)
bool CreateInMem();
void Close();
@@ -73,14 +72,12 @@ public:
void GetLastAccessAndWriteTimeUTC(DateTime* access, DateTime* write);
void Read(void* data, uint32_t size, uint32_t* bytes_read = nullptr);
ByteBuffer Read(uint32_t size);
void Write(const void* data, uint32_t size, uint32_t* bytes_written = nullptr);
void Write(const ByteBuffer& buf, uint32_t* bytes_written = nullptr);
void Read(void* data, uint32_t size, uint32_t* bytes_read = nullptr);
void Write(const void* data, uint32_t size, uint32_t* bytes_written = nullptr);
void Printf(const char* format, ...) KYTY_FORMAT_PRINTF(2, 3);
ByteBuffer ReadWholeBuffer();
std::vector<std::byte> ReadWholeBuffer();
static uint64_t Size(const std::filesystem::path& name);
-97
View File
@@ -54,103 +54,6 @@ inline uint32_t hash(const void* key, uint32_t key_len) {
return hash;
}
inline uint32_t hash8(uint8_t key) {
uint32_t hash = 0;
uint8_t* ptr = &key;
hash += ptr[0];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += (hash << 3u);
hash ^= (hash >> 11u);
hash += (hash << 15u);
return hash;
}
inline uint32_t hash16(uint16_t key) {
uint32_t hash = 0;
auto* ptr = reinterpret_cast<uint8_t*>(&key);
hash += ptr[0];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[1];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += (hash << 3u);
hash ^= (hash >> 11u);
hash += (hash << 15u);
return hash;
}
inline uint32_t hash32(uint32_t key) {
uint32_t hash = 0;
auto* ptr = reinterpret_cast<uint8_t*>(&key);
hash += ptr[0];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[1];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[2];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[3];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += (hash << 3u);
hash ^= (hash >> 11u);
hash += (hash << 15u);
return hash;
}
inline uint32_t hash64(uint64_t key) {
uint32_t hash = 0;
auto* ptr = reinterpret_cast<uint8_t*>(&key);
hash += ptr[0];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[1];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[2];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[3];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[4];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[5];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[6];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += ptr[7];
hash += (hash << 10u);
hash ^= (hash >> 6u);
hash += (hash << 3u);
hash ^= (hash >> 11u);
hash += (hash << 15u);
return hash;
}
} // namespace Common
#endif /* KYTY_COMMON_HASH_H_ */
-42
View File
@@ -1,42 +0,0 @@
#ifndef KYTY_COMMON_MAGICENUM_H_
#define KYTY_COMMON_MAGICENUM_H_
#include "common/common.h"
#include "common/stringUtils.h"
#include "magic_enum.hpp" // IWYU pragma: export
namespace Common {
template <typename E>
inline std::string EnumName(E v) {
auto str = magic_enum::enum_name(v);
return std::string(str.data(), str.length());
}
template <typename E>
inline std::string EnumName8(E v) {
auto str = magic_enum::enum_name(v);
return std::string(str.data(), str.length());
}
template <typename E>
inline E EnumValue(const std::string& str, E default_value) {
auto v = magic_enum::enum_cast<E>(str.c_str());
if (v.has_value()) {
return v.value();
}
return default_value;
}
#define KYTY_ENUM_RANGE(e, mx, mn) \
namespace magic_enum::customize { \
template <> \
struct enum_range<e> { \
static constexpr int min = (mx); \
static constexpr int max = (mn); \
}; \
}
} // namespace Common
#endif /* KYTY_COMMON_MAGICENUM_H_ */
-1
View File
@@ -52,7 +52,6 @@ uint64_t SysFileTell(sys_file_t& f); // NOLINT(google-runt
bool SysFileTruncate(sys_file_t& f, uint64_t size); // NOLINT(google-runtime-references)
bool SysFileUnlink(sys_file_t& f,
const std::filesystem::path& name); // NOLINT(google-runtime-references)
void SysFileWrite(uint32_t n, sys_file_t& f); // NOLINT(google-runtime-references)
uint64_t SysFileSize(const std::filesystem::path& file_name);
bool SysFileIsError(sys_file_t& f); // NOLINT(google-runtime-references)
bool SysFileIsDirectoryExisting(const std::filesystem::path& path);
+1 -4
View File
@@ -11,6 +11,7 @@
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <dirent.h>
#include <fcntl.h>
#include <filesystem>
@@ -151,10 +152,6 @@ void SysFileWrite(const void* data, uint32_t size, sys_file_t& f, uint32_t* byte
}
}
void SysFileWrite(uint32_t n, sys_file_t& f) {
SysFileWrite(&n, 4, f);
}
sys_file_t* SysFileCreate(const std::filesystem::path& file_name) {
auto* ret = new sys_file_t;
+29 -31
View File
@@ -5,7 +5,6 @@
#else
#include "common/assert.h"
#include "common/platform/sysVirtual.h"
#include "common/virtualMemory.h"
#include <atomic>
@@ -28,12 +27,12 @@
#define KYTY_FIXED_NOREPLACE
#endif
namespace Common {
namespace Common::VirtualMemory {
static pthread_mutex_t g_virtual_mutex {};
static std::map<uintptr_t, size_t>* g_allocs = nullptr;
void SysVirtualInit() {
void Init() {
pthread_mutexattr_t attr {};
pthread_mutexattr_init(&attr);
@@ -48,19 +47,19 @@ void SysVirtualInit() {
g_allocs = new std::map<uintptr_t, size_t>;
}
static int get_protection_flag(VirtualMemory::Mode mode) {
static int get_protection_flag(Mode mode) {
int protect = PROT_NONE;
switch (mode) {
case VirtualMemory::Mode::Read: protect = PROT_READ; break;
case VirtualMemory::Mode::Write:
case VirtualMemory::Mode::ReadWrite: protect = PROT_READ | PROT_WRITE; break; // NOLINT
case VirtualMemory::Mode::Execute: protect = PROT_EXEC; break;
case VirtualMemory::Mode::ExecuteRead: protect = PROT_EXEC | PROT_READ; break; // NOLINT
case VirtualMemory::Mode::ExecuteWrite:
case VirtualMemory::Mode::ExecuteReadWrite:
case Mode::Read: protect = PROT_READ; break;
case Mode::Write:
case Mode::ReadWrite: protect = PROT_READ | PROT_WRITE; break; // NOLINT
case Mode::Execute: protect = PROT_EXEC; break;
case Mode::ExecuteRead: protect = PROT_EXEC | PROT_READ; break; // NOLINT
case Mode::ExecuteWrite:
case Mode::ExecuteReadWrite:
protect = PROT_EXEC | PROT_WRITE | PROT_READ;
break; // NOLINT
case VirtualMemory::Mode::NoAccess:
case Mode::NoAccess:
default: protect = PROT_NONE; break;
}
return protect;
@@ -130,7 +129,7 @@ static void* map_anonymous(uintptr_t addr, size_t size, int protect, int flags)
return mmap(nullptr, size, protect, flags, -1, 0); // NOLINT
}
uint64_t SysVirtualAlloc(uint64_t address, uint64_t size, VirtualMemory::Mode mode) {
uint64_t Alloc(uint64_t address, uint64_t size, Mode mode) {
EXIT_IF(g_allocs == nullptr);
auto addr = static_cast<uintptr_t>(address);
@@ -154,8 +153,7 @@ static uintptr_t align_up(uintptr_t addr, uint64_t alignment) {
return (addr + alignment - 1) & ~(alignment - 1);
}
uint64_t SysVirtualAllocAligned(uint64_t address, uint64_t size, VirtualMemory::Mode mode,
uint64_t alignment) {
uint64_t AllocAligned(uint64_t address, uint64_t size, Mode mode, uint64_t alignment) {
if (alignment == 0) {
return 0;
}
@@ -224,7 +222,7 @@ uint64_t SysVirtualAllocAligned(uint64_t address, uint64_t size, VirtualMemory::
}
if (ptr == MAP_FAILED) {
return SysVirtualAllocAligned(address, size, mode, alignment << 1u);
return AllocAligned(address, size, mode, alignment << 1u);
}
pthread_mutex_lock(&g_virtual_mutex);
@@ -281,7 +279,7 @@ static bool is_mapped(void* ptr, size_t length) {
}
#endif
bool SysVirtualAllocFixed(uint64_t address, uint64_t size, VirtualMemory::Mode mode) {
bool AllocFixed(uint64_t address, uint64_t size, Mode mode) {
EXIT_IF(g_allocs == nullptr);
auto addr = static_cast<uintptr_t>(address);
@@ -318,15 +316,15 @@ bool SysVirtualAllocFixed(uint64_t address, uint64_t size, VirtualMemory::Mode m
return false;
}
bool SysVirtualCommit(uint64_t address, uint64_t size, VirtualMemory::Mode mode) {
return SysVirtualProtect(address, size, mode);
bool Commit(uint64_t address, uint64_t size, Mode mode) {
return Protect(address, size, mode);
}
uint64_t SysVirtualReserve(uint64_t address, uint64_t size) {
return SysVirtualReserveAligned(address, size, 1);
uint64_t Reserve(uint64_t address, uint64_t size) {
return ReserveAligned(address, size, 1);
}
uint64_t SysVirtualReserveAligned(uint64_t address, uint64_t size, uint64_t alignment) {
uint64_t ReserveAligned(uint64_t address, uint64_t size, uint64_t alignment) {
if (alignment == 0) {
return 0;
}
@@ -395,7 +393,7 @@ uint64_t SysVirtualReserveAligned(uint64_t address, uint64_t size, uint64_t alig
}
if (ptr == MAP_FAILED) {
return SysVirtualReserveAligned(address, size, alignment << 1u);
return ReserveAligned(address, size, alignment << 1u);
}
pthread_mutex_lock(&g_virtual_mutex);
@@ -405,7 +403,7 @@ uint64_t SysVirtualReserveAligned(uint64_t address, uint64_t size, uint64_t alig
return ret_addr;
}
bool SysVirtualReserveFixed(uint64_t address, uint64_t size) {
bool ReserveFixed(uint64_t address, uint64_t size) {
EXIT_IF(g_allocs == nullptr);
auto addr = static_cast<uintptr_t>(address);
@@ -441,9 +439,9 @@ bool SysVirtualReserveFixed(uint64_t address, uint64_t size) {
return false;
}
bool SysVirtualDecommit(uint64_t address, uint64_t size) {
bool Decommit(uint64_t address, uint64_t size) {
// Drop physical pages while preserving the reservation.
if (!SysVirtualProtect(address, size, VirtualMemory::Mode::NoAccess)) {
if (!Protect(address, size, Mode::NoAccess)) {
return false;
}
@@ -467,7 +465,7 @@ bool SysVirtualDecommit(uint64_t address, uint64_t size) {
return true;
}
bool SysVirtualFree(uint64_t address) {
bool Free(uint64_t address) {
EXIT_IF(g_allocs == nullptr);
size_t size = 0;
@@ -487,7 +485,7 @@ bool SysVirtualFree(uint64_t address) {
return munmap(reinterpret_cast<void*>(addr), size) == 0;
}
bool SysVirtualFreeRange(uint64_t address, uint64_t size) {
bool FreeRange(uint64_t address, uint64_t size) {
EXIT_IF(g_allocs == nullptr);
if (size == 0 || (address & 0xfffu) != 0 || (size & 0xfffu) != 0) {
return false;
@@ -543,7 +541,7 @@ bool SysVirtualFreeRange(uint64_t address, uint64_t size) {
return true;
}
bool SysVirtualProtect(uint64_t address, uint64_t size, VirtualMemory::Mode mode) {
bool Protect(uint64_t address, uint64_t size, Mode mode) {
const auto addr = static_cast<uintptr_t>(address);
const auto page_start = addr >> 12u;
const auto page_end = (addr + size - 1) >> 12u;
@@ -551,10 +549,10 @@ bool SysVirtualProtect(uint64_t address, uint64_t size, VirtualMemory::Mode mode
get_protection_flag(mode)) == 0;
}
bool SysVirtualFlushInstructionCache(uint64_t /*address*/, uint64_t /*size*/) {
bool FlushInstructionCache(uint64_t /*address*/, uint64_t /*size*/) {
return true;
}
} // namespace Common
} // namespace Common::VirtualMemory
#endif
-53
View File
@@ -1,53 +0,0 @@
#ifndef KYTY_COMMON_PLATFORM_SYSSWAPBYTEORDER_H_
#define KYTY_COMMON_PLATFORM_SYSSWAPBYTEORDER_H_
#include "common/common.h"
#include <type_traits>
inline uint16_t SwapByteOrder16(uint16_t value) {
uint16_t hi = value << 8u;
uint16_t lo = value >> 8u;
return hi | lo;
}
inline uint32_t SwapByteOrder32(uint32_t value) {
return __builtin_bswap32(value);
}
inline uint64_t SwapByteOrder64(uint64_t value) {
return __builtin_bswap64(value);
}
template <typename T>
inline void SwapByteOrder(T& x) {
if (sizeof(x) == 2) {
if (std::is_signed_v<T>) {
x = static_cast<std::make_signed_t<T>>(
SwapByteOrder16(static_cast<std::make_unsigned_t<uint16_t>>(x)));
} else {
x = SwapByteOrder16(x);
}
}
if (sizeof(x) == 4) {
if (std::is_signed_v<T>) {
x = static_cast<std::make_signed_t<T>>(
SwapByteOrder32(static_cast<std::make_unsigned_t<uint32_t>>(x)));
} else {
x = SwapByteOrder32(x);
}
}
if (sizeof(x) == 8) {
if (std::is_signed_v<T>) {
x = static_cast<std::make_signed_t<T>>(
SwapByteOrder64(static_cast<std::make_unsigned_t<uint64_t>>(x)));
} else {
x = SwapByteOrder64(x);
}
}
}
template <typename T>
inline void NoSwapByteOrder(T& x) {}
#endif /* KYTY_COMMON_PLATFORM_SYSSWAPBYTEORDER_H_ */
+1 -5
View File
@@ -151,10 +151,6 @@ inline void SysTimeTToSystem(time_t t, SysTimeStruct& s) {
SysFileToSystemTimeUtc(ft, s);
}
inline time_t SysTimegm(struct tm* tm) {
return timegm(tm);
}
inline void SysSystemToFileTimeUtc(const SysTimeStruct& f, SysFileTimeStruct& t) {
struct tm i {};
@@ -165,7 +161,7 @@ inline void SysSystemToFileTimeUtc(const SysTimeStruct& f, SysFileTimeStruct& t)
i.tm_min = f.Minute;
i.tm_sec = f.Second;
t.is_invalid = (f.is_invalid || (t.time = SysTimegm(&i)) == static_cast<time_t>(-1));
t.is_invalid = (f.is_invalid || (t.time = ::timegm(&i)) == static_cast<time_t>(-1));
}
// Retrieves the current local date and time.
-27
View File
@@ -1,27 +0,0 @@
#ifndef KYTY_COMMON_PLATFORM_SYSVIRTUAL_H_
#define KYTY_COMMON_PLATFORM_SYSVIRTUAL_H_
#include "common/common.h"
#include "common/virtualMemory.h"
namespace Common {
void SysVirtualInit();
uint64_t SysVirtualAlloc(uint64_t address, uint64_t size, VirtualMemory::Mode mode);
uint64_t SysVirtualAllocAligned(uint64_t address, uint64_t size, VirtualMemory::Mode mode,
uint64_t alignment);
bool SysVirtualAllocFixed(uint64_t address, uint64_t size, VirtualMemory::Mode mode);
bool SysVirtualCommit(uint64_t address, uint64_t size, VirtualMemory::Mode mode);
uint64_t SysVirtualReserve(uint64_t address, uint64_t size);
uint64_t SysVirtualReserveAligned(uint64_t address, uint64_t size, uint64_t alignment);
bool SysVirtualReserveFixed(uint64_t address, uint64_t size);
bool SysVirtualDecommit(uint64_t address, uint64_t size);
bool SysVirtualFree(uint64_t address);
bool SysVirtualFreeRange(uint64_t address, uint64_t size);
bool SysVirtualProtect(uint64_t address, uint64_t size, VirtualMemory::Mode mode);
bool SysVirtualFlushInstructionCache(uint64_t address, uint64_t size);
} // namespace Common
#endif /* KYTY_COMMON_PLATFORM_SYSVIRTUAL_H_ */
+3 -6
View File
@@ -14,6 +14,7 @@
#include "common/stringUtils.h"
#include <cstdlib>
#include <cstring>
#include <vector>
// NOLINTNEXTLINE(readability-identifier-naming)
@@ -135,10 +136,6 @@ void SysFileWrite(const void* data, uint32_t size, sys_file_t& f, uint32_t* byte
}
}
void SysFileWrite(uint32_t n, sys_file_t& f) {
SysFileWrite(&n, 4, f);
}
sys_file_t* SysFileCreate(const std::filesystem::path& file_name) {
auto* ret = new sys_file_t;
@@ -481,7 +478,7 @@ bool SysFileSetLastAccessAndWriteTimeUtc(const std::filesystem::path& name,
void SysFileFindFiles(const std::filesystem::path& path, std::vector<sys_file_find_t>& out) {
std::string real_path = Common::ReplaceChar(Common::PathToGenericString(path), '\\', '/');
if (!Common::EndsWith(real_path, "/")) {
if (!real_path.ends_with("/")) {
real_path += "/";
}
@@ -528,7 +525,7 @@ void SysFileFindFiles(const std::filesystem::path& path, std::vector<sys_file_fi
void SysFileGetDents(const std::filesystem::path& path, std::vector<sys_dir_entry_t>& out) {
std::string real_path = Common::ReplaceChar(Common::PathToGenericString(path), '\\', '/');
if (!Common::EndsWith(real_path, "/")) {
if (!real_path.ends_with("/")) {
real_path += "/";
}
+31 -33
View File
@@ -10,7 +10,6 @@
#include <windows.h> // IWYU pragma: keep
#include "common/assert.h"
#include "common/platform/sysVirtual.h"
#include "common/virtualMemory.h"
// IWYU pragma: no_include <basetsd.h>
@@ -22,33 +21,33 @@
// IWYU pragma: no_include <winerror.h>
// IWYU pragma: no_include <wtypes.h>
namespace Common {
namespace Common::VirtualMemory {
static DWORD GetProtectionFlag(VirtualMemory::Mode mode) {
static DWORD GetProtectionFlag(Mode mode) {
DWORD protect = PAGE_NOACCESS;
switch (mode) {
case VirtualMemory::Mode::Read: protect = PAGE_READONLY; break;
case Mode::Read: protect = PAGE_READONLY; break;
case VirtualMemory::Mode::Write:
case VirtualMemory::Mode::ReadWrite: protect = PAGE_READWRITE; break;
case Mode::Write:
case Mode::ReadWrite: protect = PAGE_READWRITE; break;
case VirtualMemory::Mode::Execute: protect = PAGE_EXECUTE; break;
case Mode::Execute: protect = PAGE_EXECUTE; break;
case VirtualMemory::Mode::ExecuteRead: protect = PAGE_EXECUTE_READ; break;
case Mode::ExecuteRead: protect = PAGE_EXECUTE_READ; break;
case VirtualMemory::Mode::ExecuteWrite:
case VirtualMemory::Mode::ExecuteReadWrite: protect = PAGE_EXECUTE_READWRITE; break;
case Mode::ExecuteWrite:
case Mode::ExecuteReadWrite: protect = PAGE_EXECUTE_READWRITE; break;
case VirtualMemory::Mode::NoAccess:
case Mode::NoAccess:
default: protect = PAGE_NOACCESS; break;
}
return protect;
}
void SysVirtualInit() {}
void Init() {}
uint64_t SysVirtualAlloc(uint64_t address, uint64_t size, VirtualMemory::Mode mode) {
auto ptr = (address == 0 ? SysVirtualAllocAligned(address, size, mode, 1)
uint64_t Alloc(uint64_t address, uint64_t size, Mode mode) {
auto ptr = (address == 0 ? AllocAligned(address, size, mode, 1)
: reinterpret_cast<uintptr_t>(VirtualAlloc(
reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE),
@@ -59,7 +58,7 @@ uint64_t SysVirtualAlloc(uint64_t address, uint64_t size, VirtualMemory::Mode mo
if (err != ERROR_INVALID_ADDRESS) {
printf("VirtualAlloc() failed: 0x%08" PRIx32 "\n", err);
} else {
return SysVirtualAllocAligned(address, size, mode, 1);
return AllocAligned(address, size, mode, 1);
}
}
return ptr;
@@ -80,8 +79,7 @@ static uint64_t AlignUp(uint64_t addr, uint64_t alignment) {
return (addr + alignment - 1) & ~(alignment - 1);
}
uint64_t SysVirtualAllocAligned(uint64_t address, uint64_t size, VirtualMemory::Mode mode,
uint64_t alignment) {
uint64_t AllocAligned(uint64_t address, uint64_t size, Mode mode, uint64_t alignment) {
if (alignment == 0) {
printf("VirtualAlloc2 failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
return 0;
@@ -135,13 +133,13 @@ uint64_t SysVirtualAllocAligned(uint64_t address, uint64_t size, VirtualMemory::
printf("VirtualAlloc2(alignment = 0x%016" PRIx64 ") failed: 0x%08" PRIx32 "\n",
alignment, err);
} else {
return SysVirtualAllocAligned(address, size, mode, alignment << 1u);
return AllocAligned(address, size, mode, alignment << 1u);
}
}
return ptr;
}
bool SysVirtualAllocFixed(uint64_t address, uint64_t size, VirtualMemory::Mode mode) {
bool AllocFixed(uint64_t address, uint64_t size, Mode mode) {
auto ptr = reinterpret_cast<uintptr_t>(VirtualAlloc(
reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE), GetProtectionFlag(mode)));
@@ -161,7 +159,7 @@ bool SysVirtualAllocFixed(uint64_t address, uint64_t size, VirtualMemory::Mode m
return true;
}
bool SysVirtualCommit(uint64_t address, uint64_t size, VirtualMemory::Mode mode) {
bool Commit(uint64_t address, uint64_t size, Mode mode) {
auto ptr = reinterpret_cast<uintptr_t>(
VirtualAlloc(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
static_cast<DWORD>(MEM_COMMIT), GetProtectionFlag(mode)));
@@ -179,8 +177,8 @@ bool SysVirtualCommit(uint64_t address, uint64_t size, VirtualMemory::Mode mode)
return true;
}
uint64_t SysVirtualReserve(uint64_t address, uint64_t size) {
auto ptr = (address == 0 ? SysVirtualReserveAligned(address, size, 1)
uint64_t Reserve(uint64_t address, uint64_t size) {
auto ptr = (address == 0 ? ReserveAligned(address, size, 1)
: reinterpret_cast<uintptr_t>(VirtualAlloc(
reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
static_cast<DWORD>(MEM_RESERVE), PAGE_NOACCESS)));
@@ -190,13 +188,13 @@ uint64_t SysVirtualReserve(uint64_t address, uint64_t size) {
if (err != ERROR_INVALID_ADDRESS) {
printf("VirtualAlloc(MEM_RESERVE) failed: 0x%08" PRIx32 "\n", err);
} else {
return SysVirtualReserveAligned(address, size, 1);
return ReserveAligned(address, size, 1);
}
}
return ptr;
}
uint64_t SysVirtualReserveAligned(uint64_t address, uint64_t size, uint64_t alignment) {
uint64_t ReserveAligned(uint64_t address, uint64_t size, uint64_t alignment) {
if (alignment == 0) {
printf("VirtualAlloc2(MEM_RESERVE) failed: 0x%08" PRIx32 "\n",
static_cast<uint32_t>(GetLastError()));
@@ -250,13 +248,13 @@ uint64_t SysVirtualReserveAligned(uint64_t address, uint64_t size, uint64_t alig
"\n",
alignment, err);
} else {
return SysVirtualReserveAligned(address, size, alignment << 1u);
return ReserveAligned(address, size, alignment << 1u);
}
}
return ptr;
}
bool SysVirtualReserveFixed(uint64_t address, uint64_t size) {
bool ReserveFixed(uint64_t address, uint64_t size) {
auto ptr = reinterpret_cast<uintptr_t>(
VirtualAlloc(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
static_cast<DWORD>(MEM_RESERVE), PAGE_NOACCESS));
@@ -276,7 +274,7 @@ bool SysVirtualReserveFixed(uint64_t address, uint64_t size) {
return true;
}
bool SysVirtualDecommit(uint64_t address, uint64_t size) {
bool Decommit(uint64_t address, uint64_t size) {
if (VirtualFree(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
MEM_DECOMMIT) == 0) {
printf("VirtualFree(MEM_DECOMMIT) failed: 0x%08" PRIx32 "\n",
@@ -286,7 +284,7 @@ bool SysVirtualDecommit(uint64_t address, uint64_t size) {
return true;
}
bool SysVirtualFree(uint64_t address) {
bool Free(uint64_t address) {
if (VirtualFree(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), 0, MEM_RELEASE) ==
0) {
printf("VirtualFree() failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
@@ -295,7 +293,7 @@ bool SysVirtualFree(uint64_t address) {
return true;
}
bool SysVirtualFreeRange(uint64_t address, uint64_t size) {
bool FreeRange(uint64_t address, uint64_t size) {
if (address == 0 || size == 0) {
return false;
}
@@ -313,10 +311,10 @@ bool SysVirtualFreeRange(uint64_t address, uint64_t size) {
}
current = next;
}
return current - address == size && SysVirtualFree(address);
return current - address == size && Free(address);
}
bool SysVirtualProtect(uint64_t address, uint64_t size, VirtualMemory::Mode mode) {
bool Protect(uint64_t address, uint64_t size, Mode mode) {
DWORD old_protect = 0;
if (VirtualProtect(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
GetProtectionFlag(mode), &old_protect) == 0) {
@@ -326,7 +324,7 @@ bool SysVirtualProtect(uint64_t address, uint64_t size, VirtualMemory::Mode mode
return true;
}
bool SysVirtualFlushInstructionCache(uint64_t address, uint64_t size) {
bool FlushInstructionCache(uint64_t address, uint64_t size) {
if (::FlushInstructionCache(GetCurrentProcess(),
reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)),
size) == 0) {
@@ -337,6 +335,6 @@ bool SysVirtualFlushInstructionCache(uint64_t address, uint64_t size) {
return true;
}
} // namespace Common
} // namespace Common::VirtualMemory
#endif
+2 -180
View File
@@ -1,7 +1,6 @@
#ifndef KYTY_COMMON_STRING_UTILS_H_
#define KYTY_COMMON_STRING_UTILS_H_
#include "common/byteBuffer.h"
#include "common/common.h"
#include <algorithm>
@@ -9,7 +8,6 @@
#include <charconv>
#include <codecvt>
#include <filesystem>
#include <fmt/format.h>
#include <locale>
#include <string>
#include <string_view>
@@ -18,8 +16,6 @@
namespace Common {
constexpr uint32_t FIND_INVALID_INDEX = static_cast<uint32_t>(-1);
inline std::string PathToString(const std::filesystem::path& path) {
#if defined(__cpp_char8_t)
auto u8 = path.u8string();
@@ -38,10 +34,6 @@ inline std::string PathToGenericString(const std::filesystem::path& path) {
#endif
}
inline bool IsSpace(char c) {
return std::isspace(static_cast<unsigned char>(c)) != 0;
}
inline bool EqualNoCase(std::string_view lhs, std::string_view rhs) {
if (lhs.size() != rhs.size()) {
return false;
@@ -63,65 +55,6 @@ inline std::string ToLower(std::string_view text) {
return ret;
}
inline bool ContainsStr(std::string_view text, std::string_view needle) {
return text.find(needle) != std::string_view::npos;
}
inline bool StartsWith(std::string_view text, std::string_view prefix) {
return text.starts_with(prefix);
}
inline bool StartsWith(std::string_view text, char prefix) {
return !text.empty() && text.front() == prefix;
}
inline bool EndsWith(std::string_view text, std::string_view suffix) {
return text.ends_with(suffix);
}
inline bool EndsWith(std::string_view text, char suffix) {
return !text.empty() && text.back() == suffix;
}
inline bool ContainsChar(std::string_view text, char needle) {
return text.find(needle) != std::string_view::npos;
}
inline bool IndexValid(std::string_view text, uint32_t index) {
return index < text.size();
}
inline uint32_t FindIndex(std::string_view text, std::string_view needle, size_t from = 0) {
const auto pos = text.find(needle, from);
return pos == std::string_view::npos ? FIND_INVALID_INDEX : static_cast<uint32_t>(pos);
}
inline uint32_t FindIndex(std::string_view text, char needle, size_t from = 0) {
const auto pos = text.find(needle, from);
return pos == std::string_view::npos ? FIND_INVALID_INDEX : static_cast<uint32_t>(pos);
}
inline uint32_t FindLastIndex(std::string_view text, std::string_view needle,
size_t from = FIND_INVALID_INDEX) {
if (needle.empty()) {
return 0;
}
if (from == FIND_INVALID_INDEX || from > text.size()) {
from = text.size();
}
const auto pos = text.rfind(needle, from);
return pos == std::string_view::npos ? FIND_INVALID_INDEX : static_cast<uint32_t>(pos);
}
inline uint32_t FindLastIndex(std::string_view text, char needle,
size_t from = FIND_INVALID_INDEX) {
if (from == FIND_INVALID_INDEX || from > text.size()) {
from = text.size();
}
const auto pos = text.rfind(needle, from);
return pos == std::string_view::npos ? FIND_INVALID_INDEX : static_cast<uint32_t>(pos);
}
inline std::string Mid(std::string_view text, size_t first, size_t count = std::string_view::npos) {
if (first >= text.size()) {
return {};
@@ -129,49 +62,18 @@ inline std::string Mid(std::string_view text, size_t first, size_t count = std::
return std::string(text.substr(first, count));
}
inline std::string Left(std::string_view text, size_t count) {
return Mid(text, 0, count);
}
inline std::string Right(std::string_view text, size_t count) {
if (count >= text.size()) {
return std::string(text);
}
return Mid(text, text.size() - count, count);
}
inline std::string RemoveLast(std::string_view text, size_t count) {
if (count >= text.size()) {
return {};
}
return Left(text, text.size() - count);
return std::string(text.substr(0, text.size() - count));
}
inline std::string RemoveFirst(std::string_view text, size_t count) {
if (count >= text.size()) {
return {};
}
return Right(text, text.size() - count);
}
inline std::string TrimRight(std::string_view text) {
size_t end = text.size();
while (end > 0 && IsSpace(text[end - 1])) {
end--;
}
return std::string(text.substr(0, end));
}
inline std::string TrimLeft(std::string_view text) {
size_t first = 0;
while (first < text.size() && IsSpace(text[first])) {
first++;
}
return std::string(text.substr(first));
}
inline std::string Trim(std::string_view text) {
return TrimRight(TrimLeft(text));
return std::string(text.substr(count));
}
inline std::string ReplaceChar(std::string_view text, char old_char, char new_char) {
@@ -204,16 +106,6 @@ inline std::string FilenameWithoutDirectory(std::string_view text) {
return pos == std::string_view::npos ? std::string(text) : std::string(text.substr(pos + 1));
}
inline std::string FilenameWithoutExtension(std::string_view text) {
const auto pos = text.find_last_of('.');
return pos == std::string_view::npos ? std::string(text) : std::string(text.substr(0, pos));
}
inline std::string ExtensionWithoutFilename(std::string_view text) {
const auto pos = text.find_last_of('.');
return pos == std::string_view::npos ? std::string() : std::string(text.substr(pos));
}
inline std::string FixFilenameSlash(std::string_view text) {
return ReplaceChar(text, '\\', '/');
}
@@ -257,65 +149,12 @@ inline std::vector<std::string> Split(std::string_view text, char sep, bool keep
return Split(text, std::string_view(&sep, 1), keep_empty);
}
inline std::string Concat(const std::vector<std::string>& list, std::string_view sep) {
std::string ret;
for (size_t i = 0; i < list.size(); i++) {
if (i != 0) {
ret += sep;
}
ret += list[i];
}
return ret;
}
inline std::string Concat(const std::vector<std::string>& list, char sep) {
return Concat(list, std::string_view(&sep, 1));
}
inline uint32_t ToUint32(std::string_view text, int base = 10) {
uint32_t value = 0;
std::from_chars(text.data(), text.data() + text.size(), value, base);
return value;
}
inline uint64_t ToUint64(std::string_view text, int base = 10) {
uint64_t value = 0;
std::from_chars(text.data(), text.data() + text.size(), value, base);
return value;
}
inline int32_t ToInt32(std::string_view text, int base = 10) {
int32_t value = 0;
std::from_chars(text.data(), text.data() + text.size(), value, base);
return value;
}
inline int64_t ToInt64(std::string_view text, int base = 10) {
int64_t value = 0;
std::from_chars(text.data(), text.data() + text.size(), value, base);
return value;
}
inline double ToDouble(std::string_view text) {
return std::stod(std::string(text));
}
inline float ToFloat(std::string_view text) {
return std::stof(std::string(text));
}
inline std::string SafeCsv(std::string_view text) {
const bool add_space =
!text.empty() && (text.front() == '+' || text.front() == '=' || text.front() == '-');
if (text.find('"') != std::string_view::npos || text.find(';') != std::string_view::npos ||
text.find('+') != std::string_view::npos || text.find('=') != std::string_view::npos ||
text.find('-') != std::string_view::npos) {
return "\"" + std::string(add_space ? " " : "") +
ReplaceStr(std::string(text), "\"", "\"\"") + "\"";
}
return std::string(text);
}
inline std::string Utf16ToUtf8(std::u16string_view utf16) {
if (utf16.empty()) {
return {};
@@ -324,23 +163,6 @@ inline std::string Utf16ToUtf8(std::u16string_view utf16) {
return convert.to_bytes(utf16.data(), utf16.data() + utf16.size());
}
inline ByteBuffer HexToBin(std::string_view text) {
ByteBuffer ret;
for (size_t i = 0; i + 1 < text.size(); i += 2) {
ret.Add(static_cast<Byte>((ToUint32(text.substr(i, 2), 16) & 0xffu)));
}
return ret;
}
inline std::string HexFromBin(const ByteBuffer& bin) {
std::string ret;
ret.reserve(bin.Size() * 2);
for (uint32_t i = 0; i < bin.Size(); i++) {
ret += fmt::format("{:02X}", std::to_integer<uint8_t>(bin.At(i)));
}
return ret;
}
} // namespace Common
#endif /* KYTY_COMMON_STRING_UTILS_H_ */
-4
View File
@@ -253,10 +253,6 @@ void Thread::Detach() {
m_thread->m_thread.detach();
}
void Thread::Sleep(uint32_t millis) {
std::this_thread::sleep_for(std::chrono::milliseconds(millis));
}
void Thread::SleepMicro(uint32_t micros) {
#ifdef KYTY_WIN_CS
SleepHighResolution100ns(static_cast<uint64_t>(micros) * 10);
-1
View File
@@ -31,7 +31,6 @@ public:
// The id is unique and can't be reused by another thread.
[[nodiscard]] int GetUniqueId() const;
static void Sleep(uint32_t millis);
static void SleepMicro(uint32_t micros);
static void SleepNano(uint64_t nanos);
static bool IsMainThread();
-17
View File
@@ -62,23 +62,6 @@ double Timer::GetTimeS() const {
return (static_cast<double>(current_time - m_StartTime)) / static_cast<double>(m_Frequency);
}
// return time in ticks
uint64_t Timer::GetTicks() const {
if (m_is_paused) {
return (m_PauseTime - m_StartTime);
}
uint64_t current_time = 0;
SysQueryPerformanceCounter(&current_time);
return (current_time - m_StartTime);
}
// return ticks frequency
uint64_t Timer::GetFrequency() const {
return m_Frequency;
}
uint64_t Timer::QueryPerformanceFrequency() {
uint64_t ret = 0;
SysQueryPerformanceFrequency(&ret);
-6
View File
@@ -24,12 +24,6 @@ public:
// return time in seconds
[[nodiscard]] double GetTimeS() const;
// return time in ticks
[[nodiscard]] uint64_t GetTicks() const;
// return ticks frequency
[[nodiscard]] uint64_t GetFrequency() const;
KYTY_CLASS_NO_COPY(Timer);
[[nodiscard]] static uint64_t QueryPerformanceFrequency();
-63
View File
@@ -1,63 +0,0 @@
#include "common/virtualMemory.h"
#include "common/platform/sysVirtual.h"
namespace Common {
namespace VirtualMemory {
void Init() {
SysVirtualInit();
}
uint64_t Alloc(uint64_t address, uint64_t size, Mode mode) {
return SysVirtualAlloc(address, size, mode);
}
uint64_t AllocAligned(uint64_t address, uint64_t size, Mode mode, uint64_t alignment) {
return SysVirtualAllocAligned(address, size, mode, alignment);
}
bool AllocFixed(uint64_t address, uint64_t size, Mode mode) {
return SysVirtualAllocFixed(address, size, mode);
}
bool Commit(uint64_t address, uint64_t size, Mode mode) {
return SysVirtualCommit(address, size, mode);
}
uint64_t Reserve(uint64_t address, uint64_t size) {
return SysVirtualReserve(address, size);
}
uint64_t ReserveAligned(uint64_t address, uint64_t size, uint64_t alignment) {
return SysVirtualReserveAligned(address, size, alignment);
}
bool ReserveFixed(uint64_t address, uint64_t size) {
return SysVirtualReserveFixed(address, size);
}
bool Decommit(uint64_t address, uint64_t size) {
return SysVirtualDecommit(address, size);
}
bool Free(uint64_t address) {
return SysVirtualFree(address);
}
bool FreeRange(uint64_t address, uint64_t size) {
return SysVirtualFreeRange(address, size);
}
bool Protect(uint64_t address, uint64_t size, Mode mode) {
return SysVirtualProtect(address, size, mode);
}
bool FlushInstructionCache(uint64_t address, uint64_t size) {
return SysVirtualFlushInstructionCache(address, size);
}
} // namespace VirtualMemory
} // namespace Common
+2 -10
View File
@@ -4,15 +4,12 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/profiler.h"
#include "common/stringUtils.h"
#include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/guest_gpu/gpu_format.h"
#include <algorithm>
#include <array>
#include <bit>
#include <fmt/format.h>
#include <vector>
namespace Libs::Graphics {
@@ -1322,13 +1319,8 @@ void TileGetTextureSize(Prospero::BufferFormat format, uint32_t width, uint32_t
return;
}
if (total_size != nullptr && total_size->size == 0) {
std::vector<std::string> list;
list.push_back(fmt::format("format = {}", static_cast<uint32_t>(format)));
list.push_back(fmt::format("width = {}", width));
list.push_back(fmt::format("height = {}", height));
list.push_back(fmt::format("levels = {}", levels));
list.push_back(fmt::format("tile = {}", static_cast<uint32_t>(tile)));
EXIT("unknown format:\n%s\n", Common::Concat(list, '\n').c_str());
EXIT("unknown format:\nformat = %u\nwidth = %u\nheight = %u\nlevels = %u\ntile = %u\n",
static_cast<uint32_t>(format), width, height, levels, static_cast<uint32_t>(tile));
}
}
+1
View File
@@ -16,6 +16,7 @@
#include <windows.h>
#undef min
#undef max
#undef MemoryBarrier
#elif defined(__APPLE__)
#include <pthread.h>
#elif defined(__linux__)
@@ -593,6 +593,21 @@ PipelineCache::GraphicsPrograms PipelineCache::GetGraphicsPrograms(
ShaderParams pixel_params;
if (pixel_active) {
pixel_params = PrepareProgram(pixel_regs, sh, target_export_mapping, pixel_info);
const auto& blend = context.GetBlendControl(0);
const auto is_dual_source = [](uint8_t factor) {
return factor >= static_cast<uint8_t>(Prospero::BlendFactor::kSrc1Color) &&
factor <= static_cast<uint8_t>(Prospero::BlendFactor::kOneMinusSrc1Alpha);
};
pixel_info.dual_source_blending =
blend.enable && !context.GetRenderTarget(0).info.blend_bypass &&
(is_dual_source(blend.color_srcblend) || is_dual_source(blend.color_destblend) ||
(blend.separate_alpha_blend &&
(is_dual_source(blend.alpha_srcblend) || is_dual_source(blend.alpha_destblend))));
if (pixel_info.dual_source_blending) {
// MRT1 supplies a second blend source for the same render target as MRT0.
pixel_info.target_output_mode[1] = pixel_info.target_output_mode[0];
pixel_info.target_export_mapping[1] = pixel_info.target_export_mapping[0];
}
}
if (context.GetClipControl().clip_disable) {
const auto& viewport = context.GetScreenViewport().viewports[0];
@@ -46,8 +46,8 @@ vk::PipelineStageFlags ShaderPipelineStages(vk::ShaderStageFlags stages) {
return result;
}
VulkanMemoryBarrier MakeShaderWriteDependency() {
VulkanMemoryBarrier barrier {};
vk::MemoryBarrier MakeShaderWriteDependency() {
vk::MemoryBarrier barrier {};
barrier.srcAccessMask = vk::AccessFlagBits::eShaderWrite;
barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eVertexAttributeRead |
@@ -58,15 +58,15 @@ VulkanMemoryBarrier MakeShaderWriteDependency() {
return barrier;
}
VulkanMemoryBarrier MakeShaderAccessDependency() {
VulkanMemoryBarrier barrier {};
vk::MemoryBarrier MakeShaderAccessDependency() {
vk::MemoryBarrier barrier {};
barrier.srcAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite;
barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
return barrier;
}
VulkanMemoryBarrier MakeShaderWriteHazardDependency() {
VulkanMemoryBarrier barrier {};
vk::MemoryBarrier MakeShaderWriteHazardDependency() {
vk::MemoryBarrier barrier {};
barrier.srcAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite;
return barrier;
@@ -10,9 +10,9 @@ struct ShaderStageRuntime;
vk::ShaderStageFlagBits NativeShaderStage(ShaderType stage);
vk::PipelineStageFlags ShaderPipelineStages(vk::ShaderStageFlags stages);
VulkanMemoryBarrier MakeShaderAccessDependency();
VulkanMemoryBarrier MakeShaderWriteHazardDependency();
VulkanMemoryBarrier MakeShaderWriteDependency();
vk::MemoryBarrier MakeShaderAccessDependency();
vk::MemoryBarrier MakeShaderWriteHazardDependency();
vk::MemoryBarrier MakeShaderWriteDependency();
vk::BufferMemoryBarrier MakeGdsDependency(vk::Buffer buffer);
bool HasShaderBufferWrites(const ShaderStageRuntime& runtime);
void ShaderAccessBarrier(vk::CommandBuffer vk_buffer, vk::PipelineStageFlags source_stages);
@@ -225,7 +225,7 @@ void RenderExecutor::DispatchDirect(uint64_t submit_id, CommandBuffer& buffer,
return;
}
if (!ShaderAddressValid(sh_ctx.GetCs().cs_regs.data_addr)) {
if (sh_ctx.GetCs().cs_regs.data_addr == 0) {
return;
}
@@ -421,7 +421,7 @@ static void SetGraphicsDynamicParams(const CommandBuffer& buffer, vk::CommandBuf
static bool DrawHasValidVertexShader(const HW::Shader& sh_ctx) {
const auto& vs = sh_ctx.GetVs();
return ShaderAddressValid(vs.es_regs.data_addr);
return vs.es_regs.data_addr != 0;
}
static bool PixelShaderHasDepthOrCoverageSideEffects(const HW::ShaderRegisters& sh_regs) {
@@ -608,7 +608,7 @@ static bool DrawHasActivePixelShader(const CommandBuffer& buffer) {
const auto& ctx = buffer.GetRegisters();
const auto& sh_regs = ctx.GetShaderRegisters();
const bool has_color_output = (ctx.GetRenderTargetMask() & sh_regs.m_cbShaderMask) != 0;
return ShaderAddressValid(buffer.GetShaders().GetPs().ps_regs.data_addr) &&
return buffer.GetShaders().GetPs().ps_regs.data_addr != 0 &&
(has_color_output || PixelShaderHasDepthOrCoverageSideEffects(sh_regs));
}
-2
View File
@@ -24,8 +24,6 @@
namespace Libs::Graphics {
using VulkanMemoryBarrier = vk::MemoryBarrier;
vk::Format VulkanFormat(Prospero::BufferFormat guest_format);
void RequireVulkanSuccess(vk::Result result, const char* operation);
vk::ShaderModule CompileSPV(std::span<const uint32_t> code, vk::Device device);
@@ -22,9 +22,6 @@
// IWYU pragma: no_include <intrin.h>
#define KYTY_ENABLE_DEBUG_PRINTF
#define KYTY_DBG_INPUT
namespace Libs::Graphics {
struct Presenter::Frame {
@@ -49,7 +49,6 @@
// IWYU pragma: no_include <intrin.h>
#define KYTY_ENABLE_DEBUG_PRINTF
#define KYTY_DBG_INPUT
namespace Libs::Graphics {
@@ -611,10 +610,11 @@ static vk::Device VulkanCreateDevice(GraphicContext& graphics,
graphics.mesh_shader_properties.maxMeshOutputPrimitives,
graphics.mesh_shader_properties.maxMeshSharedMemorySize);
}
// VulkanFindPhysicalDevice already checked the required creation features. These two
// VulkanFindPhysicalDevice already checked the required creation features. These
// requirements are specific to this creation path and are not part of device selection.
EXIT_NOT_IMPLEMENTED(supported_features2.features.shaderInt64 != VK_TRUE);
EXIT_NOT_IMPLEMENTED(supported_features2.features.vertexPipelineStoresAndAtomics != VK_TRUE);
EXIT_NOT_IMPLEMENTED(supported_features2.features.dualSrcBlend != VK_TRUE);
vk::PhysicalDeviceFeatures device_features {};
device_features.fragmentStoresAndAtomics = VK_TRUE;
device_features.samplerAnisotropy = VK_TRUE;
@@ -625,6 +625,7 @@ static vk::Device VulkanCreateDevice(GraphicContext& graphics,
device_features.shaderStorageImageWriteWithoutFormat = VK_TRUE;
device_features.shaderImageGatherExtended = VK_TRUE;
device_features.independentBlend = VK_TRUE;
device_features.dualSrcBlend = VK_TRUE;
device_features.tessellationShader = VK_TRUE;
device_features.sampleRateShading = VK_TRUE;
device_features.depthBiasClamp = VK_TRUE;
+21 -15
View File
@@ -52,7 +52,6 @@
// IWYU pragma: no_include <intrin.h>
#define KYTY_ENABLE_DEBUG_PRINTF
#define KYTY_DBG_INPUT
namespace Libs::Graphics {
@@ -180,12 +179,6 @@ struct EventDisplay {
DisplayOrientation orientation;
};
constexpr uint32_t KYTY_SDL_BUTTON_LMASK = SDL_BUTTON_LMASK; // NOLINT(hicpp-signed-bitwise)
constexpr uint32_t KYTY_SDL_BUTTON_MMASK = SDL_BUTTON_MMASK; // NOLINT(hicpp-signed-bitwise)
constexpr uint32_t KYTY_SDL_BUTTON_RMASK = SDL_BUTTON_RMASK; // NOLINT(hicpp-signed-bitwise)
constexpr uint32_t KYTY_SDL_BUTTON_X1MASK = SDL_BUTTON_X1MASK; // NOLINT(hicpp-signed-bitwise)
constexpr uint32_t KYTY_SDL_BUTTON_X2MASK = SDL_BUTTON_X2MASK; // NOLINT(hicpp-signed-bitwise)
namespace {
std::unique_ptr<WindowContext> g_window;
@@ -193,7 +186,6 @@ std::unique_ptr<WindowContext> g_window;
} // namespace
constexpr const char* KYTY_SDL_WINDOW_CAPTION = "Game";
constexpr int KYTY_SDL_WINDOWPOS_CENTERED = SDL_WINDOWPOS_CENTERED; /*NOLINT(hicpp-signed-bitwise)*/
static void SetPause(WindowLoopState& game, bool flag) {
LOGF("Pause: %s\n", flag ? "true" : "false");
@@ -614,11 +606,11 @@ void WindowContext::ProcessEvent(double time_s) {
mb.down = false;
mb.up = false;
mb.left = ((event->motion.state & KYTY_SDL_BUTTON_LMASK) != 0u);
mb.middle = ((event->motion.state & KYTY_SDL_BUTTON_MMASK) != 0u);
mb.right = ((event->motion.state & KYTY_SDL_BUTTON_RMASK) != 0u);
mb.x1 = ((event->motion.state & KYTY_SDL_BUTTON_X1MASK) != 0u);
mb.x2 = ((event->motion.state & KYTY_SDL_BUTTON_X2MASK) != 0u);
mb.left = ((event->motion.state & SDL_BUTTON_LMASK) != 0u);
mb.middle = ((event->motion.state & SDL_BUTTON_MMASK) != 0u);
mb.right = ((event->motion.state & SDL_BUTTON_RMASK) != 0u);
mb.x1 = ((event->motion.state & SDL_BUTTON_X1MASK) != 0u);
mb.x2 = ((event->motion.state & SDL_BUTTON_X2MASK) != 0u);
mb.touch = (event->motion.which == SDL_TOUCH_MOUSEID);
mb.pressed = false;
mb.released = false;
@@ -713,6 +705,20 @@ void WindowContext::ProcessEvent(double time_s) {
}
break;
case SDL_CONTROLLERSENSORUPDATE: {
const auto& sensor = event->csensor;
if (sensor.sensor == SDL_SENSOR_ACCEL || sensor.sensor == SDL_SENSOR_GYRO) {
Controller::SetSensor(sensor.which,
sensor.sensor == SDL_SENSOR_ACCEL ? Controller::Sensor::Accel
: Controller::Sensor::Gyro,
sensor.data,
sensor.timestamp_us != 0
? sensor.timestamp_us
: static_cast<uint64_t>(sensor.timestamp) * 1000);
}
break;
}
case SDL_CONTROLLERDEVICEADDED:
case SDL_CONTROLLERDEVICEREMOVED:
case SDL_CONTROLLERDEVICEREMAPPED: {
@@ -854,8 +860,8 @@ static void WindowCreate(WindowContext& context) {
window_flags |= static_cast<uint32_t>(SDL_WINDOW_BORDERLESS);
}
#endif
context.window = SDL_CreateWindow(KYTY_SDL_WINDOW_CAPTION, KYTY_SDL_WINDOWPOS_CENTERED,
KYTY_SDL_WINDOWPOS_CENTERED, width, height, window_flags);
context.window = SDL_CreateWindow(KYTY_SDL_WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, width, height, window_flags);
if (context.window == nullptr) {
EXIT("%s\n", SDL_GetError());
@@ -105,8 +105,6 @@ void ClearEmbeddedFetchVectorLanes(EmbeddedFetchVectorLanes* lanes, uint32_t reg
lanes->erase(first, last);
}
using EmbeddedFetchData = Frontend::EmbeddedFetchPlan;
bool IsDecodedSgpr(const Decoder::Operand& op) {
return op.kind == Decoder::OperandKind::Sgpr || op.kind == Decoder::OperandKind::VccLo ||
op.kind == Decoder::OperandKind::VccHi;
@@ -210,13 +208,12 @@ int BufferTableAttribFromOffset(uint32_t raw_offset, int dword) {
return static_cast<int>((raw_offset + static_cast<uint32_t>(dword) * 4u) / 16u);
}
EmbeddedFetchData DetectEmbeddedVertexFetch(const Decoder::Program& decoded,
const ShaderVertexInputInfo* input_info,
uint32_t user_data_base, uint32_t user_data_count,
uint32_t wave_size) {
Frontend::EmbeddedFetchPlan DetectEmbeddedVertexFetch(
const Decoder::Program& decoded, const ShaderVertexInputInfo* input_info,
uint32_t user_data_base, uint32_t user_data_count, uint32_t wave_size) {
const uint32_t vertex_index_reg = input_info->logical_stage == ShaderType::Local ? 2u : 5u;
const uint32_t instance_index_reg = input_info->logical_stage == ShaderType::Local ? 5u : 8u;
EmbeddedFetchData data;
Frontend::EmbeddedFetchPlan data;
data.loads.reserve(input_info->resources_num);
int32_t vertex_offset_candidate = -1;
int32_t instance_offset_candidate = -1;
@@ -560,7 +557,7 @@ TranslateResult TranslateProgram(std::span<const uint32_t> code, const CompileOp
static_cast<uint64_t>(cfg.natural_loops.size()), phase_ms());
}
EmbeddedFetchData embedded_fetch;
Frontend::EmbeddedFetchPlan embedded_fetch;
if ((options.stage == ShaderType::Vertex || options.stage == ShaderType::Local) &&
options.input_info.vertex != nullptr && options.input_info.vertex->fetch_embedded) {
embedded_fetch = DetectEmbeddedVertexFetch(
@@ -138,7 +138,7 @@ uint32_t EmitDppWriteCondition(ValueEmitContext& ctx, const IR::DppMoveFlags& fl
state.builder.AddFunction(spv::OpLogicalAnd, TypeBool(state), masks_ok, bank_ok, row_ok);
uint32_t writable = masks_ok;
if (!flags.bound_control) {
const auto target = EmitDppTargetLane(state, flags.control);
const auto target = EmitDppTargetLane(state, flags);
const auto bounded = state.builder.AllocateId();
state.builder.AddFunction(spv::OpLogicalAnd, TypeBool(state), bounded, writable,
target.valid);
@@ -611,7 +611,7 @@ uint32_t EmitUndefU1(EmitterState& state, const IR::Inst& inst) {
uint32_t EmitDppMoveU32(ValueEmitContext& ctx, const IR::Inst& inst) {
auto& state = ctx.state;
const auto flags = inst.Flags<IR::DppMoveFlags>();
const auto target = EmitDppTargetLane(state, flags.control);
const auto target = EmitDppTargetLane(state, flags);
const auto shuffled = ctx.Shuffle(inst, 0, target.lane);
if (flags.fetch_inactive) {
return shuffled;
@@ -2,24 +2,26 @@
namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter {
DppTargetLane EmitDppQuadPermTargetLane(EmitterState& state, uint32_t subid, uint32_t control) {
const auto quad_base = state.builder.AllocateId();
DppTargetLane EmitDppPermTargetLane(EmitterState& state, uint32_t subid, uint32_t control,
uint32_t lane_bits) {
const auto lane_mask = (1u << lane_bits) - 1u;
const auto group_base = state.builder.AllocateId();
const auto lane = state.builder.AllocateId();
const auto shift = state.builder.AllocateId();
const auto selected0 = state.builder.AllocateId();
const auto selected = state.builder.AllocateId();
const auto target = state.builder.AllocateId();
state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), quad_base, subid,
ConstantU32(state, 0xfffffffcu));
state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), group_base, subid,
ConstantU32(state, ~lane_mask));
state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), lane, subid,
ConstantU32(state, 3));
state.builder.AddFunction(spv::OpShiftLeftLogical, TypeU32(state), shift, lane,
ConstantU32(state, 1));
ConstantU32(state, lane_mask));
state.builder.AddFunction(spv::OpIMul, TypeU32(state), shift, lane,
ConstantU32(state, lane_bits));
state.builder.AddFunction(spv::OpShiftRightLogical, TypeU32(state), selected0,
ConstantU32(state, control), shift);
state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), selected, selected0,
ConstantU32(state, 3));
state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), target, quad_base, selected);
ConstantU32(state, lane_mask));
state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), target, group_base, selected);
return {target, ConstantBool(state, true)};
}
@@ -89,10 +91,14 @@ DppTargetLane EmitDppMirrorTargetLane(EmitterState& state, uint32_t subid, bool
return {target, ConstantBool(state, true)};
}
DppTargetLane EmitDppTargetLane(EmitterState& state, uint32_t control) {
DppTargetLane EmitDppTargetLane(EmitterState& state, const IR::DppMoveFlags& flags) {
const auto subid = EmitSubgroupLocalInvocationId(state);
const auto control = flags.control;
if (flags.dpp8) {
return EmitDppPermTargetLane(state, subid, control, 3u);
}
if (control <= 0xffu) {
return EmitDppQuadPermTargetLane(state, subid, control);
return EmitDppPermTargetLane(state, subid, control, 2u);
}
if (control >= 0x101u && control <= 0x10fu) {
return EmitDppRowShiftTargetLane(state, subid, control & 0xfu, true);
@@ -308,8 +308,6 @@ uint32_t ConstantI32(EmitterState& state, int32_t value);
uint32_t ConstantF32(EmitterState& state, uint32_t bits);
uint32_t FloatBits(float value);
uint32_t ConstantF32Value(EmitterState& state, float value);
uint32_t ConstantBool(EmitterState& state, bool value);
@@ -329,7 +327,8 @@ void EmitMeshAllocate(ValueEmitContext& ctx, const IR::Inst& inst);
uint32_t MeshOutputPointer(EmitterState& state, IR::StageOutputKind kind, uint32_t index = 0);
uint32_t MeshPrimitivePointer(EmitterState& state);
DppTargetLane EmitDppQuadPermTargetLane(EmitterState& state, uint32_t subid, uint32_t control);
DppTargetLane EmitDppPermTargetLane(EmitterState& state, uint32_t subid, uint32_t control,
uint32_t lane_bits);
DppTargetLane EmitDppRowShiftTargetLane(EmitterState& state, uint32_t subid, uint32_t amount,
bool left);
@@ -338,7 +337,7 @@ DppTargetLane EmitDppRowRotateRightTargetLane(EmitterState& state, uint32_t subi
DppTargetLane EmitDppMirrorTargetLane(EmitterState& state, uint32_t subid, bool half_row);
DppTargetLane EmitDppTargetLane(EmitterState& state, uint32_t control);
DppTargetLane EmitDppTargetLane(EmitterState& state, const IR::DppMoveFlags& flags);
uint32_t EmitSubgroupLocalInvocationId(EmitterState& state);
@@ -514,31 +514,6 @@ void StoreWord(ValueEmitContext& ctx, const IR::Inst& inst, IR::MemoryInfo mem)
});
}
void FormattedStorePrepared(ValueEmitContext& ctx, const IR::Inst& inst, const IR::MemoryInfo& mem,
uint32_t component, const MemoryResourceAccess& resource,
uint32_t data) {
const auto info = Format::GetFormatInfo(BufferFormat(ctx, mem));
if (info.type == Format::ComponentType::Unknown) {
StoreWordPrepared(ctx, inst, RebaseRawComponent(mem, component), resource, data);
return;
}
if (component >= info.component_count) return;
const auto bits = info.component_bits[component];
const auto component_mem = RebaseFormattedComponent(mem, info, component);
if (bits == 8u || bits == 16u) {
StoreSubwordPrepared(ctx, inst, component_mem, resource, bits, data);
} else {
StoreWordPrepared(ctx, inst, component_mem, resource, data);
}
}
void FormattedStore(ValueEmitContext& ctx, const IR::Inst& inst, const IR::MemoryInfo& mem) {
EmitIfCondition(ctx.state, ctx.Arg(inst, inst.NumArgs() - 1), [&]() {
const auto resource = PrepareMemoryResourceAccess(ctx.state, mem);
FormattedStorePrepared(ctx, inst, mem, 0u, resource, ctx.Arg(inst, inst.NumArgs() - 2));
});
}
spv::Op SpirvAtomicOpcode(IR::ValueOpcode opcode) {
switch (opcode) {
case IR::ValueOpcode::BufferAtomicCmpSwap32: return spv::OpAtomicCompareExchange;
@@ -729,6 +704,11 @@ void StoreFormattedInBounds(ValueEmitContext& ctx, const IR::MemoryInfo& mem,
uint32_t data) {
if (component >= plan.info.component_count) return;
const auto bits = plan.info.component_bits[component];
if (plan.info.type == Format::ComponentType::Snorm && bits == 16u) {
const auto value = EmitBitCastF32U32(ctx.state, data);
data = EmitPackSnorm2x16(
ctx.state, EmitCompositeConstructF32x2(ctx.state, value, ConstantF32Value(ctx.state, 0.0f)));
}
if (bits == 8u || bits == 16u) {
StoreSubwordInBounds(ctx, mem, plan.resource, plan.addresses[component],
plan.indices[component], bits, data);
@@ -737,6 +717,23 @@ void StoreFormattedInBounds(ValueEmitContext& ctx, const IR::MemoryInfo& mem,
}
}
void FormattedStore(ValueEmitContext& ctx, const IR::Inst& inst, const IR::MemoryInfo& mem) {
EmitIfCondition(ctx.state, ctx.Arg(inst, inst.NumArgs() - 1), [&]() {
const auto resource = PrepareMemoryResourceAccess(ctx.state, mem);
const auto data = ctx.Arg(inst, inst.NumArgs() - 2);
const auto info = Format::GetFormatInfo(BufferFormat(ctx, mem));
if (info.type == Format::ComponentType::Unknown) {
StoreWordPrepared(ctx, inst, RebaseRawComponent(mem, 0u), resource, data);
return;
}
const auto plan = PrepareFormattedMemory(ctx, inst, mem, resource, info, 1u,
FormattedAccess::Store);
EmitIfCondition(ctx.state, plan.in_bounds, [&]() {
StoreFormattedInBounds(ctx, mem, plan, 0u, data);
});
});
}
uint32_t LoadWideBuffer(ValueEmitContext& ctx, const IR::Inst& inst, uint32_t components) {
auto& state = ctx.state;
return EmitValueOrDefaultIfCondition(
@@ -1,6 +1,7 @@
#include "graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h"
#include <algorithm>
#include <bit>
namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter {
@@ -256,14 +257,8 @@ uint32_t ConstantF32(EmitterState& state, uint32_t bits) {
return state.builder.Constant(spv::OpConstant, TypeF32(state), bits);
}
uint32_t FloatBits(float value) {
uint32_t bits = 0;
std::memcpy(&bits, &value, sizeof(bits));
return bits;
}
uint32_t ConstantF32Value(EmitterState& state, float value) {
return ConstantF32(state, FloatBits(value));
return ConstantF32(state, std::bit_cast<uint32_t>(value));
}
uint32_t ConstantBool(EmitterState& state, bool value) {
@@ -558,8 +553,17 @@ void DefineOutputs(EmitterState& state) {
const auto type = uint_output ? TypeU32Vector(state, 4) : TypeF32Vector(state, 4);
binding.variable_id = DefineInterfaceVariable(state, type, spv::StorageClassOutput,
binding.debug_name.c_str());
const bool dual_source = binding.kind == IR::StageOutputKind::Mrt &&
state.program.stage == ShaderType::Pixel &&
state.input_info.pixel->dual_source_blending;
EXIT_NOT_IMPLEMENTED(dual_source && binding.index > 1);
state.builder.AddAnnotation(spv::OpDecorate, binding.variable_id,
spv::DecorationLocation, binding.location);
spv::DecorationLocation,
dual_source ? 0u : binding.location);
if (dual_source) {
state.builder.AddAnnotation(spv::OpDecorate, binding.variable_id,
spv::DecorationIndex, binding.index);
}
break;
}
}
@@ -3,6 +3,7 @@
#include "graphics/shader/recompiler/frontend/decode/OpcodeTable.h"
#include <algorithm>
#include <bit>
namespace Libs::Graphics::ShaderRecompiler::Decoder {
namespace {
@@ -203,18 +204,6 @@ constexpr auto MIMG_SAMPLE_OPS = Detail::MakeOpcodeTable<0x100>(MIMG_SAMPLE_OPCO
constexpr auto MIMG_GATHER_OPS = Detail::MakeOpcodeTable<0x100>(MIMG_GATHER_OPCODE_LIST);
constexpr auto MIMG_ATOMIC_OPS = Detail::MakeOpcodeTable<0x100>(MIMG_ATOMIC_OPCODE_LIST);
const MimgSampleInfo* LookupSample(uint32_t opcode) {
return Detail::FindOpcode(MIMG_SAMPLE_OPS, opcode);
}
const MimgGatherInfo* LookupGather(uint32_t opcode) {
return Detail::FindOpcode(MIMG_GATHER_OPS, opcode);
}
const Detail::OpcodeMap* LookupAtomic(uint32_t opcode) {
return Detail::FindOpcode(MIMG_ATOMIC_OPS, opcode);
}
Opcode DecodeMimgOpcode(uint32_t opcode, const MimgSampleInfo* sample, const MimgGatherInfo* gather,
const Detail::OpcodeMap* atomic) {
if (sample != nullptr) {
@@ -280,10 +269,6 @@ uint32_t CountDmaskComponents(uint32_t dmask) {
return count != 0 ? count : 1u;
}
bool IsSingleDmaskBit(uint32_t dmask) {
return dmask != 0u && (dmask & (dmask - 1u)) == 0u;
}
} // namespace
ImageAddressComponent ImageAddressComponentLayout(uint32_t flags, uint32_t component) {
@@ -332,9 +317,9 @@ void DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
const bool r128 = ((word0 >> 15u) & 0x1u) != 0u;
const bool a16 = ((word1 >> 30u) & 0x1u) != 0u;
const bool d16 = ((word1 >> 31u) & 0x1u) != 0u;
const auto* sample = LookupSample(opcode);
const auto* gather = LookupGather(opcode);
const auto* atomic = LookupAtomic(opcode);
const auto* sample = Detail::FindOpcode(MIMG_SAMPLE_OPS, opcode);
const auto* gather = Detail::FindOpcode(MIMG_GATHER_OPS, opcode);
const auto* atomic = Detail::FindOpcode(MIMG_ATOMIC_OPS, opcode);
inst.pc = pc;
inst.word_count = word_count;
@@ -364,7 +349,7 @@ void DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
if (inst.opcode == Opcode::UNSUPPORTED) {
SetUnsupported(inst, Family::MIMG, opcode, "MIMG opcode is not implemented");
}
if (gather != nullptr && !IsSingleDmaskBit(inst.dmask)) {
if (gather != nullptr && !std::has_single_bit(inst.dmask)) {
SetUnsupported(inst, Family::MIMG, opcode,
"MIMG image gather requires exactly one dmask bit");
}
@@ -382,7 +367,7 @@ void DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
}
const char* MimgSampleOpcodeName(uint32_t opcode) {
const auto* sample = LookupSample(opcode);
const auto* sample = Detail::FindOpcode(MIMG_SAMPLE_OPS, opcode);
return sample != nullptr ? sample->name : nullptr;
}
@@ -14,10 +14,6 @@
namespace Libs::Graphics::ShaderRecompiler::Decoder {
namespace {
uint32_t FloatBits(float value) {
return std::bit_cast<uint32_t>(value);
}
bool HasLiteral(const Instruction& inst) {
return inst.src0.kind == OperandKind::LiteralConstant ||
inst.src1.kind == OperandKind::LiteralConstant ||
@@ -242,7 +238,7 @@ void DecodeScalarSource(uint32_t code, uint32_t pc, Operand& operand) {
if (code >= 240u && code <= 247u) {
constexpr float values[] = {0.5f, -0.5f, 1.0f, -1.0f, 2.0f, -2.0f, 4.0f, -4.0f};
operand.kind = OperandKind::FloatInlineConstant;
operand.value = FloatBits(values[code - 240u]);
operand.value = std::bit_cast<uint32_t>(values[code - 240u]);
return;
}
if (code >= 256u && code <= 511u) {
@@ -260,7 +256,7 @@ void DecodeScalarSource(uint32_t code, uint32_t pc, Operand& operand) {
case 239u: operand.kind = OperandKind::PopsExitingWaveId; return;
case 248u:
operand.kind = OperandKind::FloatInlineConstant;
operand.value = FloatBits(0.15915494309189535f);
operand.value = std::bit_cast<uint32_t>(0.15915494309189535f);
return;
case 251u: operand.kind = OperandKind::VccZ; return;
case 252u: operand.kind = OperandKind::ExecZ; return;
@@ -476,8 +472,9 @@ std::string OperandToString(const Operand& operand) {
text += ".clamp";
}
if (operand.dpp) {
text += fmt::format(".dpp(ctrl=0x{:x},fi={},bc={})", operand.dpp_ctrl,
operand.dpp_fetch_inactive ? 1u : 0u, operand.dpp_bound_ctrl ? 1u : 0u);
text += fmt::format(".{}(ctrl=0x{:x},fi={},bc={})", operand.dpp8 ? "dpp8" : "dpp",
operand.dpp_ctrl, operand.dpp_fetch_inactive ? 1u : 0u,
operand.dpp_bound_ctrl ? 1u : 0u);
}
return text;
}
@@ -2,8 +2,8 @@
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SHADERDECODER_H_
#include "common/common.h"
#include "common/magicEnum.h"
#include <magic_enum.hpp>
#include <span>
#include <string_view>
#include <vector>
@@ -228,6 +228,7 @@ enum class Opcode {
V_CVT_PKRTZ_F16_F32,
V_CVT_PK_U8_F32,
V_MAD_F32,
V_MAD_I16,
V_MAD_I32_I24,
V_MAD_U32_U24,
V_MAD_U64_U32,
@@ -300,6 +301,7 @@ enum class Opcode {
V_SUBREV_NC_U32,
V_ADD_NC_U16,
V_SUB_NC_U16,
V_MUL_LO_U16,
V_MAX_U16,
V_MAX_I16,
V_MIN_U16,
@@ -378,7 +380,9 @@ enum class Opcode {
V_CMP_GT_F16,
V_CMP_LG_F16,
V_CMP_GE_F16,
V_CMP_NGT_F16,
V_CMP_NEQ_F16,
V_CMP_NLT_F16,
V_CMPX_LT_F16,
V_CMPX_EQ_F16,
V_CMPX_LE_F16,
@@ -666,6 +670,7 @@ struct Operand {
bool absolute = false;
bool clamp = false;
bool dpp = false;
bool dpp8 = false;
};
struct Instruction {
@@ -83,10 +83,6 @@ constexpr Vop2OpcodeInfo VOP2_OPCODE_LIST[] = {
constexpr auto VOP2_OPS = Detail::MakeOpcodeTable<0x40>(VOP2_OPCODE_LIST);
constexpr Opcode LookupVop2Opcode(uint32_t encoding) {
return Detail::LookupOpcode(VOP2_OPS, encoding);
}
constexpr OpcodeMap VOP1_OPCODE_LIST[] = {
{0x00u, Opcode::V_NOP},
{0x01u, Opcode::V_MOV_B32},
@@ -250,7 +246,8 @@ constexpr VopcOpcodeInfo VOPC_OPCODE_LIST[] = {
{0xf5u, Opcode::V_CMPX_NE_U64, false}, {0xc9u, Opcode::V_CMP_LT_F16},
{0xcau, Opcode::V_CMP_EQ_F16}, {0xcbu, Opcode::V_CMP_LE_F16},
{0xccu, Opcode::V_CMP_GT_F16}, {0xcdu, Opcode::V_CMP_LG_F16},
{0xceu, Opcode::V_CMP_GE_F16}, {0xedu, Opcode::V_CMP_NEQ_F16},
{0xceu, Opcode::V_CMP_GE_F16}, {0xebu, Opcode::V_CMP_NGT_F16},
{0xedu, Opcode::V_CMP_NEQ_F16}, {0xeeu, Opcode::V_CMP_NLT_F16},
{0xd9u, Opcode::V_CMPX_LT_F16}, {0xdau, Opcode::V_CMPX_EQ_F16},
{0xdbu, Opcode::V_CMPX_LE_F16}, {0xdcu, Opcode::V_CMPX_GT_F16},
{0xdeu, Opcode::V_CMPX_GE_F16}, {0xfbu, Opcode::V_CMPX_NGT_F16},
@@ -298,6 +295,7 @@ constexpr OpcodeMap VOP3_OPCODE_LIST[] = {
{0x300u, Opcode::V_LSHRREV_B64},
{0x303u, Opcode::V_ADD_NC_U16},
{0x304u, Opcode::V_SUB_NC_U16},
{0x305u, Opcode::V_MUL_LO_U16},
{0x307u, Opcode::V_LSHRREV_B16},
{0x308u, Opcode::V_ASHRREV_I16},
{0x309u, Opcode::V_MAX_U16},
@@ -314,6 +312,7 @@ constexpr OpcodeMap VOP3_OPCODE_LIST[] = {
{0x345u, Opcode::V_XAD_U32},
{0x346u, Opcode::V_LSHL_ADD_U32},
{0x347u, Opcode::V_ADD_LSHL_U32},
{0x35eu, Opcode::V_MAD_I16},
{0x360u, Opcode::V_READLANE_B32},
{0x361u, Opcode::V_WRITELANE_B32},
{0x362u, Opcode::V_LDEXP_F32},
@@ -374,7 +373,7 @@ Opcode LookupVop3Opcode(uint32_t opcode) {
if (IsUnsupportedVop3EncodedVop2Alias(opcode - 0x100u)) {
return Opcode::UNSUPPORTED;
}
return LookupVop2Opcode(opcode - 0x100u);
return Detail::LookupOpcode(VOP2_OPS, opcode - 0x100u);
}
if (opcode >= 0x180u && opcode <= 0x1ffu) {
return Detail::LookupOpcode(VOP3_ENCODED_VOP1_OPS, opcode - 0x180u);
@@ -426,13 +425,14 @@ bool IsNativeVop3F16TernaryOpcode(Opcode opcode) {
}
bool IsNativeVop3I16TernaryOpcode(Opcode opcode) {
return opcode == Opcode::V_MED3_I16;
return opcode == Opcode::V_MED3_I16 || opcode == Opcode::V_MAD_I16;
}
bool IsNativeVop3B16BinaryOpcode(Opcode opcode) {
switch (opcode) {
case Opcode::V_ADD_NC_U16:
case Opcode::V_SUB_NC_U16:
case Opcode::V_MUL_LO_U16:
case Opcode::V_MAX_U16:
case Opcode::V_MAX_I16:
case Opcode::V_MIN_U16:
@@ -685,10 +685,15 @@ void DecodeVop1Sdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_i
ReadLiteralOperands(code, word_index, inst);
}
void ApplyDppModifier(Operand& operand, uint32_t modifier) {
void ApplyDppModifier(Operand& operand, uint32_t modifier, uint32_t encoding) {
operand.dpp = true;
if (encoding == 233u) {
operand.dpp8 = true;
operand.dpp_ctrl = modifier >> 8u;
return;
}
operand.negate = ((modifier >> 20u) & 0x1u) != 0u;
operand.absolute = ((modifier >> 21u) & 0x1u) != 0u;
operand.dpp = true;
operand.dpp_ctrl = (modifier >> 8u) & 0x1ffu;
operand.dpp_fetch_inactive = ((modifier >> 18u) & 0x1u) != 0u;
operand.dpp_bound_ctrl = ((modifier >> 19u) & 0x1u) != 0u;
@@ -709,7 +714,7 @@ void DecodeVop1Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_in
DecodeVectorGpr(vdst, inst.dst);
}
DecodeScalarSource(src0 + 256u, pc, inst.src0);
ApplyDppModifier(inst.src0, modifier);
ApplyDppModifier(inst.src0, modifier, code[word_index] & 0x1ffu);
inst.src_count = 1;
if (!IsVop1FloatSourceOpcode(inst.opcode) && (inst.src0.negate || inst.src0.absolute)) {
@@ -824,7 +829,9 @@ bool IsVopcFloatCompareOpcode(Opcode opcode) {
case Opcode::V_CMP_GT_F16:
case Opcode::V_CMP_LG_F16:
case Opcode::V_CMP_GE_F16:
case Opcode::V_CMP_NGT_F16:
case Opcode::V_CMP_NEQ_F16:
case Opcode::V_CMP_NLT_F16:
case Opcode::V_CMPX_LT_F16:
case Opcode::V_CMPX_EQ_F16:
case Opcode::V_CMPX_LE_F16:
@@ -1046,7 +1053,7 @@ void DecodeVop2Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_in
DecodeVectorGpr(vdst, inst.dst);
DecodeVectorGpr(vsrc1, inst.src1);
DecodeScalarSource(src0 + 256u, pc, inst.src0);
ApplyDppModifier(inst.src0, modifier);
ApplyDppModifier(inst.src0, modifier, code[word_index] & 0x1ffu);
inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u;
inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u;
const bool packed_fmac = inst.opcode == Opcode::V_PK_FMAC_F16;
@@ -1155,7 +1162,7 @@ void DecodeVopcDpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_in
DecodeVectorGpr(vsrc1, inst.src1);
DecodeScalarSource(src0 + 256u, pc, inst.src0);
inst.dst.kind = IsVopcCompareExec(inst.opcode) ? OperandKind::ExecLo : OperandKind::VccLo;
ApplyDppModifier(inst.src0, modifier);
ApplyDppModifier(inst.src0, modifier, code[word_index] & 0x1ffu);
inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u;
inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u;
inst.src_count = 2;
@@ -1171,6 +1178,7 @@ uint32_t NativeVop3SourceCount(Opcode opcode) {
case Opcode::V_MUL_I32_I24:
case Opcode::V_ADD_NC_U16:
case Opcode::V_SUB_NC_U16:
case Opcode::V_MUL_LO_U16:
case Opcode::V_MAX_U16:
case Opcode::V_MAX_I16:
case Opcode::V_MIN_U16:
@@ -1355,7 +1363,8 @@ bool SupportsNativeVop3ResultModifiers(Opcode opcode) {
}
bool SupportsNativeVop3Clamp(Opcode opcode) {
return SupportsNativeVop3ResultModifiers(opcode) || UsesInexactClampControl(opcode);
return SupportsNativeVop3ResultModifiers(opcode) || UsesInexactClampControl(opcode) ||
opcode == Opcode::V_MAD_I16;
}
bool HasUnsupportedNativeVop3Modifiers(Opcode opcode, bool permlane, bool mad_mix,
@@ -1376,7 +1385,7 @@ bool HasUnsupportedNativeVop3Modifiers(Opcode opcode, bool permlane, bool mad_mi
return opcode != Opcode::V_FMA_F16 && (clamp != 0u || omod != 0u);
}
if (IsNativeVop3I16TernaryOpcode(opcode)) {
return abs != 0u || clamp != 0u || omod != 0u || neg != 0u;
return abs != 0u || (clamp != 0u && !clamp_modifier) || omod != 0u || neg != 0u;
}
if (IsNativeVop3B16BinaryOpcode(opcode)) {
return abs != 0u || clamp != 0u || omod != 0u || neg != 0u;
@@ -1468,7 +1477,7 @@ void DecodeVop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
inst.pc = pc;
inst.family = Family::VOP2;
inst.opcode_id = opcode;
inst.opcode = LookupVop2Opcode(opcode);
inst.opcode = Detail::LookupOpcode(VOP2_OPS, opcode);
SetRawWords(inst, code, word_index, 1);
if (inst.opcode == Opcode::UNSUPPORTED) {
@@ -1510,6 +1519,7 @@ void DecodeVop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
return;
}
switch (src0) {
case 233u: DecodeVop1Dpp(pc, code, word_index, opcode, vdst, inst); return;
case 249u: DecodeVop1Sdwa(pc, code, word_index, opcode, vdst, inst); return;
case 250u: DecodeVop1Dpp(pc, code, word_index, opcode, vdst, inst); return;
default: break;
@@ -166,9 +166,9 @@ void Translator::V_CVT_PK_U8_F32(const Decoder::Instruction& inst) {
}
void Translator::V_PACK_B32_F16(const Decoder::Instruction& inst) {
const auto low = ReadF16LaneBits(inst.src0, false);
const auto low = Read16LaneBits(inst.src0, false);
const auto high =
ir.ShiftLeftLogical(ReadF16LaneBits(inst.src1, false), IR::U32(IR::Value(16u)));
ir.ShiftLeftLogical(Read16LaneBits(inst.src1, false), IR::U32(IR::Value(16u)));
WriteOperand(DestinationOperand(inst), ir.BitwiseOr(low, high));
}
@@ -22,6 +22,18 @@ bool Translator::Integer16Binary(const Decoder::Instruction& inst, IR::ValueOpco
return true;
}
bool Translator::V_MAD_I16(const Decoder::Instruction& inst) {
const auto lhs = ReadU16AsU32(inst.src0, true);
const auto rhs = ReadU16AsU32(inst.src1, true);
auto result = ir.IAdd(ir.IMul(lhs, rhs), ReadU16AsU32(inst.src2, true));
if (inst.dst.clamp) {
result = IR::U32(ir.Emit(IR::ValueOpcode::SMax32, {result, IR::Value(0xffff8000u)}));
result = IR::U32(ir.Emit(IR::ValueOpcode::SMin32, {result, IR::Value(0x7fffu)}));
}
Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu))));
return true;
}
bool Translator::V_MED3_I16(const Decoder::Instruction& inst) {
const auto result = IR::U32(ir.Emit(
IR::ValueOpcode::SMedTri32, {ReadU16AsU32(inst.src0, true), ReadU16AsU32(inst.src1, true),
@@ -34,6 +34,7 @@ Decoder::Operand OffsetDecodedRegister(const Decoder::Operand& operand, uint32_t
result.negate_hi = false;
result.absolute = false;
result.dpp_ctrl = 0;
result.dpp8 = false;
result.dpp_row_mask = 0xf;
result.dpp_bank_mask = 0xf;
result.explicit_sdwa_dst = false;
@@ -9,6 +9,17 @@
namespace Libs::Graphics::ShaderRecompiler::Frontend {
static IR::DppMoveFlags DppFlags(const Decoder::Operand& operand) {
return {
.control = operand.dpp_ctrl,
.row_mask = operand.dpp_row_mask,
.bank_mask = operand.dpp_bank_mask,
.fetch_inactive = operand.dpp_fetch_inactive,
.bound_control = operand.dpp_bound_ctrl,
.dpp8 = operand.dpp8,
};
}
const Decoder::Operand& Translator::SourceAt(const Decoder::Instruction& inst, uint32_t index) {
switch (index) {
case 0: return inst.src0;
@@ -30,6 +41,7 @@ Decoder::Operand Translator::DestinationOperand(const Decoder::Instruction& inst
continue;
}
destination.dpp = true;
destination.dpp8 = source.dpp8;
destination.dpp_ctrl = source.dpp_ctrl;
destination.dpp_row_mask = source.dpp_row_mask;
destination.dpp_bank_mask = source.dpp_bank_mask;
@@ -106,6 +118,7 @@ Decoder::Operand Translator::PlainOperand(const Decoder::Operand& operand) {
result.dpp_fetch_inactive = false;
result.dpp_bound_ctrl = false;
result.dpp = false;
result.dpp8 = false;
return result;
}
@@ -167,14 +180,8 @@ IR::U32 Translator::ReadScalarCode(uint32_t code) {
IR::U32 Translator::ApplyBitSourceModifiers(const Decoder::Operand& operand, IR::U32 value) {
if (operand.dpp) {
const IR::DppMoveFlags flags {
.control = static_cast<uint16_t>(operand.dpp_ctrl),
.row_mask = static_cast<uint8_t>(operand.dpp_row_mask),
.bank_mask = static_cast<uint8_t>(operand.dpp_bank_mask),
.fetch_inactive = operand.dpp_fetch_inactive,
.bound_control = operand.dpp_bound_ctrl,
};
value = IR::U32(ir.Emit(IR::ValueOpcode::DppMoveU32, {value, ir.GetExec()}, flags));
value =
IR::U32(ir.Emit(IR::ValueOpcode::DppMoveU32, {value, ir.GetExec()}, DppFlags(operand)));
}
if (operand.sdwa_sel != 6u) {
uint32_t offset = 0;
@@ -301,15 +308,8 @@ void Translator::WriteRawU32(const Decoder::Operand& operand, IR::U32 value) {
const auto reg = static_cast<IR::VectorReg>(operand.reg);
const auto old = ir.GetVectorReg(reg);
if (operand.dpp) {
const IR::DppMoveFlags flags {
.control = static_cast<uint16_t>(operand.dpp_ctrl),
.row_mask = static_cast<uint8_t>(operand.dpp_row_mask),
.bank_mask = static_cast<uint8_t>(operand.dpp_bank_mask),
.fetch_inactive = operand.dpp_fetch_inactive,
.bound_control = operand.dpp_bound_ctrl,
};
value = IR::U32(
ir.Emit(IR::ValueOpcode::DppUpdateU32, {value, old, ir.GetExec()}, flags));
value = IR::U32(ir.Emit(IR::ValueOpcode::DppUpdateU32, {value, old, ir.GetExec()},
DppFlags(operand)));
} else {
value = ir.Select(ir.GetExec(), value, old);
}
@@ -541,10 +541,7 @@ IR::U32 Translator::ReadU16LaneRaw(const Decoder::Operand& operand, bool high_la
IR::U32 Translator::ReadU16LaneAsU32(const Decoder::Operand& operand, bool high_lane,
bool sign_extend) {
auto value = ReadU16LaneRaw(operand, high_lane);
if (high_lane ? operand.negate_hi : operand.negate) {
value = ir.BitwiseAnd(ir.ISub(IR::U32(IR::Value(0u)), value), IR::U32(IR::Value(0xffffu)));
}
auto value = Read16LaneBits(operand, high_lane);
if (sign_extend || operand.sdwa_sext) {
value = IR::U32(
ir.Emit(IR::ValueOpcode::BitFieldSExtract, {value, IR::Value(0u), IR::Value(16u)}));
@@ -556,12 +553,13 @@ IR::U32 Translator::ReadU16AsU32(const Decoder::Operand& operand, bool sign_exte
return ReadU16LaneAsU32(operand, false, sign_extend);
}
IR::U32 Translator::ReadF16LaneBits(const Decoder::Operand& operand, bool high_lane) {
IR::U32 Translator::Read16LaneBits(const Decoder::Operand& operand, bool high_lane) {
auto value = ReadU16LaneRaw(operand, high_lane);
if (operand.absolute) {
value = ir.BitwiseAnd(value, IR::U32(IR::Value(0x7fffu)));
}
if (high_lane ? operand.negate_hi : operand.negate) {
// RDNA2 source NEG flips the sign bit, including packed integer operands.
value = ir.BitwiseXor(value, IR::U32(IR::Value(0x8000u)));
}
return value;
@@ -44,7 +44,7 @@ private:
IR::U32 ReadU16LaneRaw(const Decoder::Operand& operand, bool high_lane);
IR::U32 ReadU16LaneAsU32(const Decoder::Operand& operand, bool high_lane, bool sign_extend);
IR::U32 ReadU16AsU32(const Decoder::Operand& operand, bool sign_extend);
IR::U32 ReadF16LaneBits(const Decoder::Operand& operand, bool high_lane);
IR::U32 Read16LaneBits(const Decoder::Operand& operand, bool high_lane);
std::array<IR::U32, 2> ExtractU64(IR::U64 value);
void WriteU32Pair(const Decoder::Operand& operand, const std::array<IR::U32, 2>& value);
IR::U32 ConditionBit(const Decoder::Operand& operand);
@@ -164,6 +164,7 @@ private:
bool FloatCube(const Decoder::Instruction& inst, uint32_t result_kind);
bool Integer16Shift(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool arithmetic);
bool Integer16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool sign);
bool V_MAD_I16(const Decoder::Instruction& inst);
bool V_MED3_I16(const Decoder::Instruction& inst);
bool PackedInteger16Shift(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool arithmetic);
@@ -264,6 +264,9 @@ bool Translator::EmitVector(const Decoder::Instruction& inst) {
case O::V_CMPX_LE_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThanEqual32, true, true);
return true;
case O::V_CMP_NGT_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThanEqual32, true, false);
return true;
case O::V_CMPX_NGT_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThanEqual32, true, true);
return true;
@@ -273,6 +276,9 @@ bool Translator::EmitVector(const Decoder::Instruction& inst) {
case O::V_CMPX_NEQ_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordNotEqual32, true, true);
return true;
case O::V_CMP_NLT_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThanEqual32, true, false);
return true;
case O::V_CMPX_NLT_F16:
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordGreaterThanEqual32, true, true);
return true;
@@ -321,6 +327,8 @@ bool Translator::EmitVector(const Decoder::Instruction& inst) {
case O::V_ADD_NC_I16: return Integer16Binary(inst, IR::ValueOpcode::IAdd32, false);
case O::V_SUB_NC_U16:
case O::V_SUB_NC_I16: return Integer16Binary(inst, IR::ValueOpcode::ISub32, false);
case O::V_MUL_LO_U16: return Integer16Binary(inst, IR::ValueOpcode::IMul32, false);
case O::V_MAD_I16: return V_MAD_I16(inst);
case O::V_MED3_I16: return V_MED3_I16(inst);
case O::V_MIN_I16: return Integer16Binary(inst, IR::ValueOpcode::SMin32, true);
case O::V_MAX_I16: return Integer16Binary(inst, IR::ValueOpcode::SMax32, true);
@@ -34,11 +34,12 @@ struct ImageOpcodeInfo {
};
struct DppMoveFlags {
uint16_t control = 0;
uint8_t row_mask = 0xf;
uint8_t bank_mask = 0xf;
uint32_t control : 24 = 0;
uint32_t row_mask : 4 = 0xf;
uint32_t bank_mask : 4 = 0xf;
bool fetch_inactive = false;
bool bound_control = false;
bool dpp8 = false;
};
static_assert(sizeof(DppMoveFlags) <= sizeof(uint64_t));
static_assert(std::is_trivially_copyable_v<DppMoveFlags>);
@@ -479,8 +479,6 @@ private:
return std::bit_cast<float>(static_cast<uint32_t>(bits));
}
static uint64_t Float32Bits(float value) { return std::bit_cast<uint32_t>(value); }
bool EvaluateWide(Value value, uint64_t& result) {
value = value.Resolve();
if (value.IsImmediate()) {
@@ -490,7 +488,7 @@ private:
case Type::U16: result = value.U16(); return true;
case Type::U32: result = value.U32(); return true;
case Type::U64: result = value.U64(); return true;
case Type::F32: result = Float32Bits(value.F32Value()); return true;
case Type::F32: result = std::bit_cast<uint32_t>(value.F32Value()); return true;
default: return false;
}
}
@@ -733,7 +731,7 @@ private:
return false;
case ValueOpcode::ConvertF32U32:
if (Arg(inst, 0, a)) {
result = Float32Bits(static_cast<float>(static_cast<uint32_t>(a)));
result = std::bit_cast<uint32_t>(static_cast<float>(static_cast<uint32_t>(a)));
return true;
}
return false;
@@ -750,13 +748,13 @@ private:
return false;
case ValueOpcode::FPMul32:
if (binary()) {
result = Float32Bits(Float32(a) * Float32(b));
result = std::bit_cast<uint32_t>(Float32(a) * Float32(b));
return true;
}
return false;
case ValueOpcode::FPTrunc32:
if (Arg(inst, 0, a)) {
result = Float32Bits(std::trunc(Float32(a)));
result = std::bit_cast<uint32_t>(std::trunc(Float32(a)));
return true;
}
return false;
+17 -27
View File
@@ -60,12 +60,12 @@ public:
: parameters(parameters_) {
builder.AddMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450);
void_type = Type(spv::OpTypeVoid);
uint_type = Type(spv::OpTypeInt, 32u, 0u);
int_type = Type(spv::OpTypeInt, 32u, 1u);
float_type = Type(spv::OpTypeFloat, 32u);
vec4_float_type = Type(spv::OpTypeVector, float_type, 4u);
function_type = Type(spv::OpTypeFunction, void_type);
void_type = builder.Type(spv::OpTypeVoid);
uint_type = builder.Type(spv::OpTypeInt, 32u, 0u);
int_type = builder.Type(spv::OpTypeInt, 32u, 1u);
float_type = builder.Type(spv::OpTypeFloat, 32u);
vec4_float_type = builder.Type(spv::OpTypeVector, float_type, 4u);
function_type = builder.Type(spv::OpTypeFunction, void_type);
per_vertex_type = builder.DecoratedType(
spv::OpTypeStruct,
@@ -76,12 +76,12 @@ public:
ptr_input_vec4_float = Pointer(spv::StorageClassInput, vec4_float_type);
ptr_output_vec4_float = Pointer(spv::StorageClassOutput, vec4_float_type);
if (model == spv::ExecutionModelTessellationControl) {
bool_type = Type(spv::OpTypeBool);
vec2_bool_type = Type(spv::OpTypeVector, bool_type, 2u);
vec2_float_type = Type(spv::OpTypeVector, float_type, 2u);
bool_type = builder.Type(spv::OpTypeBool);
vec2_bool_type = builder.Type(spv::OpTypeVector, bool_type, 2u);
vec2_float_type = builder.Type(spv::OpTypeVector, float_type, 2u);
ptr_output_float = Pointer(spv::StorageClassOutput, float_type);
} else {
vec3_float_type = Type(spv::OpTypeVector, float_type, 3u);
vec3_float_type = builder.Type(spv::OpTypeVector, float_type, 3u);
ptr_input_float = Pointer(spv::StorageClassInput, float_type);
}
}
@@ -161,8 +161,8 @@ public:
Store(Access(ptr_output_vec4_float, outputs[i], invocation), value);
}
Emit(spv::OpReturn);
Emit(spv::OpFunctionEnd);
builder.AddFunction(spv::OpReturn);
builder.AddFunction(spv::OpFunctionEnd);
return builder.Build();
}
@@ -184,27 +184,22 @@ public:
Load(vec4_float_type, Access(ptr_input_vec4_float, inputs[i], index)));
}
Emit(spv::OpReturn);
Emit(spv::OpFunctionEnd);
builder.AddFunction(spv::OpReturn);
builder.AddFunction(spv::OpFunctionEnd);
return builder.Build();
}
private:
template <typename... Args>
uint32_t Type(spv::Op opcode, Args... operands) {
return builder.Type(opcode, operands...);
}
uint32_t Constant(uint32_t type, uint32_t value) {
return builder.Constant(spv::OpConstant, type, value);
}
uint32_t Pointer(spv::StorageClass storage, uint32_t type) {
return Type(spv::OpTypePointer, storage, type);
return builder.Type(spv::OpTypePointer, storage, type);
}
uint32_t Array(uint32_t type, uint32_t size) {
return Type(spv::OpTypeArray, type, Uint(size));
return builder.Type(spv::OpTypeArray, type, Uint(size));
}
template <typename... Args>
@@ -221,11 +216,6 @@ private:
return id;
}
template <typename... Args>
void Emit(spv::Op opcode, Args... operands) {
builder.AddFunction(opcode, operands...);
}
template <typename... Args>
uint32_t Access(uint32_t pointer_type, uint32_t base, Args... indices) {
return Result(spv::OpAccessChain, pointer_type, base, indices...);
@@ -233,7 +223,7 @@ private:
uint32_t Load(uint32_t type, uint32_t pointer) { return Result(spv::OpLoad, type, pointer); }
void Store(uint32_t pointer, uint32_t value) { Emit(spv::OpStore, pointer, value); }
void Store(uint32_t pointer, uint32_t value) { builder.AddFunction(spv::OpStore, pointer, value); }
uint32_t Int(uint32_t value) { return Constant(int_type, value); }
+1 -5
View File
@@ -4,7 +4,6 @@
#include "common/common.h"
#include "common/emulatorConfig.h"
#include "common/logging/log.h"
#include "common/magicEnum.h"
#include "common/profiler.h"
#include "common/stringUtils.h"
#include "graphics/guest_gpu/gpu_defs.h"
@@ -722,6 +721,7 @@ void BuildStageStaticKey(const ShaderPixelInputInfo& info, std::vector<uint32_t>
key.push_back(static_cast<uint32_t>(info.ps_depth_export_enable));
key.push_back(static_cast<uint32_t>(info.ps_sample_mask_export_enable));
key.push_back(static_cast<uint32_t>(info.ps_early_z));
key.push_back(static_cast<uint32_t>(info.dual_source_blending));
key.insert(key.end(), std::begin(info.target_output_mode), std::end(info.target_output_mode));
for (uint32_t base = 0; base < info.target_export_mapping.size(); base += 4u) {
uint32_t packed = 0;
@@ -1006,8 +1006,4 @@ void ShaderDbgDumpInputInfo(const ShaderComputeInputInfo& info) {
info.group_id[1] ? "true" : "false", info.group_id[2] ? "true" : "false");
}
bool ShaderAddressValid(uint64_t addr) {
return reinterpret_cast<const uint32_t*>(addr) != nullptr;
}
} // namespace Libs::Graphics
+1 -1
View File
@@ -175,6 +175,7 @@ struct ShaderPixelInputInfo {
bool ps_depth_export_enable = false;
bool ps_sample_mask_export_enable = false;
bool ps_sample_shading = false;
bool dual_source_blending = false;
bool ps_early_z = false;
bool ps_execute_on_noop = false;
ShaderStageRuntime stage;
@@ -303,7 +304,6 @@ void ShaderMapUserData(uint64_t addr, const ShaderMappedData& data);
void ShaderDbgDumpInputInfo(const ShaderVertexInputInfo& info);
void ShaderDbgDumpInputInfo(const ShaderPixelInputInfo& info);
void ShaderDbgDumpInputInfo(const ShaderComputeInputInfo& info);
bool ShaderAddressValid(uint64_t addr);
} // namespace Libs::Graphics
+3 -3
View File
@@ -334,13 +334,13 @@ std::filesystem::path MountPoints::ResolvePath(const std::string& mounted_name)
// Match the entire guest path so a mount root works with or without a trailing slash.
const auto mounted_path = Common::FixDirectorySlash(mounted_name);
const auto it = std::find_if(
const auto it = std::find_if(
m_mount_pairs.begin(), m_mount_pairs.end(),
[&mounted_path](const MountPair& p) { return Common::StartsWith(mounted_path, p.point); });
[&mounted_path](const MountPair& p) { return mounted_path.starts_with(p.point); });
if (it != m_mount_pairs.end()) {
const auto& p = *it;
auto rel_path = Common::RemoveFirst(Common::FixFilenameSlash(mounted_name), p.point.size());
while (Common::StartsWith(rel_path, '/')) {
while (rel_path.starts_with('/')) {
rel_path = Common::RemoveFirst(rel_path, 1);
}
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
+10 -13
View File
@@ -2,7 +2,6 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/magicEnum.h"
#include "common/stringUtils.h"
#include "common/threads.h"
#include "common/virtualMemory.h"
@@ -14,9 +13,11 @@
#include <algorithm>
#include <array>
#include <atomic>
#include <bit>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <magic_enum.hpp>
#include <map>
#include <memory>
#include <mutex>
@@ -2324,8 +2325,8 @@ int32_t KYTY_SYSV_ABI KernelMapNamedFlexibleMemory(void** addr_in_out, size_t le
"\t flags = 0x%08" PRIx32 "\n"
"\t name = %s\n"
"\t gpu_mode = %s\n",
in_addr, out_addr, len, Common::EnumName(mode).c_str(), static_cast<uint32_t>(flags), name,
Common::EnumName(gpu_mode).c_str());
in_addr, out_addr, len, magic_enum::enum_name(mode), static_cast<uint32_t>(flags), name,
magic_enum::enum_name(gpu_mode));
MapGpuRange(out_addr, len);
@@ -3041,8 +3042,8 @@ int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int f
"\t shared = %s\n"
"\t reason = %s\n",
in_addr, out_addr, static_cast<uint64_t>(direct_memory_start), len,
Common::EnumName(mode).c_str(), static_cast<uint32_t>(flags), alignment,
Common::EnumName(gpu_mode).c_str(), shared_backing ? "yes" : "no", shared_reason);
magic_enum::enum_name(mode), static_cast<uint32_t>(flags), alignment,
magic_enum::enum_name(gpu_mode), shared_backing ? "yes" : "no", shared_reason);
if (out_addr == 0) {
if (consumed_reservation) {
@@ -3305,7 +3306,7 @@ static bool ReplaceFixedRangeWithReserved(uint64_t start, uint64_t size) {
"\t reserve-fixed replace: backend unmap failed at 0x%016" PRIx64
", size=0x%016" PRIx64 ", type=%s\n",
chunk.range.start, chunk.range.size,
Common::EnumName(chunk.range.type).c_str());
magic_enum::enum_name(chunk.range.type));
if (!restore_chunks()) {
EXIT("reserve-fixed backend-unmap rollback failed\n");
}
@@ -3769,7 +3770,7 @@ int KYTY_SYSV_ABI KernelMprotect(const void* addr, size_t len, int prot) {
}
g_virtual_ranges->Protect(aligned_addr, aligned_len, prot);
LOGF("\t prot: %s -> %s\n", Common::EnumName(old_mode).c_str(), Common::EnumName(mode).c_str());
LOGF("\t prot: %s -> %s\n", magic_enum::enum_name(old_mode), magic_enum::enum_name(mode));
return OK;
}
@@ -3879,10 +3880,6 @@ static bool IsAligned(uint64_t value, uint64_t alignment) {
return alignment == 0 || (value & (alignment - 1u)) == 0;
}
static bool IsPowerOfTwo(uint64_t value) {
return value != 0 && (value & (value - 1u)) == 0;
}
static void MemoryPoolSubtractCommitted(uint64_t len) {
auto current = g_memory_pool_committed.load(std::memory_order_relaxed);
while (current != 0) {
@@ -3904,7 +3901,7 @@ int KYTY_SYSV_ABI KernelMemoryPoolExpand(int64_t search_start, int64_t search_en
if (search_start < 0 || search_end <= search_start || len == 0 ||
(len & (POOL_PAGE_SIZE - 1u)) != 0 || phys_addr_out == nullptr ||
(alignment != 0 &&
(!IsPowerOfTwo(alignment) || (alignment & (POOL_PAGE_SIZE - 1u)) != 0))) {
(!std::has_single_bit(alignment) || (alignment & (POOL_PAGE_SIZE - 1u)) != 0))) {
return KERNEL_ERROR_EINVAL;
}
if (static_cast<uint64_t>(search_end - search_start) < len) {
@@ -3953,7 +3950,7 @@ int KYTY_SYSV_ABI KernelMemoryPoolReserve(void* addr_in, size_t len, size_t alig
return KERNEL_ERROR_EINVAL;
}
if (alignment != 0 &&
(!IsPowerOfTwo(alignment) || !IsAligned(alignment, POOL_RESERVE_ALIGNMENT))) {
(!std::has_single_bit(alignment) || !IsAligned(alignment, POOL_RESERVE_ALIGNMENT))) {
return KERNEL_ERROR_EINVAL;
}
+2 -9
View File
@@ -149,7 +149,7 @@ static uint64_t KernelGetTscFrequencyNative() {
}
KernelReadTscNative();
Common::Thread::Sleep(1);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
KernelReadTscNative();
const auto host_start = Common::Timer::QueryPerformanceCounter();
@@ -993,7 +993,7 @@ static void FreeDetachedThreads(void* /*arg*/) {
auto* pthread_pool = g_pthread_context->GetPthreadPool();
while (true) {
Common::Thread::Sleep(10000);
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
pthread_pool->FreeDetachedThreads();
}
}
@@ -1202,13 +1202,6 @@ static int32_t GetDstSeconds() {
#endif
}
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
static void sec_to_timeval(KernelTimeval* ts, double sec) {
ts->tv_sec = static_cast<int64_t>(sec);
ts->tv_usec = static_cast<int64_t>((sec - static_cast<double>(ts->tv_sec)) * 1000000.0);
}
#endif
static bool GetPosixClockId(KernelClockid clock_id, clockid_t* out) {
EXIT_IF(out == nullptr);
@@ -329,12 +329,4 @@
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>cancel_button</sender>
<signal>clicked()</signal>
<receiver>ConfigurationEditDialog</receiver>
<slot>reject()</slot>
</connection>
</connections>
</ui>
-20
View File
@@ -1,20 +0,0 @@
#ifndef LAUNCHER_INCLUDE_COMMON_H_
#define LAUNCHER_INCLUDE_COMMON_H_
// IWYU pragma: begin_exports
#include <QArgument>
#include <QObject>
#include <cinttypes>
#include <cstdint>
#include <cstdio>
// IWYU pragma: end_exports
#define KYTY_QT_CLASS_NO_COPY(name) \
public: \
name(const name&) = delete; /* NOLINT(bugprone-macro-parentheses) */ \
name& operator=(const name&) = delete; /* NOLINT(bugprone-macro-parentheses) */ \
name(name&&) noexcept = delete; /* NOLINT(bugprone-macro-parentheses) */ \
name& operator=(name&&) noexcept = delete; /* NOLINT(bugprone-macro-parentheses) */
#endif /* LAUNCHER_INCLUDE_COMMON_H_ */
@@ -1,7 +1,6 @@
#ifndef COMPATIBILITY_DATABASE_H
#define COMPATIBILITY_DATABASE_H
#include "common.h"
#include "configuration.h"
#include <QMap>
@@ -15,7 +14,6 @@ struct CompatibilityEntry {
class CompatibilityDatabase: public QObject {
Q_OBJECT
KYTY_QT_CLASS_NO_COPY(CompatibilityDatabase);
public:
explicit CompatibilityDatabase(bool local, QObject* parent = nullptr);
+1 -1
View File
@@ -1,13 +1,13 @@
#ifndef LAUNCHER_INCLUDE_CONFIGURATION_H_
#define LAUNCHER_INCLUDE_CONFIGURATION_H_
#include "common.h"
#include "common/emulatorConfig.h"
#include <QByteArray>
#include <QChar>
#include <QMetaEnum>
#include <QMetaType>
#include <QObject>
#include <QSettings>
#include <QString>
#include <QStringList>
@@ -1,8 +1,6 @@
#ifndef CONFIGURATION_EDIT_DIALOG_H
#define CONFIGURATION_EDIT_DIALOG_H
#include "common.h"
#include <QDialog>
#include <QString>
#include <QStringList>
@@ -22,7 +20,6 @@ class ConfigurationEditDialog;
class ConfigurationEditDialog: public QDialog {
Q_OBJECT
KYTY_QT_CLASS_NO_COPY(ConfigurationEditDialog);
public:
explicit ConfigurationEditDialog(Configuration& info, QWidget* parent = nullptr);
@@ -31,7 +28,6 @@ public:
static void WriteSettings(QSettings& s);
static void ReadSettings(QSettings& s);
void SetTitle(const QString& str);
void SetGameDirectories(const QStringList& dirs);
[[nodiscard]] QStringList GetGameDirectories() const;
@@ -55,8 +51,6 @@ protected:
/*slots:*/
void update_info();
void adjust_size();
void save();
void clear();
void add_game_directory();
-4
View File
@@ -1,8 +1,6 @@
#ifndef CONFIGURATION_ITEM_H
#define CONFIGURATION_ITEM_H
#include "common.h"
#include <QObject>
#include <QTreeWidgetItem>
@@ -23,8 +21,6 @@ public:
void Update();
bool operator<(const QTreeWidgetItem& other) const override;
KYTY_QT_CLASS_NO_COPY(ConfigurationItem);
Configuration& GetInfo() { return *m_info; }
[[nodiscard]] const Configuration& GetInfo() const { return *m_info; }
// void SetInfo(Configuration* info);
+1 -13
View File
@@ -1,7 +1,6 @@
#ifndef CONFIGURATION_LIST_WIDGET_H
#define CONFIGURATION_LIST_WIDGET_H
#include "common.h"
#include "configuration.h"
#include <QMap>
@@ -14,7 +13,6 @@ class CompatibilityDatabase;
class QEvent;
class QTreeWidgetItem;
class QPoint;
class MainDialog;
namespace Ui {
class ConfigurationListWidget;
@@ -22,27 +20,20 @@ class ConfigurationListWidget;
class ConfigurationListWidget: public QWidget {
Q_OBJECT
KYTY_QT_CLASS_NO_COPY(ConfigurationListWidget);
public:
explicit ConfigurationListWidget(QWidget* parent = nullptr);
~ConfigurationListWidget() override;
void SetRunEnabled(bool flag) { m_run_enabled = flag; }
[[nodiscard]] bool IsRunEnabled() const { return m_run_enabled; }
void SetRunEnabled(bool flag) { m_run_enabled = flag; }
[[nodiscard]] const ConfigurationItem* GetSelectedItem() const { return m_selected_item; }
ConfigurationItem* GetSelectedItem() { return m_selected_item; }
void SetMainDialog(MainDialog* main_dialog) { m_main_dialog = main_dialog; }
MainDialog* GetMainDialog() { return m_main_dialog; }
[[nodiscard]] const QString& GetSettingsFile() const { return m_settings_file; }
[[nodiscard]] const QStringList& GetGameDirectories() const { return m_game_dirs; }
[[nodiscard]] const QStringList& GetHostInputMapping() const {
return m_global_info.host_input_mapping;
}
[[nodiscard]] bool CanViewSelectedTrophies() const;
bool EnsureGameDirectory();
void ScanGameDirectory();
@@ -66,8 +57,6 @@ protected slots:
void delete_configuartion();
void edit_global_settings();
void edit_input_mapping();
void run_configuration();
void list_currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
void list_itemDoubleClicked(QTreeWidgetItem* witem, int column);
void show_context_menu(const QPoint& pos);
void open_game_folder();
@@ -84,7 +73,6 @@ private:
ConfigurationItem* m_selected_item = nullptr;
bool m_run_enabled = true;
Ui::ConfigurationListWidget* m_ui = nullptr;
MainDialog* m_main_dialog = nullptr;
QString m_settings_file;
QStringList m_game_dirs;
Configuration m_global_info;
-4
View File
@@ -1,8 +1,6 @@
#ifndef MAIN_DIALOG_H
#define MAIN_DIALOG_H
#include "common.h"
#include <QDialog>
#include <QString>
@@ -15,11 +13,9 @@ class QResizeEvent;
class Configuration;
class MainDialog: public QDialog {
Q_OBJECT
KYTY_QT_CLASS_NO_COPY(MainDialog);
signals:
void Start();
void Quit();
void Resize();
public:
+1 -2
View File
@@ -1,9 +1,8 @@
#ifndef MANDATORY_LINEEDIT_H
#define MANDATORY_LINEEDIT_H
#include "common.h"
#include <QLineEdit>
#include <QObject>
#include <QString>
class QPaintEvent;
-4
View File
@@ -1,8 +1,6 @@
#ifndef PATCHES_DIALOG_H
#define PATCHES_DIALOG_H
#include "common.h"
#include <QDialog>
#include <QString>
@@ -16,8 +14,6 @@ public:
explicit PatchesDialog(const Configuration& game, QWidget* parent = nullptr);
~PatchesDialog() override = default;
KYTY_QT_CLASS_NO_COPY(PatchesDialog);
[[nodiscard]] static bool IsSupportedTitleId(const QString& title_id);
[[nodiscard]] static QString PatchPlanPath(const QString& title_id);
@@ -1,8 +1,6 @@
#ifndef TROPHY_VIEWER_DIALOG_H
#define TROPHY_VIEWER_DIALOG_H
#include "common.h"
#include <QDialog>
class QTabWidget;
@@ -10,8 +8,6 @@ class QWidget;
class Configuration;
class TrophyViewerDialog: public QDialog {
KYTY_QT_CLASS_NO_COPY(TrophyViewerDialog);
public:
explicit TrophyViewerDialog(QWidget* parent = nullptr);
+2 -13
View File
@@ -108,6 +108,7 @@ ConfigurationEditDialog::ConfigurationEditDialog(Configuration& info, QWidget* p
InitGameDirectories();
connect(m_ui->ok_button, &QPushButton::clicked, this, &ConfigurationEditDialog::save);
connect(m_ui->cancel_button, &QPushButton::clicked, this, &QDialog::reject);
connect(m_ui->clear_button, &QPushButton::clicked, this, &ConfigurationEditDialog::clear);
connect(m_ui->comboBox_shader_log_direction, &QComboBox::currentTextChanged, this,
[this](const QString& text) {
@@ -306,10 +307,6 @@ void ConfigurationEditDialog::InitGameDirectories() {
update_game_directory_buttons();
}
void ConfigurationEditDialog::SetTitle(const QString& str) {
setWindowTitle(str);
}
void ConfigurationEditDialog::SetGameDirectories(const QStringList& dirs) {
m_show_game_dirs = true;
m_game_dirs_list->clear();
@@ -400,14 +397,6 @@ static void UpdateInfo(Configuration& info, Ui::ConfigurationEditDialog& ui) {
info.profiler_enabled = ui.checkBox_profiler->isChecked();
}
void ConfigurationEditDialog::update_info() {
UpdateInfo(m_info, *m_ui);
}
void ConfigurationEditDialog::adjust_size() {
this->adjustSize();
}
void ConfigurationEditDialog::save() {
if (MandatoryLineEdit::FindEmpty(this)) {
QMessageBox::critical(this, tr("Save failed"), tr("Please fill all mandatory fields"));
@@ -427,7 +416,7 @@ void ConfigurationEditDialog::save() {
return;
}
update_info();
UpdateInfo(m_info, *m_ui);
emit accept();
}
+3 -7
View File
@@ -77,10 +77,6 @@ void SetStatus(QComboBox* combo, Configuration::GameStatus status) {
combo->setCurrentIndex(index >= 0 ? index : 0);
}
QIcon StandardIcon(QStyle::StandardPixmap icon) {
return QApplication::style()->standardIcon(icon);
}
QString GetPathText(const Configuration& info) {
return !info.game_path.isEmpty() ? info.game_path : info.basedir;
}
@@ -278,11 +274,11 @@ void ConfigurationItem::UpdateIcon() {
}
if (m_running) {
setIcon(NameColumn, StandardIcon(QStyle::SP_MediaPlay));
setIcon(NameColumn, QApplication::style()->standardIcon(QStyle::SP_MediaPlay));
} else if (m_info->custom_settings) {
setIcon(NameColumn, StandardIcon(QStyle::SP_FileIcon));
setIcon(NameColumn, QApplication::style()->standardIcon(QStyle::SP_FileIcon));
} else {
setIcon(NameColumn, StandardIcon(QStyle::SP_ComputerIcon));
setIcon(NameColumn, QApplication::style()->standardIcon(QStyle::SP_ComputerIcon));
}
}
+4 -19
View File
@@ -1,6 +1,5 @@
#include "configurationListWidget.h"
#include "common.h"
#include "compatibilityDatabase.h"
#include "configuration.h"
#include "configurationEditDialog.h"
@@ -232,7 +231,7 @@ ConfigurationListWidget::ConfigurationListWidget(QWidget* parent)
connect(m_ui->delete_button, &QToolButton::clicked, this,
&ConfigurationListWidget::delete_configuartion);
connect(m_ui->cfgs_list, &QTreeWidget::currentItemChanged, this,
&ConfigurationListWidget::list_currentItemChanged);
&ConfigurationListWidget::SelectItem);
connect(m_ui->cfgs_list, &QTreeWidget::itemDoubleClicked, this,
&ConfigurationListWidget::list_itemDoubleClicked);
connect(m_ui->cfgs_list, &QTreeWidget::customContextMenuRequested, this,
@@ -676,7 +675,7 @@ void ConfigurationListWidget::edit_configuration() {
}
ConfigurationEditDialog dlg(item->GetInfo(), this);
dlg.SetTitle(tr("Edit game settings"));
dlg.setWindowTitle(tr("Edit game settings"));
if (dlg.exec() == QDialog::Accepted) {
item->GetInfo().custom_settings = true;
@@ -708,7 +707,7 @@ void ConfigurationListWidget::edit_global_settings() {
info.name = tr("Global settings");
ConfigurationEditDialog dlg(info, this);
dlg.SetTitle(tr("Global settings"));
dlg.setWindowTitle(tr("Global settings"));
dlg.SetGameDirectories(m_game_dirs);
if (dlg.exec() == QDialog::Accepted) {
@@ -731,15 +730,6 @@ void ConfigurationListWidget::ClearCustomSettings(ConfigurationItem* item) {
delete m_custom_infos.take(item->GetInfo().game_path);
}
void ConfigurationListWidget::run_configuration() {
emit Run();
}
bool ConfigurationListWidget::CanViewSelectedTrophies() const {
return m_selected_item != nullptr &&
TrophyViewerDialog::HasTrophyData(&m_selected_item->GetInfo());
}
void ConfigurationListWidget::ViewTrophies() {
auto* current = static_cast<ConfigurationItem*>(m_ui->cfgs_list->currentItem());
auto* item = current != nullptr ? current : m_selected_item;
@@ -852,11 +842,6 @@ void ConfigurationListWidget::SelectItem(QTreeWidgetItem* witem) {
emit Select();
}
void ConfigurationListWidget::list_currentItemChanged(QTreeWidgetItem* current,
QTreeWidgetItem* /*previous*/) {
SelectItem(current);
}
void ConfigurationListWidget::list_itemDoubleClicked(QTreeWidgetItem* witem, int /*column*/) {
SelectItem(witem);
if (m_run_enabled) {
@@ -877,7 +862,7 @@ void ConfigurationListWidget::show_context_menu(const QPoint& pos) {
const bool has_trophy_data =
item != nullptr && TrophyViewerDialog::HasTrophyData(&item->GetInfo());
QAction* action_run = menu.addAction(tr("Run"), this, SLOT(run_configuration()));
QAction* action_run = menu.addAction(tr("Run"), this, SIGNAL(Run()));
QAction* action_open_folder =
menu.addAction(style()->standardIcon(QStyle::SP_DirOpenIcon), tr("Open game folder"), this,
SLOT(open_game_folder()));
-4
View File
@@ -2,8 +2,6 @@
#include "launcherTheme.h"
#include <QApplication>
#include <QArgument>
#include <QObject>
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
@@ -11,8 +9,6 @@ int main(int argc, char* argv[]) {
MainDialog w;
QObject::connect(&a, &QApplication::aboutToQuit, &w, &MainDialog::Quit);
w.emit Start();
w.show();
+4 -17
View File
@@ -1,6 +1,5 @@
#include "mainDialog.h"
#include "common.h"
#include "configuration.h"
#include "configurationItem.h"
#include "configurationListWidget.h"
@@ -17,6 +16,7 @@
#include <QIODevice>
#include <QLabel>
#include <QMessageBox>
#include <QObject>
#include <QPointer>
#include <QProcess>
#include <QRadioButton>
@@ -27,6 +27,8 @@
#include <QVariant>
#include <QtCore>
#include <cstdint>
#include "ui_main_dialog.h"
#if defined(_WIN32)
@@ -58,20 +60,8 @@ constexpr char SETTINGS_MAIN_DIALOG[] = "MainDialog";
constexpr char SETTINGS_MAIN_LAST_GEOMETRY[] = "geometry";
constexpr char SETTINGS_CHECK_UPDATES[] = "check_updates_on_startup";
class DetachableProcess: public QProcess {
Q_OBJECT;
public:
explicit DetachableProcess(QObject* parent = nullptr): QProcess(parent) {}
void Detach() {
this->waitForStarted();
setProcessState(QProcess::NotRunning);
}
};
class MainDialogPrivate: public QObject {
Q_OBJECT
KYTY_QT_CLASS_NO_COPY(MainDialogPrivate);
public:
explicit MainDialogPrivate(QObject* parent = nullptr): QObject(parent) {}
@@ -99,7 +89,7 @@ private:
UpdateChecker* m_update_checker = nullptr;
QString m_interpreter;
/*DetachableProcess*/ QProcess m_process;
QProcess m_process;
QPointer<ConfigurationItem> m_running_item;
};
@@ -121,7 +111,6 @@ void MainDialogPrivate::Setup(MainDialog* main_dialog) {
m_main_dialog = main_dialog;
m_update_checker = new UpdateChecker(main_dialog);
m_ui->widget->SetMainDialog(main_dialog);
m_ui->check_updates_on_startup->setChecked(g_check_updates_on_startup);
m_ui->check_updates_link->setVisible(UpdateChecker::IsSupported());
m_ui->check_updates_on_startup->setVisible(UpdateChecker::IsSupported());
@@ -154,8 +143,6 @@ void MainDialogPrivate::Setup(MainDialog* main_dialog) {
Update();
});
// connect(main_dialog, &MainDialog::Quit, [=]() { m_process.Detach(); });
m_ui->label_settings_file->setText(tr("Settings file: ") + m_ui->widget->GetSettingsFile());
m_main_dialog->restoreGeometry(g_last_geometry);
+7 -3
View File
@@ -3,6 +3,7 @@
#include "configuration.h"
#include <QCoreApplication>
#include <QDebug>
#include <QDialogButtonBox>
#include <QDir>
#include <QFile>
@@ -129,8 +130,11 @@ void PatchesDialog::Save() {
document.setObject(root);
QSaveFile output(path);
if (output.open(QIODevice::WriteOnly) && output.write(document.toJson()) >= 0 &&
output.commit()) {
m_status->setText(tr("Cheat selection saved."));
if (!output.open(QIODevice::WriteOnly) || output.write(document.toJson()) < 0 ||
!output.commit()) {
qWarning() << "Could not save cheat file:" << output.errorString();
m_status->setText(tr("Could not save cheat file: %1").arg(output.errorString()));
return;
}
m_status->setText(tr("Cheat selection saved."));
}
+12 -25
View File
@@ -20,6 +20,7 @@
#include <QLabel>
#include <QMap>
#include <QMessageBox>
#include <QObject>
#include <QPixmap>
#include <QRegularExpression>
#include <QSet>
@@ -32,8 +33,9 @@
#include <QVBoxLayout>
#include <QVariant>
#include <QWidget>
#include <QtEndian>
#include <limits>
#include <utility>
namespace {
@@ -83,21 +85,6 @@ static bool CanRead(const QByteArray& data, qsizetype offset, qsizetype size) {
return offset >= 0 && size >= 0 && offset <= data.size() && size <= data.size() - offset;
}
static quint32 ReadBe32(const QByteArray& data, qsizetype offset) {
const auto* p = reinterpret_cast<const uchar*>(data.constData() + offset);
return (static_cast<quint32>(p[0]) << 24u) | (static_cast<quint32>(p[1]) << 16u) |
(static_cast<quint32>(p[2]) << 8u) | static_cast<quint32>(p[3]);
}
static quint64 ReadBe64(const QByteArray& data, qsizetype offset) {
return (static_cast<quint64>(ReadBe32(data, offset)) << 32u) |
static_cast<quint64>(ReadBe32(data, offset + 4));
}
static bool FitsQSizeType(quint64 value) {
return value <= static_cast<quint64>(std::numeric_limits<qsizetype>::max());
}
static QString ReadFixedString(const QByteArray& data, qsizetype offset, qsizetype max_size) {
if (!CanRead(data, offset, max_size)) {
return {};
@@ -125,33 +112,33 @@ static bool ReadUcp(const QString& file_name, QMap<QString, QByteArray>& files,
return false;
}
const auto magic = ReadBe32(data, 0x00);
const auto magic = qFromBigEndian<quint32>(data.constData() + 0x00);
if (magic != UCP_MAGIC) {
error = QObject::tr("%1 has an invalid trophy package magic.")
.arg(QFileInfo(file_name).fileName());
return false;
}
const auto version = ReadBe32(data, 0x04);
const auto version = qFromBigEndian<quint32>(data.constData() + 0x04);
if (version != UCP_VERSION) {
error = QObject::tr("%1 uses unsupported trophy package version %2.")
.arg(QFileInfo(file_name).fileName(), QString::number(version));
return false;
}
const auto declared_size = ReadBe64(data, 0x08);
const auto declared_size = qFromBigEndian<quint64>(data.constData() + 0x08);
if (declared_size > static_cast<quint64>(data.size())) {
error = QObject::tr("%1 is truncated.").arg(QFileInfo(file_name).fileName());
return false;
}
const auto file_count = ReadBe32(data, 0x10);
const auto toc_offset = static_cast<quint64>(ReadBe32(data, 0x14));
const auto file_count = qFromBigEndian<quint32>(data.constData() + 0x10);
const auto toc_offset = static_cast<quint64>(qFromBigEndian<quint32>(data.constData() + 0x14));
const auto data_size = static_cast<quint64>(data.size());
const quint64 table_size = UCP_TOC_SKIP + static_cast<quint64>(file_count) * UCP_ENTRY_LEN;
if (toc_offset > data_size || table_size > data_size - toc_offset ||
!FitsQSizeType(toc_offset + table_size)) {
!std::in_range<qsizetype>(toc_offset + table_size)) {
error = QObject::tr("%1 has an invalid table of contents.")
.arg(QFileInfo(file_name).fileName());
return false;
@@ -162,14 +149,14 @@ static bool ReadUcp(const QString& file_name, QMap<QString, QByteArray>& files,
static_cast<quint64>(i) * UCP_ENTRY_LEN);
UcpEntry entry;
entry.name = ReadFixedString(data, entry_offset, UCP_NAME_LEN).trimmed();
entry.offset = ReadBe64(data, entry_offset + 0x20);
entry.size = ReadBe64(data, entry_offset + 0x28);
entry.offset = qFromBigEndian<quint64>(data.constData() + entry_offset + 0x20);
entry.size = qFromBigEndian<quint64>(data.constData() + entry_offset + 0x28);
if (entry.name.isEmpty()) {
continue;
}
if (entry.offset > data_size || entry.size > data_size - entry.offset ||
!FitsQSizeType(entry.offset) || !FitsQSizeType(entry.size)) {
!std::in_range<qsizetype>(entry.offset) || !std::in_range<qsizetype>(entry.size)) {
error = QObject::tr("%1 has an invalid entry for %2.")
.arg(QFileInfo(file_name).fileName(), entry.name);
return false;
+3 -2
View File
@@ -849,8 +849,9 @@ int KYTY_SYSV_ABI AjmMemoryUnregister(uint32_t context, void* ptr) {
int KYTY_SYSV_ABI AjmBatchInitialize(void* buffer, size_t size, AjmBatchInfo* info) {
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(buffer == nullptr);
EXIT_NOT_IMPLEMENTED(info == nullptr);
if (buffer == nullptr || info == nullptr) {
return AJM_ERROR_INVALID_PARAMETER;
}
info->buffer = buffer;
info->offset = 0;
+32 -22
View File
@@ -38,9 +38,9 @@ static constexpr uint32_t AJM_DEC_M4AAC_MAX_SAMPLING_FREQ_INDEX = 11;
class AjmAacDecoder final: public AjmDecoder {
public:
AjmAacDecoder(uint32_t channels, uint32_t sample_rate, AjmSampleEncoding encoding,
AjmAacDecoder(uint32_t max_channels, uint32_t sample_rate, AjmSampleEncoding encoding,
uint64_t flags)
: AjmDecoder(channels, sample_rate, encoding), m_flags(flags) {
: AjmDecoder(0, sample_rate, encoding), m_max_channels(max_channels), m_flags(flags) {
m_codec = avcodec_find_decoder(AV_CODEC_ID_AAC);
if (m_codec == nullptr) {
LOGF("AJM AAC: avcodec_find_decoder failed\n");
@@ -94,6 +94,11 @@ public:
((m_flags & AJM_INSTANCE_FLAG_DEC_M4AAC_ENABLE_NONDELAY_OUTPUT) != 0 ? 0u : 2u);
m_total_decoded_samples = 0;
m_bitrate = 0;
m_channels = 0;
m_raw_configured = false;
if (m_config_number == AJM_DEC_M4AAC_CONFIG_NUMBER_RAW) {
m_sample_rate = SamplingRateFromIndex(m_sampling_freq_index);
}
if (m_is_initialized) {
OpenDecoder();
}
@@ -189,26 +194,6 @@ private:
return;
}
if (m_config_number == AJM_DEC_M4AAC_CONFIG_NUMBER_RAW) {
const auto sample_index =
std::min(m_sampling_freq_index, AJM_DEC_M4AAC_MAX_SAMPLING_FREQ_INDEX);
const auto channels = std::clamp<uint32_t>(m_channels, 1u, AJM_DEC_M4AAC_MAX_CHANNELS);
constexpr uint32_t audio_object_type = 2;
auto* extradata = static_cast<uint8_t*>(av_mallocz(2 + AV_INPUT_BUFFER_PADDING_SIZE));
if (extradata == nullptr) {
Release();
return;
}
extradata[0] = static_cast<uint8_t>((audio_object_type << 3u) | (sample_index >> 1u));
extradata[1] = static_cast<uint8_t>(((sample_index & 0x1u) << 7u) |
(std::min(channels, 7u) << 3u));
m_codec_context->extradata = extradata;
m_codec_context->extradata_size = 2;
SetFormat(channels, SamplingRateFromIndex(sample_index), m_sample_encoding);
}
if (avcodec_open2(m_codec_context, m_codec, nullptr) < 0) {
LOGF("AJM AAC: decoder initialization failed\n");
Release();
@@ -222,6 +207,10 @@ private:
}
const auto channels = static_cast<uint32_t>(std::max(frame->ch_layout.nb_channels, 1));
if (channels > m_max_channels) {
result->result = AJM_RESULT_TOO_MANY_CHANNELS;
return false;
}
const auto bpf = channels * AjmBytesPerSample(m_sample_encoding);
if (bpf == 0) {
result->result = AJM_RESULT_INVALID_PARAMETER;
@@ -306,6 +295,25 @@ private:
return false;
}
std::memcpy(packet->data, packet_data, static_cast<size_t>(packet_size));
if (m_config_number == AJM_DEC_M4AAC_CONFIG_NUMBER_RAW && !m_raw_configured) {
// Only indexed stereo starts with a channel pair; the instance limit is not
// the stream's channel count. A leading SCE remains ambiguous.
const auto channels = (packet_data[0] >> 5u) == 1u
? 2u
: std::clamp(m_max_channels, 1u, AJM_DEC_M4AAC_MAX_CHANNELS);
auto* extradata = av_packet_new_side_data(packet, AV_PKT_DATA_NEW_EXTRADATA, 2);
if (extradata == nullptr) {
av_packet_free(&packet);
result->result = AJM_RESULT_CODEC_ERROR | AJM_RESULT_FATAL;
return false;
}
constexpr uint32_t audio_object_type = 2;
extradata[0] = static_cast<uint8_t>((audio_object_type << 3u) |
(m_sampling_freq_index >> 1u));
extradata[1] = static_cast<uint8_t>(((m_sampling_freq_index & 1u) << 7u) |
(std::min(channels, 7u) << 3u));
m_raw_configured = true;
}
int rc = avcodec_send_packet(m_codec_context, packet);
av_packet_free(&packet);
@@ -353,12 +361,14 @@ private:
const AVCodec* m_codec = nullptr;
AVCodecContext* m_codec_context = nullptr;
const uint32_t m_max_channels;
uint64_t m_flags = 0;
uint32_t m_config_number = AJM_DEC_M4AAC_CONFIG_NUMBER_ADTS;
uint32_t m_sampling_freq_index = 3;
uint32_t m_skip_frames = 2;
uint32_t m_bitrate = 0;
bool m_is_initialized = false;
bool m_raw_configured = false;
};
} // namespace Libs::Audio::Ajm
+1
View File
@@ -72,6 +72,7 @@ constexpr int32_t AJM_RESULT_INVALID_DATA = 0x00000002;
constexpr int32_t AJM_RESULT_INVALID_PARAMETER = 0x00000004;
constexpr int32_t AJM_RESULT_PARTIAL_INPUT = 0x00000008;
constexpr int32_t AJM_RESULT_NOT_ENOUGH_ROOM = 0x00000010;
constexpr int32_t AJM_RESULT_TOO_MANY_CHANNELS = 0x00000040;
constexpr int32_t AJM_RESULT_CODEC_ERROR = 0x40000000;
constexpr int32_t AJM_RESULT_FATAL = static_cast<int32_t>(0x80000000u);
+5 -6
View File
@@ -5,7 +5,6 @@
#include "common/common.h"
#include "common/emulatorConfig.h"
#include "common/logging/log.h"
#include "common/magicEnum.h"
#include "common/stringUtils.h"
#include "common/threads.h"
#include "kernel/pthread.h"
@@ -20,6 +19,7 @@
#include <cstdlib>
#include <cstring>
#include <limits>
#include <magic_enum.hpp>
#include <vector>
#include "libatrac9.h"
@@ -800,8 +800,7 @@ int KYTY_SYSV_ABI AudioOutOpen(int user_id, int type, int index, uint32_t len, u
default:;
}
LOGF("\t param = %u (format=%u, %s)\n", param, format_param,
Common::EnumName(format).c_str());
LOGF("\t param = %u (format=%u, %s)\n", param, format_param, magic_enum::enum_name(format));
EXIT_NOT_IMPLEMENTED(format == Audio::Format::Unknown);
@@ -966,7 +965,7 @@ static int OpenPort(int user_id, int type, int index, uint32_t len, uint32_t fre
default: return AUDIO_IN_ERROR_INVALID_PARAM;
}
LOGF("\t param = %u (%s)\n", param, Common::EnumName(format).c_str());
LOGF("\t param = %u (%s)\n", param, magic_enum::enum_name(format));
EXIT_IF(g_audio == nullptr);
@@ -2361,7 +2360,7 @@ int KYTY_SYSV_ABI Ngs2RackCreate(uintptr_t system_handle, uint32_t rack_id,
default: EXIT("unknown rack_id: 0x%" PRIx32 "\n", rack_id);
}
LOGF("\t type = %s\n", Common::EnumName(rack->type).c_str());
LOGF("\t type = %s\n", magic_enum::enum_name(rack->type));
rack->allocator = Ngs2BufferAllocator();
rack->buffer_info = *buffer_info;
@@ -3120,7 +3119,7 @@ int KYTY_SYSV_ABI Ngs2VoiceGetState(uintptr_t voice_handle, Ngs2VoiceState* stat
sampler->waveform_data = nullptr;
break;
}
default: EXIT("unknown type: %s\n", Common::EnumName(voice->rack->type).c_str());
default: EXIT("unknown type: %s\n", magic_enum::enum_name(voice->rack->type));
}
return OK;
+2 -2
View File
@@ -1,6 +1,5 @@
#include "common/common.h"
#include "common/logging/log.h"
#include "common/magicEnum.h"
#include "common/stringUtils.h"
#include "kernel/fileSystem.h"
#include "kernel/pthread.h"
@@ -16,6 +15,7 @@
#include <cstdio>
#include <cstring>
#include <deque>
#include <magic_enum.hpp>
#include <memory>
#include <mutex>
#include <optional>
@@ -1758,7 +1758,7 @@ static void log_init_common(const AvPlayerMemAllocator& mem, const AvPlayerFileR
"= %d\n\t base_priority "
" = %u\n\t auto_start = %u\n\t default_language "
" = %s\n",
Common::EnumName(debug_level).c_str(), buffers, priority, auto_start,
magic_enum::enum_name(debug_level), buffers, priority, auto_start,
language == nullptr ? "(null)" : language);
}
+126 -2
View File
@@ -13,6 +13,8 @@
#include "libs/padData.h"
#include <algorithm>
#include <array>
#include <cmath>
#include <cstring>
#include <vector>
@@ -87,6 +89,9 @@ struct ControllerState {
uint32_t buttons = 0;
int axes[static_cast<int>(Axis::AxisMax)] = {128, 128, 128, 128, 0, 0};
Touch touch[2];
std::array<float, 3> accel {0.0f, 1.0f, 0.0f};
std::array<float, 3> gyro {};
std::array<float, 4> orientation {0.0f, 0.0f, 0.0f, 1.0f};
};
class GameController {
@@ -101,6 +106,9 @@ public:
void Axis(int id, Axis axis, int value);
void RightStick(int id, int x, int y);
void TouchPad(int id, int finger, bool down, float x, float y);
void Motion(int id, Sensor sensor, const float* data, uint64_t time_us);
void SetMotionSensorState(bool enable);
void ResetOrientation();
void ResetInputState();
void ReleaseHostPads();
void GetConnectionInfo(bool* flag, int* count);
@@ -121,6 +129,8 @@ private:
int m_active_id = -1;
bool m_connected = false;
int m_connected_count = 0;
bool m_motion_enabled = true;
uint64_t m_gyro_time = 0;
ControllerState m_state;
ControllerState m_states[STATES_MAX];
bool m_obtained[STATES_MAX] {};
@@ -144,7 +154,16 @@ static void pad_fill_data(PadData* data, const ControllerState& state, bool conn
data->right_stick_y = state.axes[static_cast<int>(Axis::RightY)];
data->analog_buttons_l2 = state.axes[static_cast<int>(Axis::TriggerLeft)];
data->analog_buttons_r2 = state.axes[static_cast<int>(Axis::TriggerRight)];
data->orientation_w = 1.0f;
data->acceleration_x = state.accel[0];
data->acceleration_y = state.accel[1];
data->acceleration_z = state.accel[2];
data->angular_velocity_x = state.gyro[0];
data->angular_velocity_y = state.gyro[1];
data->angular_velocity_z = state.gyro[2];
data->orientation_x = state.orientation[0];
data->orientation_y = state.orientation[1];
data->orientation_z = state.orientation[2];
data->orientation_w = state.orientation[3];
for (const auto& touch: state.touch) {
if (touch.down) {
auto& output = data->touch_data.touch[data->touch_data.touch_num++];
@@ -273,6 +292,18 @@ void GameController::Connect(int id) {
m_connected_ids.push_back(id);
if (id != HOST_INPUT_CONTROLLER_ID) {
if (auto* pad = SDL_GameControllerFromInstanceID(static_cast<SDL_JoystickID>(id));
pad != nullptr) {
for (auto sensor: {SDL_SENSOR_ACCEL, SDL_SENSOR_GYRO}) {
if (SDL_GameControllerHasSensor(pad, sensor) &&
SDL_GameControllerSetSensorEnabled(pad, sensor, SDL_TRUE) != 0) {
LOGF("\t enabling controller sensor failed: %s\n", SDL_GetError());
}
}
}
}
CheckActive();
}
@@ -311,6 +342,7 @@ void GameController::CheckActive() {
m_active_id = new_active_id;
m_connected = new_connected;
m_state = {};
m_gyro_time = 0;
m_states_num = 0;
m_first_state = 0;
m_next_touch_id = 1;
@@ -402,9 +434,81 @@ void GameController::TouchPad(int id, int finger, bool down, float x, float y) {
}
}
void GameController::Motion(int id, Sensor sensor, const float* data, uint64_t time_us) {
Common::LockGuard lock(m_mutex);
if (id != m_active_id || !m_motion_enabled) {
return;
}
// Convert acceleration to G; angular velocity is already in rad/s.
if (sensor == Sensor::Accel) {
for (int i = 0; i < 3; i++) {
m_state.accel[i] = data[i] / SDL_STANDARD_GRAVITY;
}
} else {
std::copy_n(data, 3, m_state.gyro.begin());
// Do not extrapolate a single sample across lost reports (e.g. loss of window focus).
constexpr uint64_t max_gyro_interval_us = 100000;
if (m_gyro_time != 0 && time_us > m_gyro_time &&
time_us - m_gyro_time <= max_gyro_interval_us) {
const float dt = static_cast<float>(time_us - m_gyro_time) * 0.000001f;
const float speed =
std::sqrt(data[0] * data[0] + data[1] * data[1] + data[2] * data[2]);
const float half_angle = speed * dt * 0.5f;
const float scale = speed > 0.0f ? std::sin(half_angle) / speed : 0.0f;
const float x = data[0] * scale;
const float y = data[1] * scale;
const float z = data[2] * scale;
const float w = std::cos(half_angle);
const auto q = m_state.orientation;
// Accumulate body-local rotation relative to connection / orientation reset.
m_state.orientation = {q[3] * x + q[0] * w + q[1] * z - q[2] * y,
q[3] * y - q[0] * z + q[1] * w + q[2] * x,
q[3] * z + q[0] * y - q[1] * x + q[2] * w,
q[3] * w - q[0] * x - q[1] * y - q[2] * z};
float length = 0.0f;
for (float value: m_state.orientation) {
length += value * value;
}
length = std::sqrt(length);
for (float& value: m_state.orientation) {
value /= length;
}
}
m_gyro_time = time_us;
}
m_state.time = LibKernel::KernelGetProcessTime();
AddState();
}
void GameController::SetMotionSensorState(bool enable) {
Common::LockGuard lock(m_mutex);
if (m_motion_enabled != enable) {
m_motion_enabled = enable;
m_gyro_time = 0;
m_state.accel = {0.0f, 1.0f, 0.0f};
m_state.gyro = {};
m_state.time = LibKernel::KernelGetProcessTime();
AddState();
}
}
void GameController::ResetOrientation() {
Common::LockGuard lock(m_mutex);
m_state.orientation = {0.0f, 0.0f, 0.0f, 1.0f};
m_gyro_time = 0;
m_state.time = LibKernel::KernelGetProcessTime();
AddState();
}
void GameController::ResetInputState() {
Common::LockGuard lock(m_mutex);
m_state = {};
m_state.buttons = 0;
std::fill_n(m_state.axes, 4, 128);
std::fill_n(m_state.axes + 4, 2, 0);
for (auto& touch: m_state.touch) {
touch = {};
}
m_state.time = LibKernel::KernelGetProcessTime();
m_states_num = 0;
m_first_state = 0;
@@ -580,6 +684,10 @@ void SetTouchPad(int id, int finger, bool down, float x, float y) {
g_controller->TouchPad(id, finger, down, x, y);
}
void SetSensor(int id, Sensor sensor, const float* data, uint64_t time_us) {
g_controller->Motion(id, sensor, data, time_us);
}
void ResetInputState() {
g_controller->ResetInputState();
}
@@ -646,6 +754,7 @@ int KYTY_SYSV_ABI PadSetMotionSensorState(int handle, bool enable) {
}
LOGF("\t enable = %s\n", (enable ? "true" : "false"));
g_controller->SetMotionSensorState(enable);
return OK;
}
@@ -669,6 +778,7 @@ int KYTY_SYSV_ABI PadResetOrientation(int handle) {
return PAD_ERROR_INVALID_HANDLE;
}
g_controller->ResetOrientation();
return OK;
}
@@ -702,6 +812,20 @@ int KYTY_SYSV_ABI PadGetControllerInformation(int handle, PadControllerInformati
return OK;
}
int KYTY_SYSV_ABI PadIsRemoteController(int handle, bool* is_remote) {
PRINT_NAME();
if (handle != 1) {
return PAD_ERROR_INVALID_HANDLE;
}
if (is_remote == nullptr) {
return PAD_ERROR_INVALID_ARG;
}
*is_remote = false;
return OK;
}
int KYTY_SYSV_ABI PadReadState(int handle, PadData* data) {
PRINT_NAME();
+4
View File
@@ -46,6 +46,8 @@ enum class Axis {
AxisMax
};
enum class Sensor { Accel, Gyro };
struct PadControllerInformation;
struct PadData;
struct PadVibrationParam;
@@ -69,6 +71,7 @@ void SetButton(int id, uint32_t button, bool down);
void SetAxis(int id, Axis axis, int value);
void SetRightStick(int id, int x, int y);
void SetTouchPad(int id, int finger, bool down, float x, float y);
void SetSensor(int id, Sensor sensor, const float* data, uint64_t time_us);
void ResetInputState();
int KYTY_SYSV_ABI PadInit();
@@ -78,6 +81,7 @@ int KYTY_SYSV_ABI PadSetMotionSensorState(int handle, bool enable);
int KYTY_SYSV_ABI PadSetAngularVelocityDeadbandState(int handle, bool enable);
int KYTY_SYSV_ABI PadResetOrientation(int handle);
int KYTY_SYSV_ABI PadGetControllerInformation(int handle, PadControllerInformation* info);
int KYTY_SYSV_ABI PadIsRemoteController(int handle, bool* is_remote);
int KYTY_SYSV_ABI PadReadState(int handle, PadData* data);
int KYTY_SYSV_ABI PadRead(int handle, PadData* data, int num);
int KYTY_SYSV_ABI PadSetVibration(int handle, const PadVibrationParam* param);
+6 -1
View File
@@ -527,7 +527,12 @@ static int kyty_printf_internal(bool sn, char* sn_s, size_t sn_n, const char* fo
} else if (*format == '*') {
// const int prec = (int)va_arg(va, int);
const int prec = VaArg_int(va_list);
precision = prec > 0 ? static_cast<unsigned int>(prec) : 0U;
if (prec < 0) {
// A negative dynamic precision is treated as omitted.
flags &= ~FLAGS_PRECISION;
} else {
precision = static_cast<unsigned int>(prec);
}
format++;
}
}
+26 -29
View File
@@ -7,6 +7,7 @@
#include <algorithm>
#include <atomic>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <deque>
#include <mutex>
@@ -18,35 +19,31 @@
namespace Libs::Ime {
namespace {
constexpr int Error(uint32_t value) {
return static_cast<int32_t>(value);
}
constexpr int ERROR_BUSY = Error(0x80bc0001);
constexpr int ERROR_NOT_OPENED = Error(0x80bc0002);
constexpr int ERROR_CONNECTION_FAILED = Error(0x80bc0004);
constexpr int ERROR_EVENT_OVERFLOW = Error(0x80bc0007);
constexpr int ERROR_INVALID_TEXT = Error(0x80bc0006);
constexpr int ERROR_INVALID_USER_ID = Error(0x80bc0010);
constexpr int ERROR_INVALID_TYPE = Error(0x80bc0011);
constexpr int ERROR_INVALID_LANGUAGES = Error(0x80bc0012);
constexpr int ERROR_INVALID_ENTER_LABEL = Error(0x80bc0013);
constexpr int ERROR_INVALID_INPUT_METHOD = Error(0x80bc0014);
constexpr int ERROR_INVALID_OPTION = Error(0x80bc0015);
constexpr int ERROR_INVALID_MAX_TEXT_LENGTH = Error(0x80bc0016);
constexpr int ERROR_INVALID_TEXT_BUFFER = Error(0x80bc0017);
constexpr int ERROR_INVALID_POSX = Error(0x80bc0018);
constexpr int ERROR_INVALID_POSY = Error(0x80bc0019);
constexpr int ERROR_INVALID_HALIGN = Error(0x80bc001a);
constexpr int ERROR_INVALID_VALIGN = Error(0x80bc001b);
constexpr int ERROR_INVALID_EXTENDED = Error(0x80bc001c);
constexpr int ERROR_INVALID_WORK = Error(0x80bc0020);
constexpr int ERROR_INVALID_HANDLER = Error(0x80bc0022);
constexpr int ERROR_NO_RESOURCE_ID = Error(0x80bc0023);
constexpr int ERROR_INVALID_MODE = Error(0x80bc0024);
constexpr int ERROR_INVALID_PARAM = Error(0x80bc0030);
constexpr int ERROR_INVALID_ADDRESS = Error(0x80bc0031);
constexpr int ERROR_INVALID_RESERVED = Error(0x80bc0032);
constexpr int ERROR_BUSY = static_cast<int32_t>(0x80bc0001);
constexpr int ERROR_NOT_OPENED = static_cast<int32_t>(0x80bc0002);
constexpr int ERROR_CONNECTION_FAILED = static_cast<int32_t>(0x80bc0004);
constexpr int ERROR_EVENT_OVERFLOW = static_cast<int32_t>(0x80bc0007);
constexpr int ERROR_INVALID_TEXT = static_cast<int32_t>(0x80bc0006);
constexpr int ERROR_INVALID_USER_ID = static_cast<int32_t>(0x80bc0010);
constexpr int ERROR_INVALID_TYPE = static_cast<int32_t>(0x80bc0011);
constexpr int ERROR_INVALID_LANGUAGES = static_cast<int32_t>(0x80bc0012);
constexpr int ERROR_INVALID_ENTER_LABEL = static_cast<int32_t>(0x80bc0013);
constexpr int ERROR_INVALID_INPUT_METHOD = static_cast<int32_t>(0x80bc0014);
constexpr int ERROR_INVALID_OPTION = static_cast<int32_t>(0x80bc0015);
constexpr int ERROR_INVALID_MAX_TEXT_LENGTH = static_cast<int32_t>(0x80bc0016);
constexpr int ERROR_INVALID_TEXT_BUFFER = static_cast<int32_t>(0x80bc0017);
constexpr int ERROR_INVALID_POSX = static_cast<int32_t>(0x80bc0018);
constexpr int ERROR_INVALID_POSY = static_cast<int32_t>(0x80bc0019);
constexpr int ERROR_INVALID_HALIGN = static_cast<int32_t>(0x80bc001a);
constexpr int ERROR_INVALID_VALIGN = static_cast<int32_t>(0x80bc001b);
constexpr int ERROR_INVALID_EXTENDED = static_cast<int32_t>(0x80bc001c);
constexpr int ERROR_INVALID_WORK = static_cast<int32_t>(0x80bc0020);
constexpr int ERROR_INVALID_HANDLER = static_cast<int32_t>(0x80bc0022);
constexpr int ERROR_NO_RESOURCE_ID = static_cast<int32_t>(0x80bc0023);
constexpr int ERROR_INVALID_MODE = static_cast<int32_t>(0x80bc0024);
constexpr int ERROR_INVALID_PARAM = static_cast<int32_t>(0x80bc0030);
constexpr int ERROR_INVALID_ADDRESS = static_cast<int32_t>(0x80bc0031);
constexpr int ERROR_INVALID_RESERVED = static_cast<int32_t>(0x80bc0032);
constexpr uint32_t VALID_OPTIONS = 0x00007bff;
constexpr uint32_t VALID_EXTENDED_OPTIONS = 0x00004fde;
+22 -25
View File
@@ -5,6 +5,7 @@
#include <algorithm>
#include <atomic>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <mutex>
#include <vector>
@@ -13,31 +14,27 @@ namespace Libs::Dialog::ImeDialog {
namespace {
constexpr int Error(uint32_t value) {
return static_cast<int32_t>(value);
}
constexpr int ERROR_BUSY = Error(0x80bc0001);
constexpr int ERROR_INVALID_USER_ID = Error(0x80bc0010);
constexpr int ERROR_INVALID_TYPE = Error(0x80bc0011);
constexpr int ERROR_INVALID_LANGUAGES = Error(0x80bc0012);
constexpr int ERROR_INVALID_ENTER_LABEL = Error(0x80bc0013);
constexpr int ERROR_INVALID_INPUT_METHOD = Error(0x80bc0014);
constexpr int ERROR_INVALID_OPTION = Error(0x80bc0015);
constexpr int ERROR_INVALID_MAX_TEXT_LENGTH = Error(0x80bc0016);
constexpr int ERROR_INVALID_TEXT_BUFFER = Error(0x80bc0017);
constexpr int ERROR_INVALID_POSX = Error(0x80bc0018);
constexpr int ERROR_INVALID_POSY = Error(0x80bc0019);
constexpr int ERROR_INVALID_HALIGN = Error(0x80bc001a);
constexpr int ERROR_INVALID_VALIGN = Error(0x80bc001b);
constexpr int ERROR_INVALID_EXTENDED = Error(0x80bc001c);
constexpr int ERROR_INVALID_PARAM = Error(0x80bc0030);
constexpr int ERROR_INVALID_ADDRESS = Error(0x80bc0031);
constexpr int ERROR_INVALID_RESERVED = Error(0x80bc0032);
constexpr int ERROR_INVALID_TITLE = Error(0x80bc0101);
constexpr int ERROR_NOT_RUNNING = Error(0x80bc0105);
constexpr int ERROR_NOT_FINISHED = Error(0x80bc0106);
constexpr int ERROR_NOT_IN_USE = Error(0x80bc0107);
constexpr int ERROR_BUSY = static_cast<int32_t>(0x80bc0001);
constexpr int ERROR_INVALID_USER_ID = static_cast<int32_t>(0x80bc0010);
constexpr int ERROR_INVALID_TYPE = static_cast<int32_t>(0x80bc0011);
constexpr int ERROR_INVALID_LANGUAGES = static_cast<int32_t>(0x80bc0012);
constexpr int ERROR_INVALID_ENTER_LABEL = static_cast<int32_t>(0x80bc0013);
constexpr int ERROR_INVALID_INPUT_METHOD = static_cast<int32_t>(0x80bc0014);
constexpr int ERROR_INVALID_OPTION = static_cast<int32_t>(0x80bc0015);
constexpr int ERROR_INVALID_MAX_TEXT_LENGTH = static_cast<int32_t>(0x80bc0016);
constexpr int ERROR_INVALID_TEXT_BUFFER = static_cast<int32_t>(0x80bc0017);
constexpr int ERROR_INVALID_POSX = static_cast<int32_t>(0x80bc0018);
constexpr int ERROR_INVALID_POSY = static_cast<int32_t>(0x80bc0019);
constexpr int ERROR_INVALID_HALIGN = static_cast<int32_t>(0x80bc001a);
constexpr int ERROR_INVALID_VALIGN = static_cast<int32_t>(0x80bc001b);
constexpr int ERROR_INVALID_EXTENDED = static_cast<int32_t>(0x80bc001c);
constexpr int ERROR_INVALID_PARAM = static_cast<int32_t>(0x80bc0030);
constexpr int ERROR_INVALID_ADDRESS = static_cast<int32_t>(0x80bc0031);
constexpr int ERROR_INVALID_RESERVED = static_cast<int32_t>(0x80bc0032);
constexpr int ERROR_INVALID_TITLE = static_cast<int32_t>(0x80bc0101);
constexpr int ERROR_NOT_RUNNING = static_cast<int32_t>(0x80bc0105);
constexpr int ERROR_NOT_FINISHED = static_cast<int32_t>(0x80bc0106);
constexpr int ERROR_NOT_IN_USE = static_cast<int32_t>(0x80bc0107);
constexpr uint32_t VALID_OPTIONS = 0x00007bff;
constexpr uint32_t VALID_EXTENDED_OPTIONS = 0x00005fde;
+5 -5
View File
@@ -51,17 +51,17 @@ static bool TryGetTitleIdFromContentId(std::string* title_id) {
return false;
}
const uint32_t dash = Common::FindIndex(content_id, '-');
if (!Common::IndexValid(content_id, dash)) {
const auto dash = content_id.find('-');
if (dash == std::string::npos) {
return false;
}
const uint32_t underscore = Common::FindIndex(content_id, '_', dash + 1);
if (!Common::IndexValid(content_id, underscore) || underscore <= dash + 1) {
const auto underscore = content_id.find('_', dash + 1);
if (underscore == std::string::npos || underscore <= dash + 1) {
return false;
}
*title_id = Common::Mid(content_id, dash + 1, underscore - dash - 1);
*title_id = content_id.substr(dash + 1, underscore - dash - 1);
return !title_id->empty();
}
+1 -1
View File
@@ -1052,7 +1052,7 @@ static int32_t KYTY_SYSV_ABI AudiodecDecode(int32_t handle, AudiodecCtrl* ctrl)
ctrl->pPcmItem->uiPcmSize = static_cast<uint32_t>(result.output_written);
audiodec_fill_info(ctrl, decoder);
auto* info = static_cast<AudiodecM4aacInfo*>(ctrl->pBsiInfo);
info->iResult = (result.result & AJM_RESULT_CODEC_ERROR) != 0
info->iResult = (result.result & (AJM_RESULT_CODEC_ERROR | AJM_RESULT_TOO_MANY_CHANNELS)) != 0
? AUDIODEC_M4AAC_RESULT_DECODE_ERROR
: (result.result & AJM_RESULT_PARTIAL_INPUT) != 0
? AUDIODEC_M4AAC_RESULT_INSUFFICIENT_DATA : 0;
+1
View File
@@ -11,6 +11,7 @@
#include "loader/symbolDatabase.h"
#include <algorithm>
#include <cstring>
#include <vector>
namespace Libs {
+1
View File
@@ -1,3 +1,4 @@
#include "common/assert.h"
#include "common/emulatorConfig.h"
#include "graphics/guest_gpu/tile.h"
#include "libs/agc.h"
+4 -7
View File
@@ -24,6 +24,7 @@
#include <algorithm>
#include <array>
#include <atomic>
#include <bit>
#include <chrono>
#include <cstddef>
#include <cstdio>
@@ -68,10 +69,6 @@ using KernelModule = int32_t;
using get_thread_atexit_count_func_t = KYTY_SYSV_ABI int (*)(KernelModule);
using thread_atexit_report_func_t = KYTY_SYSV_ABI void (*)(KernelModule);
static uint32_t sha1_rol(uint32_t value, uint32_t bits) {
return (value << bits) | (value >> (32u - bits));
}
static std::array<uint8_t, 20> sha1_digest(const uint8_t* data, size_t size) {
uint32_t h0 = 0x67452301u;
uint32_t h1 = 0xefcdab89u;
@@ -99,7 +96,7 @@ static std::array<uint8_t, 20> sha1_digest(const uint8_t* data, size_t size) {
(static_cast<uint32_t>(msg[j + 2]) << 8u) | static_cast<uint32_t>(msg[j + 3]);
}
for (int i = 16; i < 80; i++) {
w[i] = sha1_rol(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
w[i] = std::rotl(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
}
uint32_t a = h0;
@@ -125,10 +122,10 @@ static std::array<uint8_t, 20> sha1_digest(const uint8_t* data, size_t size) {
k = 0xca62c1d6u;
}
const auto temp = sha1_rol(a, 5) + f + e + k + w[i];
const auto temp = std::rotl(a, 5) + f + e + k + w[i];
e = d;
d = c;
c = sha1_rol(b, 30);
c = std::rotl(b, 30);
b = a;
a = temp;
}
+62 -43
View File
@@ -8,22 +8,13 @@
#include "loader/symbolDatabase.h"
#include <cctype>
#include <cstddef>
#include <cstring>
#include <map>
#include <mutex>
#include <string>
#include <vector>
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define NET_CALL(func) \
[&]() { \
auto result = func; \
if (result < 0) { \
*GetNetErrorAddr() = result; \
} \
return result; \
}()
namespace Libs {
namespace Network::Net {
@@ -43,8 +34,15 @@ KYTY_SYSV_ABI int* GetNetErrorAddr() {
return &g_net_errno;
}
static int FinishNetCall(int result) {
if (result < 0) {
g_net_errno = result - Network::NET_ERROR_EPERM + 1;
}
return result;
}
static int KYTY_SYSV_ABI NetInit() {
return NET_CALL(Net::NetInit());
return FinishNetCall(Net::NetInit());
}
static int PosixToNetError(int error) {
@@ -66,13 +64,7 @@ static int PosixToNetError(int error) {
}
static int FinishSocketCall(int result) {
if (result >= 0) {
return result;
}
const int net_error = PosixToNetError(*Posix::GetErrorAddr());
*GetNetErrorAddr() = net_error;
return net_error;
return FinishNetCall(result < 0 ? PosixToNetError(*Posix::GetErrorAddr()) : result);
}
int KYTY_SYSV_ABI NetSocket(const char* name, int family, int type, int protocol) {
@@ -102,48 +94,48 @@ int KYTY_SYSV_ABI NetGetsockname(int s, void* addr, uint32_t* addrlen) {
}
int KYTY_SYSV_ABI NetPoolCreate(const char* name, int size, int flags) {
return NET_CALL(Net::NetPoolCreate(name, size, flags));
return FinishNetCall(Net::NetPoolCreate(name, size, flags));
}
int KYTY_SYSV_ABI NetPoolDestroy(int memid) {
return NET_CALL(Net::NetPoolDestroy(memid));
return FinishNetCall(Net::NetPoolDestroy(memid));
}
int KYTY_SYSV_ABI NetResolverCreate(const char* name, int memid, int flags) {
return NET_CALL(Net::NetResolverCreate(name, memid, flags));
return FinishNetCall(Net::NetResolverCreate(name, memid, flags));
}
int KYTY_SYSV_ABI NetResolverDestroy(int rid) {
return NET_CALL(Net::NetResolverDestroy(rid));
return FinishNetCall(Net::NetResolverDestroy(rid));
}
int KYTY_SYSV_ABI NetResolverStartNtoa(int rid, const char* hostname, void* addr, int timeout,
int retry, int flags) {
return NET_CALL(Net::NetResolverStartNtoa(rid, hostname, addr, timeout, retry, flags));
return FinishNetCall(Net::NetResolverStartNtoa(rid, hostname, addr, timeout, retry, flags));
}
int KYTY_SYSV_ABI NetInetPton(int af, const char* src, void* dst) {
return NET_CALL(Net::NetInetPton(af, src, dst));
return FinishNetCall(Net::NetInetPton(af, src, dst));
}
const char* KYTY_SYSV_ABI NetInetNtop(int af, const void* src, char* dst, uint32_t size) {
const char* result = Net::NetInetNtop(af, src, dst, size);
if (result == nullptr) {
*GetNetErrorAddr() = PosixToNetError(*Posix::GetErrorAddr());
FinishNetCall(PosixToNetError(*Posix::GetErrorAddr()));
}
return result;
}
int KYTY_SYSV_ABI NetEtherNtostr(const Net::NetEtherAddr* n, char* str, size_t len) {
return NET_CALL(Net::NetEtherNtostr(n, str, len));
return FinishNetCall(Net::NetEtherNtostr(n, str, len));
}
int KYTY_SYSV_ABI NetGetMacAddress(Net::NetEtherAddr* addr, int flags) {
return NET_CALL(Net::NetGetMacAddress(addr, flags));
return FinishNetCall(Net::NetGetMacAddress(addr, flags));
}
int KYTY_SYSV_ABI NetGetSockInfo(int s, void* info, int n, int flags) {
return NET_CALL(Net::NetGetSockInfo(s, info, n, flags));
return FinishNetCall(Net::NetGetSockInfo(s, info, n, flags));
}
int KYTY_SYSV_ABI NetEpollCreate(const char* name, int flags) {
@@ -163,7 +155,7 @@ int KYTY_SYSV_ABI NetEpollDestroy(int eid) {
}
int KYTY_SYSV_ABI NetSocketClose(int s) {
return NET_CALL(Net::SocketClose(s));
return FinishNetCall(Net::SocketClose(s));
}
int KYTY_SYSV_ABI NetSetsockopt(int s, int level, int optname, const void* optval,
@@ -1465,7 +1457,7 @@ LIB_DEFINE(InitNet_1_NpManager) {
LIB_FUNC("Ec63y59l9tw", NpManager::NpSetNpTitleId);
LIB_FUNC("A2CQ3kgSopQ", NpManager::NpSetContentRestriction);
LIB_FUNC("VfRSmPmj8Q8", NpManager::NpRegisterStateCallback);
LIB_FUNC("qQJfO8HAiaY", NpManager::NpRegisterStateCallback);
LIB_FUNC("qQJfO8HAiaY", NpManager::NpRegisterStateCallbackA);
LIB_FUNC("M3wFXbYQtAA", NpManager::NpUnregisterStateCallback);
LIB_FUNC("uFJpaKNBAj4", NpManager::NpRegisterGamePresenceCallback);
LIB_FUNC("GImICnh+boA", NpManager::NpRegisterPlusEventCallback);
@@ -3118,16 +3110,6 @@ static std::map<int64_t, NpWebApi2Request>& NpWebApi2Requests() {
return requests;
}
[[maybe_unused]] static std::string NpWebApi2MakeResponse(const NpWebApi2Request& request) {
if (request.api_group.find("sessionManager") != std::string::npos ||
request.path.find("sessions") != std::string::npos ||
request.path.find("Sessions") != std::string::npos) {
return R"({"gameSessions":[],"playerSessions":[]})";
}
return "{}";
}
static int KYTY_SYSV_ABI NpWebApi2Initialize(int lib_http_ctx_id, size_t pool_size) {
PRINT_NAME();
@@ -3224,12 +3206,10 @@ NpWebApi2SendRequest(int64_t request_id, const void* data, size_t data_size,
return NP_WEBAPI2_ERROR_REQUEST_NOT_FOUND;
}
// request->second.response = NpWebApi2MakeResponse(request->second);
request->second.response.clear();
request->second.read_offset = 0;
if (response_info_option != nullptr) {
// response_info_option->http_status = 200;
response_info_option->http_status = 0;
response_info_option->response_data_size = request->second.response.size();
if (response_info_option->error_object != nullptr &&
@@ -3238,7 +3218,6 @@ NpWebApi2SendRequest(int64_t request_id, const void* data, size_t data_size,
}
}
// return 0;
return NP_WEBAPI2_ERROR_NOT_SIGNED_IN;
}
@@ -3743,6 +3722,21 @@ namespace LibGameLiveStreaming {
LIB_VERSION("GameLiveStreaming", 1, "GameLiveStreaming", 1, 1);
constexpr int GAME_LIVE_STREAMING_ERROR_INVALID_PARAM = -2136997886;
struct GameLiveStreamingStatus2 {
int32_t user_id;
bool is_on_air;
uint32_t spectator_count;
uint32_t text_message_count;
uint32_t command_message_count;
uint8_t reserved[52];
};
static_assert(sizeof(GameLiveStreamingStatus2) == 72);
static_assert(offsetof(GameLiveStreamingStatus2, is_on_air) == 4);
static_assert(offsetof(GameLiveStreamingStatus2, spectator_count) == 8);
static int KYTY_SYSV_ABI GameLiveStreamingInitialize(size_t heap_size) {
PRINT_NAME();
@@ -3757,9 +3751,34 @@ static int KYTY_SYSV_ABI GameLiveStreamingTerminate() {
return 0;
}
static int KYTY_SYSV_ABI GameLiveStreamingGetCurrentStatus2(GameLiveStreamingStatus2* status) {
PRINT_NAME();
if (status == nullptr) {
return GAME_LIVE_STREAMING_ERROR_INVALID_PARAM;
}
std::memset(status, 0, sizeof(*status));
status->user_id = -1;
return OK;
}
static int KYTY_SYSV_ABI GameLiveStreamingGetSocialFeedbackMessagesCount(int type, uint32_t* count) {
PRINT_NAME();
if (type < 1 || type > 3 || count == nullptr) {
return GAME_LIVE_STREAMING_ERROR_INVALID_PARAM;
}
*count = 0;
return OK;
}
LIB_DEFINE(InitPlatform_1_GameLiveStreaming) {
LIB_FUNC("kvYEw2lBndk", LibGameLiveStreaming::GameLiveStreamingInitialize);
LIB_FUNC("9yK6Fk8mKOQ", LibGameLiveStreaming::GameLiveStreamingTerminate);
LIB_FUNC("lK8dLBNp9OE", LibGameLiveStreaming::GameLiveStreamingGetCurrentStatus2);
LIB_FUNC("yeQKjHETi40", LibGameLiveStreaming::GameLiveStreamingGetSocialFeedbackMessagesCount);
}
} // namespace LibGameLiveStreaming
+1
View File
@@ -206,6 +206,7 @@ LIB_DEFINE(InitPad_1) {
LIB_FUNC("rIZnR6eSpvk", Controller::PadResetOrientation);
LIB_FUNC("vDLMoJLde8I", PadSetTiltCorrectionState);
LIB_FUNC("gjP9-KQzoUk", Controller::PadGetControllerInformation);
LIB_FUNC("fCWdlnmB1Ks", Controller::PadIsRemoteController);
LIB_FUNC("hGbf2QTBmqc", PadGetExtControllerInformationStub);
LIB_FUNC("2JgFB2n9oUM", Controller::PadSetTriggerEffect);
LIB_FUNC("YndgXqQVV7c", Controller::PadReadState);
+5 -9
View File
@@ -13,15 +13,11 @@ LIB_VERSION("Psml", 1, "Psml", 1, 1);
namespace Psml {
constexpr int Error(uint32_t value) {
return static_cast<int>(value);
}
constexpr int PSML_ERROR_NOT_INITIALIZED = Error(0x8a810001u);
constexpr int PSML_ERROR_INVALID_OBJECT = Error(0x8a810005u);
constexpr int PSML_ERROR_INVALID_POINTER = Error(0x8a810009u);
constexpr int PSML_ERROR_INVALID_VALUE = Error(0x8a81000du);
constexpr int PSML_ERROR_NULL_OBJECT = Error(0x8a810014u);
constexpr int PSML_ERROR_NOT_INITIALIZED = static_cast<int>(0x8a810001u);
constexpr int PSML_ERROR_INVALID_OBJECT = static_cast<int>(0x8a810005u);
constexpr int PSML_ERROR_INVALID_POINTER = static_cast<int>(0x8a810009u);
constexpr int PSML_ERROR_INVALID_VALUE = static_cast<int>(0x8a81000du);
constexpr int PSML_ERROR_NULL_OBJECT = static_cast<int>(0x8a810014u);
constexpr uint32_t SHARED_RESOURCES_MAGIC = 0xa9c4;
constexpr uint32_t CONTEXT_MAGIC = 0x9231;
+1 -1
View File
@@ -376,7 +376,7 @@ int KYTY_SYSV_ABI SaveDataDirNameSearch(const SaveDataDirNameSearchCond* cond,
if (Common::File::IsDirectoryExisting(root)) {
for (const auto& entry: Common::File::GetDirEntries(root)) {
if (!entry.is_file && entry.name != "." && entry.name != ".." &&
!Common::StartsWith(entry.name, "sce_")) {
!entry.name.starts_with("sce_")) {
if (cond->dir_name == nullptr || cond->dir_name->data[0] == '\0' ||
dir_name_match(Common::ToLower(entry.name).c_str(),
Common::ToLower(std::string(cond->dir_name->data)).c_str())) {
+297 -88
View File
@@ -14,18 +14,18 @@
#endif
#else
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
#include "common/assert.h"
#include "common/byteBuffer.h"
#include "common/common.h"
#include "common/emulatorConfig.h"
#include "common/logging/log.h"
#include "common/stringUtils.h"
#include "common/threads.h"
#include "kernel/pthread.h"
#include "libs/errno.h"
@@ -40,9 +40,13 @@
#include <cstdio>
#include <cstring>
#include <fmt/format.h>
#include <fmt/ranges.h>
#include <limits>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <utility>
#include <vector>
namespace Libs::Network {
@@ -252,7 +256,7 @@ void Shutdown() {
int Network::PoolCreate(const char* name, int size) {
Common::LockGuard lock(m_mutex);
for (int id = 0; id < POOLS_MAX; id++) {
for (int id = 1; id < POOLS_MAX; id++) {
if (!m_pools[id].used) {
m_pools[id].used = true;
m_pools[id].size = size;
@@ -844,9 +848,37 @@ using SocketLength = socklen_t;
using SocketIoLength = size_t;
#endif
struct SocketTransport {
explicit SocketTransport(NativeSocket value): socket(value) {}
~SocketTransport() { Close(); }
int Close() {
if (socket == INVALID_NATIVE_SOCKET) {
return 0;
}
const auto value = std::exchange(socket, INVALID_NATIVE_SOCKET);
#if defined(_WIN32)
return closesocket(value);
#else
return ::close(value);
#endif
}
NativeSocket socket;
};
struct P2pEndpoint {
bool bound = false;
uint32_t address = 0;
uint16_t port = 0;
uint16_t virtual_port = 0;
int nonblocking = 0;
int broadcast = 0;
int send_buffer = 9216;
int receive_buffer = 40 * 1024;
};
struct SocketSlot {
bool used = false;
NativeSocket socket = INVALID_NATIVE_SOCKET;
std::shared_ptr<SocketTransport> transport;
std::optional<P2pEndpoint> p2p;
};
struct NetTimeval {
@@ -998,6 +1030,16 @@ static int ConvertSocketOptionLevel(int level) {
return (level == 0xffff ? SOL_SOCKET : level);
}
static int* P2pSocketOption(P2pEndpoint& endpoint, int option) {
switch (option) {
case 0x0020: return &endpoint.broadcast;
case 0x1001: return &endpoint.send_buffer;
case 0x1002: return &endpoint.receive_buffer;
case 0x1200: return &endpoint.nonblocking;
default: return nullptr;
}
}
static int ConvertMessageFlags(int flags) {
constexpr int guest_msg_peek = 0x00000002;
constexpr int guest_msg_dontroute = 0x00000004;
@@ -1104,19 +1146,30 @@ static int ConvertHostSockaddr(const sockaddr_storage* addr, SocketLength addrle
return 0;
}
static bool GetSocketBackend(int guest_fd, NativeSocket* out) {
static bool GetSocketBackend(int guest_fd, NativeSocket* out, SocketSlot* state = nullptr) {
EXIT_IF(out == nullptr);
if (guest_fd < 0 || guest_fd >= SOCKET_FD_MAX) {
SetGuestSocketError(Posix::POSIX_EBADF);
return false;
}
Common::LockGuard lock(g_socket_mutex);
if (!g_sockets[static_cast<size_t>(guest_fd)].used) {
const auto& slot = g_sockets[static_cast<size_t>(guest_fd)];
if (!slot.transport) {
SetGuestSocketError(Posix::POSIX_EBADF);
return false;
}
// Native-only operations cannot act on a transport shared by virtual ports.
if (slot.p2p && state == nullptr) {
SetGuestSocketError(Posix::POSIX_EOPNOTSUPP);
return false;
}
*out = g_sockets[static_cast<size_t>(guest_fd)].socket;
*out = slot.transport->socket;
if (state != nullptr) {
*state = slot;
}
return true;
}
@@ -1126,10 +1179,10 @@ bool KYTY_SYSV_ABI IsSocket(int s) {
}
Common::LockGuard lock(g_socket_mutex);
return g_sockets[static_cast<size_t>(s)].used;
return g_sockets[static_cast<size_t>(s)].transport != nullptr;
}
static bool TakeSocketBackend(int guest_fd, NativeSocket* out) {
static bool TakeSocketBackend(int guest_fd, SocketSlot* out) {
EXIT_IF(out == nullptr);
if (guest_fd < 0 || guest_fd >= SOCKET_FD_MAX) {
@@ -1138,22 +1191,24 @@ static bool TakeSocketBackend(int guest_fd, NativeSocket* out) {
Common::LockGuard lock(g_socket_mutex);
auto& slot = g_sockets[static_cast<size_t>(guest_fd)];
if (!slot.used) {
if (!slot.transport) {
return false;
}
*out = slot.socket;
*out = std::move(slot);
slot = {};
return true;
}
static int AllocSocketFd(NativeSocket socket) {
static int AllocSocketFd(const std::shared_ptr<SocketTransport>& transport, bool p2p = false) {
Common::LockGuard lock(g_socket_mutex);
for (int fd = SOCKET_FD_MIN; fd < SOCKET_FD_MAX; fd++) {
auto& slot = g_sockets[static_cast<size_t>(fd)];
if (!slot.used) {
slot.used = true;
slot.socket = socket;
if (!slot.transport) {
slot.transport = transport;
if (p2p) {
slot.p2p.emplace();
}
return fd;
}
}
@@ -1528,10 +1583,10 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
return 0;
}
#if defined(_WIN32)
struct HostRegistration {
EpollRegistration guest;
NativeSocket socket = INVALID_NATIVE_SOCKET;
SocketSlot state;
};
fd_set host_read {};
@@ -1543,14 +1598,23 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
std::vector<HostRegistration> host_registrations;
host_registrations.reserve(registrations.size());
int host_nfds = 0;
for (const auto& registration: registrations) {
NativeSocket socket = INVALID_NATIVE_SOCKET;
if (!GetSocketBackend(registration.id, &socket)) {
SocketSlot state;
if (!GetSocketBackend(registration.id, &socket, &state)) {
continue;
}
#if defined(_WIN32)
if (host_registrations.size() >= FD_SETSIZE) {
return SetGuestSocketError(Posix::POSIX_EINVAL);
}
#else
if (socket >= FD_SETSIZE) {
return SetGuestSocketError(Posix::POSIX_EINVAL);
}
host_nfds = std::max(host_nfds, socket + 1);
#endif
if ((registration.event.events & EPOLL_IN) != 0) {
FD_SET(socket, &host_read);
}
@@ -1558,7 +1622,7 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
FD_SET(socket, &host_write);
}
FD_SET(socket, &host_except);
host_registrations.push_back({registration, socket});
host_registrations.push_back({registration, socket, std::move(state)});
}
if (host_registrations.empty()) {
@@ -1573,8 +1637,8 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
host_timeout_ptr = &host_timeout;
}
const int result = ::select(0, &host_read, &host_write, &host_except, host_timeout_ptr);
if (result == SOCKET_ERROR) {
const int result = ::select(host_nfds, &host_read, &host_write, &host_except, host_timeout_ptr);
if (result < 0) {
return SetHostSocketError();
}
if (result == 0) {
@@ -1584,10 +1648,15 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
int count = 0;
for (const auto& registration: host_registrations) {
uint32_t ready = 0;
if (FD_ISSET(registration.socket, &host_read)) {
if ((registration.guest.event.events & EPOLL_IN) != 0 &&
FD_ISSET(registration.socket, &host_read)) {
if (registration.state.p2p) {
return SetGuestSocketError(Posix::POSIX_EOPNOTSUPP);
}
ready |= EPOLL_IN;
}
if (FD_ISSET(registration.socket, &host_write)) {
if ((registration.guest.event.events & EPOLL_OUT) != 0 &&
FD_ISSET(registration.socket, &host_write)) {
ready |= EPOLL_OUT;
}
if (FD_ISSET(registration.socket, &host_except)) {
@@ -1607,10 +1676,6 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
}
}
return count;
#else
(void)timeout;
return SetGuestSocketError(Posix::POSIX_ENOSYS);
#endif
}
int KYTY_SYSV_ABI EpollDestroy(int eid) {
@@ -1632,18 +1697,13 @@ int KYTY_SYSV_ABI SocketClose(int s) {
LOGF("\t s = %d\n", s);
NativeSocket socket = INVALID_NATIVE_SOCKET;
if (!TakeSocketBackend(s, &socket)) {
SocketSlot slot;
if (!TakeSocketBackend(s, &slot)) {
return NET_ERROR_EBADF;
}
RemoveSocketFromEpolls(s);
#if defined(_WIN32)
const int result = closesocket(socket);
#else
const int result = ::close(socket);
#endif
if (result != 0) {
if (slot.transport.use_count() == 1 && slot.transport->Close() != 0) {
return NET_ERROR_EBADF;
}
@@ -1668,18 +1728,31 @@ int KYTY_SYSV_ABI Socket(int family, int type, int protocol) {
return -1;
}
NativeSocket socket = ::socket(host_family, type, protocol);
constexpr int socket_dgram_p2p = 6;
const bool p2p = type == socket_dgram_p2p;
if (p2p && (family != 2 || protocol != 0)) {
return SetGuestSocketError(Posix::POSIX_EPROTONOSUPPORT);
}
NativeSocket socket = ::socket(host_family, p2p ? SOCK_DGRAM : type, protocol);
if (socket == INVALID_NATIVE_SOCKET) {
return SetHostSocketError();
}
const int fd = AllocSocketFd(socket);
if (fd < 0) {
auto transport = std::make_shared<SocketTransport>(socket);
if (p2p) {
// Logical sockets keep their own blocking mode; the shared transport never blocks.
#if defined(_WIN32)
closesocket(socket);
u_long enabled = 1;
const int result = ioctlsocket(socket, FIONBIO, &enabled);
#else
::close(socket);
const int result = ::fcntl(socket, F_SETFL, O_NONBLOCK);
#endif
if (result != 0) {
return SetHostSocketError();
}
}
const int fd = AllocSocketFd(transport, p2p);
if (fd < 0) {
*Posix::GetErrorAddr() = Posix::POSIX_EMFILE;
return -1;
}
@@ -1697,8 +1770,11 @@ int KYTY_SYSV_ABI Bind(int s, const void* addr, uint32_t addrlen) {
s, reinterpret_cast<uint64_t>(addr), addrlen);
NativeSocket socket = INVALID_NATIVE_SOCKET;
if (addr == nullptr || !GetSocketBackend(s, &socket)) {
*Posix::GetErrorAddr() = (addr == nullptr ? Posix::POSIX_EFAULT : Posix::POSIX_EBADF);
SocketSlot state;
if (addr == nullptr) {
return SetGuestSocketError(Posix::POSIX_EFAULT);
}
if (!GetSocketBackend(s, &socket, &state)) {
return -1;
}
@@ -1708,6 +1784,67 @@ int KYTY_SYSV_ABI Bind(int s, const void* addr, uint32_t addrlen) {
return -1;
}
if (state.p2p) {
if (addrlen < 16) {
return SetGuestSocketError(Posix::POSIX_EINVAL);
}
const auto& in = *reinterpret_cast<const sockaddr_in*>(&host_addr);
uint32_t address = 0;
std::memcpy(&address, &in.sin_addr, sizeof(address));
uint16_t virtual_port = 0;
std::memcpy(&virtual_port, static_cast<const uint8_t*>(addr) + 8, sizeof(virtual_port));
const auto requested_port = ntohs(virtual_port);
if (requested_port == 0) {
return SetGuestSocketError(Posix::POSIX_EOPNOTSUPP);
}
if (ntohs(in.sin_port) != 3658) {
return SetGuestSocketError(Posix::POSIX_EINVAL);
}
if (requested_port == 5353 || requested_port >= 32768) {
return SetGuestSocketError(Posix::POSIX_EACCES);
}
Common::LockGuard lock(g_socket_mutex);
auto& slot = g_sockets[static_cast<size_t>(s)];
if (slot.transport != state.transport) {
return SetGuestSocketError(Posix::POSIX_EBADF);
}
auto& endpoint = *slot.p2p;
if (endpoint.bound) {
return SetGuestSocketError(Posix::POSIX_EINVAL);
}
auto conflicts = [&](uint16_t port) {
return std::any_of(g_sockets.begin(), g_sockets.end(), [&](const auto& other) {
return other.p2p && other.p2p->bound && other.p2p->port == in.sin_port &&
other.p2p->address == address && other.p2p->virtual_port == port;
});
};
if (conflicts(virtual_port)) {
return SetGuestSocketError(Posix::POSIX_EADDRINUSE);
}
std::shared_ptr<SocketTransport> shared;
for (const auto& other: g_sockets) {
if (other.p2p && other.p2p->bound && other.p2p->port == in.sin_port &&
other.p2p->address == address) {
shared = other.transport;
break;
}
}
if (shared) {
slot.transport = std::move(shared);
} else if (::bind(socket, reinterpret_cast<const sockaddr*>(&host_addr), host_addrlen) !=
0) {
return SetHostSocketError();
}
endpoint.bound = true;
endpoint.address = address;
endpoint.port = in.sin_port;
endpoint.virtual_port = virtual_port;
LOGF("\t UDPP2P bound UDP port=%u virtual port=%u\n", ntohs(endpoint.port),
ntohs(endpoint.virtual_port));
return 0;
}
if (::bind(socket, reinterpret_cast<const sockaddr*>(&host_addr), host_addrlen) != 0) {
return SetHostSocketError();
}
@@ -1724,8 +1861,10 @@ int KYTY_SYSV_ABI Connect(int s, const void* addr, uint32_t addrlen) {
s, reinterpret_cast<uint64_t>(addr), addrlen);
NativeSocket socket = INVALID_NATIVE_SOCKET;
if (addr == nullptr || !GetSocketBackend(s, &socket)) {
*Posix::GetErrorAddr() = (addr == nullptr ? Posix::POSIX_EFAULT : Posix::POSIX_EBADF);
if (addr == nullptr) {
return SetGuestSocketError(Posix::POSIX_EFAULT);
}
if (!GetSocketBackend(s, &socket)) {
return -1;
}
@@ -1751,7 +1890,6 @@ int KYTY_SYSV_ABI Listen(int s, int backlog) {
NativeSocket socket = INVALID_NATIVE_SOCKET;
if (!GetSocketBackend(s, &socket)) {
*Posix::GetErrorAddr() = Posix::POSIX_EBADF;
return -1;
}
@@ -1772,7 +1910,6 @@ int KYTY_SYSV_ABI Accept(int s, void* addr, uint32_t* addrlen) {
NativeSocket socket = INVALID_NATIVE_SOCKET;
if (!GetSocketBackend(s, &socket)) {
*Posix::GetErrorAddr() = Posix::POSIX_EBADF;
return -1;
}
@@ -1784,13 +1921,9 @@ int KYTY_SYSV_ABI Accept(int s, void* addr, uint32_t* addrlen) {
return SetHostSocketError();
}
const int fd = AllocSocketFd(accepted);
auto transport = std::make_shared<SocketTransport>(accepted);
const int fd = AllocSocketFd(transport);
if (fd < 0) {
#if defined(_WIN32)
closesocket(accepted);
#else
::close(accepted);
#endif
*Posix::GetErrorAddr() = Posix::POSIX_EMFILE;
return -1;
}
@@ -1819,7 +1952,6 @@ int KYTY_SYSV_ABI Shutdown(int s, int how) {
NativeSocket socket = INVALID_NATIVE_SOCKET;
if (!GetSocketBackend(s, &socket)) {
*Posix::GetErrorAddr() = Posix::POSIX_EBADF;
return -1;
}
@@ -1848,12 +1980,14 @@ int KYTY_SYSV_ABI Getsockname(int s, void* addr, uint32_t* addrlen) {
"\t addrlen = 0x%016" PRIx64 "\n",
s, reinterpret_cast<uint64_t>(addr), reinterpret_cast<uint64_t>(addrlen));
NativeSocket socket = INVALID_NATIVE_SOCKET;
const bool socket_ok = GetSocketBackend(s, &socket);
if (addr == nullptr || addrlen == nullptr || !socket_ok) {
*Posix::GetErrorAddr() = (!socket_ok ? Posix::POSIX_EBADF : Posix::POSIX_EFAULT);
NativeSocket socket = INVALID_NATIVE_SOCKET;
SocketSlot state;
if (!GetSocketBackend(s, &socket, &state)) {
return -1;
}
if (addr == nullptr || addrlen == nullptr) {
return SetGuestSocketError(Posix::POSIX_EFAULT);
}
sockaddr_storage host_addr {};
SocketLength host_addrlen = sizeof(host_addr);
@@ -1861,7 +1995,11 @@ int KYTY_SYSV_ABI Getsockname(int s, void* addr, uint32_t* addrlen) {
return SetHostSocketError();
}
return ConvertHostSockaddr(&host_addr, host_addrlen, addr, addrlen);
const int result = ConvertHostSockaddr(&host_addr, host_addrlen, addr, addrlen);
if (result == 0 && state.p2p) {
std::memcpy(static_cast<uint8_t*>(addr) + 8, &state.p2p->virtual_port, sizeof(uint16_t));
}
return result;
}
int KYTY_SYSV_ABI Getsockopt(int s, int level, int optname, void* optval, uint32_t* optlen) {
@@ -1872,12 +2010,26 @@ int KYTY_SYSV_ABI Getsockopt(int s, int level, int optname, void* optval, uint32
"\t optname = 0x%08" PRIx32 "\n",
s, static_cast<uint32_t>(level), static_cast<uint32_t>(optname));
NativeSocket socket = INVALID_NATIVE_SOCKET;
const bool socket_ok = GetSocketBackend(s, &socket);
if (optval == nullptr || optlen == nullptr || !socket_ok) {
*Posix::GetErrorAddr() = (!socket_ok ? Posix::POSIX_EBADF : Posix::POSIX_EFAULT);
NativeSocket socket = INVALID_NATIVE_SOCKET;
SocketSlot state;
if (!GetSocketBackend(s, &socket, &state)) {
return -1;
}
if (optval == nullptr || optlen == nullptr) {
return SetGuestSocketError(Posix::POSIX_EFAULT);
}
if (state.p2p) {
const auto* value = level == 0xffff ? P2pSocketOption(*state.p2p, optname) : nullptr;
if (value == nullptr) {
return SetGuestSocketError(Posix::POSIX_ENOPROTOOPT);
}
if (*optlen < sizeof(int)) {
return SetGuestSocketError(Posix::POSIX_EINVAL);
}
std::memcpy(optval, value, sizeof(int));
*optlen = sizeof(int);
return 0;
}
// Guest socket options: SOL_SOCKET=0xffff, SO_ERROR=0x1007.
const bool socket_error = (level == 0xffff && optname == 0x1007);
@@ -1912,10 +2064,38 @@ int KYTY_SYSV_ABI Setsockopt(int s, int level, int optname, const void* optval,
s, static_cast<uint32_t>(level), static_cast<uint32_t>(optname), optlen);
NativeSocket socket = INVALID_NATIVE_SOCKET;
if (optval == nullptr || !GetSocketBackend(s, &socket)) {
*Posix::GetErrorAddr() = (optval == nullptr ? Posix::POSIX_EFAULT : Posix::POSIX_EBADF);
SocketSlot state;
if (optval == nullptr) {
return SetGuestSocketError(Posix::POSIX_EFAULT);
}
if (!GetSocketBackend(s, &socket, &state)) {
return -1;
}
if (state.p2p) {
Common::LockGuard lock(g_socket_mutex);
auto& slot = g_sockets[static_cast<size_t>(s)];
if (slot.transport != state.transport) {
return SetGuestSocketError(Posix::POSIX_EBADF);
}
auto* option = level == 0xffff ? P2pSocketOption(*slot.p2p, optname) : nullptr;
if (option == nullptr) {
return SetGuestSocketError(Posix::POSIX_ENOPROTOOPT);
}
if (optlen != sizeof(int)) {
return SetGuestSocketError(Posix::POSIX_EINVAL);
}
int value = 0;
std::memcpy(&value, optval, sizeof(value));
if (optname == 0x1001 || optname == 0x1002) {
if (value <= 0) {
return SetGuestSocketError(Posix::POSIX_EINVAL);
}
*option = optname == 0x1002 ? std::min(value, 512 * 1024) : value;
} else {
*option = value != 0;
}
return 0;
}
#if defined(_WIN32)
constexpr int ORBIS_SO_NBIO = 0x1200;
@@ -1962,8 +2142,11 @@ int64_t KYTY_SYSV_ABI Sendto(int s, const void* buf, uint64_t len, int flags, co
reinterpret_cast<uint64_t>(addr), addrlen);
NativeSocket socket = INVALID_NATIVE_SOCKET;
if (buf == nullptr || !GetSocketBackend(s, &socket)) {
*Posix::GetErrorAddr() = (buf == nullptr ? Posix::POSIX_EFAULT : Posix::POSIX_EBADF);
if (buf == nullptr) {
return SetGuestSocketError(Posix::POSIX_EFAULT);
}
// UDPP2P requires protocol framing; the native-only lookup rejects raw sends.
if (!GetSocketBackend(s, &socket)) {
return -1;
}
@@ -2017,7 +2200,6 @@ int64_t KYTY_SYSV_ABI Recvfrom(int s, void* buf, uint64_t len, int flags, void*
NativeSocket socket = INVALID_NATIVE_SOCKET;
if (!GetSocketBackend(s, &socket)) {
*Posix::GetErrorAddr() = Posix::POSIX_EBADF;
return -1;
}
@@ -2107,7 +2289,7 @@ int KYTY_SYSV_ABI Select(int nfds, void* readfds, void* writefds, void* exceptfd
} else
#endif
if (!GetSocketBackend(fd, &socket)) {
return SetGuestSocketError(Posix::POSIX_EBADF);
return -1;
}
#if defined(_WIN32)
if ((read && host_read.fd_count == FD_SETSIZE) ||
@@ -3103,17 +3285,10 @@ static HostNetworkInfo QueryHostNetworkInfo() {
#endif
}
[[maybe_unused]] static bool HostNetworkConnected() {
return QueryHostNetworkInfo().connected;
}
static bool NetCtlConnected() {
if (!g_net_ctl_status_initialized.load()) {
// g_net_ctl_connected = HostNetworkConnected();
g_net_ctl_connected = false;
g_net_ctl_status_initialized = true;
// LOGF("\t host network connected = %s\n", (g_net_ctl_connected.load() ? "true" :
// "false"));
LOGF("\t host network connected = false (forced offline)\n");
}
@@ -3123,10 +3298,8 @@ static bool NetCtlConnected() {
int KYTY_SYSV_ABI NetCtlInit() {
PRINT_NAME();
// g_net_ctl_connected = HostNetworkConnected();
g_net_ctl_connected = false;
g_net_ctl_status_initialized = true;
// LOGF("\t host network connected = %s\n", (g_net_ctl_connected.load() ? "true" : "false"));
LOGF("\t host network connected = false (forced offline)\n");
return OK;
@@ -3380,14 +3553,24 @@ struct NpCheckPremiumResult {
uint8_t reserved[32];
};
constexpr int np_error_invalid_argument = -2141913085; /* 0x80550003 */
constexpr int np_error_signed_out = -2141913082; /* 0x80550006 */
constexpr int np_error_invalid_size = -2141913071; /* 0x80550011 */
constexpr int np_error_aborted = -2141913070; /* 0x80550012 */
constexpr int np_error_request_max = -2141913069; /* 0x80550013 */
constexpr int np_error_request_not_found = -2141913068; /* 0x80550014 */
constexpr int np_error_invalid_id = -2141913067; /* 0x80550015 */
constexpr int np_request_max = 128;
constexpr int np_error_invalid_argument = -2141913085; /* 0x80550003 */
constexpr int np_error_signed_out = -2141913082; /* 0x80550006 */
constexpr int np_error_callback_already_registered = -2141913080; /* 0x80550008 */
constexpr int np_error_invalid_size = -2141913071; /* 0x80550011 */
constexpr int np_error_aborted = -2141913070; /* 0x80550012 */
constexpr int np_error_request_max = -2141913069; /* 0x80550013 */
constexpr int np_error_request_not_found = -2141913068; /* 0x80550014 */
constexpr int np_error_invalid_id = -2141913067; /* 0x80550015 */
constexpr int np_request_max = 128;
constexpr uint32_t np_state_signed_out = 1;
struct NpStateCallback {
NpStateCallbackA callback = nullptr;
void* userdata = nullptr;
bool pending = false;
};
static std::vector<NpStateCallback> g_np_state_callbacks;
enum class NpRequestState {
Free,
@@ -3458,6 +3641,17 @@ static int np_complete_signed_out_locked(NpRequest* request) {
int KYTY_SYSV_ABI NpCheckCallback() {
PRINT_NAME();
std::vector<NpStateCallback> pending;
for (auto& entry: g_np_state_callbacks) {
if (entry.pending) {
pending.push_back(entry);
entry.pending = false;
}
}
for (const auto& entry: pending) {
entry.callback(Config::GetUserId(), np_state_signed_out, entry.userdata);
}
return OK;
}
@@ -3469,7 +3663,7 @@ int KYTY_SYSV_ABI NpSetNpTitleId(const NpTitleId* title_id, const NpTitleSecret*
LOGF("\t title_id = %.12s\n"
"\t title_secret = %s\n",
title_id->id, Common::HexFromBin(Common::ByteBuffer(title_secret->data, 128)).c_str());
title_id->id, fmt::format("{:02X}", fmt::join(title_secret->data, "")));
return OK;
}
@@ -3506,6 +3700,21 @@ int KYTY_SYSV_ABI NpUnregisterStateCallback() {
return OK;
}
int KYTY_SYSV_ABI NpRegisterStateCallbackA(NpStateCallbackA callback, void* userdata) {
PRINT_NAME();
if (callback == nullptr) {
return np_error_invalid_argument;
}
for (const auto& entry: g_np_state_callbacks) {
if (entry.callback == callback) {
return np_error_callback_already_registered;
}
}
g_np_state_callbacks.push_back({callback, userdata, true});
return static_cast<int>(g_np_state_callbacks.size());
}
void KYTY_SYSV_ABI NpRegisterGamePresenceCallback(void* /*callback*/, void* /*userdata*/) {
PRINT_NAME();
}
@@ -3811,7 +4020,7 @@ int KYTY_SYSV_ABI NpGetState(int user_id, uint32_t* state) {
LOGF("\t user_id = %d\n", user_id);
*state = 1; // Signed out
*state = np_state_signed_out;
return OK;
}
+3
View File
@@ -167,11 +167,14 @@ struct NpCreateAsyncRequestParameter;
struct NpCheckPremiumParameter;
struct NpCheckPremiumResult;
using NpStateCallbackA = KYTY_SYSV_ABI void (*)(int user_id, uint32_t state, void* userdata);
int KYTY_SYSV_ABI NpCheckCallback();
int KYTY_SYSV_ABI NpSetNpTitleId(const NpTitleId* title_id, const NpTitleSecret* title_secret);
int KYTY_SYSV_ABI NpSetContentRestriction(const NpContentRestriction* restriction);
int KYTY_SYSV_ABI NpRegisterStateCallback(void* callback, void* userdata);
int KYTY_SYSV_ABI NpUnregisterStateCallback();
int KYTY_SYSV_ABI NpRegisterStateCallbackA(NpStateCallbackA callback, void* userdata);
void KYTY_SYSV_ABI NpRegisterGamePresenceCallback(void* callback, void* userdata);
int KYTY_SYSV_ABI NpRegisterPlusEventCallback(void* callback, void* userdata);
int KYTY_SYSV_ABI NpRegisterPremiumEventCallback(void* callback, void* userdata);
+1
View File
@@ -1,5 +1,6 @@
#include "loader/gamePatch.h"
#include "common/assert.h"
#include "common/stringUtils.h"
#include "common/virtualMemory.h"
#include "kernel/memory.h"
+3 -7
View File
@@ -103,11 +103,6 @@ static ZydisDecoder& GetDecoder() {
return decoder;
}
static ZyanStatus DecodeInstruction(ZydisDecodedInstruction& instruction,
ZydisDecodedOperand* operands, void* data, u64 size) {
return ZydisDecoderDecodeFull(&GetDecoder(), data, size, &instruction, operands);
}
#endif
#if defined(_WIN32)
@@ -177,8 +172,9 @@ uintptr_t GetRelativeTarget(const DecodedCodeInstruction& decoded) {
DecodedCodeInstruction DecodeCodeInstruction(uintptr_t address, uintptr_t end) {
DecodedCodeInstruction decoded {.address = address};
const auto status = DecodeInstruction(decoded.instruction, decoded.operands.data(),
reinterpret_cast<void*>(address), end - address);
const auto status = ZydisDecoderDecodeFull(&GetDecoder(), reinterpret_cast<void*>(address),
end - address, &decoded.instruction,
decoded.operands.data());
if (!ZYAN_SUCCESS(status)) {
decoded.instruction.length = 0;
return decoded;
+18 -19
View File
@@ -6,7 +6,6 @@
#include "common/file.h"
#include "common/hostException.h"
#include "common/logging/log.h"
#include "common/magicEnum.h"
#include "common/platform/sysDbg.h"
#include "common/profiler.h"
#include "common/singleton.h"
@@ -29,6 +28,7 @@
#include <cstdlib>
#include <cstring>
#include <fmt/format.h>
#include <magic_enum.hpp>
#include <memory>
#include <vector>
@@ -301,9 +301,9 @@ static KYTY_SYSV_ABI uint64_t ResolveImportStubWithId(uint64_t record_id) {
if (record_id < g_stubbed_imports.size()) {
auto& record = g_stubbed_imports[record_id];
auto nid = record.name;
auto pos = Common::FindIndex(nid, "[");
if (Common::IndexValid(nid, pos)) {
nid = Common::Left(nid, pos);
auto pos = nid.find('[');
if (pos != std::string::npos) {
nid.resize(pos);
}
SymbolRecord resolved {};
@@ -330,7 +330,7 @@ static KYTY_SYSV_ABI uint64_t ResolveImportStubWithId(uint64_t record_id) {
LOGF("Unresolved import stub called [%u]: patch_vaddr=0x%016" PRIx64
" jmprela_index=%" PRIu32 " symbol=%s type=%s bind=%s program=%s\n",
log_index, record.patch_vaddr, record.index, record.name.c_str(),
Common::EnumName(record.type).c_str(), Common::EnumName(record.bind).c_str(),
magic_enum::enum_name(record.type), magic_enum::enum_name(record.bind),
record.program.c_str());
} else {
printf("Unresolved import stub called: <bad-record>\n");
@@ -1046,8 +1046,8 @@ static void RelocateRecord(uint32_t index, Elf64_Rela* r, Program* program, bool
patched = PatchGuestMemory64(ri.vaddr, value);
} else {
auto dbg_str = fmt::format("[{:016x}] <- {:016x}, {}, {}, {}, {}", ri.vaddr, ri.value,
ri.name.c_str(), Common::EnumName(ri.type).c_str(),
Common::EnumName(ri.bind).c_str(), ri.dbg_name.c_str());
ri.name.c_str(), magic_enum::enum_name(ri.type),
magic_enum::enum_name(ri.bind), ri.dbg_name.c_str());
if (unresolved != nullptr) {
unresolved->push_back(dbg_str);
@@ -1077,23 +1077,23 @@ static void RelocateRecord(uint32_t index, Elf64_Rela* r, Program* program, bool
const auto thunk = RegisterStubbedImport(index, program, ri);
LOGF("Relocate: unresolved PLT import patched to stub [%u] [%016" PRIx64 "] <- %016" PRIx64
", %s, %s, %s, %s\n",
index, ri.vaddr, thunk, ri.name.c_str(), Common::EnumName(ri.type).c_str(),
Common::EnumName(ri.bind).c_str(), Common::PathToString(program->file_name).c_str());
index, ri.vaddr, thunk, ri.name.c_str(), magic_enum::enum_name(ri.type),
magic_enum::enum_name(ri.bind), Common::PathToString(program->file_name).c_str());
} else if (patched && stubbed_func) {
const auto thunk = RegisterStubbedImport(index, program, ri);
LOGF("Relocate: unresolved non-PLT function patched to stub [%u] [%016" PRIx64
"] <- %016" PRIx64 ", %s, %s, %s, %s\n",
index, ri.vaddr, thunk, ri.name.c_str(), Common::EnumName(ri.type).c_str(),
Common::EnumName(ri.bind).c_str(), Common::PathToString(program->file_name).c_str());
index, ri.vaddr, thunk, ri.name.c_str(), magic_enum::enum_name(ri.type),
magic_enum::enum_name(ri.bind), Common::PathToString(program->file_name).c_str());
}
if (program->dbg_print_reloc) {
if (/* !dbg_str.ContainsStr("libc_") && */ patched && !ri.bind_self &&
if (patched && !ri.bind_self &&
(ri.bind == BindType::Global || ri.bind == BindType::Weak ||
ri.type == SymbolType::TlsModule)) {
auto dbg_str = fmt::format("[{:016x}] <- {:016x}, {}, {}, {}, {}", ri.vaddr, ri.value,
ri.name.c_str(), Common::EnumName(ri.type).c_str(),
Common::EnumName(ri.bind).c_str(), ri.dbg_name.c_str());
ri.name.c_str(), magic_enum::enum_name(ri.type),
magic_enum::enum_name(ri.bind), ri.dbg_name.c_str());
LOGF("Relocate: %s\n", dbg_str.c_str());
}
@@ -1390,9 +1390,8 @@ Program* RuntimeLinker::LoadProgram(const std::filesystem::path& elf_name) {
Libs::LibKernel::SetProgName(elf_name.filename().string());
}
if (Common::EndsWith(Common::ToLower(Common::DirectoryWithoutFilename(
Common::PathToGenericString(elf_name))),
"_module/")) {
if (Common::ToLower(Common::DirectoryWithoutFilename(Common::PathToGenericString(elf_name)))
.ends_with("_module/")) {
program->fail_if_global_not_resolved = false;
}
@@ -1818,7 +1817,7 @@ void RuntimeLinker::StopAllModules() {
static bool IsAdjacentModuleFile(const std::string& name) {
auto lower = Common::ToLower(name);
return Common::EndsWith(lower, ".prx") || Common::EndsWith(lower, ".sprx");
return lower.ends_with(".prx") || lower.ends_with(".sprx");
}
static bool SkipAdjacentModuleFile(const std::string& name) {
@@ -2082,7 +2081,7 @@ void RuntimeLinker::LoadProgramToMemory(Program* program) {
"[%d] memory_size = %" PRIu64 "\n"
"[%d] mode = %s\n",
i, segment_addr, i, segment_file_size, i, segment_memory_size, i,
Common::EnumName(mode).c_str());
magic_enum::enum_name(mode));
program->elf->LoadSegment(segment_addr, phdr[i].p_offset, segment_file_size);
+7 -7
View File
@@ -1,16 +1,16 @@
#include "loader/symbolDatabase.h"
#include "common/file.h"
#include "common/magicEnum.h"
#include <fmt/format.h>
#include <magic_enum.hpp>
namespace Loader {
constexpr char LIB_PREFIX[] = "libSce";
static std::string UpdateName(const std::string& str) {
return Common::StartsWith(str, LIB_PREFIX) ? Common::RemoveFirst(str, 6) : str;
return str.starts_with(LIB_PREFIX) ? Common::RemoveFirst(str, 6) : str;
}
std::string SymbolDatabase::GenerateName(const SymbolResolve& s) {
@@ -18,7 +18,7 @@ std::string SymbolDatabase::GenerateName(const SymbolResolve& s) {
auto module = UpdateName(s.module);
return fmt::format("{}[{}_v{}][{}_v{}.{}][{}]", s.name.c_str(), library.c_str(),
s.library_version, module.c_str(), s.module_version_major,
s.module_version_minor, Common::EnumName(s.type).c_str());
s.module_version_minor, magic_enum::enum_name(s.type));
}
void SymbolDatabase::Add(const SymbolResolve& s, uint64_t vaddr) {
@@ -67,10 +67,10 @@ const SymbolRecord* SymbolDatabase::Find(const SymbolResolve& s) const {
const SymbolRecord* SymbolDatabase::FindByNid(const std::string& nid, SymbolType type) const {
auto prefix = nid + "[";
auto suffix = fmt::format("[{}]", Common::EnumName(type).c_str());
auto suffix = fmt::format("[{}]", magic_enum::enum_name(type));
for (const auto& symbol: m_symbols) {
if (Common::StartsWith(symbol.name, prefix) && Common::EndsWith(symbol.name, suffix)) {
if (symbol.name.starts_with(prefix) && symbol.name.ends_with(suffix)) {
return &symbol;
}
}
@@ -80,10 +80,10 @@ const SymbolRecord* SymbolDatabase::FindByNid(const std::string& nid, SymbolType
const SymbolRecord* SymbolDatabase::FindByName(const std::string& name, SymbolType type) const {
auto prefix = name + "[";
auto suffix = fmt::format("[{}]", Common::EnumName(type).c_str());
auto suffix = fmt::format("[{}]", magic_enum::enum_name(type));
for (const auto& symbol: m_symbols) {
if (Common::StartsWith(symbol.name, prefix) && Common::EndsWith(symbol.name, suffix)) {
if (symbol.name.starts_with(prefix) && symbol.name.ends_with(suffix)) {
return &symbol;
}
}
Loaded 100 of 110 files, more files were not shown because too many files have changed in this diff. Show more