mirror of
https://github.com/InoriRus/Kyty.git
synced 2026-08-28 05:06:40 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_COMMON_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_COMMON_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#if (KYTY_COMPILER == KYTY_COMPILER_CLANG || KYTY_COMPILER == KYTY_COMPILER_MINGW) && KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS && KYTY_BITNESS == 64 && \
|
||||
KYTY_ENDIAN == KYTY_ENDIAN_LITTLE && KYTY_ABI == KYTY_ABI_X86_64 && KYTY_PROJECT == KYTY_PROJECT_EMULATOR
|
||||
#define KYTY_EMU_ENABLED
|
||||
#endif
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
#include "Emulator/Log.h" // IWYU pragma: export
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define KYTY_MS_ABI __attribute__((ms_abi))
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define KYTY_SYSV_ABI __attribute__((sysv_abi))
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_COMMON_H_ */
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_CONFIG_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_CONFIG_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/String.h"
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Scripts {
|
||||
class ScriptVar;
|
||||
} // namespace Kyty::Scripts
|
||||
|
||||
namespace Kyty::Config {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Config);
|
||||
|
||||
enum class ShaderOptimizationType
|
||||
{
|
||||
None,
|
||||
Size,
|
||||
Performance
|
||||
};
|
||||
|
||||
enum class ShaderLogDirection
|
||||
{
|
||||
Silent,
|
||||
Console,
|
||||
File
|
||||
};
|
||||
|
||||
enum class ProfilerDirection
|
||||
{
|
||||
None,
|
||||
File,
|
||||
Network,
|
||||
FileAndNetwork
|
||||
};
|
||||
|
||||
void Load(const Scripts::ScriptVar& cfg);
|
||||
|
||||
uint32_t GetScreenWidth();
|
||||
uint32_t GetScreenHeight();
|
||||
bool IsNeo();
|
||||
bool VulkanValidationEnabled();
|
||||
|
||||
bool ShaderValidationEnabled();
|
||||
ShaderOptimizationType GetShaderOptimizationType();
|
||||
ShaderLogDirection GetShaderLogDirection();
|
||||
String GetShaderLogFolder();
|
||||
|
||||
bool CommandBufferDumpEnabled();
|
||||
String GetCommandBufferDumpFolder();
|
||||
|
||||
Log::Direction GetPrintfDirection();
|
||||
String GetPrintfOutputFile();
|
||||
|
||||
ProfilerDirection GetProfilerDirection();
|
||||
String GetProfilerOutputFile();
|
||||
|
||||
} // namespace Kyty::Config
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_CONFIG_H_ */
|
||||
@@ -0,0 +1,68 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_CONTROLLER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_CONTROLLER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Controller {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Controller);
|
||||
|
||||
constexpr uint32_t PAD_BUTTON_L3 = 0x00000002;
|
||||
constexpr uint32_t PAD_BUTTON_R3 = 0x00000004;
|
||||
constexpr uint32_t PAD_BUTTON_OPTIONS = 0x00000008;
|
||||
constexpr uint32_t PAD_BUTTON_UP = 0x00000010;
|
||||
constexpr uint32_t PAD_BUTTON_RIGHT = 0x00000020;
|
||||
constexpr uint32_t PAD_BUTTON_DOWN = 0x00000040;
|
||||
constexpr uint32_t PAD_BUTTON_LEFT = 0x00000080;
|
||||
constexpr uint32_t PAD_BUTTON_L2 = 0x00000100;
|
||||
constexpr uint32_t PAD_BUTTON_R2 = 0x00000200;
|
||||
constexpr uint32_t PAD_BUTTON_L1 = 0x00000400;
|
||||
constexpr uint32_t PAD_BUTTON_R1 = 0x00000800;
|
||||
constexpr uint32_t PAD_BUTTON_TRIANGLE = 0x00001000;
|
||||
constexpr uint32_t PAD_BUTTON_CIRCLE = 0x00002000;
|
||||
constexpr uint32_t PAD_BUTTON_CROSS = 0x00004000;
|
||||
constexpr uint32_t PAD_BUTTON_SQUARE = 0x00008000;
|
||||
constexpr uint32_t PAD_BUTTON_TOUCH_PAD = 0x00100000;
|
||||
|
||||
enum class Axis
|
||||
{
|
||||
LeftX = 0,
|
||||
LeftY = 1,
|
||||
RightX = 2,
|
||||
RightY = 3,
|
||||
TriggerLeft = 4,
|
||||
TriggerRight = 5,
|
||||
|
||||
AxisMax
|
||||
};
|
||||
|
||||
struct PadControllerInformation;
|
||||
struct PadData;
|
||||
|
||||
inline int controller_get_axis(int min, int max, int value)
|
||||
{
|
||||
int v = (255 * (value - min)) / (max - min);
|
||||
return (v < 0 ? 0 : (v > 255 ? 255 : v));
|
||||
}
|
||||
|
||||
void ControllerConnect(int id);
|
||||
void ControllerDisconnect(int id);
|
||||
void ControllerButton(int id, uint32_t button, bool down);
|
||||
void ControllerAxis(int id, Axis axis, int value);
|
||||
|
||||
int KYTY_SYSV_ABI PadInit();
|
||||
int KYTY_SYSV_ABI PadOpen(int user_id, int type, int index, const void* param);
|
||||
int KYTY_SYSV_ABI PadSetMotionSensorState(int handle, bool enable);
|
||||
int KYTY_SYSV_ABI PadGetControllerInformation(int handle, PadControllerInformation* info);
|
||||
int KYTY_SYSV_ABI PadReadState(int handle, PadData* data);
|
||||
|
||||
} // namespace Kyty::Libs::Controller
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_CONTROLLER_H_ */
|
||||
@@ -0,0 +1,285 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_ELF_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_ELF_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/String.h"
|
||||
#include "Kyty/Core/Vector.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
namespace Kyty::Core {
|
||||
class File;
|
||||
} // namespace Kyty::Core
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Loader {
|
||||
|
||||
using Elf64_Addr = uint64_t; // Unsigned program address
|
||||
using Elf64_Off = uint64_t; // Unsigned file offset
|
||||
using Elf64_Half = uint16_t; // Unsigned medium integer
|
||||
using Elf64_Word = uint32_t; // Unsigned integer
|
||||
using Elf64_Sword = int32_t; // Signed integer
|
||||
using Elf64_Xword = uint64_t; // Unsigned long integer
|
||||
using Elf64_Sxword = int64_t; // Signed long integer
|
||||
|
||||
constexpr int EI_MAG0 = 0;
|
||||
constexpr int EI_MAG1 = 1;
|
||||
constexpr int EI_MAG2 = 2;
|
||||
constexpr int EI_MAG3 = 3;
|
||||
constexpr int EI_CLASS = 4;
|
||||
constexpr int EI_DATA = 5;
|
||||
constexpr int EI_VERSION = 6;
|
||||
constexpr int EI_OSABI = 7;
|
||||
constexpr int EI_ABIVERSION = 8;
|
||||
constexpr int EI_PAD = 9;
|
||||
constexpr int EI_NIDENT = 16;
|
||||
|
||||
constexpr char ELFCLASS64 = 2; // 64-bit objects
|
||||
|
||||
constexpr char ELFDATA2LSB = 1; // Object file data structures are little-endian
|
||||
|
||||
constexpr Elf64_Half EM_X86_64 = 62; /* AMD x86-64 architecture */
|
||||
|
||||
constexpr int EV_CURRENT = 1;
|
||||
|
||||
constexpr char ELFOSABI_FREEBSD = 9; // FreeBSD operating system
|
||||
|
||||
constexpr Elf64_Half ET_DYNEXEC = 0xfe10; // Executable file
|
||||
constexpr Elf64_Half ET_DYNAMIC = 0xfe18; // Shared
|
||||
|
||||
//#define SHT_PROGBITS 1
|
||||
|
||||
constexpr Elf64_Word PT_LOAD = 1;
|
||||
constexpr Elf64_Word PT_DYNAMIC = 2;
|
||||
constexpr Elf64_Word PT_TLS = 7;
|
||||
constexpr Elf64_Word PT_OS_DYNLIBDATA = 0x61000000;
|
||||
constexpr Elf64_Word PT_OS_PROCPARAM = 0x61000001;
|
||||
constexpr Elf64_Word PT_OS_RELRO = 0x61000010;
|
||||
|
||||
constexpr Elf64_Word PF_X = 0x1; // Execute
|
||||
constexpr Elf64_Word PF_W = 0x2; // Write
|
||||
constexpr Elf64_Word PF_R = 0x4; // Read
|
||||
|
||||
constexpr Elf64_Sxword DT_DEBUG = 0x00000015;
|
||||
constexpr Elf64_Sxword DT_FINI = 0x0000000d;
|
||||
constexpr Elf64_Sxword DT_FINI_ARRAY = 0x0000001a;
|
||||
constexpr Elf64_Sxword DT_FINI_ARRAYSZ = 0x0000001c;
|
||||
constexpr Elf64_Sxword DT_FLAGS = 0x0000001e;
|
||||
constexpr Elf64_Sxword DT_INIT = 0x0000000c;
|
||||
constexpr Elf64_Sxword DT_INIT_ARRAY = 0x00000019;
|
||||
constexpr Elf64_Sxword DT_INIT_ARRAYSZ = 0x0000001b;
|
||||
constexpr Elf64_Sxword DT_NEEDED = 0x00000001;
|
||||
constexpr Elf64_Sxword DT_OS_EXPORT_LIB = 0x61000013;
|
||||
constexpr Elf64_Sxword DT_OS_EXPORT_LIB_1 = 0x61000047;
|
||||
constexpr Elf64_Sxword DT_OS_EXPORT_LIB_ATTR = 0x61000017;
|
||||
constexpr Elf64_Sxword DT_OS_FINGERPRINT = 0x61000007;
|
||||
constexpr Elf64_Sxword DT_OS_HASH = 0x61000025;
|
||||
constexpr Elf64_Sxword DT_OS_HASHSZ = 0x6100003d;
|
||||
constexpr Elf64_Sxword DT_OS_IMPORT_LIB = 0x61000015;
|
||||
constexpr Elf64_Sxword DT_OS_IMPORT_LIB_1 = 0x61000049;
|
||||
constexpr Elf64_Sxword DT_OS_IMPORT_LIB_ATTR = 0x61000019;
|
||||
constexpr Elf64_Sxword DT_OS_JMPREL = 0x61000029;
|
||||
constexpr Elf64_Sxword DT_OS_MODULE_ATTR = 0x61000011;
|
||||
constexpr Elf64_Sxword DT_OS_MODULE_INFO = 0x6100000d;
|
||||
constexpr Elf64_Sxword DT_OS_MODULE_INFO_1 = 0x61000043;
|
||||
constexpr Elf64_Sxword DT_OS_NEEDED_MODULE = 0x6100000f;
|
||||
constexpr Elf64_Sxword DT_OS_NEEDED_MODULE_1 = 0x61000045;
|
||||
constexpr Elf64_Sxword DT_OS_ORIGINAL_FILENAME = 0x61000009;
|
||||
constexpr Elf64_Sxword DT_OS_ORIGINAL_FILENAME_1 = 0x61000041;
|
||||
constexpr Elf64_Sxword DT_OS_PLTGOT = 0x61000027;
|
||||
constexpr Elf64_Sxword DT_OS_PLTREL = 0x6100002b;
|
||||
constexpr Elf64_Sxword DT_OS_PLTRELSZ = 0x6100002d;
|
||||
constexpr Elf64_Sxword DT_OS_RELA = 0x6100002f;
|
||||
constexpr Elf64_Sxword DT_OS_RELAENT = 0x61000033;
|
||||
constexpr Elf64_Sxword DT_OS_RELASZ = 0x61000031;
|
||||
constexpr Elf64_Sxword DT_OS_STRSZ = 0x61000037;
|
||||
constexpr Elf64_Sxword DT_OS_STRTAB = 0x61000035;
|
||||
constexpr Elf64_Sxword DT_OS_SYMENT = 0x6100003b;
|
||||
constexpr Elf64_Sxword DT_OS_SYMTAB = 0x61000039;
|
||||
constexpr Elf64_Sxword DT_OS_SYMTABSZ = 0x6100003f;
|
||||
constexpr Elf64_Sxword DT_PREINIT_ARRAY = 0x00000020;
|
||||
constexpr Elf64_Sxword DT_PREINIT_ARRAYSZ = 0x00000021;
|
||||
constexpr Elf64_Sxword DT_REL = 0x00000011;
|
||||
constexpr Elf64_Sxword DT_RELA = 0x00000007;
|
||||
constexpr Elf64_Sxword DT_SONAME = 0x0000000e;
|
||||
constexpr Elf64_Sxword DT_TEXTREL = 0x00000016;
|
||||
|
||||
constexpr Elf64_Sxword DT_HASH = 0x00000004;
|
||||
constexpr Elf64_Sxword DT_STRTAB = 0x00000005;
|
||||
constexpr Elf64_Sxword DT_STRSZ = 0x0000000a;
|
||||
constexpr Elf64_Sxword DT_SYMTAB = 0x00000006;
|
||||
constexpr Elf64_Sxword DT_SYMENT = 0x0000000b;
|
||||
constexpr Elf64_Sxword DT_PLTGOT = 0x00000003;
|
||||
constexpr Elf64_Sxword DT_PLTREL = 0x00000014;
|
||||
constexpr Elf64_Sxword DT_JMPREL = 0x00000017;
|
||||
constexpr Elf64_Sxword DT_PLTRELSZ = 0x00000002;
|
||||
constexpr Elf64_Sxword DT_RELASZ = 0x00000008;
|
||||
constexpr Elf64_Sxword DT_RELAENT = 0x00000009;
|
||||
constexpr Elf64_Sxword DT_RELACOUNT = 0x6ffffff9;
|
||||
|
||||
constexpr Elf64_Sxword DT_NULL = 0;
|
||||
|
||||
constexpr Elf64_Word R_X86_64_64 = 1;
|
||||
constexpr Elf64_Word R_X86_64_GLOB_DAT = 6;
|
||||
constexpr Elf64_Word R_X86_64_JUMP_SLOT = 7;
|
||||
constexpr Elf64_Word R_X86_64_RELATIVE = 8;
|
||||
constexpr Elf64_Word R_X86_64_DTPMOD64 = 16;
|
||||
|
||||
constexpr uint8_t STB_LOCAL = 0;
|
||||
constexpr uint8_t STB_GLOBAL = 1;
|
||||
constexpr uint8_t STB_WEAK = 2;
|
||||
|
||||
constexpr uint8_t STT_OBJECT = 1;
|
||||
constexpr uint8_t STT_FUNC = 2;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
struct Elf64_Ehdr // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT]; /* ELF identification */
|
||||
Elf64_Half e_type; /* Object file type */
|
||||
Elf64_Half e_machine; /* Machine type */
|
||||
Elf64_Word e_version; /* Object file version */
|
||||
Elf64_Addr e_entry; /* Entry point address */
|
||||
Elf64_Off e_phoff; /* Program header offset */
|
||||
Elf64_Off e_shoff; /* Section header offset */
|
||||
Elf64_Word e_flags; /* Processor-specific flags */
|
||||
Elf64_Half e_ehsize; /* ELF header size */
|
||||
Elf64_Half e_phentsize; /* Size of program header entry */
|
||||
Elf64_Half e_phnum; /* Number of program header entries */
|
||||
Elf64_Half e_shentsize; /* Size of section header entry */
|
||||
Elf64_Half e_shnum; /* Number of section header entries */
|
||||
Elf64_Half e_shstrndx; /* Section name string table index */
|
||||
};
|
||||
|
||||
struct Elf64_Phdr // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
Elf64_Word p_type; /* Type of segment */
|
||||
Elf64_Word p_flags; /* Segment attributes */
|
||||
Elf64_Off p_offset; /* Offset in file */
|
||||
Elf64_Addr p_vaddr; /* Virtual address in memory */
|
||||
Elf64_Addr p_paddr; /* Reserved */
|
||||
Elf64_Xword p_filesz; /* Size of segment in file */
|
||||
Elf64_Xword p_memsz; /* Size of segment in memory */
|
||||
Elf64_Xword p_align; /* Alignment of segment */
|
||||
};
|
||||
|
||||
struct Elf64_Shdr // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
Elf64_Word sh_name; /* Section name */
|
||||
Elf64_Word sh_type; /* Section type */
|
||||
Elf64_Xword sh_flags; /* Section attributes */
|
||||
Elf64_Addr sh_addr; /* Virtual address in memory */
|
||||
Elf64_Off sh_offset; /* Offset in file */
|
||||
Elf64_Xword sh_size; /* Size of section */
|
||||
Elf64_Word sh_link; /* Link to other section */
|
||||
Elf64_Word sh_info; /* Miscellaneous information */
|
||||
Elf64_Xword sh_addralign; /* Address alignment boundary */
|
||||
Elf64_Xword sh_entsize; /* Size of entries, if section has table */
|
||||
};
|
||||
|
||||
struct Elf64_Dyn // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
Elf64_Sxword d_tag;
|
||||
union
|
||||
{
|
||||
Elf64_Xword d_val;
|
||||
Elf64_Addr d_ptr;
|
||||
} d_un;
|
||||
};
|
||||
|
||||
struct Elf64_Sym // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
[[nodiscard]] unsigned char GetBind() const { return st_info >> 4u; }
|
||||
[[nodiscard]] unsigned char GetType() const { return st_info & 0xfu; }
|
||||
|
||||
Elf64_Word st_name;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
Elf64_Half st_shndx;
|
||||
Elf64_Addr st_value;
|
||||
Elf64_Xword st_size;
|
||||
};
|
||||
|
||||
// struct Elf64_Rel // NOLINT(readability-identifier-naming)
|
||||
//{
|
||||
// Elf64_Addr r_offset;
|
||||
// Elf64_Xword r_info;
|
||||
//};
|
||||
|
||||
struct Elf64_Rela // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
[[nodiscard]] Elf64_Word GetSymbol() const { return static_cast<Elf64_Word>(r_info >> 32u); }
|
||||
[[nodiscard]] Elf64_Word GetType() const { return static_cast<Elf64_Word>(r_info & 0xffffffff); }
|
||||
|
||||
Elf64_Addr r_offset;
|
||||
Elf64_Xword r_info;
|
||||
Elf64_Sxword r_addend;
|
||||
};
|
||||
|
||||
struct tls_info_t // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
uint64_t addr;
|
||||
uint64_t filesz;
|
||||
uint64_t memsz;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
class Elf64
|
||||
{
|
||||
public:
|
||||
Elf64() = default;
|
||||
virtual ~Elf64();
|
||||
|
||||
void Open(const String& file_name);
|
||||
|
||||
void DbgDump(const String& folder);
|
||||
|
||||
const char* GetSectionName(int index) { return m_str_table + m_shdr[index].sh_name; }
|
||||
|
||||
[[nodiscard]] bool IsValid() const;
|
||||
[[nodiscard]] bool IsShared() const;
|
||||
[[nodiscard]] bool IsNextGen() const;
|
||||
|
||||
void LoadSegment(uint64_t vaddr, uint64_t file_offset, uint64_t size);
|
||||
|
||||
uint64_t GetEntry();
|
||||
|
||||
[[nodiscard]] const Elf64_Dyn* GetDynValue(Elf64_Sxword tag) const;
|
||||
[[nodiscard]] Vector<const Elf64_Dyn*> GetDynList(Elf64_Sxword tag) const;
|
||||
[[nodiscard]] bool HasDynValue(Elf64_Sxword tag) const { return GetDynValue(tag) != nullptr; }
|
||||
|
||||
KYTY_CLASS_NO_COPY(Elf64);
|
||||
|
||||
[[nodiscard]] const Elf64_Dyn* GetDynamic() const { return static_cast<Elf64_Dyn*>(m_dynamic); }
|
||||
[[nodiscard]] const Elf64_Ehdr* GetEhdr() const { return m_ehdr; }
|
||||
[[nodiscard]] const Elf64_Phdr* GetPhdr() const { return m_phdr; }
|
||||
[[nodiscard]] const Elf64_Shdr* GetShdr() const { return m_shdr; }
|
||||
[[nodiscard]] char* GetStrTable() const { return m_str_table; }
|
||||
|
||||
template <class T>
|
||||
[[nodiscard]] T GetDynamicData(uint64_t offset) const
|
||||
{
|
||||
return (m_dynamic_data == nullptr ? nullptr : reinterpret_cast<T>(static_cast<uint8_t*>(m_dynamic_data) + offset));
|
||||
}
|
||||
|
||||
private:
|
||||
void Clear();
|
||||
|
||||
Core::File* m_f = nullptr;
|
||||
Elf64_Ehdr* m_ehdr = nullptr;
|
||||
Elf64_Phdr* m_phdr = nullptr;
|
||||
Elf64_Shdr* m_shdr = nullptr;
|
||||
void* m_dynamic = nullptr;
|
||||
void* m_dynamic_data = nullptr;
|
||||
char* m_str_table = nullptr;
|
||||
// uint64_t m_base_vaddr = 0;
|
||||
};
|
||||
|
||||
} // namespace Kyty::Loader
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_ELF_H_ */
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_EMULATOR_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_EMULATOR_H_
|
||||
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
namespace Kyty::Emulator {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Emulator);
|
||||
|
||||
} // namespace Kyty::Emulator
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_EMULATOR_H_ */
|
||||
@@ -0,0 +1,94 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_ASYNCJOB_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_ASYNCJOB_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/Threads.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Profiler.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
class AsyncJob
|
||||
{
|
||||
public:
|
||||
using func_t = std::function<void(void*)>;
|
||||
explicit AsyncJob(const char* name): m_name(name) { m_thread = new Core::Thread(ThreadRun, this); }
|
||||
virtual ~AsyncJob()
|
||||
{
|
||||
EXIT_IF(m_thread == nullptr);
|
||||
Core::LockGuard lock(m_mutex);
|
||||
m_need_exit = true;
|
||||
m_cond_var1.Signal();
|
||||
m_thread->Join();
|
||||
delete m_thread;
|
||||
}
|
||||
KYTY_CLASS_NO_COPY(AsyncJob);
|
||||
|
||||
void Execute(func_t func, void* arg = nullptr)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
while (m_func != nullptr)
|
||||
{
|
||||
m_cond_var2.Wait(&m_mutex);
|
||||
}
|
||||
m_func = std::move(func);
|
||||
m_arg = arg;
|
||||
m_cond_var1.Signal();
|
||||
}
|
||||
|
||||
void Wait()
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
while (m_func != nullptr)
|
||||
{
|
||||
m_cond_var2.Wait(&m_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Core::Mutex m_mutex;
|
||||
Core::CondVar m_cond_var1;
|
||||
Core::CondVar m_cond_var2;
|
||||
Core::Thread* m_thread = nullptr;
|
||||
const char* m_name = nullptr;
|
||||
|
||||
func_t m_func = nullptr;
|
||||
void* m_arg = nullptr;
|
||||
bool m_need_exit = false;
|
||||
|
||||
static void ThreadRun(void* data)
|
||||
{
|
||||
// printf("Start AsyncJob Thread: 0x%" PRIx64 "\n", static_cast<uint64_t>(GetCurrentThreadId()));
|
||||
auto* aj = static_cast<AsyncJob*>(data);
|
||||
|
||||
if (aj->m_name != nullptr)
|
||||
{
|
||||
KYTY_PROFILER_THREAD(aj->m_name);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Core::LockGuard lock(aj->m_mutex);
|
||||
while (aj->m_func == nullptr && !aj->m_need_exit)
|
||||
{
|
||||
aj->m_cond_var1.Wait(&aj->m_mutex);
|
||||
}
|
||||
if (aj->m_need_exit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
aj->m_func(aj->m_arg);
|
||||
aj->m_func = nullptr;
|
||||
aj->m_cond_var2.Signal();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_ASYNCJOB_H_ */
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_DEPTHSTENCILBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_DEPTHSTENCILBUFFER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
class DepthStencilBufferObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
static constexpr int PARAM_FORMAT = 0;
|
||||
static constexpr int PARAM_WIDTH = 1;
|
||||
static constexpr int PARAM_HEIGHT = 2;
|
||||
static constexpr int PARAM_HTILE = 3;
|
||||
static constexpr int PARAM_NEO = 4;
|
||||
|
||||
DepthStencilBufferObject(uint64_t vk_format, uint32_t width, uint32_t height, bool htile, bool neo)
|
||||
{
|
||||
params[PARAM_FORMAT] = vk_format;
|
||||
params[PARAM_WIDTH] = width;
|
||||
params[PARAM_HEIGHT] = height;
|
||||
params[PARAM_HTILE] = htile ? 1 : 0;
|
||||
params[PARAM_NEO] = neo ? 1 : 0;
|
||||
check_hash = false;
|
||||
type = Graphics::GpuMemoryObjectType::DepthStencilBuffer;
|
||||
}
|
||||
|
||||
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
|
||||
bool Equal(const uint64_t* other) const override;
|
||||
|
||||
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
|
||||
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
|
||||
[[nodiscard]] update_func_t GetUpdateFunc() const override;
|
||||
};
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_DEPTHSTENCILBUFFER_H_ */
|
||||
@@ -0,0 +1,99 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GPUMEMORY_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GPUMEMORY_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
struct VulkanBuffer;
|
||||
struct TextureVulkanImage;
|
||||
struct VideoOutVulkanImage;
|
||||
struct DepthStencilVulkanImage;
|
||||
|
||||
enum class GpuMemoryMode
|
||||
{
|
||||
NoAccess,
|
||||
Read,
|
||||
Write,
|
||||
ReadWrite
|
||||
};
|
||||
|
||||
enum class GpuMemoryObjectType
|
||||
{
|
||||
Invalid,
|
||||
VideoOutBuffer,
|
||||
DepthStencilBuffer,
|
||||
Label,
|
||||
IndexBuffer,
|
||||
VertexBuffer,
|
||||
StorageBuffer,
|
||||
Texture
|
||||
};
|
||||
|
||||
class GpuObject
|
||||
{
|
||||
public:
|
||||
using write_back_func_t = void (*)(GraphicContext* ctx, void* obj, const uint64_t* vaddr, const uint64_t* size, int vaddr_num);
|
||||
using delete_func_t = void (*)(GraphicContext* ctx, void* obj, VulkanMemory* mem);
|
||||
using update_func_t = void (*)(GraphicContext* ctx, const uint64_t* params, void* obj, const uint64_t* vaddr, const uint64_t* size,
|
||||
int vaddr_num);
|
||||
|
||||
static constexpr int PARAMS_MAX = 8;
|
||||
|
||||
GpuObject() = default;
|
||||
virtual ~GpuObject() = default;
|
||||
|
||||
KYTY_CLASS_DEFAULT_COPY(GpuObject);
|
||||
|
||||
virtual void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const = 0;
|
||||
virtual bool Equal(const uint64_t* other) const = 0;
|
||||
|
||||
[[nodiscard]] virtual write_back_func_t GetWriteBackFunc() const = 0;
|
||||
[[nodiscard]] virtual delete_func_t GetDeleteFunc() const = 0;
|
||||
[[nodiscard]] virtual update_func_t GetUpdateFunc() const = 0;
|
||||
|
||||
uint64_t params[PARAMS_MAX] = {};
|
||||
bool check_hash = false;
|
||||
bool read_only = false;
|
||||
GpuMemoryObjectType type = GpuMemoryObjectType::Invalid;
|
||||
};
|
||||
|
||||
void GpuMemoryInit();
|
||||
|
||||
void GpuMemorySetAllocatedRange(uint64_t vaddr, uint64_t size);
|
||||
void GpuMemoryFree(GraphicContext* ctx, uint64_t vaddr, uint64_t size);
|
||||
void* GpuMemoryGetObject(GraphicContext* ctx, uint64_t vaddr, uint64_t size, const GpuObject& info);
|
||||
void* GpuMemoryGetObject(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, const GpuObject& info);
|
||||
void GpuMemoryResetHash(GraphicContext* ctx, uint64_t vaddr, uint64_t size, GpuMemoryObjectType type);
|
||||
void GpuMemoryDbgDump();
|
||||
void GpuMemoryFlush();
|
||||
void GpuMemoryFrameDone();
|
||||
void GpuMemoryWriteBack(GraphicContext* ctx);
|
||||
|
||||
bool VulkanAllocate(GraphicContext* ctx, VulkanMemory* mem);
|
||||
void VulkanFree(GraphicContext* ctx, VulkanMemory* mem);
|
||||
void VulkanMapMemory(GraphicContext* ctx, VulkanMemory* mem, void** data);
|
||||
void VulkanUnmapMemory(GraphicContext* ctx, VulkanMemory* mem);
|
||||
void VulkanBindImageMemory(GraphicContext* ctx, TextureVulkanImage* image, VulkanMemory* mem);
|
||||
void VulkanBindImageMemory(GraphicContext* ctx, VideoOutVulkanImage* image, VulkanMemory* mem);
|
||||
void VulkanBindImageMemory(GraphicContext* ctx, DepthStencilVulkanImage* image, VulkanMemory* mem);
|
||||
void VulkanBindBufferMemory(GraphicContext* ctx, VulkanBuffer* buffer, VulkanMemory* mem);
|
||||
|
||||
void GpuMemoryRegisterOwner(uint32_t* owner_handle, const char* name);
|
||||
void GpuMemoryRegisterResource(uint32_t* resource_handle, uint32_t owner_handle, const void* memory, size_t size, const char* name,
|
||||
uint32_t type, uint64_t user_data);
|
||||
void GpuMemoryUnregisterAllResourcesForOwner(uint32_t owner_handle);
|
||||
void GpuMemoryUnregisterOwnerAndResources(uint32_t owner_handle);
|
||||
void GpuMemoryUnregisterResource(uint32_t resource_handle);
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GPUMEMORY_H_ */
|
||||
@@ -0,0 +1,106 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICCONTEXT_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICCONTEXT_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/Threads.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct VulkanSwapchain
|
||||
{
|
||||
VkSwapchainKHR swapchain = nullptr;
|
||||
VkFormat swapchain_format = VK_FORMAT_UNDEFINED;
|
||||
VkExtent2D swapchain_extent = {};
|
||||
VkImage* swapchain_images = nullptr;
|
||||
VkImageView* swapchain_image_views = nullptr;
|
||||
uint32_t swapchain_images_count = 0;
|
||||
VkSemaphore present_complete_semaphore = nullptr;
|
||||
VkFence present_complete_fence = nullptr;
|
||||
uint32_t current_index = 0;
|
||||
};
|
||||
|
||||
struct VulkanCommandPool
|
||||
{
|
||||
Core::Mutex mutex;
|
||||
VkCommandPool pool = nullptr;
|
||||
VkCommandBuffer* buffers = nullptr;
|
||||
VkFence* fences = nullptr;
|
||||
VkSemaphore* semaphores = nullptr;
|
||||
bool* busy = nullptr;
|
||||
uint32_t buffers_count = 0;
|
||||
};
|
||||
|
||||
struct GraphicContext
|
||||
{
|
||||
static constexpr int QUEUES_NUM = 11;
|
||||
static constexpr int QUEUE_GFX = 8;
|
||||
static constexpr int QUEUE_UTIL = 9;
|
||||
static constexpr int QUEUE_PRESENT = 10;
|
||||
static constexpr int QUEUE_COMPUTE_START = 0;
|
||||
static constexpr int QUEUE_COMPUTE_NUM = 8;
|
||||
|
||||
uint32_t screen_width = 0;
|
||||
uint32_t screen_height = 0;
|
||||
VkInstance instance = nullptr;
|
||||
VkDebugUtilsMessengerEXT debug_messenger = nullptr;
|
||||
VkPhysicalDevice physical_device = nullptr;
|
||||
VkDevice device = nullptr;
|
||||
uint32_t queue_family_index = static_cast<uint32_t>(-1);
|
||||
VkQueue queue[QUEUES_NUM] = {};
|
||||
};
|
||||
|
||||
struct VulkanMemory
|
||||
{
|
||||
VkMemoryRequirements requirements = {};
|
||||
VkMemoryPropertyFlags property = 0;
|
||||
VkDeviceMemory memory = nullptr;
|
||||
VkDeviceSize offset = 0;
|
||||
uint32_t type = 0;
|
||||
uint64_t unique_id = 0;
|
||||
};
|
||||
|
||||
struct VideoOutVulkanImage
|
||||
{
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkExtent2D extent = {};
|
||||
VkImage image = nullptr;
|
||||
VkImageView image_view = nullptr;
|
||||
Graphics::VulkanMemory memory;
|
||||
};
|
||||
|
||||
struct DepthStencilVulkanImage
|
||||
{
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkExtent2D extent = {};
|
||||
VkImage image = nullptr;
|
||||
VkImageView image_view = nullptr;
|
||||
Graphics::VulkanMemory memory;
|
||||
};
|
||||
|
||||
struct TextureVulkanImage
|
||||
{
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkExtent2D extent = {};
|
||||
VkImage image = nullptr;
|
||||
VkImageView image_view = nullptr;
|
||||
Graphics::VulkanMemory memory;
|
||||
};
|
||||
|
||||
struct VulkanBuffer
|
||||
{
|
||||
VkBuffer buffer = nullptr;
|
||||
VulkanMemory memory;
|
||||
VkBufferUsageFlags usage = 0;
|
||||
};
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICCONTEXT_H_ */
|
||||
@@ -0,0 +1,60 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICS_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICS_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Kernel/EventQueue.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct VsStageRegisters;
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Graphics);
|
||||
|
||||
int KYTY_SYSV_ABI GraphicsSetVsShader(uint32_t* cmd, uint64_t size, const VsStageRegisters* vs_regs, uint32_t shader_modifier);
|
||||
int KYTY_SYSV_ABI GraphicsSetPsShader350(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs);
|
||||
int KYTY_SYSV_ABI GraphicsSetCsShaderWithModifier(uint32_t* cmd, uint64_t size, const uint32_t* cs_regs, uint32_t shader_modifier);
|
||||
int KYTY_SYSV_ABI GraphicsSetEmbeddedVsShader(uint32_t* cmd, uint64_t size, uint32_t id, uint32_t shader_modifier);
|
||||
int KYTY_SYSV_ABI GraphicsDrawIndex(uint32_t* cmd, uint64_t size, uint32_t index_count, const void* index_addr, uint32_t flags,
|
||||
uint32_t type);
|
||||
int KYTY_SYSV_ABI GraphicsDrawIndexAuto(uint32_t* cmd, uint64_t size, uint32_t index_count, uint32_t flags);
|
||||
int KYTY_SYSV_ABI GraphicsSubmitCommandBuffers(uint32_t count, void* dcb_gpu_addrs[], const uint32_t* dcb_sizes_in_bytes,
|
||||
void* ccb_gpu_addrs[], const uint32_t* ccb_sizes_in_bytes);
|
||||
int KYTY_SYSV_ABI GraphicsSubmitAndFlipCommandBuffers(uint32_t count, void* dcb_gpu_addrs[], const uint32_t* dcb_sizes_in_bytes,
|
||||
void* ccb_gpu_addrs[], const uint32_t* ccb_sizes_in_bytes, int handle, int index,
|
||||
int flip_mode, int64_t flip_arg);
|
||||
int KYTY_SYSV_ABI GraphicsSubmitDone();
|
||||
void KYTY_SYSV_ABI GraphicsFlushMemory();
|
||||
int KYTY_SYSV_ABI GraphicsAddEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id, void* udata);
|
||||
int KYTY_SYSV_ABI GraphicsDeleteEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDrawInitDefaultHardwareState350(uint32_t* cmd, uint64_t size);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDispatchInitDefaultHardwareState(uint32_t* cmd, uint64_t size);
|
||||
int KYTY_SYSV_ABI GraphicsInsertWaitFlipDone(uint32_t* cmd, uint64_t size, uint32_t video_out_handle, uint32_t display_buffer_index);
|
||||
int KYTY_SYSV_ABI GraphicsDispatchDirect(uint32_t* cmd, uint64_t size, uint32_t thread_group_x, uint32_t thread_group_y,
|
||||
uint32_t thread_group_z, uint32_t mode);
|
||||
uint32_t KYTY_SYSV_ABI GraphicsMapComputeQueue(uint32_t pipe_id, uint32_t queue_id, uint32_t* ring_addr, uint32_t ring_size_dw,
|
||||
uint32_t* read_ptr_addr);
|
||||
int KYTY_SYSV_ABI GraphicsComputeWaitOnAddress(uint32_t* cmd, uint64_t size, uint32_t* gpu_addr, uint32_t mask, uint32_t func,
|
||||
uint32_t ref);
|
||||
void KYTY_SYSV_ABI GraphicsDingDong(uint32_t ring_id, uint32_t offset_dw);
|
||||
void KYTY_SYSV_ABI GraphicsUnmapComputeQueue(uint32_t id);
|
||||
int KYTY_SYSV_ABI GraphicsInsertPushMarker(uint32_t* cmd, uint64_t size, const char* str);
|
||||
int KYTY_SYSV_ABI GraphicsInsertPopMarker(uint32_t* cmd, uint64_t size);
|
||||
uint64_t KYTY_SYSV_ABI GraphicsGetGpuCoreClockFrequency();
|
||||
|
||||
int KYTY_SYSV_ABI GraphicsRegisterOwner(uint32_t* owner_handle, const char* name);
|
||||
int KYTY_SYSV_ABI GraphicsRegisterResource(uint32_t* resource_handle, uint32_t owner_handle, const void* memory, size_t size,
|
||||
const char* name, uint32_t type, uint64_t user_data);
|
||||
int KYTY_SYSV_ABI GraphicsUnregisterAllResourcesForOwner(uint32_t owner_handle);
|
||||
int KYTY_SYSV_ABI GraphicsUnregisterOwnerAndResources(uint32_t owner_handle);
|
||||
int KYTY_SYSV_ABI GraphicsUnregisterResource(uint32_t resource_handle);
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICS_H_ */
|
||||
@@ -0,0 +1,92 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICSRENDER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICSRENDER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Kernel/EventQueue.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
class HardwareContext;
|
||||
class UserConfig;
|
||||
struct VideoOutVulkanImage;
|
||||
struct DepthStencilVulkanImage;
|
||||
struct TextureVulkanImage;
|
||||
struct VulkanCommandPool;
|
||||
struct VulkanBuffer;
|
||||
struct VulkanFramebuffer;
|
||||
struct RenderDepthInfo;
|
||||
struct RenderColorInfo;
|
||||
|
||||
class CommandBuffer
|
||||
{
|
||||
public:
|
||||
CommandBuffer() { Allocate(); }
|
||||
virtual ~CommandBuffer() { Free(); }
|
||||
|
||||
KYTY_CLASS_NO_COPY(CommandBuffer);
|
||||
|
||||
[[nodiscard]] bool IsInvalid() const;
|
||||
|
||||
void Allocate();
|
||||
void Free();
|
||||
void Begin() const;
|
||||
void End() const;
|
||||
void Execute();
|
||||
void ExecuteWithSemaphore();
|
||||
VulkanFramebuffer* BeginRenderPass(RenderColorInfo* color, RenderDepthInfo* depth) const;
|
||||
void EndRenderPass() const;
|
||||
void WaitForFence();
|
||||
void WaitForFenceAndReset();
|
||||
|
||||
[[nodiscard]] uint32_t GetIndex() const { return m_index; }
|
||||
VulkanCommandPool* GetPool() { return m_pool; }
|
||||
[[nodiscard]] bool IsExecute() const { return m_execute; }
|
||||
|
||||
void SetQueue(int queue) { m_queue = queue; }
|
||||
|
||||
private:
|
||||
VulkanCommandPool* m_pool = nullptr;
|
||||
uint32_t m_index = static_cast<uint32_t>(-1);
|
||||
int m_queue = -1;
|
||||
bool m_execute = false;
|
||||
};
|
||||
|
||||
void GraphicsRenderInit();
|
||||
void GraphicsRenderCreateContext();
|
||||
|
||||
void GraphicsRenderDrawIndex(CommandBuffer* buffer, HardwareContext* ctx, UserConfig* ucfg, uint32_t index_type_and_size,
|
||||
uint32_t index_count, const void* index_addr, uint32_t flags, uint32_t type);
|
||||
void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HardwareContext* ctx, UserConfig* ucfg, uint32_t index_count, uint32_t flags);
|
||||
void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value);
|
||||
void GraphicsRenderWriteAtEndOfPipeClockCounter(CommandBuffer* buffer, uint64_t* dst_gpu_addr);
|
||||
void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value);
|
||||
void GraphicsRenderWriteAtEndOfPipeGds(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t dw_offset, uint32_t dw_num);
|
||||
void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBackFlip(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value, int handle,
|
||||
int index, int flip_mode, int64_t flip_arg);
|
||||
void GraphicsRenderWriteAtEndOfPipeWithWriteBack(CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value);
|
||||
void GraphicsRenderWriteAtEndOfPipeWithInterrupt(CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value);
|
||||
void GraphicsRenderWriteBack();
|
||||
void GraphicsRenderDispatchDirect(CommandBuffer* buffer, HardwareContext* ctx, uint32_t thread_group_x, uint32_t thread_group_y,
|
||||
uint32_t thread_group_z, uint32_t mode);
|
||||
void GraphicsRenderMemoryBarrier(CommandBuffer* buffer);
|
||||
|
||||
void DeleteFramebuffer(VideoOutVulkanImage* image);
|
||||
void DeleteFramebuffer(DepthStencilVulkanImage* image);
|
||||
void DeleteDescriptor(VulkanBuffer* buffer);
|
||||
void DeleteDescriptor(TextureVulkanImage* image);
|
||||
|
||||
int GraphicsRenderAddEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id, void* udata);
|
||||
int GraphicsRenderDeleteEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id);
|
||||
|
||||
void GraphicsRenderClearGds(uint64_t dw_offset, uint32_t dw_num, uint32_t clear_value);
|
||||
void GraphicsRenderReadGds(uint32_t* dst, uint32_t dw_offset, uint32_t dw_size);
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICSRENDER_H_ */
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICSRUN_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICSRUN_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
void GraphicsRunInit();
|
||||
|
||||
void GraphicsRunSubmit(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint32_t* cmd_const_buffer, uint32_t num_const_dw);
|
||||
void GraphicsRunSubmitAndFlip(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint32_t* cmd_const_buffer, uint32_t num_const_dw,
|
||||
int handle, int index, int flip_mode, int64_t flip_arg);
|
||||
uint32_t GraphicsRunMapComputeQueue(uint32_t pipe_id, uint32_t queue_id, uint32_t* ring_addr, uint32_t ring_size_dw,
|
||||
uint32_t* read_ptr_addr);
|
||||
void GraphicsRunUnmapComputeQueue(uint32_t id);
|
||||
void GraphicsRunWait();
|
||||
void GraphicsRunDone();
|
||||
void GraphicsRunDingDong(uint32_t ring_id, uint32_t offset_dw);
|
||||
int GraphicsRunGetFrameNum();
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICSRUN_H_ */
|
||||
@@ -0,0 +1,511 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_HARDWARECONTEXT_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_HARDWARECONTEXT_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct RenderTarget
|
||||
{
|
||||
uint64_t base_addr = 0;
|
||||
uint32_t pitch_div8_minus1 = 0;
|
||||
uint32_t fmask_pitch_div8_minus1 = 0;
|
||||
uint32_t slice_div64_minus1 = 0;
|
||||
uint32_t base_array_slice_index = 0;
|
||||
uint32_t last_array_slice_index = 0;
|
||||
bool fmask_compression_enable = false;
|
||||
uint32_t fmask_compression_mode = 0;
|
||||
bool cmask_fast_clear_enable = false;
|
||||
bool dcc_compression_enable = false;
|
||||
bool neo_mode = false;
|
||||
uint32_t cmask_tile_mode = 0;
|
||||
uint32_t cmask_tile_mode_neo = 0;
|
||||
uint32_t format = 0;
|
||||
uint32_t channel_type = 0;
|
||||
uint32_t channel_order = 0;
|
||||
bool force_dest_alpha_to_one = false;
|
||||
uint32_t tile_mode = 0;
|
||||
uint32_t fmask_tile_mode = 0;
|
||||
uint32_t num_samples = 0;
|
||||
uint32_t num_fragments = 0;
|
||||
uint32_t dcc_max_uncompressed_block_size = 0;
|
||||
uint32_t dcc_max_compressed_block_size = 0;
|
||||
uint32_t dcc_min_compressed_block_size = 0;
|
||||
uint32_t dcc_color_transform = 0;
|
||||
bool dcc_enable_overwrite_combiner = false;
|
||||
bool dcc_force_independent_blocks = false;
|
||||
uint64_t cmask_addr = 0;
|
||||
uint32_t cmask_slice_minus1 = 0;
|
||||
uint64_t fmask_addr = 0;
|
||||
uint32_t fmask_slice_minus1 = 0;
|
||||
uint32_t clear_color_word0 = 0;
|
||||
uint32_t clear_color_word1 = 0;
|
||||
uint64_t dcc_addr = 0;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
};
|
||||
|
||||
struct DepthRenderTargetZInfo
|
||||
{
|
||||
uint32_t format = 0;
|
||||
uint32_t tile_mode_index = 0;
|
||||
uint32_t num_samples = 0;
|
||||
bool tile_surface_enable = false;
|
||||
bool expclear_enabled = false;
|
||||
uint32_t zrange_precision = 0;
|
||||
};
|
||||
|
||||
struct DepthRenderTargetStencilInfo
|
||||
{
|
||||
uint32_t format = 0;
|
||||
uint32_t tile_mode_index = 0;
|
||||
uint32_t tile_split = 0;
|
||||
bool expclear_enabled = false;
|
||||
bool tile_stencil_disable = false;
|
||||
};
|
||||
|
||||
struct DepthRenderTargetDepthInfo
|
||||
{
|
||||
uint32_t addr5_swizzle_mask = 0;
|
||||
uint32_t array_mode = 0;
|
||||
uint32_t pipe_config = 0;
|
||||
uint32_t bank_width = 0;
|
||||
uint32_t bank_height = 0;
|
||||
uint32_t macro_tile_aspect = 0;
|
||||
uint32_t num_banks = 0;
|
||||
};
|
||||
|
||||
struct DepthRenderTargetDepthView
|
||||
{
|
||||
uint32_t slice_start = 0;
|
||||
uint32_t slice_max = 0;
|
||||
};
|
||||
|
||||
struct DepthRenderTargetHTileSurface
|
||||
{
|
||||
uint32_t linear = 0;
|
||||
uint32_t full_cache = 0;
|
||||
uint32_t htile_uses_preload_win = 0;
|
||||
uint32_t preload = 0;
|
||||
uint32_t prefetch_width = 0;
|
||||
uint32_t prefetch_height = 0;
|
||||
uint32_t dst_outside_zero_to_one = 0;
|
||||
};
|
||||
|
||||
struct DepthRenderTarget
|
||||
{
|
||||
DepthRenderTargetZInfo z_info;
|
||||
DepthRenderTargetStencilInfo stencil_info;
|
||||
DepthRenderTargetDepthInfo depth_info;
|
||||
DepthRenderTargetDepthView depth_view;
|
||||
DepthRenderTargetHTileSurface htile_surface;
|
||||
|
||||
uint64_t z_read_base_addr = 0;
|
||||
uint64_t stencil_read_base_addr = 0;
|
||||
uint64_t z_write_base_addr = 0;
|
||||
uint64_t stencil_write_base_addr = 0;
|
||||
uint32_t pitch_div8_minus1 = 0;
|
||||
uint32_t height_div8_minus1 = 0;
|
||||
uint32_t slice_div64_minus1 = 0;
|
||||
uint64_t htile_data_base_addr = 0;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
};
|
||||
|
||||
struct RenderControl
|
||||
{
|
||||
bool depth_clear_enable = false;
|
||||
bool stencil_clear_enable = false;
|
||||
bool resummarize_enable = false;
|
||||
bool stencil_compress_disable = false;
|
||||
bool depth_compress_disable = false;
|
||||
bool copy_centroid = false;
|
||||
uint8_t copy_sample = 0;
|
||||
};
|
||||
|
||||
struct ClipControl
|
||||
{
|
||||
uint32_t user_clip_planes = 0;
|
||||
uint32_t user_clip_plane_mode = 0;
|
||||
uint32_t clip_space = 0;
|
||||
uint32_t vertex_kill_mode = 0;
|
||||
uint32_t min_z_clip_enable = 0;
|
||||
uint32_t max_z_clip_enable = 0;
|
||||
bool user_clip_plane_negate_y = false;
|
||||
bool clip_enable = false;
|
||||
bool user_clip_plane_cull_only = false;
|
||||
bool cull_on_clipping_error_disable = false;
|
||||
bool linear_attribute_clip_enable = false;
|
||||
bool force_viewport_index_from_vs_enable = false;
|
||||
};
|
||||
|
||||
struct DepthControl
|
||||
{
|
||||
bool stencil_enable = false;
|
||||
bool z_enable = false;
|
||||
bool z_write_enable = false;
|
||||
bool depth_bounds_enable = false;
|
||||
uint8_t zfunc = 0;
|
||||
bool backface_enable = false;
|
||||
uint8_t stencilfunc = 0;
|
||||
uint8_t stencilfunc_bf = 0;
|
||||
};
|
||||
|
||||
struct ModeControl
|
||||
{
|
||||
bool cull_front = false;
|
||||
bool cull_back = false;
|
||||
bool face = false;
|
||||
uint8_t poly_mode = 0;
|
||||
uint8_t polymode_front_ptype = 0;
|
||||
uint8_t polymode_back_ptype = 0;
|
||||
bool poly_offset_front_enable = false;
|
||||
bool poly_offset_back_enable = false;
|
||||
bool vtx_window_offset_enable = false;
|
||||
bool provoking_vtx_last = false;
|
||||
bool persp_corr_dis = false;
|
||||
};
|
||||
|
||||
struct BlendControl
|
||||
{
|
||||
uint8_t color_srcblend = 0;
|
||||
uint8_t color_comb_fcn = 0;
|
||||
uint8_t color_destblend = 0;
|
||||
uint8_t alpha_srcblend = 0;
|
||||
uint8_t alpha_comb_fcn = 0;
|
||||
uint8_t alpha_destblend = 0;
|
||||
bool separate_alpha_blend = false;
|
||||
bool enable = false;
|
||||
};
|
||||
|
||||
struct Viewport
|
||||
{
|
||||
float zmin = 0.0f;
|
||||
float zmax = 0.0f;
|
||||
float xscale = 0.0f;
|
||||
float xoffset = 0.0f;
|
||||
float yscale = 0.0f;
|
||||
float yoffset = 0.0f;
|
||||
float zscale = 0.0f;
|
||||
float zoffset = 0.0f;
|
||||
};
|
||||
|
||||
struct ScreenViewport
|
||||
{
|
||||
Viewport viewports[15];
|
||||
uint32_t transform_control = 0;
|
||||
int scissor_left = 0;
|
||||
int scissor_top = 0;
|
||||
int scissor_right = 0;
|
||||
int scissor_bottom = 0;
|
||||
uint32_t hw_offset_x = 0;
|
||||
uint32_t hw_offset_y = 0;
|
||||
float guard_band_horz_clip = 0.0f;
|
||||
float guard_band_vert_clip = 0.0f;
|
||||
float guard_band_horz_discard = 0.0f;
|
||||
float guard_band_vert_discard = 0.0f;
|
||||
};
|
||||
|
||||
struct VsStageRegisters
|
||||
{
|
||||
uint32_t m_spiShaderPgmLoVs = 0;
|
||||
uint32_t m_spiShaderPgmHiVs = 0;
|
||||
uint32_t m_spiShaderPgmRsrc1Vs = 0;
|
||||
uint32_t m_spiShaderPgmRsrc2Vs = 0;
|
||||
|
||||
uint32_t m_spiVsOutConfig = 0;
|
||||
uint32_t m_spiShaderPosFormat = 0;
|
||||
uint32_t m_paClVsOutCntl = 0;
|
||||
|
||||
[[nodiscard]] uint64_t GetGpuAddress() const;
|
||||
[[nodiscard]] bool GetStreamoutEnabled() const;
|
||||
[[nodiscard]] uint32_t GetSgprCount() const;
|
||||
[[nodiscard]] uint32_t GetInputComponentsCount() const;
|
||||
[[nodiscard]] uint32_t GetUnknown1() const;
|
||||
[[nodiscard]] uint32_t GetUnknown2() const;
|
||||
};
|
||||
|
||||
struct PsStageRegisters
|
||||
{
|
||||
uint64_t data_addr = 0;
|
||||
uint8_t vgprs = 0;
|
||||
uint8_t sgprs = 0;
|
||||
uint8_t scratch_en = 0;
|
||||
uint8_t user_sgpr = 0;
|
||||
uint8_t wave_cnt_en = 0;
|
||||
uint32_t shader_z_format = 0;
|
||||
uint8_t target_output_mode[8] = {};
|
||||
uint32_t ps_input_ena = 0;
|
||||
uint32_t ps_input_addr = 0;
|
||||
uint32_t ps_in_control = 0;
|
||||
uint32_t baryc_cntl = 0;
|
||||
|
||||
uint8_t conservative_z_export_value = 0;
|
||||
uint8_t shader_z_behavior = 0;
|
||||
bool shader_kill_enable = false;
|
||||
bool shader_z_export_enable = false;
|
||||
bool shader_execute_on_noop = false;
|
||||
|
||||
uint32_t m_cbShaderMask = 0;
|
||||
};
|
||||
|
||||
struct CsStageRegisters
|
||||
{
|
||||
|
||||
uint64_t data_addr = 0;
|
||||
uint32_t num_thread_x = 0;
|
||||
uint32_t num_thread_y = 0;
|
||||
uint32_t num_thread_z = 0;
|
||||
uint8_t vgprs = 0;
|
||||
uint8_t sgprs = 0;
|
||||
uint8_t bulky = 0;
|
||||
uint8_t scratch_en = 0;
|
||||
uint8_t user_sgpr = 0;
|
||||
uint8_t tgid_x_en = 0;
|
||||
uint8_t tgid_y_en = 0;
|
||||
uint8_t tgid_z_en = 0;
|
||||
uint8_t tg_size_en = 0;
|
||||
uint8_t tidig_comp_cnt = 0;
|
||||
uint8_t lds_size = 0;
|
||||
};
|
||||
|
||||
enum class UserSgprType
|
||||
{
|
||||
Unknown,
|
||||
Region,
|
||||
Vsharp
|
||||
};
|
||||
|
||||
struct UserSgprInfo
|
||||
{
|
||||
uint32_t value[16] = {0};
|
||||
UserSgprType type[16] = {};
|
||||
uint32_t count = 0;
|
||||
};
|
||||
|
||||
struct VertexShaderInfo
|
||||
{
|
||||
VsStageRegisters vs_regs;
|
||||
uint32_t vs_shader_modifier = 0;
|
||||
uint32_t vs_embedded_id = 0;
|
||||
UserSgprInfo vs_user_sgpr;
|
||||
bool vs_embedded = false;
|
||||
};
|
||||
|
||||
struct PixelShaderInfo
|
||||
{
|
||||
PsStageRegisters ps_regs;
|
||||
uint32_t ps_interpolator_settings[32] = {0};
|
||||
uint32_t ps_input_num = 0;
|
||||
UserSgprInfo ps_user_sgpr;
|
||||
};
|
||||
|
||||
struct ComputeShaderInfo
|
||||
{
|
||||
CsStageRegisters cs_regs;
|
||||
uint32_t cs_shader_modifier = 0;
|
||||
UserSgprInfo cs_user_sgpr;
|
||||
};
|
||||
|
||||
class HardwareContext
|
||||
{
|
||||
public:
|
||||
HardwareContext() = default;
|
||||
virtual ~HardwareContext() = default;
|
||||
|
||||
KYTY_CLASS_DEFAULT_COPY(HardwareContext);
|
||||
|
||||
void Reset() { *this = HardwareContext(); }
|
||||
|
||||
void SetRenderTarget(uint32_t slot, const RenderTarget& target) { m_render_targets[slot] = target; }
|
||||
[[nodiscard]] const RenderTarget& GetRenderTargets(uint32_t slot) const { return m_render_targets[slot]; }
|
||||
|
||||
void SetBlendControl(uint32_t slot, const BlendControl& control) { m_blend_control[slot] = control; }
|
||||
[[nodiscard]] const BlendControl& GetBlendControl(uint32_t slot) const { return m_blend_control[slot]; }
|
||||
|
||||
void SetRenderTargetMask(uint32_t mask) { m_render_target_mask = mask; }
|
||||
[[nodiscard]] uint32_t GetRenderTargetMask() const { return m_render_target_mask; }
|
||||
|
||||
void SetShaderStages(uint32_t flags) { m_shader_stages = flags; }
|
||||
[[nodiscard]] uint32_t GetShaderStages() const { return m_shader_stages; }
|
||||
|
||||
void SetDepthRenderTarget(const DepthRenderTarget& target) { m_depth_render_target = target; }
|
||||
[[nodiscard]] const DepthRenderTarget& GetDepthRenderTarget() const { return m_depth_render_target; }
|
||||
void SetDepthRenderTargetZInfo(const DepthRenderTargetZInfo& info) { m_depth_render_target.z_info = info; }
|
||||
[[nodiscard]] const DepthRenderTargetZInfo& GetDepthRenderTargetZInfo() const { return m_depth_render_target.z_info; }
|
||||
void SetDepthRenderTargetStencilInfo(const DepthRenderTargetStencilInfo& info) { m_depth_render_target.stencil_info = info; }
|
||||
[[nodiscard]] const DepthRenderTargetStencilInfo& GetDepthRenderTargetStencilInfo() const { return m_depth_render_target.stencil_info; }
|
||||
|
||||
void SetViewportZ(uint32_t viewport_id, float zmin, float zmax)
|
||||
{
|
||||
m_screen_viewport.viewports[viewport_id].zmin = zmin;
|
||||
m_screen_viewport.viewports[viewport_id].zmax = zmax;
|
||||
}
|
||||
void SetViewportScaleOffset(uint32_t viewport_id, float xscale, float xoffset, float yscale, float yoffset, float zscale, float zoffset)
|
||||
{
|
||||
m_screen_viewport.viewports[viewport_id].xscale = xscale;
|
||||
m_screen_viewport.viewports[viewport_id].xoffset = xoffset;
|
||||
m_screen_viewport.viewports[viewport_id].yscale = yscale;
|
||||
m_screen_viewport.viewports[viewport_id].yoffset = yoffset;
|
||||
m_screen_viewport.viewports[viewport_id].zscale = zscale;
|
||||
m_screen_viewport.viewports[viewport_id].zoffset = zoffset;
|
||||
}
|
||||
void SetViewportTransformControl(uint32_t control) { m_screen_viewport.transform_control = control; }
|
||||
void SetScreenScissor(int left, int top, int right, int bottom)
|
||||
{
|
||||
m_screen_viewport.scissor_left = left;
|
||||
m_screen_viewport.scissor_top = top;
|
||||
m_screen_viewport.scissor_right = right;
|
||||
m_screen_viewport.scissor_bottom = bottom;
|
||||
}
|
||||
void SetHardwareScreenOffset(uint32_t offset_x, uint32_t offset_y)
|
||||
{
|
||||
m_screen_viewport.hw_offset_x = offset_x;
|
||||
m_screen_viewport.hw_offset_y = offset_y;
|
||||
}
|
||||
void SetGuardBands(float horz_clip, float vert_clip, float horz_discard, float vert_discard)
|
||||
{
|
||||
m_screen_viewport.guard_band_horz_clip = horz_clip;
|
||||
m_screen_viewport.guard_band_vert_clip = vert_clip;
|
||||
m_screen_viewport.guard_band_horz_discard = horz_discard;
|
||||
m_screen_viewport.guard_band_vert_discard = vert_discard;
|
||||
}
|
||||
[[nodiscard]] const ScreenViewport& GetScreenViewport() const { return m_screen_viewport; }
|
||||
|
||||
void SetVsShader(const VsStageRegisters* vs_regs, uint32_t shader_modifier)
|
||||
{
|
||||
m_vs.vs_regs = *vs_regs;
|
||||
m_vs.vs_shader_modifier = shader_modifier;
|
||||
m_vs.vs_embedded = false;
|
||||
}
|
||||
void SetVsEmbedded(uint32_t id, uint32_t shader_modifier)
|
||||
{
|
||||
m_vs.vs_embedded_id = id;
|
||||
m_vs.vs_shader_modifier = shader_modifier;
|
||||
m_vs.vs_embedded = true;
|
||||
}
|
||||
|
||||
void SetPsShader(const PsStageRegisters* ps_regs) { m_ps.ps_regs = *ps_regs; }
|
||||
|
||||
void SetCsShader(const CsStageRegisters* cs_regs, uint32_t shader_modifier)
|
||||
{
|
||||
m_cs.cs_regs = *cs_regs;
|
||||
m_cs.cs_shader_modifier = shader_modifier;
|
||||
}
|
||||
|
||||
[[nodiscard]] const ClipControl& GetClipControl() const { return m_clip_control; }
|
||||
void SetClipControl(const ClipControl& control) { m_clip_control = control; }
|
||||
[[nodiscard]] const RenderControl& GetRenderControl() const { return m_render_control; }
|
||||
void SetRenderControl(const RenderControl& control) { m_render_control = control; }
|
||||
[[nodiscard]] const DepthControl& GetDepthControl() const { return m_depth_control; }
|
||||
void SetDepthControl(const DepthControl& control) { m_depth_control = control; }
|
||||
[[nodiscard]] const ModeControl& GetModeControl() const { return m_mode_control; }
|
||||
void SetModeControl(const ModeControl& control) { m_mode_control = control; }
|
||||
|
||||
void SetVsUserSgpr(uint32_t id, uint32_t value, UserSgprType type)
|
||||
{
|
||||
m_vs.vs_user_sgpr.value[id] = value;
|
||||
m_vs.vs_user_sgpr.type[id] = type;
|
||||
m_vs.vs_user_sgpr.count = ((id + 1) > m_vs.vs_user_sgpr.count ? (id + 1) : m_vs.vs_user_sgpr.count);
|
||||
}
|
||||
void SetPsUserSgpr(uint32_t id, uint32_t value, UserSgprType type)
|
||||
{
|
||||
m_ps.ps_user_sgpr.value[id] = value;
|
||||
m_ps.ps_user_sgpr.type[id] = type;
|
||||
m_ps.ps_user_sgpr.count = ((id + 1) > m_ps.ps_user_sgpr.count ? (id + 1) : m_ps.ps_user_sgpr.count);
|
||||
}
|
||||
void SetCsUserSgpr(uint32_t id, uint32_t value, UserSgprType type)
|
||||
{
|
||||
m_cs.cs_user_sgpr.value[id] = value;
|
||||
m_cs.cs_user_sgpr.type[id] = type;
|
||||
m_cs.cs_user_sgpr.count = ((id + 1) > m_cs.cs_user_sgpr.count ? (id + 1) : m_cs.cs_user_sgpr.count);
|
||||
}
|
||||
void SetPsInputSettings(uint32_t id, uint32_t value)
|
||||
{
|
||||
m_ps.ps_interpolator_settings[id] = value;
|
||||
m_ps.ps_input_num = ((id + 1) > m_ps.ps_input_num ? (id + 1) : m_ps.ps_input_num);
|
||||
}
|
||||
|
||||
[[nodiscard]] const PixelShaderInfo& GetPs() const { return m_ps; }
|
||||
[[nodiscard]] const VertexShaderInfo& GetVs() const { return m_vs; }
|
||||
[[nodiscard]] const ComputeShaderInfo& GetCs() const { return m_cs; }
|
||||
|
||||
[[nodiscard]] float GetDepthClearValue() const { return m_depth_clear_value; }
|
||||
void SetDepthClearValue(float clear_value) { m_depth_clear_value = clear_value; }
|
||||
|
||||
private:
|
||||
BlendControl m_blend_control[8];
|
||||
RenderTarget m_render_targets[8];
|
||||
uint32_t m_render_target_mask = 0;
|
||||
ScreenViewport m_screen_viewport;
|
||||
ClipControl m_clip_control;
|
||||
|
||||
VertexShaderInfo m_vs;
|
||||
PixelShaderInfo m_ps;
|
||||
ComputeShaderInfo m_cs;
|
||||
uint32_t m_shader_stages = 0;
|
||||
|
||||
DepthRenderTarget m_depth_render_target;
|
||||
RenderControl m_render_control;
|
||||
DepthControl m_depth_control;
|
||||
float m_depth_clear_value = 0.0f;
|
||||
|
||||
ModeControl m_mode_control;
|
||||
};
|
||||
|
||||
class UserConfig
|
||||
{
|
||||
public:
|
||||
UserConfig() = default;
|
||||
virtual ~UserConfig() = default;
|
||||
|
||||
KYTY_CLASS_DEFAULT_COPY(UserConfig);
|
||||
|
||||
void Reset() { *this = UserConfig(); }
|
||||
|
||||
void SetPrimitiveType(uint32_t prim_type) { m_prim_type = prim_type; }
|
||||
[[nodiscard]] uint32_t GetPrimType() const { return m_prim_type; }
|
||||
|
||||
private:
|
||||
uint32_t m_prim_type = 0;
|
||||
};
|
||||
|
||||
inline uint64_t VsStageRegisters::GetGpuAddress() const
|
||||
{
|
||||
return (static_cast<uint64_t>(m_spiShaderPgmLoVs) << 8u) | (static_cast<uint64_t>(m_spiShaderPgmHiVs) << 40u);
|
||||
}
|
||||
|
||||
inline bool VsStageRegisters::GetStreamoutEnabled() const
|
||||
{
|
||||
return (m_spiShaderPgmRsrc2Vs & 0x00001000u) != 0u;
|
||||
}
|
||||
|
||||
inline uint32_t VsStageRegisters::GetSgprCount() const
|
||||
{
|
||||
return (m_spiShaderPgmRsrc1Vs >> 6u) & 0xfu;
|
||||
}
|
||||
|
||||
inline uint32_t VsStageRegisters::GetInputComponentsCount() const
|
||||
{
|
||||
return (m_spiShaderPgmRsrc1Vs >> 24u) & 0x3u;
|
||||
}
|
||||
|
||||
inline uint32_t VsStageRegisters::GetUnknown1() const
|
||||
{
|
||||
return m_spiShaderPgmRsrc1Vs & 0xfcfffc3fu;
|
||||
}
|
||||
|
||||
inline uint32_t VsStageRegisters::GetUnknown2() const
|
||||
{
|
||||
return m_spiShaderPgmRsrc2Vs & 0xFFFFEFFFu;
|
||||
}
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_HARDWARECONTEXT_H_ */
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_INDEXBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_INDEXBUFFER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
class IndexBufferGpuObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
IndexBufferGpuObject()
|
||||
{
|
||||
check_hash = true;
|
||||
type = Graphics::GpuMemoryObjectType::IndexBuffer;
|
||||
}
|
||||
|
||||
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
|
||||
bool Equal(const uint64_t* other) const override;
|
||||
|
||||
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
|
||||
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
|
||||
[[nodiscard]] update_func_t GetUpdateFunc() const override;
|
||||
};
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_INDEXBUFFER_H_ */
|
||||
@@ -0,0 +1,63 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_LABEL_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_LABEL_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct Label;
|
||||
struct GraphicContext;
|
||||
class CommandBuffer;
|
||||
struct VulkanMemory;
|
||||
|
||||
void LabelInit();
|
||||
|
||||
class LabelGpuObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
using callback_t = bool (*)(const uint64_t* args);
|
||||
|
||||
static constexpr int PARAM_VALUE = 0;
|
||||
static constexpr int PARAM_CALLBACK_1 = 1;
|
||||
static constexpr int PARAM_CALLBACK_2 = 2;
|
||||
static constexpr int PARAM_ARG_1 = 3;
|
||||
static constexpr int PARAM_ARG_2 = 4;
|
||||
static constexpr int PARAM_ARG_3 = 5;
|
||||
static constexpr int PARAM_ARG_4 = 6;
|
||||
|
||||
explicit LabelGpuObject(uint64_t value, callback_t callback_1, callback_t callback_2, const uint64_t* args = nullptr)
|
||||
{
|
||||
params[PARAM_VALUE] = value;
|
||||
params[PARAM_CALLBACK_1] = reinterpret_cast<uint64_t>(callback_1);
|
||||
params[PARAM_CALLBACK_2] = reinterpret_cast<uint64_t>(callback_2);
|
||||
if (args != nullptr)
|
||||
{
|
||||
params[PARAM_ARG_1] = args[0];
|
||||
params[PARAM_ARG_2] = args[1];
|
||||
params[PARAM_ARG_3] = args[2];
|
||||
params[PARAM_ARG_4] = args[3];
|
||||
}
|
||||
check_hash = false;
|
||||
type = Graphics::GpuMemoryObjectType::Label;
|
||||
}
|
||||
|
||||
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
|
||||
bool Equal(const uint64_t* other) const override;
|
||||
|
||||
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
|
||||
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
|
||||
[[nodiscard]] update_func_t GetUpdateFunc() const override;
|
||||
};
|
||||
|
||||
void LabelSet(CommandBuffer* buffer, Label* label);
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_LABEL_H_ */
|
||||
@@ -0,0 +1,315 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_PM4_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_PM4_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Core {
|
||||
class File;
|
||||
} // namespace Kyty::Core
|
||||
|
||||
#define KYTY_PM4_GET(u, r, f) (((u) >> Pm4::r##_##f##_SHIFT) & Pm4::r##_##f##_MASK)
|
||||
|
||||
#define KYTY_PM4(len, op, r) \
|
||||
(0xC0000000u | (((static_cast<uint16_t>(len) - 2u) & 0x3fffu) << 16u) | (((op)&0xffu) << 8u) | (((r)&0x3fu) << 2u))
|
||||
|
||||
namespace Kyty::Libs::Graphics::Pm4 {
|
||||
|
||||
constexpr uint32_t IT_NOP = 0x10;
|
||||
constexpr uint32_t IT_SET_BASE = 0x11;
|
||||
constexpr uint32_t IT_CLEAR_STATE = 0x12;
|
||||
constexpr uint32_t IT_INDEX_BUFFER_SIZE = 0x13;
|
||||
constexpr uint32_t IT_DISPATCH_DIRECT = 0x15;
|
||||
constexpr uint32_t IT_DISPATCH_INDIRECT = 0x16;
|
||||
constexpr uint32_t IT_SET_PREDICATION = 0x20;
|
||||
constexpr uint32_t IT_COND_EXEC = 0x22;
|
||||
constexpr uint32_t IT_DRAW_INDIRECT = 0x24;
|
||||
constexpr uint32_t IT_DRAW_INDEX_INDIRECT = 0x25;
|
||||
constexpr uint32_t IT_INDEX_BASE = 0x26;
|
||||
constexpr uint32_t IT_DRAW_INDEX_2 = 0x27;
|
||||
constexpr uint32_t IT_CONTEXT_CONTROL = 0x28;
|
||||
constexpr uint32_t IT_INDEX_TYPE = 0x2A;
|
||||
constexpr uint32_t IT_DRAW_INDIRECT_MULTI = 0x2C;
|
||||
constexpr uint32_t IT_DRAW_INDEX_AUTO = 0x2D;
|
||||
constexpr uint32_t IT_NUM_INSTANCES = 0x2F;
|
||||
constexpr uint32_t IT_INDIRECT_BUFFER_CNST = 0x33;
|
||||
constexpr uint32_t IT_DRAW_INDEX_OFFSET_2 = 0x35;
|
||||
constexpr uint32_t IT_WRITE_DATA = 0x37;
|
||||
constexpr uint32_t IT_MEM_SEMAPHORE = 0x39;
|
||||
constexpr uint32_t IT_DRAW_INDEX_INDIRECT_MULTI = 0x38;
|
||||
constexpr uint32_t IT_WAIT_REG_MEM = 0x3C;
|
||||
constexpr uint32_t IT_INDIRECT_BUFFER = 0x3F;
|
||||
constexpr uint32_t IT_COPY_DATA = 0x40;
|
||||
constexpr uint32_t IT_CP_DMA = 0x41;
|
||||
constexpr uint32_t IT_PFP_SYNC_ME = 0x42;
|
||||
constexpr uint32_t IT_SURFACE_SYNC = 0x43;
|
||||
constexpr uint32_t IT_EVENT_WRITE = 0x46;
|
||||
constexpr uint32_t IT_EVENT_WRITE_EOP = 0x47;
|
||||
constexpr uint32_t IT_EVENT_WRITE_EOS = 0x48;
|
||||
constexpr uint32_t IT_RELEASE_MEM = 0x49;
|
||||
constexpr uint32_t IT_DMA_DATA = 0x50;
|
||||
constexpr uint32_t IT_ACQUIRE_MEM = 0x58;
|
||||
constexpr uint32_t IT_REWIND = 0x59;
|
||||
constexpr uint32_t IT_SET_CONFIG_REG = 0x68;
|
||||
constexpr uint32_t IT_SET_CONTEXT_REG = 0x69;
|
||||
constexpr uint32_t IT_SET_SH_REG = 0x76;
|
||||
constexpr uint32_t IT_SET_QUEUE_REG = 0x78;
|
||||
constexpr uint32_t IT_SET_UCONFIG_REG = 0x79;
|
||||
constexpr uint32_t IT_WRITE_CONST_RAM = 0x81;
|
||||
constexpr uint32_t IT_DUMP_CONST_RAM = 0x83;
|
||||
constexpr uint32_t IT_INCREMENT_CE_COUNTER = 0x84;
|
||||
constexpr uint32_t IT_INCREMENT_DE_COUNTER = 0x85;
|
||||
constexpr uint32_t IT_WAIT_ON_CE_COUNTER = 0x86;
|
||||
constexpr uint32_t IT_WAIT_ON_DE_COUNTER_DIFF = 0x88;
|
||||
constexpr uint32_t IT_DISPATCH_DRAW_PREAMBLE = 0x8C;
|
||||
constexpr uint32_t IT_DISPATCH_DRAW = 0x8D;
|
||||
|
||||
constexpr uint32_t R_ZERO = 0x00;
|
||||
constexpr uint32_t R_VS = 0x01;
|
||||
constexpr uint32_t R_PS = 0x02;
|
||||
constexpr uint32_t R_DRAW_INDEX = 0x03;
|
||||
constexpr uint32_t R_DRAW_INDEX_AUTO = 0x04;
|
||||
constexpr uint32_t R_DRAW_RESET = 0x05;
|
||||
constexpr uint32_t R_WAIT_FLIP_DONE = 0x06;
|
||||
constexpr uint32_t R_CS = 0x07;
|
||||
constexpr uint32_t R_DISPATCH_DIRECT = 0x08;
|
||||
constexpr uint32_t R_DISPATCH_RESET = 0x09;
|
||||
constexpr uint32_t R_DISPATCH_WAIT_MEM = 0x0A;
|
||||
constexpr uint32_t R_PUSH_MARKER = 0x0B;
|
||||
constexpr uint32_t R_POP_MARKER = 0x0C;
|
||||
constexpr uint32_t R_VS_EMBEDDED = 0x0D;
|
||||
|
||||
constexpr uint32_t DB_RENDER_CONTROL = 0x0;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_DEPTH_CLEAR_ENABLE_SHIFT = 0;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_DEPTH_CLEAR_ENABLE_MASK = 0x1;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_STENCIL_CLEAR_ENABLE_SHIFT = 1;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_STENCIL_CLEAR_ENABLE_MASK = 0x1;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_RESUMMARIZE_ENABLE_SHIFT = 4;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_RESUMMARIZE_ENABLE_MASK = 0x1;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_STENCIL_COMPRESS_DISABLE_SHIFT = 5;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_STENCIL_COMPRESS_DISABLE_MASK = 0x1;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_DEPTH_COMPRESS_DISABLE_SHIFT = 6;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_DEPTH_COMPRESS_DISABLE_MASK = 0x1;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_COPY_CENTROID_SHIFT = 7;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_COPY_CENTROID_MASK = 0x1;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_COPY_SAMPLE_SHIFT = 8;
|
||||
constexpr uint32_t DB_RENDER_CONTROL_COPY_SAMPLE_MASK = 0xF;
|
||||
|
||||
constexpr uint32_t DB_DEPTH_VIEW = 0x2;
|
||||
constexpr uint32_t DB_DEPTH_VIEW_SLICE_START_SHIFT = 0;
|
||||
constexpr uint32_t DB_DEPTH_VIEW_SLICE_START_MASK = 0x7FF;
|
||||
constexpr uint32_t DB_DEPTH_VIEW_SLICE_MAX_SHIFT = 13;
|
||||
constexpr uint32_t DB_DEPTH_VIEW_SLICE_MAX_MASK = 0x7FF;
|
||||
|
||||
constexpr uint32_t DB_HTILE_DATA_BASE = 0x5;
|
||||
constexpr uint32_t DB_HTILE_DATA_BASE_BASE_256B_SHIFT = 0;
|
||||
constexpr uint32_t DB_HTILE_DATA_BASE_BASE_256B_MASK = 0xFFFFFFFF;
|
||||
|
||||
constexpr uint32_t DB_DEPTH_CLEAR = 0xB;
|
||||
constexpr uint32_t DB_DEPTH_CLEAR_DEPTH_CLEAR_SHIFT = 0;
|
||||
constexpr uint32_t DB_DEPTH_CLEAR_DEPTH_CLEAR_MASK = 0xFFFFFFFF;
|
||||
|
||||
constexpr uint32_t DB_DEPTH_INFO = 0xF;
|
||||
constexpr uint32_t DB_DEPTH_INFO_ADDR5_SWIZZLE_MASK_SHIFT = 0;
|
||||
constexpr uint32_t DB_DEPTH_INFO_ADDR5_SWIZZLE_MASK_MASK = 0xF;
|
||||
constexpr uint32_t DB_DEPTH_INFO_ARRAY_MODE_SHIFT = 4;
|
||||
constexpr uint32_t DB_DEPTH_INFO_ARRAY_MODE_MASK = 0xF;
|
||||
constexpr uint32_t DB_DEPTH_INFO_PIPE_CONFIG_SHIFT = 8;
|
||||
constexpr uint32_t DB_DEPTH_INFO_PIPE_CONFIG_MASK = 0x1F;
|
||||
constexpr uint32_t DB_DEPTH_INFO_BANK_WIDTH_SHIFT = 13;
|
||||
constexpr uint32_t DB_DEPTH_INFO_BANK_WIDTH_MASK = 0x3;
|
||||
constexpr uint32_t DB_DEPTH_INFO_BANK_HEIGHT_SHIFT = 15;
|
||||
constexpr uint32_t DB_DEPTH_INFO_BANK_HEIGHT_MASK = 0x3;
|
||||
constexpr uint32_t DB_DEPTH_INFO_MACRO_TILE_ASPECT_SHIFT = 17;
|
||||
constexpr uint32_t DB_DEPTH_INFO_MACRO_TILE_ASPECT_MASK = 0x3;
|
||||
constexpr uint32_t DB_DEPTH_INFO_NUM_BANKS_SHIFT = 19;
|
||||
constexpr uint32_t DB_DEPTH_INFO_NUM_BANKS_MASK = 0x3;
|
||||
|
||||
constexpr uint32_t DB_Z_INFO = 0x10;
|
||||
constexpr uint32_t DB_Z_INFO_FORMAT_SHIFT = 0;
|
||||
constexpr uint32_t DB_Z_INFO_FORMAT_MASK = 0x3;
|
||||
constexpr uint32_t DB_Z_INFO_NUM_SAMPLES_SHIFT = 2;
|
||||
constexpr uint32_t DB_Z_INFO_NUM_SAMPLES_MASK = 0x3;
|
||||
constexpr uint32_t DB_Z_INFO_TILE_MODE_INDEX_SHIFT = 20;
|
||||
constexpr uint32_t DB_Z_INFO_TILE_MODE_INDEX_MASK = 0x7;
|
||||
constexpr uint32_t DB_Z_INFO_TILE_SURFACE_ENABLE_SHIFT = 29;
|
||||
constexpr uint32_t DB_Z_INFO_TILE_SURFACE_ENABLE_MASK = 0x1;
|
||||
constexpr uint32_t DB_Z_INFO_ZRANGE_PRECISION_SHIFT = 31;
|
||||
constexpr uint32_t DB_Z_INFO_ZRANGE_PRECISION_MASK = 0x1;
|
||||
|
||||
constexpr uint32_t DB_STENCIL_INFO = 0x11;
|
||||
constexpr uint32_t DB_STENCIL_INFO_FORMAT_SHIFT = 0;
|
||||
constexpr uint32_t DB_STENCIL_INFO_FORMAT_MASK = 0x1;
|
||||
constexpr uint32_t DB_STENCIL_INFO_TILE_MODE_INDEX_SHIFT = 20;
|
||||
constexpr uint32_t DB_STENCIL_INFO_TILE_MODE_INDEX_MASK = 0x7;
|
||||
constexpr uint32_t DB_STENCIL_INFO_TILE_STENCIL_DISABLE_SHIFT = 29;
|
||||
constexpr uint32_t DB_STENCIL_INFO_TILE_STENCIL_DISABLE_MASK = 0x1;
|
||||
|
||||
constexpr uint32_t DB_Z_READ_BASE = 0x12;
|
||||
constexpr uint32_t DB_Z_READ_BASE_BASE_256B_SHIFT = 0;
|
||||
constexpr uint32_t DB_Z_READ_BASE_BASE_256B_MASK = 0xFFFFFFFF;
|
||||
constexpr uint32_t DB_STENCIL_READ_BASE = 0x13;
|
||||
constexpr uint32_t DB_STENCIL_READ_BASE_BASE_256B_SHIFT = 0;
|
||||
constexpr uint32_t DB_STENCIL_READ_BASE_BASE_256B_MASK = 0xFFFFFFFF;
|
||||
constexpr uint32_t DB_Z_WRITE_BASE = 0x14;
|
||||
constexpr uint32_t DB_Z_WRITE_BASE_BASE_256B_SHIFT = 0;
|
||||
constexpr uint32_t DB_Z_WRITE_BASE_BASE_256B_MASK = 0xFFFFFFFF;
|
||||
constexpr uint32_t DB_STENCIL_WRITE_BASE = 0x15;
|
||||
constexpr uint32_t DB_STENCIL_WRITE_BASE_BASE_256B_SHIFT = 0;
|
||||
constexpr uint32_t DB_STENCIL_WRITE_BASE_BASE_256B_MASK = 0xFFFFFFFF;
|
||||
|
||||
constexpr uint32_t DB_DEPTH_SIZE = 0x16;
|
||||
constexpr uint32_t DB_DEPTH_SIZE_PITCH_TILE_MAX_SHIFT = 0;
|
||||
constexpr uint32_t DB_DEPTH_SIZE_PITCH_TILE_MAX_MASK = 0x7FF;
|
||||
constexpr uint32_t DB_DEPTH_SIZE_HEIGHT_TILE_MAX_SHIFT = 11;
|
||||
constexpr uint32_t DB_DEPTH_SIZE_HEIGHT_TILE_MAX_MASK = 0x7FF;
|
||||
|
||||
constexpr uint32_t DB_DEPTH_SLICE = 0x17;
|
||||
constexpr uint32_t DB_DEPTH_SLICE_SLICE_TILE_MAX_SHIFT = 0;
|
||||
constexpr uint32_t DB_DEPTH_SLICE_SLICE_TILE_MAX_MASK = 0x3FFFFF;
|
||||
|
||||
constexpr uint32_t PA_SC_VPORT_ZMIN_0 = 0xB4;
|
||||
|
||||
constexpr uint32_t PA_CL_VPORT_XSCALE = 0x10F;
|
||||
|
||||
constexpr uint32_t SPI_PS_INPUT_CNTL_0 = 0x191;
|
||||
|
||||
constexpr uint32_t CB_BLEND0_CONTROL = 0x1E0;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_SRCBLEND_SHIFT = 0;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_SRCBLEND_MASK = 0x1F;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_COMB_FCN_SHIFT = 5;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_COMB_FCN_MASK = 0x7;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_DESTBLEND_SHIFT = 8;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_DESTBLEND_MASK = 0x1F;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_ALPHA_SRCBLEND_SHIFT = 16;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_ALPHA_SRCBLEND_MASK = 0x1F;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_ALPHA_COMB_FCN_SHIFT = 21;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_ALPHA_COMB_FCN_MASK = 0x7;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_ALPHA_DESTBLEND_SHIFT = 24;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_ALPHA_DESTBLEND_MASK = 0x1F;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_SEPARATE_ALPHA_BLEND_SHIFT = 29;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_SEPARATE_ALPHA_BLEND_MASK = 0x1;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_ENABLE_SHIFT = 30;
|
||||
constexpr uint32_t CB_BLEND0_CONTROL_ENABLE_MASK = 0x1;
|
||||
|
||||
constexpr uint32_t DB_DEPTH_CONTROL = 0x200;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_STENCIL_ENABLE_SHIFT = 0;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_STENCIL_ENABLE_MASK = 0x1;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_Z_ENABLE_SHIFT = 1;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_Z_ENABLE_MASK = 0x1;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_Z_WRITE_ENABLE_SHIFT = 2;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_Z_WRITE_ENABLE_MASK = 0x1;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_DEPTH_BOUNDS_ENABLE_SHIFT = 3;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_DEPTH_BOUNDS_ENABLE_MASK = 0x1;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_ZFUNC_SHIFT = 4;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_ZFUNC_MASK = 0x7;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_BACKFACE_ENABLE_SHIFT = 7;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_BACKFACE_ENABLE_MASK = 0x1;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_STENCILFUNC_SHIFT = 8;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_STENCILFUNC_MASK = 0x7;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_STENCILFUNC_BF_SHIFT = 20;
|
||||
constexpr uint32_t DB_DEPTH_CONTROL_STENCILFUNC_BF_MASK = 0x7;
|
||||
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL = 0x205;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_CULL_FRONT_SHIFT = 0;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_CULL_FRONT_MASK = 0x1;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_CULL_BACK_SHIFT = 1;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_CULL_BACK_MASK = 0x1;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_FACE_SHIFT = 2;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_FACE_MASK = 0x1;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLY_MODE_SHIFT = 3;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLY_MODE_MASK = 0x3;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLYMODE_FRONT_PTYPE_SHIFT = 5;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLYMODE_FRONT_PTYPE_MASK = 0x7;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLYMODE_BACK_PTYPE_SHIFT = 8;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLYMODE_BACK_PTYPE_MASK = 0x7;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLY_OFFSET_FRONT_ENABLE_SHIFT = 11;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLY_OFFSET_FRONT_ENABLE_MASK = 0x1;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLY_OFFSET_BACK_ENABLE_SHIFT = 12;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLY_OFFSET_BACK_ENABLE_MASK = 0x1;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE_SHIFT = 16;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE_MASK = 0x1;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST_SHIFT = 19;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST_MASK = 0x1;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_PERSP_CORR_DIS_SHIFT = 20;
|
||||
constexpr uint32_t PA_SU_SC_MODE_CNTL_PERSP_CORR_DIS_MASK = 0x1;
|
||||
|
||||
constexpr uint32_t DB_HTILE_SURFACE = 0x2AF;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_LINEAR_SHIFT = 0;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_LINEAR_MASK = 0x1;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_FULL_CACHE_SHIFT = 1;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_FULL_CACHE_MASK = 0x1;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_HTILE_USES_PRELOAD_WIN_SHIFT = 2;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_HTILE_USES_PRELOAD_WIN_MASK = 0x1;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_PRELOAD_SHIFT = 3;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_PRELOAD_MASK = 0x1;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_PREFETCH_WIDTH_SHIFT = 4;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_PREFETCH_WIDTH_MASK = 0x3F;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_PREFETCH_HEIGHT_SHIFT = 10;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_PREFETCH_HEIGHT_MASK = 0x3F;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_DST_OUTSIDE_ZERO_TO_ONE_SHIFT = 16;
|
||||
constexpr uint32_t DB_HTILE_SURFACE_DST_OUTSIDE_ZERO_TO_ONE_MASK = 0x1;
|
||||
|
||||
constexpr uint32_t VGT_SHADER_STAGES_EN = 0x2D5;
|
||||
|
||||
constexpr uint32_t CB_COLOR0_BASE = 0x318;
|
||||
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC1_PS = 0xA;
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC1_PS_VGPRS_SHIFT = 0;
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC1_PS_VGPRS_MASK = 0x3F;
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC1_PS_SGPRS_SHIFT = 6;
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC1_PS_SGPRS_MASK = 0xF;
|
||||
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS = 0xB;
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS_SCRATCH_EN_SHIFT = 0;
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS_SCRATCH_EN_MASK = 0x1;
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS_USER_SGPR_SHIFT = 1;
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS_USER_SGPR_MASK = 0x1F;
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS_WAVE_CNT_EN_SHIFT = 7;
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS_WAVE_CNT_EN_MASK = 0x0;
|
||||
|
||||
constexpr uint32_t SPI_SHADER_USER_DATA_PS_0 = 0xC;
|
||||
constexpr uint32_t SPI_SHADER_USER_DATA_PS_15 = 0x1B;
|
||||
|
||||
constexpr uint32_t SPI_SHADER_USER_DATA_VS_0 = 0x4C;
|
||||
constexpr uint32_t SPI_SHADER_USER_DATA_VS_15 = 0x5B;
|
||||
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC1 = 0x212;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC1_VGPRS_SHIFT = 0;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC1_VGPRS_MASK = 0x3F;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC1_SGPRS_SHIFT = 6;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC1_SGPRS_MASK = 0xF;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC1_BULKY_SHIFT = 24;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC1_BULKY_MASK = 0x1;
|
||||
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2 = 0x213;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_SCRATCH_EN_SHIFT = 0;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_SCRATCH_EN_MASK = 0x1;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_USER_SGPR_SHIFT = 1;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_USER_SGPR_MASK = 0x1F;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_TGID_X_EN_SHIFT = 7;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_TGID_X_EN_MASK = 0x1;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_TGID_Y_EN_SHIFT = 8;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_TGID_Y_EN_MASK = 0x1;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_TGID_Z_EN_SHIFT = 9;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_TGID_Z_EN_MASK = 0x1;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_TG_SIZE_EN_SHIFT = 10;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_TG_SIZE_EN_MASK = 0x1;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_TIDIG_COMP_CNT_SHIFT = 11;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_TIDIG_COMP_CNT_MASK = 0x3;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_LDS_SIZE_SHIFT = 15;
|
||||
constexpr uint32_t COMPUTE_PGM_RSRC2_LDS_SIZE_MASK = 0x1FF;
|
||||
|
||||
constexpr uint32_t COMPUTE_USER_DATA_0 = 0x240;
|
||||
constexpr uint32_t COMPUTE_USER_DATA_15 = 0x24F;
|
||||
|
||||
void DumpPm4PacketStream(Core::File* file, uint32_t* cmd_buffer, uint32_t start_dw, uint32_t num_dw);
|
||||
|
||||
} // namespace Kyty::Libs::Graphics::Pm4
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_PM4_H_ */
|
||||
@@ -0,0 +1,554 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/String.h"
|
||||
#include "Kyty/Core/Vector.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct VertexShaderInfo;
|
||||
struct PixelShaderInfo;
|
||||
struct ComputeShaderInfo;
|
||||
|
||||
enum class ShaderType
|
||||
{
|
||||
Unknown,
|
||||
Vertex,
|
||||
Pixel,
|
||||
Fetch,
|
||||
Compute
|
||||
};
|
||||
|
||||
enum class ShaderInstructionType
|
||||
{
|
||||
Unknown,
|
||||
DsAppend,
|
||||
DsConsume,
|
||||
Exp,
|
||||
BufferLoadDword,
|
||||
BufferLoadFormatX,
|
||||
BufferLoadFormatXy,
|
||||
BufferLoadFormatXyz,
|
||||
BufferLoadFormatXyzw,
|
||||
BufferStoreDword,
|
||||
BufferStoreFormatX,
|
||||
ImageSample,
|
||||
TBufferLoadFormatXyzw,
|
||||
SAndn2B64,
|
||||
SAndSaveexecB64,
|
||||
SEndpgm,
|
||||
SCbranchExecz,
|
||||
SLshlB32,
|
||||
SLoadDwordx4,
|
||||
SLoadDwordx8,
|
||||
SBufferLoadDword,
|
||||
SBufferLoadDwordx4,
|
||||
SBufferLoadDwordx8,
|
||||
SBufferLoadDwordx16,
|
||||
SMovB32,
|
||||
SMovB64,
|
||||
SSetpcB64,
|
||||
SSwappcB64,
|
||||
SWaitcnt,
|
||||
SWqmB64,
|
||||
VAddI32,
|
||||
VAndB32,
|
||||
VCmpEqF32,
|
||||
VCmpEqU32,
|
||||
VCmpLeF32,
|
||||
VCmpLeU32,
|
||||
VCmpNeU32,
|
||||
VCmpNeqF32,
|
||||
VCmpxEqU32,
|
||||
VCmpxGtU32,
|
||||
VCndmaskB32,
|
||||
VCvtF32U32,
|
||||
VCvtPkrtzF16F32,
|
||||
VCvtU32F32,
|
||||
VMacF32,
|
||||
VMadakF32,
|
||||
VMadF32,
|
||||
VMaxF32,
|
||||
VMbcntHiU32B32,
|
||||
VMbcntLoU32B32,
|
||||
VMinF32,
|
||||
VMovB32,
|
||||
VMulF32,
|
||||
VInterpP1F32,
|
||||
VInterpP2F32,
|
||||
VRcpF32,
|
||||
VRsqF32,
|
||||
VSadU32,
|
||||
VSqrtF32,
|
||||
VSubF32,
|
||||
VSubI32,
|
||||
VSubrevF32,
|
||||
VSubrevI32,
|
||||
};
|
||||
|
||||
namespace ShaderInstructionFormat {
|
||||
|
||||
enum FormatByte : uint64_t
|
||||
{
|
||||
U = 0,
|
||||
N,
|
||||
D, // operand_to_str(inst.dst)
|
||||
D2, // operand_to_str(inst.dst2)
|
||||
S0, // operand_to_str(inst.src[0])
|
||||
S1, // operand_to_str(inst.src[1])
|
||||
S2, // operand_to_str(inst.src[2])
|
||||
S3, // operand_to_str(inst.src[3])
|
||||
DA2, // operand_array_to_str(inst.dst, 2)
|
||||
DA3, // operand_array_to_str(inst.dst, 3)
|
||||
DA4, // operand_array_to_str(inst.dst, 4)
|
||||
DA8, // operand_array_to_str(inst.dst, 8)
|
||||
DA16, // operand_array_to_str(inst.dst, 16)
|
||||
D2A2, // operand_array_to_str(inst.dst2, 2)
|
||||
D2A3, // operand_array_to_str(inst.dst2, 3)
|
||||
D2A4, // operand_array_to_str(inst.dst2, 4)
|
||||
S0A2, // operand_array_to_str(inst.src[0], 2)
|
||||
S0A3, // operand_array_to_str(inst.src[0], 3)
|
||||
S0A4, // operand_array_to_str(inst.src[0], 4)
|
||||
S1A2, // operand_array_to_str(inst.src[1], 2)
|
||||
S1A3, // operand_array_to_str(inst.src[1], 3)
|
||||
S1A4, // operand_array_to_str(inst.src[1], 4)
|
||||
S1A8, // operand_array_to_str(inst.src[1], 8)
|
||||
S2A2, // operand_array_to_str(inst.src[2], 2)
|
||||
S2A3, // operand_array_to_str(inst.src[2], 3)
|
||||
S2A4, // operand_array_to_str(inst.src[2], 4)
|
||||
Attr, // attr%u.%u <- inst.src[1].constant.u, inst.src[2].constant.u
|
||||
Idxen, // idxen
|
||||
Float4, // format:float4
|
||||
Pos0, // pos0
|
||||
Done, // done
|
||||
Param0, // param0
|
||||
Param1, // param1
|
||||
Param2, // param2
|
||||
Param3, // param3
|
||||
Mrt0, // mrt_color0
|
||||
Compr, // compr
|
||||
Vm, // vm
|
||||
L, // label_%u
|
||||
DmaskF, // dmask:0xf
|
||||
Dmask7, // dmask:0x7
|
||||
Gds, // gds
|
||||
};
|
||||
|
||||
constexpr uint64_t FormatDefine(std::initializer_list<uint64_t> f)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
for (auto n: f)
|
||||
{
|
||||
r = (r << 8u) | n;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
enum Format : uint64_t
|
||||
{
|
||||
Unknown = FormatDefine({U}),
|
||||
Empty = FormatDefine({N}),
|
||||
Imm = FormatDefine({S0}),
|
||||
Label = FormatDefine({L}),
|
||||
Mrt0Vsrc0Vsrc1ComprVmDone = FormatDefine({Mrt0, S0, S1, Compr, Vm, Done}),
|
||||
Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone = FormatDefine({Mrt0, S0, S1, S2, S3, Vm, Done}),
|
||||
Param0Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param0, S0, S1, S2, S3}),
|
||||
Param1Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param1, S0, S1, S2, S3}),
|
||||
Param2Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param2, S0, S1, S2, S3}),
|
||||
Param3Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param3, S0, S1, S2, S3}),
|
||||
Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done = FormatDefine({Pos0, S0, S1, S2, S3, Done}),
|
||||
Saddr = FormatDefine({S0A2}),
|
||||
Sdst4SbaseSoffset = FormatDefine({DA4, S0A2, S1}),
|
||||
Sdst8SbaseSoffset = FormatDefine({DA8, S0A2, S1}),
|
||||
SdstSvSoffset = FormatDefine({D, S0A4, S1}),
|
||||
Sdst4SvSoffset = FormatDefine({DA4, S0A4, S1}),
|
||||
Sdst8SvSoffset = FormatDefine({DA8, S0A4, S1}),
|
||||
Sdst16SvSoffset = FormatDefine({DA16, S0A4, S1}),
|
||||
SVdstSVsrc0 = FormatDefine({D, S0}),
|
||||
SVdstSVsrc0SVsrc1 = FormatDefine({D, S0, S1}),
|
||||
Sdst2Ssrc02 = FormatDefine({DA2, S0A2}),
|
||||
Sdst2Ssrc02Ssrc12 = FormatDefine({DA2, S0A2, S1A2}),
|
||||
SmaskVsrc0Vsrc1 = FormatDefine({DA2, S0, S1}),
|
||||
Vdata1VaddrSvSoffsIdxen = FormatDefine({D, S0, S1A4, S2, Idxen}),
|
||||
Vdata2VaddrSvSoffsIdxen = FormatDefine({DA2, S0, S1A4, S2, Idxen}),
|
||||
Vdata3VaddrSvSoffsIdxen = FormatDefine({DA3, S0, S1A4, S2, Idxen}),
|
||||
Vdata4VaddrSvSoffsIdxen = FormatDefine({DA4, S0, S1A4, S2, Idxen}),
|
||||
Vdata4VaddrSvSoffsIdxenFloat4 = FormatDefine({DA4, S0, S1A4, S2, Idxen, Float4}),
|
||||
Vdata3Vaddr3StSsDmask7 = FormatDefine({DA3, S0A3, S1A8, S2A4, Dmask7}),
|
||||
Vdata4Vaddr3StSsDmaskF = FormatDefine({DA4, S0A3, S1A8, S2A4, DmaskF}),
|
||||
VdstVsrc0Vsrc1Smask2 = FormatDefine({D, S0, S1, S2A2}),
|
||||
VdstVsrc0Vsrc1Vsrc2 = FormatDefine({D, S0, S1, S2}),
|
||||
VdstVsrcAttrChan = FormatDefine({D, S0, Attr}),
|
||||
VdstSdst2Vsrc0Vsrc1 = FormatDefine({D, D2A2, S0, S1}),
|
||||
VdstGds = FormatDefine({D, Gds})
|
||||
};
|
||||
|
||||
} // namespace ShaderInstructionFormat
|
||||
|
||||
enum class ShaderOperandType
|
||||
{
|
||||
Unknown,
|
||||
LiteralConstant,
|
||||
IntegerInlineConstant,
|
||||
FloatInlineConstant,
|
||||
VccLo,
|
||||
VccHi,
|
||||
ExecLo,
|
||||
ExecHi,
|
||||
ExecZ,
|
||||
Vgpr,
|
||||
Sgpr,
|
||||
M0
|
||||
};
|
||||
|
||||
union ShaderConstant
|
||||
{
|
||||
int32_t i;
|
||||
uint32_t u;
|
||||
float f;
|
||||
};
|
||||
|
||||
struct ShaderOperand
|
||||
{
|
||||
ShaderOperandType type = ShaderOperandType::Unknown;
|
||||
ShaderConstant constant = {0};
|
||||
int register_id = 0;
|
||||
int size = 0;
|
||||
float multiplier = 1.0f;
|
||||
bool negate = false;
|
||||
bool clamp = false;
|
||||
|
||||
bool operator==(const ShaderOperand& other) const
|
||||
{
|
||||
return type == other.type && constant.u == other.constant.u && register_id == other.register_id && size == other.size;
|
||||
}
|
||||
};
|
||||
|
||||
struct ShaderInstruction
|
||||
{
|
||||
uint32_t pc = 0;
|
||||
ShaderInstructionType type = ShaderInstructionType::Unknown;
|
||||
ShaderInstructionFormat::Format format = ShaderInstructionFormat::Unknown;
|
||||
ShaderOperand src[4];
|
||||
int src_num = 0;
|
||||
ShaderOperand dst;
|
||||
ShaderOperand dst2;
|
||||
};
|
||||
|
||||
class ShaderCode
|
||||
{
|
||||
public:
|
||||
ShaderCode() { m_instructions.Expand(128); };
|
||||
virtual ~ShaderCode() = default;
|
||||
KYTY_CLASS_DEFAULT_COPY(ShaderCode);
|
||||
|
||||
[[nodiscard]] const Vector<ShaderInstruction>& GetInstructions() const { return m_instructions; }
|
||||
Vector<ShaderInstruction>& GetInstructions() { return m_instructions; }
|
||||
[[nodiscard]] const Vector<uint32_t>& GetLabels() const { return m_labels; }
|
||||
Vector<uint32_t>& GetLabels() { return m_labels; }
|
||||
|
||||
[[nodiscard]] String DbgDump() const;
|
||||
|
||||
static String DbgInstructionToStr(const ShaderInstruction& inst);
|
||||
|
||||
[[nodiscard]] ShaderType GetType() const { return m_type; }
|
||||
void SetType(ShaderType type) { this->m_type = type; }
|
||||
|
||||
private:
|
||||
Vector<ShaderInstruction> m_instructions;
|
||||
Vector<uint32_t> m_labels;
|
||||
ShaderType m_type = ShaderType::Unknown;
|
||||
};
|
||||
|
||||
struct ShaderId
|
||||
{
|
||||
Vector<uint32_t> ids;
|
||||
|
||||
bool operator==(const ShaderId& other) const { return ids == other.ids; }
|
||||
bool operator!=(const ShaderId& other) const { return !(*this == other); }
|
||||
};
|
||||
|
||||
struct ShaderBufferResource
|
||||
{
|
||||
uint32_t fields[4] = {0};
|
||||
|
||||
void UpdateAddress(uint64_t gpu_addr)
|
||||
{
|
||||
auto lo = static_cast<uint32_t>(gpu_addr & 0xffffffffu);
|
||||
auto hi = static_cast<uint32_t>(gpu_addr >> 32u);
|
||||
fields[0] = lo;
|
||||
fields[1] = (fields[1] & 0xfffff000u) | (hi & 0xfffu);
|
||||
}
|
||||
|
||||
[[nodiscard]] uint64_t Base() const { return (fields[0] | (static_cast<uint64_t>(fields[1]) << 32u)) & 0xFFFFFFFFFFFu; }
|
||||
[[nodiscard]] uint16_t Stride() const { return (fields[1] >> 16u) & 0x3FFFu; }
|
||||
[[nodiscard]] bool SwizzleEnabled() const { return ((fields[1] >> 31u) & 0x1u) == 1; }
|
||||
[[nodiscard]] uint32_t NumRecords() const { return fields[2]; }
|
||||
[[nodiscard]] uint8_t DstSelX() const { return (fields[3] >> 0u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t DstSelY() const { return (fields[3] >> 3u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t DstSelZ() const { return (fields[3] >> 6u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t DstSelW() const { return (fields[3] >> 9u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t Nfmt() const { return (fields[3] >> 12u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t Dfmt() const { return (fields[3] >> 15u) & 0xFu; }
|
||||
[[nodiscard]] bool AddTid() const { return ((fields[3] >> 23u) & 0x1u) == 1; }
|
||||
|
||||
[[nodiscard]] uint8_t MemoryType() const
|
||||
{
|
||||
return ((fields[1] >> 7u) & 0x60u) | ((fields[3] >> 25u) & 0x1cu) | ((fields[1] >> 14u) & 0x3u);
|
||||
}
|
||||
};
|
||||
|
||||
struct ShaderTextureResource
|
||||
{
|
||||
uint32_t fields[8] = {0};
|
||||
|
||||
void UpdateAddress(uint64_t gpu_addr)
|
||||
{
|
||||
auto lo = static_cast<uint32_t>(gpu_addr & 0xffffffffu);
|
||||
auto hi = static_cast<uint32_t>(gpu_addr >> 32u);
|
||||
fields[0] = lo;
|
||||
fields[1] = (fields[1] & 0xffffffc0u) | (hi & 0x3fu);
|
||||
}
|
||||
|
||||
[[nodiscard]] uint64_t Base() const { return ((fields[0] | (static_cast<uint64_t>(fields[1]) << 32u)) & 0x3FFFFFFFFFu) << 8u; }
|
||||
[[nodiscard]] uint16_t MinLod() const { return (fields[1] >> 8u) & 0xFFFu; }
|
||||
[[nodiscard]] uint8_t Dfmt() const { return (fields[1] >> 20u) & 0x3Fu; }
|
||||
[[nodiscard]] uint8_t Nfmt() const { return (fields[1] >> 26u) & 0xFu; }
|
||||
[[nodiscard]] uint16_t Width() const { return (fields[2] >> 0u) & 0x3FFFu; }
|
||||
[[nodiscard]] uint16_t Height() const { return (fields[2] >> 14u) & 0x3FFFu; }
|
||||
[[nodiscard]] uint8_t PerfMod() const { return (fields[2] >> 28u) & 0x7u; }
|
||||
[[nodiscard]] bool Interlaced() const { return ((fields[2] >> 31u) & 0x1u) == 1; }
|
||||
[[nodiscard]] uint8_t DstSelX() const { return (fields[3] >> 0u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t DstSelY() const { return (fields[3] >> 3u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t DstSelZ() const { return (fields[3] >> 6u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t DstSelW() const { return (fields[3] >> 9u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t BaseLevel() const { return (fields[3] >> 12u) & 0xFu; }
|
||||
[[nodiscard]] uint8_t LastLevel() const { return (fields[3] >> 16u) & 0xFu; }
|
||||
[[nodiscard]] uint8_t TilingIdx() const { return (fields[3] >> 20u) & 0x1Fu; }
|
||||
[[nodiscard]] bool Pow2Pad() const { return ((fields[3] >> 25u) & 0x1u) == 1; }
|
||||
[[nodiscard]] uint8_t Type() const { return (fields[3] >> 28u) & 0xFu; }
|
||||
|
||||
[[nodiscard]] uint16_t Depth() const { return (fields[4] >> 0u) & 0x1FFFu; }
|
||||
[[nodiscard]] uint16_t Pitch() const { return (fields[4] >> 13u) & 0x3FFFu; }
|
||||
[[nodiscard]] uint16_t BaseArray() const { return (fields[5] >> 0u) & 0x1FFFu; }
|
||||
[[nodiscard]] uint16_t LastArray() const { return (fields[5] >> 13u) & 0x1FFFu; }
|
||||
[[nodiscard]] uint16_t MinLodWarn() const { return (fields[6] >> 0u) & 0xFFFu; }
|
||||
[[nodiscard]] uint8_t CounterBankId() const { return (fields[6] >> 12u) & 0xFFu; }
|
||||
[[nodiscard]] bool LodHdwCntEn() const { return ((fields[6] >> 20u) & 0x1u) == 1; }
|
||||
|
||||
[[nodiscard]] uint8_t MemoryType() const
|
||||
{
|
||||
return ((fields[1] >> 6u) & 0x3u) | ((fields[1] >> 30u) << 2u) | ((fields[3] & 0x04000000u) == 0 ? 0x60u : 0x10u);
|
||||
}
|
||||
};
|
||||
|
||||
struct ShaderSamplerResource
|
||||
{
|
||||
uint32_t fields[4] = {0};
|
||||
|
||||
void UpdateIndex(uint32_t index) { fields[0] = index; }
|
||||
|
||||
[[nodiscard]] uint8_t ClampX() const { return (fields[0] >> 0u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t ClampY() const { return (fields[0] >> 3u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t ClampZ() const { return (fields[0] >> 6u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t MaxAnisoRatio() const { return (fields[0] >> 9u) & 0x7u; }
|
||||
[[nodiscard]] uint8_t DepthCompareFunc() const { return (fields[0] >> 12u) & 0x7u; }
|
||||
[[nodiscard]] bool ForceUnormCoords() const { return ((fields[0] >> 15u) & 0x1u) == 1; }
|
||||
[[nodiscard]] uint8_t AnisoThreshold() const { return (fields[0] >> 16u) & 0x7u; }
|
||||
[[nodiscard]] bool McCoordTrunc() const { return ((fields[0] >> 19u) & 0x1u) == 1; }
|
||||
[[nodiscard]] bool ForceDegamma() const { return ((fields[0] >> 20u) & 0x1u) == 1; }
|
||||
[[nodiscard]] uint8_t AnisoBias() const { return (fields[0] >> 21u) & 0x3Fu; }
|
||||
[[nodiscard]] bool TruncCoord() const { return ((fields[0] >> 27u) & 0x1u) == 1; }
|
||||
[[nodiscard]] bool DisableCubeWrap() const { return ((fields[0] >> 28u) & 0x1u) == 1; }
|
||||
[[nodiscard]] uint8_t FilterMode() const { return (fields[0] >> 29u) & 0x3u; }
|
||||
[[nodiscard]] uint16_t MinLod() const { return (fields[1] >> 0u) & 0xFFFu; }
|
||||
[[nodiscard]] uint16_t MaxLod() const { return (fields[1] >> 12u) & 0xFFFu; }
|
||||
[[nodiscard]] uint8_t PerfMip() const { return (fields[1] >> 24u) & 0xFu; }
|
||||
[[nodiscard]] uint8_t PerfZ() const { return (fields[1] >> 28u) & 0xFu; }
|
||||
[[nodiscard]] uint16_t LodBias() const { return (fields[2] >> 0u) & 0x3FFFu; }
|
||||
[[nodiscard]] uint8_t LodBiasSec() const { return (fields[2] >> 14u) & 0x3Fu; }
|
||||
[[nodiscard]] uint8_t XyMagFilter() const { return (fields[2] >> 20u) & 0x3u; }
|
||||
[[nodiscard]] uint8_t XyMinFilter() const { return (fields[2] >> 22u) & 0x3u; }
|
||||
[[nodiscard]] uint8_t ZFilter() const { return (fields[2] >> 24u) & 0x3u; }
|
||||
[[nodiscard]] uint8_t MipFilter() const { return (fields[2] >> 26u) & 0x3u; }
|
||||
[[nodiscard]] uint16_t BorderColorPtr() const { return (fields[3] >> 0u) & 0xFFFu; }
|
||||
[[nodiscard]] uint8_t BorderColorType() const { return (fields[3] >> 30u) & 0x3u; }
|
||||
};
|
||||
|
||||
struct ShaderGdsResource
|
||||
{
|
||||
uint32_t field = 0;
|
||||
|
||||
[[nodiscard]] uint16_t Base() const { return (field >> 16u) & 0xFFFFu; }
|
||||
[[nodiscard]] uint16_t Size() const { return field & 0xFFFFu; }
|
||||
};
|
||||
|
||||
struct ShaderExtendedResource
|
||||
{
|
||||
uint32_t fields[2] = {0};
|
||||
|
||||
void UpdateAddress(uint64_t gpu_addr)
|
||||
{
|
||||
auto lo = static_cast<uint32_t>(gpu_addr & 0xffffffffu);
|
||||
auto hi = static_cast<uint32_t>(gpu_addr >> 32u);
|
||||
fields[0] = lo;
|
||||
fields[1] = hi;
|
||||
}
|
||||
|
||||
[[nodiscard]] uint64_t Base() const { return (fields[0] | (static_cast<uint64_t>(fields[1]) << 32u)); }
|
||||
};
|
||||
|
||||
struct ShaderVertexInputBuffer
|
||||
{
|
||||
static constexpr int ATTR_MAX = 16;
|
||||
|
||||
uint64_t addr = 0;
|
||||
uint32_t stride = 0;
|
||||
uint32_t num_records = 0;
|
||||
int attr_num = 0;
|
||||
int attr_indices[ATTR_MAX] = {0};
|
||||
uint32_t attr_offsets[ATTR_MAX] = {0};
|
||||
};
|
||||
|
||||
struct ShaderVertexDestination
|
||||
{
|
||||
int register_start = 0;
|
||||
int registers_num = 0;
|
||||
};
|
||||
|
||||
enum class ShaderStorageUsage
|
||||
{
|
||||
Unknown,
|
||||
Constant,
|
||||
ReadOnly,
|
||||
ReadWrite,
|
||||
};
|
||||
|
||||
struct ShaderStorageResources
|
||||
{
|
||||
static constexpr int BUFFERS_MAX = 16;
|
||||
|
||||
ShaderBufferResource buffers[BUFFERS_MAX];
|
||||
ShaderStorageUsage usages[BUFFERS_MAX] = {};
|
||||
int slots[BUFFERS_MAX] = {0};
|
||||
int start_register[BUFFERS_MAX] = {0};
|
||||
bool extended[BUFFERS_MAX] = {};
|
||||
// int extended_index[BUFFERS_MAX] = {0};
|
||||
int buffers_num = 0;
|
||||
int binding_index = 0;
|
||||
};
|
||||
|
||||
struct ShaderTextureResources
|
||||
{
|
||||
static constexpr int RES_MAX = 16;
|
||||
|
||||
ShaderTextureResource textures[RES_MAX];
|
||||
int start_register[RES_MAX] = {0};
|
||||
bool extended[RES_MAX] = {};
|
||||
// int extended_index[RES_MAX] = {0};
|
||||
int textures_num = 0;
|
||||
int binding_index = 0;
|
||||
};
|
||||
|
||||
struct ShaderSamplerResources
|
||||
{
|
||||
static constexpr int RES_MAX = 16;
|
||||
|
||||
ShaderSamplerResource samplers[RES_MAX];
|
||||
int start_register[RES_MAX] = {0};
|
||||
bool extended[RES_MAX] = {};
|
||||
// int extended_index[RES_MAX] = {0};
|
||||
int samplers_num = 0;
|
||||
int binding_index = 0;
|
||||
};
|
||||
|
||||
struct ShaderGdsResources
|
||||
{
|
||||
static constexpr int POINTERS_MAX = 1;
|
||||
|
||||
ShaderGdsResource pointers[POINTERS_MAX];
|
||||
int slots[POINTERS_MAX] = {0};
|
||||
int start_register[POINTERS_MAX] = {0};
|
||||
bool extended[POINTERS_MAX] = {};
|
||||
// int extended_index[POINTERS_MAX] = {0};
|
||||
int pointers_num = 0;
|
||||
int binding_index = 0;
|
||||
};
|
||||
|
||||
struct ShaderExtendedResources
|
||||
{
|
||||
bool used = false;
|
||||
int slot = 0;
|
||||
// int dw_num = 0;
|
||||
int start_register = 0;
|
||||
ShaderExtendedResource data;
|
||||
};
|
||||
|
||||
struct ShaderResources
|
||||
{
|
||||
uint32_t push_constant_offset = 0;
|
||||
uint32_t push_constant_size = 0;
|
||||
uint32_t descriptor_set_slot = 0;
|
||||
ShaderStorageResources storage_buffers;
|
||||
ShaderTextureResources textures2D;
|
||||
ShaderSamplerResources samplers;
|
||||
ShaderGdsResources gds_pointers;
|
||||
ShaderExtendedResources extended;
|
||||
};
|
||||
|
||||
struct ShaderVertexInputInfo
|
||||
{
|
||||
static constexpr int RES_MAX = 16;
|
||||
|
||||
ShaderBufferResource resources[RES_MAX];
|
||||
ShaderVertexDestination resources_dst[RES_MAX];
|
||||
int resources_num = 0;
|
||||
bool fetch = false;
|
||||
ShaderVertexInputBuffer buffers[RES_MAX];
|
||||
int buffers_num = 0;
|
||||
int export_count = 0;
|
||||
ShaderResources bind;
|
||||
};
|
||||
|
||||
struct ShaderComputeInputInfo
|
||||
{
|
||||
uint32_t threads_num[3] = {};
|
||||
int workgroup_register = 0;
|
||||
ShaderResources bind;
|
||||
};
|
||||
|
||||
struct ShaderPixelInputInfo
|
||||
{
|
||||
uint32_t interpolator_settings[32] = {0};
|
||||
uint32_t input_num = 0;
|
||||
uint8_t target_output_mode[8] = {};
|
||||
bool ps_pos_xy = false;
|
||||
bool ps_pixel_kill_enable = false;
|
||||
ShaderResources bind;
|
||||
};
|
||||
|
||||
void ShaderGetInputInfoVS(const VertexShaderInfo* regs, ShaderVertexInputInfo* info);
|
||||
void ShaderGetInputInfoPS(const PixelShaderInfo* regs, const ShaderVertexInputInfo* vs_info, ShaderPixelInputInfo* ps_info);
|
||||
void ShaderGetInputInfoCS(const ComputeShaderInfo* regs, ShaderComputeInputInfo* info);
|
||||
void ShaderDbgDumpInputInfo(const ShaderVertexInputInfo* info);
|
||||
void ShaderDbgDumpInputInfo(const ShaderPixelInputInfo* info);
|
||||
void ShaderDbgDumpInputInfo(const ShaderComputeInputInfo* info);
|
||||
ShaderId ShaderGetIdVS(const VertexShaderInfo* regs, const ShaderVertexInputInfo* input_info);
|
||||
ShaderId ShaderGetIdPS(const PixelShaderInfo* regs, const ShaderPixelInputInfo* input_info);
|
||||
ShaderId ShaderGetIdCS(const ComputeShaderInfo* regs, const ShaderComputeInputInfo* input_info);
|
||||
Vector<uint32_t> ShaderRecompileVS(const VertexShaderInfo* regs, const ShaderVertexInputInfo* input_info);
|
||||
Vector<uint32_t> ShaderRecompilePS(const PixelShaderInfo* regs, const ShaderPixelInputInfo* input_info);
|
||||
Vector<uint32_t> ShaderRecompileCS(const ComputeShaderInfo* regs, const ShaderComputeInputInfo* input_info);
|
||||
bool ShaderIsDisabled(uint64_t addr);
|
||||
void ShaderDisable(uint64_t id);
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_H_ */
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADERSPIRV_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADERSPIRV_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/String.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
class ShaderCode;
|
||||
struct ShaderVertexInputInfo;
|
||||
struct ShaderPixelInputInfo;
|
||||
struct ShaderComputeInputInfo;
|
||||
|
||||
String SpirvGenerateSource(const ShaderCode& code, const ShaderVertexInputInfo* vs_input_info, const ShaderPixelInputInfo* ps_input_info,
|
||||
const ShaderComputeInputInfo* cs_input_info);
|
||||
String SpirvGetEmbeddedVs(uint32_t id);
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADERSPIRV_H_ */
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_STORAGEBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_STORAGEBUFFER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
class StorageBufferGpuObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
StorageBufferGpuObject(uint64_t stride, uint64_t num_records, bool ronly)
|
||||
{
|
||||
params[0] = stride;
|
||||
params[1] = num_records;
|
||||
check_hash = true;
|
||||
read_only = ronly;
|
||||
type = Graphics::GpuMemoryObjectType::StorageBuffer;
|
||||
}
|
||||
|
||||
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
|
||||
bool Equal(const uint64_t* other) const override;
|
||||
|
||||
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override;
|
||||
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
|
||||
[[nodiscard]] update_func_t GetUpdateFunc() const override;
|
||||
};
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_STORAGEBUFFER_H_ */
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TEXTURE_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TEXTURE_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
class TextureObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
static constexpr int PARAM_DFMT = 0;
|
||||
static constexpr int PARAM_NFMT = 1;
|
||||
static constexpr int PARAM_WIDTH = 2;
|
||||
static constexpr int PARAM_HEIGHT = 3;
|
||||
static constexpr int PARAM_LEVELS = 4;
|
||||
static constexpr int PARAM_TILE = 5;
|
||||
static constexpr int PARAM_NEO = 6;
|
||||
static constexpr int PARAM_SWIZZLE = 7;
|
||||
|
||||
TextureObject(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t levels, bool htile, bool neo, uint32_t swizzle)
|
||||
{
|
||||
params[PARAM_DFMT] = dfmt;
|
||||
params[PARAM_NFMT] = nfmt;
|
||||
params[PARAM_WIDTH] = width;
|
||||
params[PARAM_HEIGHT] = height;
|
||||
params[PARAM_LEVELS] = levels;
|
||||
params[PARAM_TILE] = htile ? 1 : 0;
|
||||
params[PARAM_NEO] = neo ? 1 : 0;
|
||||
params[PARAM_SWIZZLE] = swizzle;
|
||||
check_hash = true;
|
||||
type = Graphics::GpuMemoryObjectType::Texture;
|
||||
}
|
||||
|
||||
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
|
||||
bool Equal(const uint64_t* other) const override;
|
||||
|
||||
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
|
||||
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
|
||||
[[nodiscard]] update_func_t GetUpdateFunc() const override;
|
||||
};
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TEXTURE_H_ */
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TILE_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TILE_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
enum class TileMode
|
||||
{
|
||||
VideoOutLinear,
|
||||
VideoOutTiled,
|
||||
TextureLinear,
|
||||
TextureTiled,
|
||||
};
|
||||
|
||||
void TileInit();
|
||||
void TileConvertTiledToLinear(void* dst, const void* src, TileMode mode, uint32_t width, uint32_t height, bool neo);
|
||||
void TileConvertTiledToLinear(void* dst, const void* src, TileMode mode, uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height,
|
||||
uint32_t levels, bool neo);
|
||||
|
||||
void TileGetDepthSize(uint32_t width, uint32_t height, uint32_t z_format, uint32_t stencil_format, bool htile, bool neo,
|
||||
uint32_t* stencil_size, uint32_t* htile_size, uint32_t* depth_size, uint32_t* pitch);
|
||||
void TileGetVideoOutSize(uint32_t width, uint32_t height, bool tile, bool neo, uint32_t* size);
|
||||
void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t levels, bool tile, bool neo,
|
||||
uint32_t* total_size, uint32_t* level_sizes, uint32_t* padded_width, uint32_t* padded_height);
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TILE_H_ */
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_UTILS_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_UTILS_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty {
|
||||
template <typename T>
|
||||
class Vector;
|
||||
} // namespace Kyty
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
class CommandBuffer;
|
||||
struct GraphicContext;
|
||||
struct VulkanBuffer;
|
||||
struct VideoOutVulkanImage;
|
||||
struct TextureVulkanImage;
|
||||
struct DepthStencilVulkanImage;
|
||||
struct VulkanSwapchain;
|
||||
|
||||
struct BufferImageCopy
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, VideoOutVulkanImage* dst_image);
|
||||
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, TextureVulkanImage* dst_image,
|
||||
const Vector<BufferImageCopy>& regions);
|
||||
void UtilBlitImage(CommandBuffer* buffer, VideoOutVulkanImage* src_image, VulkanSwapchain* dst_swapchain);
|
||||
void UtilFillImage(GraphicContext* ctx, VideoOutVulkanImage* dst_image, const void* src_data, uint64_t size);
|
||||
void UtilFillImage(GraphicContext* ctx, TextureVulkanImage* dst_image, const void* src_data, uint64_t size,
|
||||
const Vector<BufferImageCopy>& regions);
|
||||
void UtilCopyBuffer(VulkanBuffer* src_buffer, VulkanBuffer* dst_buffer, uint64_t size);
|
||||
void UtilSetImageLayoutOptimal(DepthStencilVulkanImage* image);
|
||||
void UtilSetImageLayoutOptimal(VideoOutVulkanImage* image);
|
||||
|
||||
void VulkanCreateBuffer(GraphicContext* gctx, uint64_t size, VulkanBuffer* buffer);
|
||||
void VulkanDeleteBuffer(GraphicContext* gctx, VulkanBuffer* buffer);
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_UTILS_H_ */
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VERTEXBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VERTEXBUFFER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
class VertexBufferGpuObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
VertexBufferGpuObject()
|
||||
{
|
||||
check_hash = true;
|
||||
type = Graphics::GpuMemoryObjectType::VertexBuffer;
|
||||
}
|
||||
|
||||
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
|
||||
bool Equal(const uint64_t* other) const override;
|
||||
|
||||
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
|
||||
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
|
||||
[[nodiscard]] update_func_t GetUpdateFunc() const override;
|
||||
};
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VERTEXBUFFER_H_ */
|
||||
@@ -0,0 +1,52 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUT_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUT_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
//#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Kernel/EventQueue.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
// struct VulkanSwapchain;
|
||||
struct VideoOutVulkanImage;
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
namespace Kyty::Libs::VideoOut {
|
||||
|
||||
struct VideoOutResolutionStatus;
|
||||
struct VideoOutBufferAttribute;
|
||||
struct VideoOutFlipStatus;
|
||||
|
||||
struct VideoOutBufferImageInfo
|
||||
{
|
||||
Graphics::VideoOutVulkanImage* image = nullptr;
|
||||
uint32_t index = static_cast<uint32_t>(-1);
|
||||
uint64_t buffer_size = 0;
|
||||
};
|
||||
|
||||
void VideoOutInit(uint32_t width, uint32_t height);
|
||||
VideoOutBufferImageInfo VideoOutGetImage(uint64_t addr);
|
||||
void VideoOutWaitFlipDone(int handle, int index);
|
||||
|
||||
KYTY_SYSV_ABI int VideoOutOpen(int user_id, int bus_type, int index, const void* param);
|
||||
KYTY_SYSV_ABI int VideoOutClose(int handle);
|
||||
KYTY_SYSV_ABI int VideoOutGetResolutionStatus(int handle, VideoOutResolutionStatus* status);
|
||||
KYTY_SYSV_ABI void VideoOutSetBufferAttribute(VideoOutBufferAttribute* attribute, uint32_t pixel_format, uint32_t tiling_mode,
|
||||
uint32_t aspect_ratio, uint32_t width, uint32_t height, uint32_t pitch_in_pixel);
|
||||
KYTY_SYSV_ABI int VideoOutSetFlipRate(int handle, int rate);
|
||||
KYTY_SYSV_ABI int VideoOutAddFlipEvent(LibKernel::EventQueue::KernelEqueue eq, int handle, void* udata);
|
||||
KYTY_SYSV_ABI int VideoOutRegisterBuffers(int handle, int start_index, void* const* addresses, int buffer_num,
|
||||
const VideoOutBufferAttribute* attribute);
|
||||
KYTY_SYSV_ABI int VideoOutSubmitFlip(int handle, int index, int flip_mode, int64_t flip_arg);
|
||||
KYTY_SYSV_ABI int VideoOutGetFlipStatus(int handle, VideoOutFlipStatus* status);
|
||||
|
||||
bool FlipWindow(uint32_t micros);
|
||||
|
||||
} // namespace Kyty::Libs::VideoOut
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUT_H_ */
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUTBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUTBUFFER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
class VideoOutBufferObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
static constexpr int PARAM_FORMAT = 0;
|
||||
static constexpr int PARAM_WIDTH = 1;
|
||||
static constexpr int PARAM_HEIGHT = 2;
|
||||
static constexpr int PARAM_TILED = 3;
|
||||
static constexpr int PARAM_NEO = 4;
|
||||
|
||||
explicit VideoOutBufferObject(uint32_t pixel_format, uint32_t width, uint32_t height, bool tiled, bool neo)
|
||||
{
|
||||
params[PARAM_FORMAT] = pixel_format;
|
||||
params[PARAM_WIDTH] = width;
|
||||
params[PARAM_HEIGHT] = height;
|
||||
params[PARAM_TILED] = tiled ? 1 : 0;
|
||||
params[PARAM_NEO] = neo ? 1 : 0;
|
||||
check_hash = true;
|
||||
type = Graphics::GpuMemoryObjectType::VideoOutBuffer;
|
||||
}
|
||||
|
||||
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
|
||||
bool Equal(const uint64_t* other) const override;
|
||||
|
||||
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
|
||||
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
|
||||
[[nodiscard]] update_func_t GetUpdateFunc() const override;
|
||||
};
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUTBUFFER_H_ */
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_WINDOW_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_WINDOW_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
struct VkSurfaceCapabilitiesKHR;
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VideoOutVulkanImage;
|
||||
|
||||
VkSurfaceCapabilitiesKHR* VulkanGetSurfaceCapabilities();
|
||||
|
||||
GraphicContext* WindowGetGraphicContext();
|
||||
|
||||
void WindowInit(uint32_t width, uint32_t height);
|
||||
void WindowRun();
|
||||
void WindowWaitForGraphicInitialized();
|
||||
void WindowDrawBuffer(VideoOutVulkanImage* image);
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_WINDOW_H_ */
|
||||
@@ -0,0 +1,150 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_JIT_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_JIT_H_
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Loader::Jit {
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
struct JmpWithIndex
|
||||
{
|
||||
void SetIndex(uint32_t index) { *reinterpret_cast<uint32_t*>(&code[1]) = index; }
|
||||
|
||||
void SetFunc(void* handler)
|
||||
{
|
||||
auto func_addr = reinterpret_cast<int64_t>(handler);
|
||||
auto rip_addr = reinterpret_cast<int64_t>(&code[10]);
|
||||
auto offset64 = func_addr - rip_addr;
|
||||
auto offset32 = static_cast<uint32_t>(static_cast<uint64_t>(offset64) & 0xffffffffu);
|
||||
|
||||
*reinterpret_cast<uint32_t*>(&code[6]) = offset32;
|
||||
}
|
||||
|
||||
static uint64_t GetSize() { return 16; }
|
||||
|
||||
// 68 00 00 00 00 push <index>
|
||||
// E9 E0 FF FF FF jmp <handler>
|
||||
uint8_t code[16] = {0x68, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
|
||||
};
|
||||
|
||||
struct CallPlt
|
||||
{
|
||||
explicit CallPlt(uint32_t table_size)
|
||||
{
|
||||
for (uint32_t index = 0; index < table_size; index++)
|
||||
{
|
||||
auto* c = new (&code[32] + JmpWithIndex::GetSize() * index) JmpWithIndex;
|
||||
c->SetIndex(index);
|
||||
c->SetFunc(this);
|
||||
}
|
||||
}
|
||||
|
||||
void SetPltGot(uint64_t vaddr) { *reinterpret_cast<uint64_t*>(&code[2]) = vaddr; }
|
||||
|
||||
uint64_t GetAddr(uint32_t index) { return reinterpret_cast<uint64_t>(&code[32] + JmpWithIndex::GetSize() * index); }
|
||||
|
||||
static uint64_t GetSize(uint32_t table_size) { return 32 + JmpWithIndex::GetSize() * table_size; }
|
||||
|
||||
// 0: 49 bb 88 77 66 55 44 movabs r11,0x1122334455667788
|
||||
// 7: 33 22 11
|
||||
// a: 41 ff 73 08 push QWORD PTR [r11+0x8]
|
||||
// e: 41 ff 63 10 jmp QWORD PTR [r11+0x10]
|
||||
uint8_t code[32] = {0x49, 0xBB, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x41, 0xFF,
|
||||
0x73, 0x08, 0x41, 0xFF, 0x63, 0x10, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
|
||||
};
|
||||
|
||||
struct JmpRax
|
||||
{
|
||||
template <class Handler>
|
||||
void SetFunc(Handler func)
|
||||
{
|
||||
*reinterpret_cast<Handler*>(&code[2]) = func;
|
||||
}
|
||||
|
||||
// mov rax, 0x1122334455667788
|
||||
// jmp rax
|
||||
uint8_t code[16] = {0x48, 0xB8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xFF, 0xE0};
|
||||
};
|
||||
|
||||
struct Call9
|
||||
{
|
||||
template <class Handler>
|
||||
void SetFunc(Handler func)
|
||||
{
|
||||
auto func_addr = reinterpret_cast<int64_t>(reinterpret_cast<void*>(func));
|
||||
auto rip_addr = reinterpret_cast<int64_t>(&code[5]);
|
||||
auto offset64 = func_addr - rip_addr;
|
||||
auto offset32 = static_cast<uint32_t>(static_cast<uint64_t>(offset64) & 0xffffffffu);
|
||||
|
||||
*reinterpret_cast<uint32_t*>(&code[1]) = offset32;
|
||||
}
|
||||
|
||||
static uint64_t GetSize() { return 9; }
|
||||
|
||||
// call func
|
||||
// mov rax,rax
|
||||
// nop
|
||||
uint8_t code[9] = {0xE8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x89, 0xC0, 0x90};
|
||||
};
|
||||
|
||||
struct SafeCall
|
||||
{
|
||||
using func_t = KYTY_MS_ABI uint8_t* (*)();
|
||||
|
||||
void SetFunc(func_t func) { *reinterpret_cast<func_t*>(&code[0x22]) = func; }
|
||||
void SetRegSaveArea(uint8_t* area) { *reinterpret_cast<uint8_t**>(&code[0x18]) = area; }
|
||||
void SetLockVar(uint8_t* lock_var) { *reinterpret_cast<uint8_t**>(&code[0x0e]) = lock_var; }
|
||||
|
||||
static uint64_t GetSize() { return 0x1000; }
|
||||
|
||||
uint8_t code[0x6c] = {
|
||||
/*00*/ 0x51, // push rcx /* Save general purpose registers */
|
||||
/*01*/ 0x52, // push rdx
|
||||
/*02*/ 0x41, 0x50, // push r8
|
||||
/*04*/ 0x41, 0x51, // push r9
|
||||
/*06*/ 0x41, 0x52, // push r10
|
||||
/*08*/ 0x41, 0x53, // push r11
|
||||
/*0a*/ 0x57, // push rdi
|
||||
/*0b*/ 0x56, // push rsi
|
||||
/*0c*/ 0x48, 0xbf, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // movabs rdi,0x1122334455667788
|
||||
/*16*/ 0x48, 0xbe, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // movabs rsi,0x1122334455667788
|
||||
/*20*/ 0x48, 0xb9, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // movabs rcx,0x1122334455667788
|
||||
/*2a*/ 0xb0, 0x01, // mov al,0x1 /* Lock */
|
||||
/*2c*/ 0x86, 0x07, // xchg BYTE PTR [rdi],al
|
||||
/*2e*/ 0x84, 0xc0, // test al,al
|
||||
/*30*/ 0x75, 0xf8, // jne 2a <LOCK>
|
||||
/*32*/ 0xb8, 0xff, 0xff, 0xff, 0xff, // mov eax,0xffffffff
|
||||
/*37*/ 0xba, 0xff, 0xff, 0xff, 0xff, // mov edx,0xffffffff
|
||||
/*3c*/ 0x0f, 0xae, 0x26, // xsave [rsi] /* Save float registers */
|
||||
/*3f*/ 0x48, 0x83, 0xec, 0x08, // sub rsp,0x8 /* Align stack */
|
||||
/*43*/ 0xff, 0xd1, // call rcx
|
||||
/*45*/ 0x48, 0x83, 0xc4, 0x08, // add rsp,0x8
|
||||
/*49*/ 0x48, 0x89, 0xc1, // mov rcx,rax
|
||||
/*4c*/ 0xb8, 0xff, 0xff, 0xff, 0xff, // mov eax,0xffffffff
|
||||
/*51*/ 0xba, 0xff, 0xff, 0xff, 0xff, // mov edx,0xffffffff
|
||||
/*56*/ 0x0f, 0xae, 0x2e, // xrstor [rsi] /* Restore float registers */
|
||||
/*59*/ 0x48, 0x89, 0xc8, // mov rax,rcx
|
||||
/*5c*/ 0xc6, 0x07, 0x00, // mov BYTE PTR [rdi],0x0 /* Unlock */
|
||||
/*5f*/ 0x5e, // pop rsi /* Restore general purpose registers */
|
||||
/*60*/ 0x5f, // pop rdi
|
||||
/*61*/ 0x41, 0x5b, // pop r11
|
||||
/*63*/ 0x41, 0x5a, // pop r10
|
||||
/*65*/ 0x41, 0x59, // pop r9
|
||||
/*67*/ 0x41, 0x58, // pop r8
|
||||
/*69*/ 0x5a, // pop rdx
|
||||
/*6a*/ 0x59, // pop rcx
|
||||
/*6b*/ 0xc3, // ret
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
} // namespace Kyty::Loader::Jit
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_JIT_H_ */
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_KERNEL_EVENTFLAG_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_KERNEL_EVENTFLAG_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Kernel/Pthread.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::LibKernel::EventFlag {
|
||||
|
||||
class KernelEventFlagPrivate;
|
||||
|
||||
using KernelEventFlag = KernelEventFlagPrivate*;
|
||||
|
||||
int KYTY_SYSV_ABI KernelCreateEventFlag(KernelEventFlag* ef, const char* name, uint32_t attr, uint64_t init_pattern, const void* param);
|
||||
int KYTY_SYSV_ABI KernelDeleteEventFlag(KernelEventFlag ef);
|
||||
int KYTY_SYSV_ABI KernelWaitEventFlag(KernelEventFlag ef, uint64_t bit_pattern, uint32_t wait_mode, uint64_t* result_pat,
|
||||
KernelUseconds* timeout);
|
||||
int KYTY_SYSV_ABI KernelPollEventFlag(KernelEventFlag ef, uint64_t bit_pattern, uint32_t wait_mode, uint64_t* result_pat);
|
||||
int KYTY_SYSV_ABI KernelSetEventFlag(KernelEventFlag ef, uint64_t bit_pattern);
|
||||
int KYTY_SYSV_ABI KernelClearEventFlag(KernelEventFlag ef, uint64_t bit_pattern);
|
||||
int KYTY_SYSV_ABI KernelCancelEventFlag(KernelEventFlag ef, uint64_t set_pattern, int* num_wait_threads);
|
||||
|
||||
} // namespace Kyty::Libs::LibKernel::EventFlag
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_KERNEL_EVENTFLAG_H_ */
|
||||
@@ -0,0 +1,75 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_KERNEL_EVENTQUEUE_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_KERNEL_EVENTQUEUE_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Kernel/Pthread.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::LibKernel::EventQueue {
|
||||
|
||||
constexpr int16_t KERNEL_EVFILT_TIMER = -7;
|
||||
constexpr int16_t KERNEL_EVFILT_READ = -1;
|
||||
constexpr int16_t KERNEL_EVFILT_WRITE = -2;
|
||||
constexpr int16_t KERNEL_EVFILT_USER = -11;
|
||||
constexpr int16_t KERNEL_EVFILT_FILE = -4;
|
||||
constexpr int16_t KERNEL_EVFILT_GRAPHICS = -14;
|
||||
constexpr int16_t KERNEL_EVFILT_VIDEO_OUT = -13;
|
||||
constexpr int16_t KERNEL_EVFILT_HRTIMER = -15;
|
||||
|
||||
class KernelEqueuePrivate;
|
||||
struct KernelEqueueEvent;
|
||||
|
||||
using trigger_func_t = void (*)(KernelEqueueEvent* event, void* trigger_data);
|
||||
using reset_func_t = void (*)(KernelEqueueEvent* event);
|
||||
using delete_func_t = void (*)(KernelEqueueEvent* event);
|
||||
|
||||
struct KernelEvent
|
||||
{
|
||||
uintptr_t ident = 0;
|
||||
int16_t filter = 0;
|
||||
uint16_t flags = 0;
|
||||
uint32_t fflags = 0;
|
||||
intptr_t data = 0;
|
||||
void* udata = nullptr;
|
||||
};
|
||||
|
||||
struct KernelFilter
|
||||
{
|
||||
void* data = nullptr;
|
||||
trigger_func_t trigger_func = nullptr;
|
||||
reset_func_t reset_func = nullptr;
|
||||
delete_func_t delete_func = nullptr;
|
||||
};
|
||||
|
||||
struct KernelEqueueEvent
|
||||
{
|
||||
bool triggered = false;
|
||||
KernelEvent event;
|
||||
KernelFilter filter;
|
||||
};
|
||||
|
||||
using KernelEqueue = KernelEqueuePrivate*;
|
||||
|
||||
int KYTY_SYSV_ABI KernelAddEvent(KernelEqueue eq, const KernelEqueueEvent& event);
|
||||
int KYTY_SYSV_ABI KernelTriggerEvent(KernelEqueue eq, uintptr_t ident, int16_t filter, void* trigger_data);
|
||||
int KYTY_SYSV_ABI KernelDeleteEvent(KernelEqueue eq, uintptr_t ident, int16_t filter);
|
||||
|
||||
int KYTY_SYSV_ABI KernelCreateEqueue(KernelEqueue* eq, const char* name);
|
||||
int KYTY_SYSV_ABI KernelDeleteEqueue(KernelEqueue eq);
|
||||
int KYTY_SYSV_ABI KernelWaitEqueue(KernelEqueue eq, KernelEvent* ev, int num, int* out, const KernelUseconds* timo);
|
||||
|
||||
intptr_t KYTY_SYSV_ABI KernelGetEventData(const KernelEvent* ev);
|
||||
intptr_t KYTY_SYSV_ABI KernelGetEventFflags(const KernelEvent* ev);
|
||||
int KYTY_SYSV_ABI KernelGetEventFilter(const KernelEvent* ev);
|
||||
uintptr_t KYTY_SYSV_ABI KernelGetEventId(const KernelEvent* ev);
|
||||
void* KYTY_SYSV_ABI KernelGetEventUserData(const KernelEvent* ev);
|
||||
int KYTY_SYSV_ABI KernelGetEventError(const KernelEvent* ev);
|
||||
|
||||
} // namespace Kyty::Libs::LibKernel::EventQueue
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_KERNEL_EVENTQUEUE_H_ */
|
||||
@@ -0,0 +1,60 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_KERNEL_FILESYSTEM_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_KERNEL_FILESYSTEM_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/String.h"
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Kernel/Pthread.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::LibKernel::FileSystem {
|
||||
|
||||
struct FileStat
|
||||
{
|
||||
uint32_t st_dev;
|
||||
uint32_t st_ino;
|
||||
uint16_t st_mode;
|
||||
uint16_t st_nlink;
|
||||
uint32_t st_uid;
|
||||
uint32_t st_gid;
|
||||
uint32_t st_rdev;
|
||||
KernelTimespec st_atim;
|
||||
KernelTimespec st_mtim;
|
||||
KernelTimespec st_ctim;
|
||||
int64_t st_size;
|
||||
int64_t st_blocks;
|
||||
uint32_t st_blksize;
|
||||
uint32_t st_flags;
|
||||
uint32_t st_gen;
|
||||
int32_t st_lspare;
|
||||
KernelTimespec st_birthtim;
|
||||
unsigned int: (8 / 2) * (16 - static_cast<int>(sizeof(KernelTimespec)));
|
||||
unsigned int: (8 / 2) * (16 - static_cast<int>(sizeof(KernelTimespec)));
|
||||
};
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(FileSystem);
|
||||
|
||||
void Mount(const String& folder, const String& point);
|
||||
void Umount(const String& folder_or_point);
|
||||
String GetRealFilename(const String& mounted_file_name);
|
||||
|
||||
int KYTY_SYSV_ABI KernelOpen(const char* path, int flags, uint16_t mode);
|
||||
int KYTY_SYSV_ABI KernelClose(int d);
|
||||
int64_t KYTY_SYSV_ABI KernelRead(int d, void* buf, size_t nbytes);
|
||||
int64_t KYTY_SYSV_ABI KernelPread(int d, void* buf, size_t nbytes, int64_t offset);
|
||||
int64_t KYTY_SYSV_ABI KernelWrite(int d, const void* buf, size_t nbytes);
|
||||
int64_t KYTY_SYSV_ABI KernelPwrite(int d, const void* buf, size_t nbytes, int64_t offset);
|
||||
int64_t KYTY_SYSV_ABI KernelLseek(int d, int64_t offset, int whence);
|
||||
int KYTY_SYSV_ABI KernelStat(const char* path, FileStat* sb);
|
||||
int KYTY_SYSV_ABI KernelFstat(int d, FileStat* sb);
|
||||
int KYTY_SYSV_ABI KernelUnlink(const char* path);
|
||||
int KYTY_SYSV_ABI KernelGetdirentries(int fd, char* buf, int nbytes, int64_t* basep);
|
||||
|
||||
} // namespace Kyty::Libs::LibKernel::FileSystem
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_KERNEL_FILESYSTEM_H_ */
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_KERNEL_MEMORY_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_KERNEL_MEMORY_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::LibKernel::Memory {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Memory);
|
||||
|
||||
int KYTY_SYSV_ABI KernelMapNamedFlexibleMemory(void** addr_in_out, size_t len, int prot, int flags, const char* name);
|
||||
int KYTY_SYSV_ABI KernelMunmap(uint64_t vaddr, size_t len);
|
||||
size_t KYTY_SYSV_ABI KernelGetDirectMemorySize();
|
||||
int KYTY_SYSV_ABI KernelAllocateDirectMemory(int64_t search_start, int64_t search_end, size_t len, size_t alignment, int memory_type,
|
||||
int64_t* phys_addr_out);
|
||||
int KYTY_SYSV_ABI KernelReleaseDirectMemory(int64_t start, size_t len);
|
||||
int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int flags, int64_t direct_memory_start, size_t alignment);
|
||||
int KYTY_SYSV_ABI KernelQueryMemoryProtection(void* addr, void** start, void** end, int* prot);
|
||||
|
||||
} // namespace Kyty::Libs::LibKernel::Memory
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_KERNEL_MEMORY_H_ */
|
||||
@@ -0,0 +1,159 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_KERNEL_PTHREAD_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_KERNEL_PTHREAD_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
// IWYU pragma: no_include <pthread.h>
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
extern "C" {
|
||||
struct sched_param;
|
||||
}
|
||||
|
||||
namespace Kyty::Loader {
|
||||
struct Program;
|
||||
} // namespace Kyty::Loader
|
||||
|
||||
namespace Kyty::Libs::LibKernel {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Pthread);
|
||||
|
||||
struct PthreadAttrPrivate;
|
||||
struct PthreadPrivate;
|
||||
struct PthreadMutexPrivate;
|
||||
struct PthreadMutexattrPrivate;
|
||||
struct PthreadRwlockPrivate;
|
||||
struct PthreadRwlockattrPrivate;
|
||||
struct PthreadCondattrPrivate;
|
||||
struct PthreadCondPrivate;
|
||||
|
||||
struct KernelTimespec
|
||||
{
|
||||
int64_t tv_sec;
|
||||
int64_t tv_nsec;
|
||||
};
|
||||
|
||||
struct KernelTimeval
|
||||
{
|
||||
int64_t tv_sec;
|
||||
int64_t tv_usec;
|
||||
};
|
||||
|
||||
using PthreadAttr = PthreadAttrPrivate*;
|
||||
using Pthread = PthreadPrivate*;
|
||||
using KernelCpumask = uint64_t;
|
||||
using PthreadMutex = PthreadMutexPrivate*;
|
||||
using PthreadMutexattr = PthreadMutexattrPrivate*;
|
||||
using KernelSchedParam = struct sched_param;
|
||||
using PthreadRwlock = PthreadRwlockPrivate*;
|
||||
using PthreadRwlockattr = PthreadRwlockattrPrivate*;
|
||||
using KernelUseconds = unsigned int;
|
||||
using PthreadCondattr = PthreadCondattrPrivate*;
|
||||
using PthreadCond = PthreadCondPrivate*;
|
||||
using KernelClockid = int32_t;
|
||||
|
||||
using pthread_entry_func_t = KYTY_SYSV_ABI void* (*)(void*);
|
||||
using thread_dtors_func_t = KYTY_SYSV_ABI void (*)();
|
||||
|
||||
void PthreadInitSelfForMainThread();
|
||||
void PthreadDeleteStaticObjects(Loader::Program* program);
|
||||
|
||||
int KYTY_SYSV_ABI PthreadMutexattrInit(PthreadMutexattr* attr);
|
||||
int KYTY_SYSV_ABI PthreadMutexattrDestroy(PthreadMutexattr* attr);
|
||||
int KYTY_SYSV_ABI PthreadMutexattrSettype(PthreadMutexattr* attr, int type);
|
||||
int KYTY_SYSV_ABI PthreadMutexattrSetprotocol(PthreadMutexattr* attr, int protocol);
|
||||
int KYTY_SYSV_ABI PthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name);
|
||||
int KYTY_SYSV_ABI PthreadMutexDestroy(PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI PthreadMutexLock(PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI PthreadMutexTrylock(PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI PthreadMutexUnlock(PthreadMutex* mutex);
|
||||
|
||||
Pthread KYTY_SYSV_ABI PthreadSelf();
|
||||
int KYTY_SYSV_ABI PthreadCreate(Pthread* thread, const PthreadAttr* attr, pthread_entry_func_t entry, void* arg, const char* name);
|
||||
int KYTY_SYSV_ABI PthreadDetach(Pthread thread);
|
||||
int KYTY_SYSV_ABI PthreadJoin(Pthread thread, void** value);
|
||||
int KYTY_SYSV_ABI PthreadCancel(Pthread thread);
|
||||
int KYTY_SYSV_ABI PthreadSetcancelstate(int state, int* old_state);
|
||||
int KYTY_SYSV_ABI PthreadSetcanceltype(int type, int* old_type);
|
||||
void KYTY_SYSV_ABI PthreadTestcancel();
|
||||
void KYTY_SYSV_ABI PthreadExit(void* value);
|
||||
int KYTY_SYSV_ABI PthreadEqual(Pthread thread1, Pthread thread2);
|
||||
int KYTY_SYSV_ABI PthreadGetname(Pthread thread, char* name);
|
||||
int KYTY_SYSV_ABI KernelUsleep(KernelUseconds microseconds);
|
||||
unsigned int KYTY_SYSV_ABI KernelSleep(unsigned int seconds);
|
||||
int KYTY_SYSV_ABI KernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rmtp);
|
||||
|
||||
void KYTY_SYSV_ABI KernelSetThreadDtors(thread_dtors_func_t dtors);
|
||||
|
||||
int KYTY_SYSV_ABI PthreadAttrInit(PthreadAttr* attr);
|
||||
int KYTY_SYSV_ABI PthreadAttrDestroy(PthreadAttr* attr);
|
||||
int KYTY_SYSV_ABI PthreadAttrGet(Pthread thread, PthreadAttr* attr);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetaffinity(const PthreadAttr* attr, KernelCpumask* mask);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetdetachstate(const PthreadAttr* attr, int* state);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetguardsize(const PthreadAttr* attr, size_t* guard_size);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetinheritsched(const PthreadAttr* attr, int* inherit_sched);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetschedparam(const PthreadAttr* attr, KernelSchedParam* param);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetschedpolicy(const PthreadAttr* attr, int* policy);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetstack(const PthreadAttr* __restrict attr, void** __restrict stack_addr, size_t* __restrict stack_size);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetstackaddr(const PthreadAttr* attr, void** stack_addr);
|
||||
int KYTY_SYSV_ABI PthreadAttrGetstacksize(const PthreadAttr* attr, size_t* stack_size);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetaffinity(PthreadAttr* attr, KernelCpumask mask);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetdetachstate(PthreadAttr* attr, int state);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetguardsize(PthreadAttr* attr, size_t guard_size);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetinheritsched(PthreadAttr* attr, int inherit_sched);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedParam* param);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetschedpolicy(PthreadAttr* attr, int policy);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetstack(PthreadAttr* attr, void* addr, size_t size);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetstackaddr(PthreadAttr* attr, void* addr);
|
||||
int KYTY_SYSV_ABI PthreadAttrSetstacksize(PthreadAttr* attr, size_t stack_size);
|
||||
|
||||
int KYTY_SYSV_ABI PthreadRwlockDestroy(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI PthreadRwlockInit(PthreadRwlock* rwlock, const PthreadRwlockattr* attr, const char* name);
|
||||
int KYTY_SYSV_ABI PthreadRwlockRdlock(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI PthreadRwlockTimedrdlock(PthreadRwlock* rwlock, KernelUseconds usec);
|
||||
int KYTY_SYSV_ABI PthreadRwlockTimedwrlock(PthreadRwlock* rwlock, KernelUseconds usec);
|
||||
int KYTY_SYSV_ABI PthreadRwlockTryrdlock(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI PthreadRwlockTrywrlock(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI PthreadRwlockUnlock(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI PthreadRwlockWrlock(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI PthreadRwlockattrDestroy(PthreadRwlockattr* attr);
|
||||
int KYTY_SYSV_ABI PthreadRwlockattrInit(PthreadRwlockattr* attr);
|
||||
int KYTY_SYSV_ABI PthreadRwlockattrGettype(PthreadRwlockattr* attr, int* type);
|
||||
int KYTY_SYSV_ABI PthreadRwlockattrSettype(PthreadRwlockattr* attr, int type);
|
||||
|
||||
int KYTY_SYSV_ABI PthreadCondattrDestroy(PthreadCondattr* attr);
|
||||
int KYTY_SYSV_ABI PthreadCondattrInit(PthreadCondattr* attr);
|
||||
int KYTY_SYSV_ABI PthreadCondBroadcast(PthreadCond* cond);
|
||||
int KYTY_SYSV_ABI PthreadCondDestroy(PthreadCond* cond);
|
||||
int KYTY_SYSV_ABI PthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name);
|
||||
int KYTY_SYSV_ABI PthreadCondSignal(PthreadCond* cond);
|
||||
int KYTY_SYSV_ABI PthreadCondSignalto(PthreadCond* cond, Pthread thread);
|
||||
int KYTY_SYSV_ABI PthreadCondTimedwait(PthreadCond* cond, PthreadMutex* mutex, KernelUseconds usec);
|
||||
int KYTY_SYSV_ABI PthreadCondWait(PthreadCond* cond, PthreadMutex* mutex);
|
||||
|
||||
int KYTY_SYSV_ABI KernelClockGetres(KernelClockid clock_id, KernelTimespec* tp);
|
||||
int KYTY_SYSV_ABI KernelClockGettime(KernelClockid clock_id, KernelTimespec* tp);
|
||||
int KYTY_SYSV_ABI KernelGettimeofday(KernelTimeval* tp);
|
||||
uint64_t KYTY_SYSV_ABI KernelGetTscFrequency();
|
||||
uint64_t KYTY_SYSV_ABI KernelReadTsc();
|
||||
uint64_t KYTY_SYSV_ABI KernelGetProcessTime();
|
||||
uint64_t KYTY_SYSV_ABI KernelGetProcessTimeCounter();
|
||||
uint64_t KYTY_SYSV_ABI KernelGetProcessTimeCounterFrequency();
|
||||
|
||||
int KYTY_SYSV_ABI pthread_cond_broadcast_s(PthreadCond* cond);
|
||||
int KYTY_SYSV_ABI pthread_cond_wait_s(PthreadCond* cond, PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI pthread_mutex_lock_s(PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI pthread_mutex_unlock_s(PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI pthread_rwlock_rdlock_s(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI pthread_rwlock_unlock_s(PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI pthread_rwlock_wrlock_s(PthreadRwlock* rwlock);
|
||||
|
||||
} // namespace Kyty::Libs::LibKernel
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_KERNEL_PTHREAD_H_ */
|
||||
@@ -0,0 +1,155 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_LIBS_ERRNO_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LIBS_ERRNO_H_
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
constexpr int OK = 0;
|
||||
|
||||
namespace Kyty::Libs::LibKernel {
|
||||
|
||||
constexpr int KERNEL_ERROR_UNKNOWN = -2147352576; /* 0x80020000 */
|
||||
constexpr int KERNEL_ERROR_EPERM = -2147352575; /* 0x80020001 */
|
||||
constexpr int KERNEL_ERROR_ENOENT = -2147352574; /* 0x80020002 */
|
||||
constexpr int KERNEL_ERROR_ESRCH = -2147352573; /* 0x80020003 */
|
||||
constexpr int KERNEL_ERROR_EINTR = -2147352572; /* 0x80020004 */
|
||||
constexpr int KERNEL_ERROR_EIO = -2147352571; /* 0x80020005 */
|
||||
constexpr int KERNEL_ERROR_ENXIO = -2147352570; /* 0x80020006 */
|
||||
constexpr int KERNEL_ERROR_E2BIG = -2147352569; /* 0x80020007 */
|
||||
constexpr int KERNEL_ERROR_ENOEXEC = -2147352568; /* 0x80020008 */
|
||||
constexpr int KERNEL_ERROR_EBADF = -2147352567; /* 0x80020009 */
|
||||
constexpr int KERNEL_ERROR_ECHILD = -2147352566; /* 0x8002000A */
|
||||
constexpr int KERNEL_ERROR_EDEADLK = -2147352565; /* 0x8002000B */
|
||||
constexpr int KERNEL_ERROR_ENOMEM = -2147352564; /* 0x8002000C */
|
||||
constexpr int KERNEL_ERROR_EACCES = -2147352563; /* 0x8002000D */
|
||||
constexpr int KERNEL_ERROR_EFAULT = -2147352562; /* 0x8002000E */
|
||||
constexpr int KERNEL_ERROR_ENOTBLK = -2147352561; /* 0x8002000F */
|
||||
constexpr int KERNEL_ERROR_EBUSY = -2147352560; /* 0x80020010 */
|
||||
constexpr int KERNEL_ERROR_EEXIST = -2147352559; /* 0x80020011 */
|
||||
constexpr int KERNEL_ERROR_EXDEV = -2147352558; /* 0x80020012 */
|
||||
constexpr int KERNEL_ERROR_ENODEV = -2147352557; /* 0x80020013 */
|
||||
constexpr int KERNEL_ERROR_ENOTDIR = -2147352556; /* 0x80020014 */
|
||||
constexpr int KERNEL_ERROR_EISDIR = -2147352555; /* 0x80020015 */
|
||||
constexpr int KERNEL_ERROR_EINVAL = -2147352554; /* 0x80020016 */
|
||||
constexpr int KERNEL_ERROR_ENFILE = -2147352553; /* 0x80020017 */
|
||||
constexpr int KERNEL_ERROR_EMFILE = -2147352552; /* 0x80020018 */
|
||||
constexpr int KERNEL_ERROR_ENOTTY = -2147352551; /* 0x80020019 */
|
||||
constexpr int KERNEL_ERROR_ETXTBSY = -2147352550; /* 0x8002001A */
|
||||
constexpr int KERNEL_ERROR_EFBIG = -2147352549; /* 0x8002001B */
|
||||
constexpr int KERNEL_ERROR_ENOSPC = -2147352548; /* 0x8002001C */
|
||||
constexpr int KERNEL_ERROR_ESPIPE = -2147352547; /* 0x8002001D */
|
||||
constexpr int KERNEL_ERROR_EROFS = -2147352546; /* 0x8002001E */
|
||||
constexpr int KERNEL_ERROR_EMLINK = -2147352545; /* 0x8002001F */
|
||||
constexpr int KERNEL_ERROR_EPIPE = -2147352544; /* 0x80020020 */
|
||||
constexpr int KERNEL_ERROR_EDOM = -2147352543; /* 0x80020021 */
|
||||
constexpr int KERNEL_ERROR_ERANGE = -2147352542; /* 0x80020022 */
|
||||
constexpr int KERNEL_ERROR_EAGAIN = -2147352541; /* 0x80020023 */
|
||||
constexpr int KERNEL_ERROR_EWOULDBLOCK = -2147352541; /* 0x80020023 */
|
||||
constexpr int KERNEL_ERROR_EINPROGRESS = -2147352540; /* 0x80020024 */
|
||||
constexpr int KERNEL_ERROR_EALREADY = -2147352539; /* 0x80020025 */
|
||||
constexpr int KERNEL_ERROR_ENOTSOCK = -2147352538; /* 0x80020026 */
|
||||
constexpr int KERNEL_ERROR_EDESTADDRREQ = -2147352537; /* 0x80020027 */
|
||||
constexpr int KERNEL_ERROR_EMSGSIZE = -2147352536; /* 0x80020028 */
|
||||
constexpr int KERNEL_ERROR_EPROTOTYPE = -2147352535; /* 0x80020029 */
|
||||
constexpr int KERNEL_ERROR_ENOPROTOOPT = -2147352534; /* 0x8002002A */
|
||||
constexpr int KERNEL_ERROR_EPROTONOSUPPORT = -2147352533; /* 0x8002002B */
|
||||
constexpr int KERNEL_ERROR_ESOCKTNOSUPPORT = -2147352532; /* 0x8002002C */
|
||||
constexpr int KERNEL_ERROR_EOPNOTSUPP = -2147352531; /* 0x8002002D */
|
||||
constexpr int KERNEL_ERROR_ENOTSUP = -2147352531; /* 0x8002002D */
|
||||
constexpr int KERNEL_ERROR_EPFNOSUPPORT = -2147352530; /* 0x8002002E */
|
||||
constexpr int KERNEL_ERROR_EAFNOSUPPORT = -2147352529; /* 0x8002002F */
|
||||
constexpr int KERNEL_ERROR_EADDRINUSE = -2147352528; /* 0x80020030 */
|
||||
constexpr int KERNEL_ERROR_EADDRNOTAVAIL = -2147352527; /* 0x80020031 */
|
||||
constexpr int KERNEL_ERROR_ENETDOWN = -2147352526; /* 0x80020032 */
|
||||
constexpr int KERNEL_ERROR_ENETUNREACH = -2147352525; /* 0x80020033 */
|
||||
constexpr int KERNEL_ERROR_ENETRESET = -2147352524; /* 0x80020034 */
|
||||
constexpr int KERNEL_ERROR_ECONNABORTED = -2147352523; /* 0x80020035 */
|
||||
constexpr int KERNEL_ERROR_ECONNRESET = -2147352522; /* 0x80020036 */
|
||||
constexpr int KERNEL_ERROR_ENOBUFS = -2147352521; /* 0x80020037 */
|
||||
constexpr int KERNEL_ERROR_EISCONN = -2147352520; /* 0x80020038 */
|
||||
constexpr int KERNEL_ERROR_ENOTCONN = -2147352519; /* 0x80020039 */
|
||||
constexpr int KERNEL_ERROR_ESHUTDOWN = -2147352518; /* 0x8002003A */
|
||||
constexpr int KERNEL_ERROR_ETOOMANYREFS = -2147352517; /* 0x8002003B */
|
||||
constexpr int KERNEL_ERROR_ETIMEDOUT = -2147352516; /* 0x8002003C */
|
||||
constexpr int KERNEL_ERROR_ECONNREFUSED = -2147352515; /* 0x8002003D */
|
||||
constexpr int KERNEL_ERROR_ELOOP = -2147352514; /* 0x8002003E */
|
||||
constexpr int KERNEL_ERROR_ENAMETOOLONG = -2147352513; /* 0x8002003F */
|
||||
constexpr int KERNEL_ERROR_EHOSTDOWN = -2147352512; /* 0x80020040 */
|
||||
constexpr int KERNEL_ERROR_EHOSTUNREACH = -2147352511; /* 0x80020041 */
|
||||
constexpr int KERNEL_ERROR_ENOTEMPTY = -2147352510; /* 0x80020042 */
|
||||
constexpr int KERNEL_ERROR_EPROCLIM = -2147352509; /* 0x80020043 */
|
||||
constexpr int KERNEL_ERROR_EUSERS = -2147352508; /* 0x80020044 */
|
||||
constexpr int KERNEL_ERROR_EDQUOT = -2147352507; /* 0x80020045 */
|
||||
constexpr int KERNEL_ERROR_ESTALE = -2147352506; /* 0x80020046 */
|
||||
constexpr int KERNEL_ERROR_EREMOTE = -2147352505; /* 0x80020047 */
|
||||
constexpr int KERNEL_ERROR_EBADRPC = -2147352504; /* 0x80020048 */
|
||||
constexpr int KERNEL_ERROR_ERPCMISMATCH = -2147352503; /* 0x80020049 */
|
||||
constexpr int KERNEL_ERROR_EPROGUNAVAIL = -2147352502; /* 0x8002004A */
|
||||
constexpr int KERNEL_ERROR_EPROGMISMATCH = -2147352501; /* 0x8002004B */
|
||||
constexpr int KERNEL_ERROR_EPROCUNAVAIL = -2147352500; /* 0x8002004C */
|
||||
constexpr int KERNEL_ERROR_ENOLCK = -2147352499; /* 0x8002004D */
|
||||
constexpr int KERNEL_ERROR_ENOSYS = -2147352498; /* 0x8002004E */
|
||||
constexpr int KERNEL_ERROR_EFTYPE = -2147352497; /* 0x8002004F */
|
||||
constexpr int KERNEL_ERROR_EAUTH = -2147352496; /* 0x80020050 */
|
||||
constexpr int KERNEL_ERROR_ENEEDAUTH = -2147352495; /* 0x80020051 */
|
||||
constexpr int KERNEL_ERROR_EIDRM = -2147352494; /* 0x80020052 */
|
||||
constexpr int KERNEL_ERROR_ENOMSG = -2147352493; /* 0x80020053 */
|
||||
constexpr int KERNEL_ERROR_EOVERFLOW = -2147352492; /* 0x80020054 */
|
||||
constexpr int KERNEL_ERROR_ECANCELED = -2147352491; /* 0x80020055 */
|
||||
constexpr int KERNEL_ERROR_EILSEQ = -2147352490; /* 0x80020056 */
|
||||
constexpr int KERNEL_ERROR_ENOATTR = -2147352489; /* 0x80020057 */
|
||||
constexpr int KERNEL_ERROR_EDOOFUS = -2147352488; /* 0x80020058 */
|
||||
constexpr int KERNEL_ERROR_EBADMSG = -2147352487; /* 0x80020059 */
|
||||
constexpr int KERNEL_ERROR_EMULTIHOP = -2147352486; /* 0x8002005A */
|
||||
constexpr int KERNEL_ERROR_ENOLINK = -2147352485; /* 0x8002005B */
|
||||
constexpr int KERNEL_ERROR_EPROTO = -2147352484; /* 0x8002005C */
|
||||
constexpr int KERNEL_ERROR_ENOTCAPABLE = -2147352483; /* 0x8002005D */
|
||||
constexpr int KERNEL_ERROR_ECAPMODE = -2147352482; /* 0x8002005E */
|
||||
constexpr int KERNEL_ERROR_ENOBLK = -2147352481; /* 0x8002005F */
|
||||
constexpr int KERNEL_ERROR_EICV = -2147352480; /* 0x80020060 */
|
||||
constexpr int KERNEL_ERROR_ENOPLAYGOENT = -2147352479; /* 0x80020061 */
|
||||
constexpr int KERNEL_ERROR_EREVOKE = -2147352478; /* 0x80020062 */
|
||||
constexpr int KERNEL_ERROR_ESDKVERSION = -2147352477; /* 0x80020063 */
|
||||
constexpr int KERNEL_ERROR_ESTART = -2147352476; /* 0x80020064 */
|
||||
constexpr int KERNEL_ERROR_ESTOP = -2147352475; /* 0x80020065 */
|
||||
|
||||
} // namespace Kyty::Libs::LibKernel
|
||||
|
||||
namespace Kyty::Libs::VideoOut {
|
||||
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_VALUE = -2144796671; /* 0x80290001 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_ADDRESS = -2144796670; /* 0x80290002 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_PIXEL_FORMAT = -2144796669; /* 0x80290003 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_PITCH = -2144796668; /* 0x80290004 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_RESOLUTION = -2144796667; /* 0x80290005 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_FLIP_MODE = -2144796666; /* 0x80290006 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_TILING_MODE = -2144796665; /* 0x80290007 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_ASPECT_RATIO = -2144796664; /* 0x80290008 */
|
||||
constexpr int VIDEO_OUT_ERROR_RESOURCE_BUSY = -2144796663; /* 0x80290009 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_INDEX = -2144796662; /* 0x8029000A */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_HANDLE = -2144796661; /* 0x8029000B */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE = -2144796660; /* 0x8029000C */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_EVENT = -2144796659; /* 0x8029000D */
|
||||
constexpr int VIDEO_OUT_ERROR_NO_EMPTY_SLOT = -2144796657; /* 0x8029000F */
|
||||
constexpr int VIDEO_OUT_ERROR_SLOT_OCCUPIED = -2144796656; /* 0x80290010 */
|
||||
constexpr int VIDEO_OUT_ERROR_FLIP_QUEUE_FULL = -2144796654; /* 0x80290012 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_MEMORY = -2144796653; /* 0x80290013 */
|
||||
constexpr int VIDEO_OUT_ERROR_MEMORY_NOT_PHYSICALLY_CONTIGUOUS = -2144796652; /* 0x80290014 */
|
||||
constexpr int VIDEO_OUT_ERROR_MEMORY_INVALID_ALIGNMENT = -2144796651; /* 0x80290015 */
|
||||
constexpr int VIDEO_OUT_ERROR_UNSUPPORTED_OUTPUT_MODE = -2144796650; /* 0x80290016 */
|
||||
constexpr int VIDEO_OUT_ERROR_OVERFLOW = -2144796649; /* 0x80290017 */
|
||||
constexpr int VIDEO_OUT_ERROR_NO_DEVICE = -2144796648; /* 0x80290018 */
|
||||
constexpr int VIDEO_OUT_ERROR_UNAVAILABLE_OUTPUT_MODE = -2144796647; /* 0x80290019 */
|
||||
constexpr int VIDEO_OUT_ERROR_INVALID_OPTION = -2144796646; /* 0x8029001A */
|
||||
constexpr int VIDEO_OUT_ERROR_PORT_UNSUPPORTED_FUNCTION = -2144796645; /* 0x8029001B */
|
||||
constexpr int VIDEO_OUT_ERROR_UNSUPPORTED_OPERATION = -2144796644; /* 0x8029001C */
|
||||
constexpr int VIDEO_OUT_ERROR_FATAL = -2144796417; /* 0x802900FF */
|
||||
constexpr int VIDEO_OUT_ERROR_UNKNOWN = -2144796418; /* 0x802900FE */
|
||||
constexpr int VIDEO_OUT_ERROR_ENOMEM = -2144792564; /* 0x8029100C */
|
||||
|
||||
} // namespace Kyty::Libs::VideoOut
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LIBS_ERRNO_H_ */
|
||||
@@ -0,0 +1,87 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_LIBS_LIBS_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LIBS_LIBS_H_
|
||||
|
||||
#include "Kyty/Core/String.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Timer.h" // IWYU pragma: keep
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define PRINT_NAME_ENABLED g_print_name
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define PRINT_NAME_ENABLE(flag) PRINT_NAME_ENABLED = flag;
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_DEFINE(name) void name(Loader::SymbolDatabase* s)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_NAME(l, m) \
|
||||
static thread_local bool PRINT_NAME_ENABLED = true; \
|
||||
static constexpr char g_library[] = l; \
|
||||
static constexpr char g_module[] = m;
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_VERSION(l, lv, m, mv1, mv2) \
|
||||
LIB_NAME(l, m); \
|
||||
static constexpr int g_library_version = lv; \
|
||||
static constexpr int g_module_version_major = mv1; \
|
||||
static constexpr int g_module_version_minor = mv2;
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_USING(n) \
|
||||
using n::g_library; \
|
||||
using n::g_library_version; \
|
||||
using n::g_module; \
|
||||
using n::g_module_version_major; \
|
||||
using n::g_module_version_minor;
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_CHECK(ids, name) \
|
||||
if (id == (ids)) \
|
||||
{ \
|
||||
name(s); \
|
||||
return true; \
|
||||
}
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_ADD(n, f, t) \
|
||||
{ \
|
||||
Loader::SymbolResolve sr {}; \
|
||||
sr.name = n; \
|
||||
sr.library = g_library; \
|
||||
sr.library_version = g_library_version; \
|
||||
sr.module = g_module; \
|
||||
sr.module_version_major = g_module_version_major; \
|
||||
sr.module_version_minor = g_module_version_minor; \
|
||||
sr.type = t; \
|
||||
auto func = reinterpret_cast<uint64_t>(f); \
|
||||
const char32_t* dbg_name = U"" #f; \
|
||||
s->Add(sr, func, dbg_name); \
|
||||
}
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_OBJECT(n, f) LIB_ADD(n, f, Loader::SymbolType::Object)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define LIB_FUNC(n, f) LIB_ADD(n, f, Loader::SymbolType::Func)
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define PRINT_NAME() \
|
||||
if (PRINT_NAME_ENABLED) \
|
||||
{ \
|
||||
Kyty::printf(FG_CYAN "[%d][%s] %s::%s::%s()" DEFAULT "\n", Core::Thread::GetThreadIdUnique(), \
|
||||
Loader::Timer::GetTime().ToString("HH24:MI:SS.FFF").C_Str(), g_library, g_module, __func__); \
|
||||
}
|
||||
|
||||
namespace Kyty {
|
||||
|
||||
namespace Loader {
|
||||
class SymbolDatabase;
|
||||
} // namespace Loader
|
||||
|
||||
namespace Libs {
|
||||
|
||||
bool Init(const String& id, Loader::SymbolDatabase* s);
|
||||
|
||||
} // namespace Libs
|
||||
} // namespace Kyty
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LIBS_LIBS_H_ */
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_LIBS_PRINTF_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LIBS_PRINTF_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs {
|
||||
|
||||
struct VaContext;
|
||||
struct VaList;
|
||||
|
||||
using libc_print_func_t = KYTY_FORMAT_PRINTF(1, 2) KYTY_SYSV_ABI int (*)(const char* str, ...);
|
||||
using libc_print_v_func_t = int (*)(VaContext* c);
|
||||
using libc_vprint_func_t = int (*)(const char* str, VaList* c);
|
||||
|
||||
libc_print_func_t GetPrintFunc();
|
||||
libc_print_v_func_t GetPrintFuncV();
|
||||
libc_vprint_func_t GetVPrintFunc();
|
||||
|
||||
} // namespace Kyty::Libs
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LIBS_PRINTF_H_ */
|
||||
@@ -0,0 +1,241 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_LIBS_VACONTEXT_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LIBS_VACONTEXT_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <xmmintrin.h>
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define VA_ARGS \
|
||||
uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, uint64_t overflow_arg_area, __m128 xmm0, \
|
||||
__m128 xmm1, __m128 xmm2, __m128 xmm3, __m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7, ...
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define VA_CONTEXT(ctx) \
|
||||
alignas(16) VaContext ctx; \
|
||||
(ctx).reg_save_area.gp[0] = rdi; \
|
||||
(ctx).reg_save_area.gp[1] = rsi; \
|
||||
(ctx).reg_save_area.gp[2] = rdx; \
|
||||
(ctx).reg_save_area.gp[3] = rcx; \
|
||||
(ctx).reg_save_area.gp[4] = r8; \
|
||||
(ctx).reg_save_area.gp[5] = r9; \
|
||||
(ctx).reg_save_area.fp[0] = xmm0; \
|
||||
(ctx).reg_save_area.fp[1] = xmm1; \
|
||||
(ctx).reg_save_area.fp[2] = xmm2; \
|
||||
(ctx).reg_save_area.fp[3] = xmm3; \
|
||||
(ctx).reg_save_area.fp[4] = xmm4; \
|
||||
(ctx).reg_save_area.fp[5] = xmm5; \
|
||||
(ctx).reg_save_area.fp[6] = xmm6; \
|
||||
(ctx).reg_save_area.fp[7] = xmm7; \
|
||||
(ctx).va_list.reg_save_area = &(ctx).reg_save_area; \
|
||||
(ctx).va_list.gp_offset = offsetof(VaRegSave, gp); \
|
||||
(ctx).va_list.fp_offset = offsetof(VaRegSave, fp); \
|
||||
(ctx).va_list.overflow_arg_area = &overflow_arg_area;
|
||||
|
||||
namespace Kyty::Libs {
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
struct VaList
|
||||
{
|
||||
uint32_t gp_offset;
|
||||
uint32_t fp_offset;
|
||||
void* overflow_arg_area;
|
||||
void* reg_save_area;
|
||||
};
|
||||
|
||||
// typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
|
||||
struct VaRegSave
|
||||
{
|
||||
uint64_t gp[6];
|
||||
__m128 fp[8];
|
||||
};
|
||||
|
||||
struct VaContext
|
||||
{
|
||||
VaRegSave reg_save_area;
|
||||
VaList va_list;
|
||||
};
|
||||
|
||||
struct VaCharX16
|
||||
{
|
||||
char x[16];
|
||||
};
|
||||
|
||||
struct VaShortX8
|
||||
{
|
||||
short x[8]; // NOLINT(google-runtime-int)
|
||||
};
|
||||
|
||||
struct VaIntX4
|
||||
{
|
||||
int x[4];
|
||||
};
|
||||
|
||||
struct VaFloatX4
|
||||
{
|
||||
float x[4];
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
template <class T, uint64_t Align, uint64_t Size>
|
||||
T VaArg_overflow_arg_area(VaList* l)
|
||||
{
|
||||
auto ptr = ((reinterpret_cast<uint64_t>(l->overflow_arg_area) + (Align - 1)) & ~(Align - 1));
|
||||
auto* addr = reinterpret_cast<T*>(ptr);
|
||||
l->overflow_arg_area = reinterpret_cast<void*>(ptr + Size);
|
||||
return *addr;
|
||||
}
|
||||
|
||||
template <class T, uint32_t Size>
|
||||
T VaArg_reg_save_area_gp(VaList* l)
|
||||
{
|
||||
auto* addr = reinterpret_cast<T*>(static_cast<uint8_t*>(l->reg_save_area) + l->gp_offset);
|
||||
l->gp_offset += Size;
|
||||
return *addr;
|
||||
}
|
||||
|
||||
template <class T, uint32_t Size>
|
||||
T VaArg_reg_save_area_fp(VaList* l)
|
||||
{
|
||||
auto* addr = reinterpret_cast<T*>(static_cast<uint8_t*>(l->reg_save_area) + l->fp_offset);
|
||||
l->fp_offset += Size;
|
||||
return *addr;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline VaFloatX4 VaArg_reg_save_area_fp<VaFloatX4, 32>(VaList* l)
|
||||
{
|
||||
auto* addr = reinterpret_cast<VaFloatX4*>(static_cast<uint8_t*>(l->reg_save_area) + l->fp_offset);
|
||||
l->fp_offset += 32;
|
||||
VaFloatX4 ret = {{addr[0].x[0], addr[0].x[1], addr[1].x[0], addr[1].x[1]}};
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int VaArg_int(VaList* l)
|
||||
{
|
||||
if (l->gp_offset <= 40)
|
||||
{
|
||||
return VaArg_reg_save_area_gp<int, 8>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<int, 1, 8>(l);
|
||||
}
|
||||
|
||||
inline double VaArg_double(VaList* l)
|
||||
{
|
||||
if (l->fp_offset <= 160)
|
||||
{
|
||||
return VaArg_reg_save_area_fp<double, 16>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<double, 1, 8>(l);
|
||||
}
|
||||
|
||||
inline long double VaArg_long_double(VaList* l)
|
||||
{
|
||||
return VaArg_overflow_arg_area<long double, 16, 16>(l);
|
||||
}
|
||||
|
||||
inline wint_t VaArg_wint_t(VaList* l)
|
||||
{
|
||||
if (l->gp_offset <= 40)
|
||||
{
|
||||
return VaArg_reg_save_area_gp<wint_t, 8>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<wint_t, 1, 8>(l);
|
||||
}
|
||||
|
||||
inline VaCharX16 VaArg_char_x16(VaList* l)
|
||||
{
|
||||
if (l->gp_offset <= 32)
|
||||
{
|
||||
return VaArg_reg_save_area_gp<VaCharX16, 16>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<VaCharX16, 1, 16>(l);
|
||||
}
|
||||
|
||||
inline long VaArg_long(VaList* l) // NOLINT(google-runtime-int)
|
||||
{
|
||||
if (l->gp_offset <= 40)
|
||||
{
|
||||
return VaArg_reg_save_area_gp<long, 8>(l); // NOLINT(google-runtime-int)
|
||||
}
|
||||
return VaArg_overflow_arg_area<long, 1, 8>(l); // NOLINT(google-runtime-int)
|
||||
}
|
||||
|
||||
inline intmax_t VaArg_intmax_t(VaList* l)
|
||||
{
|
||||
if (l->gp_offset <= 40)
|
||||
{
|
||||
return VaArg_reg_save_area_gp<intmax_t, 8>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<intmax_t, 1, 8>(l);
|
||||
}
|
||||
|
||||
inline long long VaArg_long_long(VaList* l) // NOLINT(google-runtime-int)
|
||||
{
|
||||
if (l->gp_offset <= 40)
|
||||
{
|
||||
return VaArg_reg_save_area_gp<long long, 8>(l); // NOLINT(google-runtime-int)
|
||||
}
|
||||
return VaArg_overflow_arg_area<long long, 1, 8>(l); // NOLINT(google-runtime-int)
|
||||
}
|
||||
|
||||
inline ptrdiff_t VaArg_ptrdiff_t(VaList* l)
|
||||
{
|
||||
if (l->gp_offset <= 40)
|
||||
{
|
||||
return VaArg_reg_save_area_gp<ptrdiff_t, 8>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<ptrdiff_t, 1, 8>(l);
|
||||
}
|
||||
|
||||
inline size_t VaArg_size_t(VaList* l)
|
||||
{
|
||||
if (l->gp_offset <= 40)
|
||||
{
|
||||
return VaArg_reg_save_area_gp<size_t, 8>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<size_t, 1, 8>(l);
|
||||
}
|
||||
|
||||
inline VaShortX8 VaArg_ShortX8(VaList* l)
|
||||
{
|
||||
if (l->gp_offset <= 32)
|
||||
{
|
||||
return VaArg_reg_save_area_gp<VaShortX8, 16>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<VaShortX8, 1, 16>(l);
|
||||
}
|
||||
|
||||
inline VaIntX4 VaArg_IntX4(VaList* l)
|
||||
{
|
||||
if (l->gp_offset <= 32)
|
||||
{
|
||||
return VaArg_reg_save_area_gp<VaIntX4, 16>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<VaIntX4, 1, 16>(l);
|
||||
}
|
||||
|
||||
inline VaFloatX4 VaArg_FloatX4(VaList* l)
|
||||
{
|
||||
if (l->fp_offset <= 144)
|
||||
{
|
||||
return VaArg_reg_save_area_fp<VaFloatX4, 32>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<VaFloatX4, 1, 16>(l);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* VaArg_ptr(VaList* l)
|
||||
{
|
||||
if (l->gp_offset <= 40)
|
||||
{
|
||||
return VaArg_reg_save_area_gp<T*, 8>(l);
|
||||
}
|
||||
return VaArg_overflow_arg_area<T*, 1, 8>(l);
|
||||
}
|
||||
|
||||
} // namespace Kyty::Libs
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LIBS_VACONTEXT_H_ */
|
||||
@@ -0,0 +1,83 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_LOG_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LOG_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/File.h"
|
||||
#include "Kyty/Core/String.h"
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
//#include "Emulator/Config.h"
|
||||
|
||||
//#define KYTY_LOG_ENABLED
|
||||
|
||||
#define CSI "\x1b[" // NOLINT
|
||||
#define DEFAULT CSI "0m" // NOLINT // Returns all attributes to the default state prior to modification
|
||||
#define BOLD CSI "1m" // NOLINT // Applies brightness/intensity flag to foreground color
|
||||
#define NO_BOLD CSI "22m" // NOLINT // Removes brightness/intensity flag from foreground color
|
||||
#define UNDERLINE CSI "4m" // NOLINT // Adds underline
|
||||
#define NO_UNDERLINE CSI "24m" // NOLINT // Removes underline
|
||||
#define NEGATIVE CSI "7m" // NOLINT // Swaps foreground and background colors
|
||||
#define POSITIVE CSI "27m" // NOLINT // Returns foreground/background to normal
|
||||
#define FG_BLACK CSI "30m" // NOLINT // Applies non-bold/bright black to foreground
|
||||
#define FG_RED CSI "31m" // NOLINT // Applies non-bold/bright red to foreground
|
||||
#define FG_GREEN CSI "32m" // NOLINT // Applies non-bold/bright green to foreground
|
||||
#define FG_YELLOW CSI "33m" // NOLINT // Applies non-bold/bright yellow to foreground
|
||||
#define FG_BLUE CSI "34m" // NOLINT // Applies non-bold/bright blue to foreground
|
||||
#define FG_MAGENTA CSI "35m" // NOLINT // Applies non-bold/bright magenta to foreground
|
||||
#define FG_CYAN CSI "36m" // NOLINT // Applies non-bold/bright cyan to foreground
|
||||
#define FG_WHITE CSI "37m" // NOLINT // Applies non-bold/bright white to foreground
|
||||
#define FG_EXTENDED CSI "38m" // NOLINT // Applies extended color value to the foreground (see details below)
|
||||
#define FG_DEFAULT CSI "39m" // NOLINT // Applies only the foreground portion of the defaults (see 0)
|
||||
#define BG_BLACK CSI "40m" // NOLINT // Applies non-bold/bright black to background
|
||||
#define BG_RED CSI "41m" // NOLINT // Applies non-bold/bright red to background
|
||||
#define BG_GREEN CSI "42m" // NOLINT // Applies non-bold/bright green to background
|
||||
#define BG_YELLOW CSI "43m" // NOLINT // Applies non-bold/bright yellow to background
|
||||
#define BG_BLUE CSI "44m" // NOLINT // Applies non-bold/bright blue to background
|
||||
#define BG_MAGENTA CSI "45m" // NOLINT // Applies non-bold/bright magenta to background
|
||||
#define BG_CYAN CSI "46m" // NOLINT // Applies non-bold/bright cyan to background
|
||||
#define BG_WHITE CSI "47m" // NOLINT // Applies non-bold/bright white to background
|
||||
#define BG_EXTENDED CSI "48m" // NOLINT // Applies extended color value to the background (see details below)
|
||||
#define BG_DEFAULT CSI "49m" // NOLINT // Applies only the background portion of the defaults (see 0)
|
||||
#define FG_BRIGHT_BLACK CSI "90m" // NOLINT // Applies bold/bright black to foreground
|
||||
#define FG_BRIGHT_RED CSI "91m" // NOLINT // Applies bold/bright red to foreground
|
||||
#define FG_BRIGHT_GREEN CSI "92m" // NOLINT // Applies bold/bright green to foreground
|
||||
#define FG_BRIGHT_YELLOW CSI "93m" // NOLINT // Applies bold/bright yellow to foreground
|
||||
#define FG_BRIGHT_BLUE CSI "94m" // NOLINT // Applies bold/bright blue to foreground
|
||||
#define FG_BRIGHT_MAGENTA CSI "95m" // NOLINT // Applies bold/bright magenta to foreground
|
||||
#define FG_BRIGHT_CYAN CSI "96m" // NOLINT // Applies bold/bright cyan to foreground
|
||||
#define FG_BRIGHT_WHITE CSI "97m" // NOLINT // Applies bold/bright white to foreground
|
||||
#define BG_BRIGHT_BLACK CSI "100m" // NOLINT // Applies bold/bright black to background
|
||||
#define BG_BRIGHT_RED CSI "101m" // NOLINT // Applies bold/bright red to background
|
||||
#define BG_BRIGHT_GREEN CSI "102m" // NOLINT // Applies bold/bright green to background
|
||||
#define BG_BRIGHT_YELLOW CSI "103m" // NOLINT // Applies bold/bright yellow to background
|
||||
#define BG_BRIGHT_BLUE CSI "104m" // NOLINT // Applies bold/bright blue to background
|
||||
#define BG_BRIGHT_MAGENTA CSI "105m" // NOLINT // Applies bold/bright magenta to background
|
||||
#define BG_BRIGHT_CYAN CSI "106m" // NOLINT // Applies bold/bright cyan to background
|
||||
#define BG_BRIGHT_WHITE CSI "107m" // NOLINT // Applies bold/bright white to background
|
||||
|
||||
namespace Kyty {
|
||||
|
||||
namespace Log {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Log);
|
||||
|
||||
enum class Direction
|
||||
{
|
||||
Silent,
|
||||
Console,
|
||||
File
|
||||
};
|
||||
|
||||
void SetDirection(Direction dir);
|
||||
void SetOutputFile(const String& file_name, Core::File::Encoding enc = Core::File::Encoding::Utf8);
|
||||
|
||||
bool IsColoredPrintf();
|
||||
String RemoveColors(const String& str);
|
||||
|
||||
} // namespace Log
|
||||
|
||||
void printf(const char* format, ...) KYTY_FORMAT_PRINTF(1, 2);
|
||||
|
||||
} // namespace Kyty
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LOG_H_ */
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_PROFILER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_PROFILER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
#define BUILD_WITH_EASY_PROFILER
|
||||
#define EASY_PROFILER_STATIC
|
||||
|
||||
#include <easy/profiler.h> // IWYU pragma: export
|
||||
|
||||
//
|
||||
#include "easy/details/profiler_aux.h" // IWYU pragma: export
|
||||
#include "easy/details/profiler_colors.h" // IWYU pragma: export
|
||||
|
||||
#include <cwchar> // IWYU pragma: export
|
||||
|
||||
// IWYU pragma: no_include "easy/profiler.h"
|
||||
|
||||
#if KYTY_COMPILER == KYTY_COMPILER_MSVC
|
||||
#define KYTY_PROFILER_BLOCK(f, ...) EASY_BLOCK(f, __VA_ARGS__);
|
||||
#else
|
||||
#define KYTY_PROFILER_BLOCK(f, s...) EASY_BLOCK(f, ##s);
|
||||
#endif
|
||||
|
||||
#if KYTY_COMPILER == KYTY_COMPILER_MSVC
|
||||
#define KYTY_PROFILER_FUNCTION(f, ...) EASY_FUNCTION(f, __VA_ARGS__);
|
||||
#else
|
||||
#define KYTY_PROFILER_FUNCTION(f, s...) EASY_FUNCTION(f, ##s);
|
||||
#endif
|
||||
|
||||
#define KYTY_PROFILER_END_BLOCK EASY_END_BLOCK
|
||||
|
||||
#define KYTY_PROFILER_THREAD(f) EASY_THREAD(f)
|
||||
|
||||
namespace Kyty::Profiler {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Profiler);
|
||||
|
||||
} // namespace Kyty::Profiler
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_PROFILER_H_ */
|
||||
@@ -0,0 +1,185 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_RUNTIMELINKER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_RUNTIMELINKER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/Hashmap.h"
|
||||
#include "Kyty/Core/String.h"
|
||||
#include "Kyty/Core/Threads.h"
|
||||
#include "Kyty/Core/Vector.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/SymbolDatabase.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Loader {
|
||||
|
||||
class Elf64;
|
||||
struct Elf64_Sym;
|
||||
struct Elf64_Rela;
|
||||
class RuntimeLinker;
|
||||
|
||||
namespace VirtualMemory {
|
||||
class ExceptionHandler;
|
||||
} // namespace VirtualMemory
|
||||
|
||||
using module_func_t = int (*)(size_t args, const void* argp);
|
||||
|
||||
struct ModuleId
|
||||
{
|
||||
bool operator==(const ModuleId& other) const
|
||||
{
|
||||
return version_major == other.version_major && version_minor == other.version_minor && name == other.name;
|
||||
}
|
||||
|
||||
String id;
|
||||
int version_major;
|
||||
int version_minor;
|
||||
String name;
|
||||
};
|
||||
|
||||
struct LibraryId
|
||||
{
|
||||
bool operator==(const LibraryId& other) const { return version == other.version && name == other.name; }
|
||||
|
||||
String id;
|
||||
int version;
|
||||
String name;
|
||||
};
|
||||
|
||||
struct ThreadLocalStorage
|
||||
{
|
||||
uint64_t image_vaddr = 0;
|
||||
uint64_t image_size = 0;
|
||||
uint64_t handler_vaddr = 0;
|
||||
|
||||
Core::Hashmap<int, uint8_t*> tlss;
|
||||
Core::Mutex mutex;
|
||||
};
|
||||
|
||||
struct DynamicInfo
|
||||
{
|
||||
void* hash_table = nullptr;
|
||||
uint64_t hash_table_size = 0;
|
||||
|
||||
char* str_table = nullptr;
|
||||
uint64_t str_table_size = 0;
|
||||
|
||||
Elf64_Sym* symbol_table = nullptr;
|
||||
uint64_t symbol_table_total_size = 0;
|
||||
uint64_t symbol_table_entry_size = 0;
|
||||
|
||||
uint64_t init_vaddr = 0;
|
||||
uint64_t fini_vaddr = 0;
|
||||
uint64_t init_array_vaddr = 0;
|
||||
uint64_t fini_array_vaddr = 0;
|
||||
uint64_t preinit_array_vaddr = 0;
|
||||
uint64_t init_array_size = 0;
|
||||
uint64_t fini_array_size = 0;
|
||||
uint64_t preinit_array_size = 0;
|
||||
uint64_t pltgot_vaddr = 0;
|
||||
|
||||
Elf64_Rela* jmprela_table = nullptr;
|
||||
uint64_t jmprela_table_size = 0;
|
||||
|
||||
Elf64_Rela* rela_table = nullptr;
|
||||
uint64_t rela_table_total_size = 0;
|
||||
uint64_t rela_table_entry_size = 0;
|
||||
|
||||
uint64_t relative_count = 0;
|
||||
|
||||
uint64_t debug = 0;
|
||||
uint64_t textrel = 0;
|
||||
uint64_t flags = 0;
|
||||
|
||||
const char* so_name = nullptr;
|
||||
|
||||
Vector<const char*> needed;
|
||||
Vector<ModuleId> export_modules;
|
||||
Vector<ModuleId> import_modules;
|
||||
Vector<LibraryId> export_libs;
|
||||
Vector<LibraryId> import_libs;
|
||||
};
|
||||
|
||||
struct Program
|
||||
{
|
||||
int32_t unique_id = -1;
|
||||
RuntimeLinker* rt = nullptr;
|
||||
String file_name;
|
||||
Elf64* elf = nullptr;
|
||||
VirtualMemory::ExceptionHandler* exception_handler = nullptr;
|
||||
DynamicInfo* dynamic_info = nullptr;
|
||||
uint64_t base_vaddr = 0;
|
||||
uint64_t base_size = 0;
|
||||
uint64_t base_size_aligned = 0;
|
||||
SymbolDatabase* export_symbols = nullptr;
|
||||
SymbolDatabase* import_symbols = nullptr;
|
||||
ThreadLocalStorage tls;
|
||||
bool fail_if_global_not_resolved = true;
|
||||
bool dbg_print_reloc = false;
|
||||
uint64_t proc_param_vaddr = 0;
|
||||
uint64_t custom_call_plt_vaddr = 0;
|
||||
uint32_t custom_call_plt_num = 0;
|
||||
};
|
||||
|
||||
class RuntimeLinker
|
||||
{
|
||||
public:
|
||||
RuntimeLinker();
|
||||
virtual ~RuntimeLinker();
|
||||
void Clear();
|
||||
|
||||
KYTY_CLASS_NO_COPY(RuntimeLinker);
|
||||
|
||||
void DbgDump(const String& folder);
|
||||
|
||||
Program* LoadProgram(const String& elf_name);
|
||||
void UnloadProgram(Program* program);
|
||||
|
||||
[[nodiscard]] uint64_t GetEntry();
|
||||
[[nodiscard]] uint64_t GetProcParam();
|
||||
|
||||
void RelocateAll();
|
||||
|
||||
void Execute();
|
||||
int StartModule(Program* program, size_t args, const void* argp, module_func_t func);
|
||||
int StopModule(Program* program, size_t args, const void* argp, module_func_t func);
|
||||
void StartAllModules();
|
||||
void StopAllModules();
|
||||
void DeleteTlss(int thread_id);
|
||||
|
||||
void Resolve(const String& name, SymbolType type, Program* program, SymbolRecord* out_info, bool* bind_self);
|
||||
|
||||
SymbolDatabase* Symbols() { return m_symbols; }
|
||||
|
||||
static uint64_t ReadFromElf(Program* program, uint64_t vaddr);
|
||||
Program* FindProgramByAddr(uint64_t vaddr);
|
||||
Program* FindProgramById(int32_t id);
|
||||
|
||||
static uint8_t* TlsGetAddr(Program* program);
|
||||
static void DeleteTls(Program* program, int thread_id);
|
||||
|
||||
private:
|
||||
static void LoadProgramToMemory(Program* program);
|
||||
static void ParseProgramDynamicInfo(Program* program);
|
||||
static void CreateSymbolDatabase(Program* program);
|
||||
static void Relocate(Program* program);
|
||||
static void DeleteProgram(Program* program);
|
||||
static void SetupTlsHandler(Program* program);
|
||||
|
||||
Program* FindProgram(const ModuleId& m, const LibraryId& l);
|
||||
|
||||
static const ModuleId* FindModule(const Program& program, const String& id);
|
||||
static const LibraryId* FindLibrary(const Program& program, const String& id);
|
||||
|
||||
Vector<Program*> m_programs;
|
||||
SymbolDatabase* m_symbols = nullptr;
|
||||
bool m_relocated = false;
|
||||
Core::Mutex m_mutex;
|
||||
};
|
||||
|
||||
} // namespace Kyty::Loader
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_RUNTIMELINKER_H_ */
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_SYMBOLDATABASE_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_SYMBOLDATABASE_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/Hashmap.h"
|
||||
#include "Kyty/Core/String.h"
|
||||
#include "Kyty/Core/Vector.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Loader {
|
||||
|
||||
enum class SymbolType
|
||||
{
|
||||
Unknown,
|
||||
Func,
|
||||
Object,
|
||||
TlsModule
|
||||
};
|
||||
|
||||
struct SymbolRecord
|
||||
{
|
||||
String name;
|
||||
String dbg_name;
|
||||
uint64_t vaddr;
|
||||
};
|
||||
|
||||
struct SymbolResolve
|
||||
{
|
||||
String name;
|
||||
String library;
|
||||
int library_version;
|
||||
String module;
|
||||
int module_version_major;
|
||||
int module_version_minor;
|
||||
SymbolType type;
|
||||
};
|
||||
|
||||
class SymbolDatabase
|
||||
{
|
||||
public:
|
||||
SymbolDatabase() = default;
|
||||
virtual ~SymbolDatabase() = default;
|
||||
|
||||
void Add(const SymbolResolve& s, uint64_t vaddr);
|
||||
void Add(const SymbolResolve& s, uint64_t vaddr, const String& dbg_name);
|
||||
|
||||
[[nodiscard]] const SymbolRecord* Find(const SymbolResolve& s) const;
|
||||
|
||||
void DbgDump(const String& folder, const String& file_name);
|
||||
|
||||
KYTY_CLASS_NO_COPY(SymbolDatabase);
|
||||
|
||||
static String GenerateName(const SymbolResolve& s);
|
||||
|
||||
private:
|
||||
Vector<SymbolRecord> m_symbols;
|
||||
Core::Hashmap<String, uint32_t> m_map;
|
||||
};
|
||||
|
||||
} // namespace Kyty::Loader
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_SYMBOLDATABASE_H_ */
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_TIMER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_TIMER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/DateTime.h"
|
||||
#include "Kyty/Core/Subsystems.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Loader::Timer {
|
||||
|
||||
KYTY_SUBSYSTEM_DEFINE(Timer);
|
||||
|
||||
void Start();
|
||||
double GetTimeMs();
|
||||
Core::Time GetTime();
|
||||
uint64_t GetCounter();
|
||||
uint64_t GetFrequency();
|
||||
|
||||
} // namespace Kyty::Loader::Timer
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_TIMER_H_ */
|
||||
@@ -0,0 +1,107 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_VIRTUALMEMORY_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_VIRTUALMEMORY_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Loader {
|
||||
|
||||
enum class ProcessorArchitecture
|
||||
{
|
||||
Unknown,
|
||||
Amd64, // x64 (AMD or Intel)
|
||||
};
|
||||
|
||||
struct SystemInfo
|
||||
{
|
||||
uint32_t PageSize;
|
||||
uint64_t MinimumApplicationAddress;
|
||||
uint64_t MaximumApplicationAddress;
|
||||
uint32_t ActiveProcessorMask;
|
||||
uint32_t NumberOfProcessors;
|
||||
ProcessorArchitecture ProcessorArchitecture;
|
||||
uint32_t AllocationGranularity;
|
||||
uint16_t ProcessorLevel;
|
||||
uint16_t ProcessorRevision;
|
||||
};
|
||||
|
||||
SystemInfo GetSystemInfo();
|
||||
|
||||
namespace VirtualMemory {
|
||||
|
||||
class ExceptionHandlerPrivate;
|
||||
|
||||
class ExceptionHandler
|
||||
{
|
||||
public:
|
||||
enum class ExceptionType
|
||||
{
|
||||
Unknown,
|
||||
AccessViolation
|
||||
};
|
||||
|
||||
enum class AccessViolationType
|
||||
{
|
||||
Unknown,
|
||||
Read,
|
||||
Write,
|
||||
Execute
|
||||
};
|
||||
|
||||
struct ExceptionInfo
|
||||
{
|
||||
ExceptionType type = ExceptionType::Unknown;
|
||||
AccessViolationType access_violation_type = AccessViolationType::Unknown;
|
||||
uint64_t access_violation_vaddr = 0;
|
||||
};
|
||||
|
||||
using handler_func_t = void (*)(const ExceptionInfo*);
|
||||
|
||||
ExceptionHandler();
|
||||
virtual ~ExceptionHandler();
|
||||
|
||||
KYTY_CLASS_NO_COPY(ExceptionHandler);
|
||||
|
||||
static uint64_t GetSize();
|
||||
|
||||
bool Install(uint64_t base_address, uint64_t handler_addr, uint64_t image_size, handler_func_t func);
|
||||
bool Uninstall();
|
||||
|
||||
private:
|
||||
ExceptionHandlerPrivate* m_p = nullptr;
|
||||
};
|
||||
|
||||
enum class Mode : uint32_t
|
||||
{
|
||||
NoAccess = 0,
|
||||
Read = 1,
|
||||
Write = 2,
|
||||
ReadWrite = Read | Write,
|
||||
Execute = 4,
|
||||
ExecuteRead = Execute | Read,
|
||||
ExecuteWrite = Execute | Write,
|
||||
ExecuteReadWrite = Execute | Read | Write,
|
||||
};
|
||||
|
||||
inline bool IsExecute(Mode mode)
|
||||
{
|
||||
return (mode == Mode::Execute || mode == Mode::ExecuteRead || mode == Mode::ExecuteWrite || mode == Mode::ExecuteReadWrite);
|
||||
}
|
||||
|
||||
uint64_t Alloc(uint64_t address, uint64_t size, Mode mode);
|
||||
uint64_t AllocAligned(uint64_t address, uint64_t size, Mode mode, uint64_t alignment);
|
||||
bool Free(uint64_t address);
|
||||
bool Protect(uint64_t address, uint64_t size, Mode mode, Mode* old_mode = nullptr);
|
||||
bool FlushInstructionCache(uint64_t address, uint64_t size);
|
||||
bool PatchReplace(uint64_t vaddr, uint64_t value);
|
||||
|
||||
} // namespace VirtualMemory
|
||||
|
||||
} // namespace Kyty::Loader
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_VIRTUALMEMORY_H_ */
|
||||
Reference in New Issue
Block a user