Linux support. (#3)

* Compiling and running on Linux.

* Fix xpointer constructor.

* Convert dependencies to submodules.

* Fix wchar_t usage for Linux.
This commit is contained in:
Skyth (Asilkan) 2024-12-21 00:49:06 +03:00 committed by GitHub
parent 45c00cfec6
commit 4650dc69fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 295 additions and 201 deletions

9
.gitmodules vendored Normal file
View File

@ -0,0 +1,9 @@
[submodule "thirdparty/xxHash"]
path = thirdparty/xxHash
url = https://github.com/Cyan4973/xxHash.git
[submodule "thirdparty/fmt"]
path = thirdparty/fmt
url = https://github.com/fmtlib/fmt.git
[submodule "thirdparty/tomlplusplus"]
path = thirdparty/tomlplusplus
url = https://github.com/marzer/tomlplusplus.git

View File

@ -1,6 +1,5 @@
cmake_minimum_required (VERSION 3.20) cmake_minimum_required (VERSION 3.20)
include($ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
set(THIRDPARTY_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty) set(THIRDPARTY_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
@ -16,10 +15,10 @@ set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
include("cmake/bin2h.cmake") include("cmake/bin2h.cmake")
add_subdirectory(${THIRDPARTY_ROOT}/disasm) add_subdirectory(${THIRDPARTY_ROOT})
set(POWERANALYSE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/PowerAnalyse) set(POWERANALYSE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/PowerAnalyse)
set(POWERRECOMP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/PowerRecomp)
set(POWERUTILS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/PowerUtils) set(POWERUTILS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/PowerUtils)
set(POWERRECOMP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/PowerRecomp)
project ("PowerRecomp-ALL") project ("PowerRecomp-ALL")

View File

@ -2,12 +2,13 @@
project("PowerAnalyse") project("PowerAnalyse")
add_executable(PowerAnalyse "main.cpp" "function.h" "function.cpp") add_executable(PowerAnalyse
add_library(LibPowerAnalyse "function.h" "function.cpp") "main.cpp"
"function.cpp")
find_package(fmt CONFIG REQUIRED)
target_include_directories(LibPowerAnalyse PUBLIC .)
target_link_libraries(LibPowerAnalyse PUBLIC PowerUtils)
target_link_libraries(PowerAnalyse PRIVATE PowerUtils fmt::fmt) target_link_libraries(PowerAnalyse PRIVATE PowerUtils fmt::fmt)
add_library(LibPowerAnalyse "function.cpp")
target_include_directories(LibPowerAnalyse PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(LibPowerAnalyse PUBLIC PowerUtils)

View File

@ -1,4 +1,6 @@
#pragma once #pragma once
#include <cstddef>
#include <vector> #include <vector>
#ifdef _DEBUG #ifdef _DEBUG

View File

@ -364,7 +364,7 @@ int main()
if (f.base == 0x82BD7420) if (f.base == 0x82BD7420)
{ {
__debugbreak(); __builtin_debugtrap();
} }
image.symbols.emplace(fmt::format("sub_{:X}", f.base), f.base, f.size, Symbol_Function); image.symbols.emplace(fmt::format("sub_{:X}", f.base), f.base, f.size, Symbol_Function);

View File

@ -2,20 +2,29 @@ cmake_minimum_required (VERSION 3.8)
project("PowerRecomp") project("PowerRecomp")
BIN2H(SOURCE_FILE ${POWERUTILS_ROOT}/ppc_context.h HEADER_FILE "generated/ppc_context.gen.h" ARRAY_TYPE "char" VARIABLE_NAME "g_PPCContextText") BIN2H(SOURCE_FILE
${POWERUTILS_ROOT}/ppc_context.h
HEADER_FILE "generated/ppc_context.gen.h"
ARRAY_TYPE "char"
VARIABLE_NAME "g_PPCContextText")
add_executable(PowerRecomp
"main.cpp"
"recompiler.cpp"
"test_recompiler.cpp"
"recompiler_config.cpp")
add_executable(PowerRecomp "main.cpp" "pch.h" "recompiler.cpp" "recompiler.h" "test_recompiler.cpp" "test_recompiler.h" "recompiler_config.h" "recompiler_config.cpp")
target_precompile_headers(PowerRecomp PUBLIC "pch.h") target_precompile_headers(PowerRecomp PUBLIC "pch.h")
find_package(fmt CONFIG REQUIRED) target_link_libraries(PowerRecomp PRIVATE
find_package(PkgConfig REQUIRED) LibPowerAnalyse
pkg_check_modules(tomlplusplus REQUIRED IMPORTED_TARGET tomlplusplus) PowerUtils
find_package(xxHash CONFIG REQUIRED) fmt::fmt
tomlplusplus::tomlplusplus
target_link_libraries(PowerRecomp PRIVATE LibPowerAnalyse fmt::fmt PkgConfig::tomlplusplus xxHash::xxhash) xxHash::xxhash)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(PowerRecomp PRIVATE -Wno-switch -Wno-unused-variable) target_compile_options(PowerRecomp PRIVATE -Wno-switch -Wno-unused-variable -Wno-null-arithmetic)
endif() endif()
target_compile_definitions(PowerRecomp PRIVATE _CRT_SECURE_NO_WARNINGS) target_compile_definitions(PowerRecomp PRIVATE _CRT_SECURE_NO_WARNINGS)

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <algorithm>
#include <cassert> #include <cassert>
#include <cstddef>
#include <charconv> #include <charconv>
#include <disasm.h> #include <disasm.h>
#include <file.h> #include <file.h>
@ -14,4 +16,5 @@
#include <xbox.h> #include <xbox.h>
#include <xxhash.h> #include <xxhash.h>
#include <fmt/core.h> #include <fmt/core.h>
#include <xmmintrin.h>
#include "generated/ppc_context.gen.h" #include "generated/ppc_context.gen.h"

View File

@ -607,7 +607,7 @@ bool Recompiler::Recompile(
break; break;
case PPC_INST_BLRL: case PPC_INST_BLRL:
println("__debugbreak();"); println("__builtin_debugtrap();");
break; break;
case PPC_INST_BLT: case PPC_INST_BLT:
@ -688,7 +688,7 @@ bool Recompiler::Recompile(
break; break;
case PPC_INST_CNTLZW: case PPC_INST_CNTLZW:
println("\t{}.u64 = __lzcnt({}.u32);", r(insn.operands[0]), r(insn.operands[1])); println("\t{}.u64 = __lzcnt32({}.u32);", r(insn.operands[0]), r(insn.operands[1]));
break; break;
case PPC_INST_DB16CYC: case PPC_INST_DB16CYC:
@ -1263,43 +1263,43 @@ bool Recompiler::Recompile(
break; break;
case PPC_INST_RLDICL: case PPC_INST_RLDICL:
println("\t{}.u64 = _rotl64({}.u64, {}) & 0x{:X};", r(insn.operands[0]), r(insn.operands[1]), insn.operands[2], ComputeMask(insn.operands[3], 63)); println("\t{}.u64 = __builtin_rotateleft64({}.u64, {}) & 0x{:X};", r(insn.operands[0]), r(insn.operands[1]), insn.operands[2], ComputeMask(insn.operands[3], 63));
break; break;
case PPC_INST_RLDICR: case PPC_INST_RLDICR:
println("\t{}.u64 = _rotl64({}.u64, {}) & 0x{:X};", r(insn.operands[0]), r(insn.operands[1]), insn.operands[2], ComputeMask(0, insn.operands[3])); println("\t{}.u64 = __builtin_rotateleft64({}.u64, {}) & 0x{:X};", r(insn.operands[0]), r(insn.operands[1]), insn.operands[2], ComputeMask(0, insn.operands[3]));
break; break;
case PPC_INST_RLDIMI: case PPC_INST_RLDIMI:
{ {
const uint64_t mask = ComputeMask(insn.operands[3], ~insn.operands[2]); const uint64_t mask = ComputeMask(insn.operands[3], ~insn.operands[2]);
println("\t{}.u64 = (_rotl64({}.u64, {}) & 0x{:X}) | ({}.u64 & 0x{:X});", r(insn.operands[0]), r(insn.operands[1]), insn.operands[2], mask, r(insn.operands[0]), ~mask); println("\t{}.u64 = (__builtin_rotateleft64({}.u64, {}) & 0x{:X}) | ({}.u64 & 0x{:X});", r(insn.operands[0]), r(insn.operands[1]), insn.operands[2], mask, r(insn.operands[0]), ~mask);
break; break;
} }
case PPC_INST_RLWIMI: case PPC_INST_RLWIMI:
{ {
const uint64_t mask = ComputeMask(insn.operands[3] + 32, insn.operands[4] + 32); const uint64_t mask = ComputeMask(insn.operands[3] + 32, insn.operands[4] + 32);
println("\t{}.u64 = (_rotl({}.u32, {}) & 0x{:X}) | ({}.u64 & 0x{:X});", r(insn.operands[0]), r(insn.operands[1]), insn.operands[2], mask, r(insn.operands[0]), ~mask); println("\t{}.u64 = (__builtin_rotateleft32({}.u32, {}) & 0x{:X}) | ({}.u64 & 0x{:X});", r(insn.operands[0]), r(insn.operands[1]), insn.operands[2], mask, r(insn.operands[0]), ~mask);
break; break;
} }
case PPC_INST_RLWINM: case PPC_INST_RLWINM:
println("\t{}.u64 = _rotl64({}.u32 | ({}.u64 << 32), {}) & 0x{:X};", r(insn.operands[0]), r(insn.operands[1]), r(insn.operands[1]), insn.operands[2], ComputeMask(insn.operands[3] + 32, insn.operands[4] + 32)); println("\t{}.u64 = __builtin_rotateleft64({}.u32 | ({}.u64 << 32), {}) & 0x{:X};", r(insn.operands[0]), r(insn.operands[1]), r(insn.operands[1]), insn.operands[2], ComputeMask(insn.operands[3] + 32, insn.operands[4] + 32));
if (strchr(insn.opcode->name, '.')) if (strchr(insn.opcode->name, '.'))
println("\t{}.compare<int32_t>({}.s32, 0, {});", cr(0), r(insn.operands[0]), xer()); println("\t{}.compare<int32_t>({}.s32, 0, {});", cr(0), r(insn.operands[0]), xer());
break; break;
case PPC_INST_ROTLDI: case PPC_INST_ROTLDI:
println("\t{}.u64 = _rotl64({}.u64, {});", r(insn.operands[0]), r(insn.operands[1]), insn.operands[2]); println("\t{}.u64 = __builtin_rotateleft64({}.u64, {});", r(insn.operands[0]), r(insn.operands[1]), insn.operands[2]);
break; break;
case PPC_INST_ROTLW: case PPC_INST_ROTLW:
println("\t{}.u64 = _rotl({}.u32, {}.u8 & 0x1F);", r(insn.operands[0]), r(insn.operands[1]), r(insn.operands[2])); println("\t{}.u64 = __builtin_rotateleft32({}.u32, {}.u8 & 0x1F);", r(insn.operands[0]), r(insn.operands[1]), r(insn.operands[2]));
break; break;
case PPC_INST_ROTLWI: case PPC_INST_ROTLWI:
println("\t{}.u64 = _rotl({}.u32, {});", r(insn.operands[0]), r(insn.operands[1]), insn.operands[2]); println("\t{}.u64 = __builtin_rotateleft32({}.u32, {});", r(insn.operands[0]), r(insn.operands[1]), insn.operands[2]);
if (strchr(insn.opcode->name, '.')) if (strchr(insn.opcode->name, '.'))
println("\t{}.compare<int32_t>({}.s32, 0, {});", cr(0), r(insn.operands[0]), xer()); println("\t{}.compare<int32_t>({}.s32, 0, {});", cr(0), r(insn.operands[0]), xer());
break; break;
@ -1398,10 +1398,10 @@ bool Recompiler::Recompile(
case PPC_INST_STDCX: case PPC_INST_STDCX:
println("\t{}.lt = 0;", cr(0)); println("\t{}.lt = 0;", cr(0));
println("\t{}.gt = 0;", cr(0)); println("\t{}.gt = 0;", cr(0));
print("\t{}.eq = _InterlockedCompareExchange64(reinterpret_cast<__int64*>(base + ", cr(0)); print("\t{}.eq = __sync_bool_compare_and_swap(reinterpret_cast<uint64_t*>(base + ", cr(0));
if (insn.operands[1] != 0) if (insn.operands[1] != 0)
print("{}.u32 + ", r(insn.operands[1])); print("{}.u32 + ", r(insn.operands[1]));
println("{}.u32), __builtin_bswap64({}.s64), {}.s64) == {}.s64;", r(insn.operands[2]), r(insn.operands[0]), reserved(), reserved()); println("{}.u32), {}.s64, __builtin_bswap64({}.s64));", r(insn.operands[2]), reserved(), r(insn.operands[0]));
println("\t{}.so = {}.so;", cr(0), xer()); println("\t{}.so = {}.so;", cr(0), xer());
break; break;
@ -1553,10 +1553,10 @@ bool Recompiler::Recompile(
case PPC_INST_STWCX: case PPC_INST_STWCX:
println("\t{}.lt = 0;", cr(0)); println("\t{}.lt = 0;", cr(0));
println("\t{}.gt = 0;", cr(0)); println("\t{}.gt = 0;", cr(0));
print("\t{}.eq = _InterlockedCompareExchange(reinterpret_cast<long*>(base + ", cr(0)); print("\t{}.eq = __sync_bool_compare_and_swap(reinterpret_cast<uint32_t*>(base + ", cr(0));
if (insn.operands[1] != 0) if (insn.operands[1] != 0)
print("{}.u32 + ", r(insn.operands[1])); print("{}.u32 + ", r(insn.operands[1]));
println("{}.u32), __builtin_bswap32({}.s32), {}.s32) == {}.s32;", r(insn.operands[2]), r(insn.operands[0]), reserved(), reserved()); println("{}.u32), {}.s32, __builtin_bswap32({}.s32));", r(insn.operands[2]), reserved(), r(insn.operands[0]));
println("\t{}.so = {}.so;", cr(0), xer()); println("\t{}.so = {}.so;", cr(0), xer());
break; break;
@ -1726,7 +1726,7 @@ bool Recompiler::Recompile(
case PPC_INST_VCMPBFP: case PPC_INST_VCMPBFP:
case PPC_INST_VCMPBFP128: case PPC_INST_VCMPBFP128:
println("\t__debugbreak();"); println("\t__builtin_debugtrap();");
break; break;
case PPC_INST_VCMPEQFP: case PPC_INST_VCMPEQFP:
@ -1910,7 +1910,7 @@ bool Recompiler::Recompile(
break; break;
default: default:
println("\t__debugbreak();"); println("\t__builtin_debugtrap();");
break; break;
} }
break; break;
@ -2086,7 +2086,7 @@ bool Recompiler::Recompile(
break; break;
default: default:
println("\t__debugbreak();"); println("\t__builtin_debugtrap();");
break; break;
} }
break; break;

View File

@ -2,6 +2,7 @@
#include "elf.h" #include "elf.h"
#include "xex.h" #include "xex.h"
#include <cassert> #include <cassert>
#include <cstring>
void Image::Map(const std::string_view& name, size_t base, uint32_t size, uint8_t flags, uint8_t* data) void Image::Map(const std::string_view& name, size_t base, uint32_t size, uint8_t flags, uint8_t* data)
{ {

View File

@ -5,15 +5,22 @@
#error "ppc_config.h must be included before ppc_context.h" #error "ppc_config.h must be included before ppc_context.h"
#endif #endif
#include <climits>
#include <cmath> #include <cmath>
#include <csetjmp> #include <csetjmp>
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <intrin.h>
#include <x86intrin.h> #include <x86intrin.h>
#ifdef _WIN32
#include <intrin.h>
#else
#include <xmmintrin.h>
#include <smmintrin.h>
#endif
#define PPC_JOIN(x, y) x##y #define PPC_JOIN(x, y) x##y
#define PPC_XSTRINGIFY(x) #x #define PPC_XSTRINGIFY(x) #x
#define PPC_STRINGIFY(x) PPC_XSTRINGIFY(x) #define PPC_STRINGIFY(x) PPC_XSTRINGIFY(x)

View File

@ -7,45 +7,6 @@
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#else
#define near
#define far
typedef char CHAR;
typedef wchar_t WCHAR;
typedef unsigned long DWORD;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef float FLOAT;
typedef FLOAT* PFLOAT;
typedef BOOL near* PBOOL;
typedef BOOL far* LPBOOL;
typedef BYTE near* PBYTE;
typedef BYTE far* LPBYTE;
typedef int near* PINT;
typedef int far* LPINT;
typedef WORD near* PWORD;
typedef WORD far* LPWORD;
typedef long far* LPLONG;
typedef DWORD near* PDWORD;
typedef DWORD far* LPDWORD;
typedef void far* LPVOID;
typedef const void far* LPCVOID;
typedef unsigned long ULONG;
typedef ULONG* PULONG;
typedef signed long LONG;
typedef LONG* PLONG;
typedef unsigned long long ULONGLONG;
typedef ULONGLONG* PULONGLONG;
typedef unsigned short USHORT;
typedef USHORT* PUSHORT;
typedef unsigned char UCHAR;
typedef UCHAR* PUCHAR;
typedef char* PSZ;
typedef int INT;
typedef unsigned int UINT;
typedef unsigned int* PUINT;
#endif #endif
// real win32 handles will never use the upper bits unless something goes really wrong // real win32 handles will never use the upper bits unless something goes really wrong
@ -144,7 +105,7 @@ struct xpointer
{ {
} }
xpointer(T* ptr) : ptr((uint32_t)ptr) xpointer(T* ptr) : ptr(reinterpret_cast<size_t>(ptr) - reinterpret_cast<size_t>(MmGetHostAddress(0)))
{ {
} }
@ -175,33 +136,23 @@ struct HostObject
typedef TGuest guest_type; typedef TGuest guest_type;
}; };
typedef BYTE XBYTE;
typedef be<uint16_t> XWORD;
typedef be<uint32_t> XDWORD;
typedef be<uint64_t> XQWORD;
typedef XBYTE* XLPBYTE;
typedef XWORD* XLPWORD;
typedef XDWORD* XLPDWORD;
typedef XQWORD* XLPQWORD;
struct _XLIST_ENTRY; struct _XLIST_ENTRY;
typedef _XLIST_ENTRY XLIST_ENTRY; typedef _XLIST_ENTRY XLIST_ENTRY;
typedef xpointer<XLIST_ENTRY> PXLIST_ENTRY; typedef xpointer<XLIST_ENTRY> PXLIST_ENTRY;
typedef struct _IMAGE_CE_RUNTIME_FUNCTION typedef struct _IMAGE_CE_RUNTIME_FUNCTION
{ {
DWORD BeginAddress; uint32_t BeginAddress;
union union
{ {
DWORD Data; uint32_t Data;
struct struct
{ {
DWORD PrologLength : 8; uint32_t PrologLength : 8;
DWORD FunctionLength : 22; uint32_t FunctionLength : 22;
DWORD ThirtyTwoBit : 1; uint32_t ThirtyTwoBit : 1;
DWORD ExceptionFlag : 1; uint32_t ExceptionFlag : 1;
}; };
}; };
} IMAGE_CE_RUNTIME_FUNCTION; } IMAGE_CE_RUNTIME_FUNCTION;
@ -210,8 +161,8 @@ static_assert(sizeof(IMAGE_CE_RUNTIME_FUNCTION) == 8);
typedef struct _XLIST_ENTRY typedef struct _XLIST_ENTRY
{ {
XDWORD Flink; be<uint32_t> Flink;
XDWORD Blink; be<uint32_t> Blink;
} XLIST_ENTRY; } XLIST_ENTRY;
typedef struct _XDISPATCHER_HEADER typedef struct _XDISPATCHER_HEADER
@ -220,30 +171,30 @@ typedef struct _XDISPATCHER_HEADER
{ {
struct struct
{ {
UCHAR Type; uint8_t Type;
union union
{ {
UCHAR Abandoned; uint8_t Abandoned;
UCHAR Absolute; uint8_t Absolute;
UCHAR NpxIrql; uint8_t NpxIrql;
UCHAR Signalling; uint8_t Signalling;
}; };
union union
{ {
UCHAR Size; uint8_t Size;
UCHAR Hand; uint8_t Hand;
}; };
union union
{ {
UCHAR Inserted; uint8_t Inserted;
UCHAR DebugActive; uint8_t DebugActive;
UCHAR DpcActive; uint8_t DpcActive;
}; };
}; };
XDWORD Lock; be<uint32_t> Lock;
}; };
XDWORD SignalState; be<uint32_t> SignalState;
XLIST_ENTRY WaitListHead; XLIST_ENTRY WaitListHead;
} XDISPATCHER_HEADER, * XPDISPATCHER_HEADER; } XDISPATCHER_HEADER, * XPDISPATCHER_HEADER;
@ -251,20 +202,20 @@ typedef struct _XDISPATCHER_HEADER
typedef struct _XRTL_CRITICAL_SECTION typedef struct _XRTL_CRITICAL_SECTION
{ {
XDISPATCHER_HEADER Header; XDISPATCHER_HEADER Header;
long LockCount; int32_t LockCount;
int32_t RecursionCount; int32_t RecursionCount;
uint32_t OwningThread; uint32_t OwningThread;
} XRTL_CRITICAL_SECTION; } XRTL_CRITICAL_SECTION;
typedef struct _XANSI_STRING { typedef struct _XANSI_STRING {
XWORD Length; be<uint16_t> Length;
XWORD MaximumLength; be<uint16_t> MaximumLength;
xpointer<char> Buffer; xpointer<char> Buffer;
} XANSI_STRING; } XANSI_STRING;
typedef struct _XOBJECT_ATTRIBUTES typedef struct _XOBJECT_ATTRIBUTES
{ {
XDWORD RootDirectory; be<uint32_t> RootDirectory;
xpointer<XANSI_STRING> Name; xpointer<XANSI_STRING> Name;
xpointer<void> Attributes; xpointer<void> Attributes;
} XOBJECT_ATTRIBUTES; } XOBJECT_ATTRIBUTES;
@ -274,18 +225,18 @@ typedef XDISPATCHER_HEADER XKEVENT;
typedef struct _XIO_STATUS_BLOCK typedef struct _XIO_STATUS_BLOCK
{ {
union { union {
XDWORD Status; be<uint32_t> Status;
XDWORD Pointer; be<uint32_t> Pointer;
}; };
be<uint32_t> Information; be<uint32_t> Information;
} XIO_STATUS_BLOCK; } XIO_STATUS_BLOCK;
typedef struct _XOVERLAPPED { typedef struct _XOVERLAPPED {
XDWORD Internal; be<uint32_t> Internal;
XDWORD InternalHigh; be<uint32_t> InternalHigh;
XDWORD Offset; be<uint32_t> Offset;
XDWORD OffsetHigh; be<uint32_t> OffsetHigh;
XDWORD hEvent; be<uint32_t> hEvent;
} XOVERLAPPED; } XOVERLAPPED;
// this name is so dumb // this name is so dumb
@ -294,8 +245,8 @@ typedef struct _XXOVERLAPPED {
{ {
struct struct
{ {
XDWORD Error; be<uint32_t> Error;
XDWORD Length; be<uint32_t> Length;
}; };
struct struct
@ -305,24 +256,24 @@ typedef struct _XXOVERLAPPED {
}; };
}; };
uint32_t InternalContext; uint32_t InternalContext;
XDWORD hEvent; be<uint32_t> hEvent;
XDWORD pCompletionRoutine; be<uint32_t> pCompletionRoutine;
XDWORD dwCompletionContext; be<uint32_t> dwCompletionContext;
XDWORD dwExtendedError; be<uint32_t> dwExtendedError;
} XXOVERLAPPED, *PXXOVERLAPPED; } XXOVERLAPPED, *PXXOVERLAPPED;
static_assert(sizeof(_XXOVERLAPPED) == 0x1C); static_assert(sizeof(_XXOVERLAPPED) == 0x1C);
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-memorystatus // https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-memorystatus
typedef struct _XMEMORYSTATUS { typedef struct _XMEMORYSTATUS {
XDWORD dwLength; be<uint32_t> dwLength;
XDWORD dwMemoryLoad; be<uint32_t> dwMemoryLoad;
XDWORD dwTotalPhys; be<uint32_t> dwTotalPhys;
XDWORD dwAvailPhys; be<uint32_t> dwAvailPhys;
XDWORD dwTotalPageFile; be<uint32_t> dwTotalPageFile;
XDWORD dwAvailPageFile; be<uint32_t> dwAvailPageFile;
XDWORD dwTotalVirtual; be<uint32_t> dwTotalVirtual;
XDWORD dwAvailVirtual; be<uint32_t> dwAvailVirtual;
} XMEMORYSTATUS, * XLPMEMORYSTATUS; } XMEMORYSTATUS, * XLPMEMORYSTATUS;
typedef struct _XVIDEO_MODE typedef struct _XVIDEO_MODE
@ -342,28 +293,28 @@ typedef struct _XVIDEO_MODE
typedef struct _XKSEMAPHORE typedef struct _XKSEMAPHORE
{ {
XDISPATCHER_HEADER Header; XDISPATCHER_HEADER Header;
XDWORD Limit; be<uint32_t> Limit;
} XKSEMAPHORE; } XKSEMAPHORE;
typedef struct _XUSER_SIGNIN_INFO { typedef struct _XUSER_SIGNIN_INFO {
be<ULONGLONG> xuid; be<uint64_t> xuid;
XDWORD dwField08; be<uint32_t> dwField08;
XDWORD SigninState; be<uint32_t> SigninState;
XDWORD dwField10; be<uint32_t> dwField10;
XDWORD dwField14; be<uint32_t> dwField14;
CHAR Name[16]; char Name[16];
} XUSER_SIGNIN_INFO; } XUSER_SIGNIN_INFO;
typedef struct _XTIME_FIELDS typedef struct _XTIME_FIELDS
{ {
XWORD Year; be<uint16_t> Year;
XWORD Month; be<uint16_t> Month;
XWORD Day; be<uint16_t> Day;
XWORD Hour; be<uint16_t> Hour;
XWORD Minute; be<uint16_t> Minute;
XWORD Second; be<uint16_t> Second;
XWORD Milliseconds; be<uint16_t> Milliseconds;
XWORD Weekday; be<uint16_t> Weekday;
} XTIME_FIELDS, * PXTIME_FIELDS; } XTIME_FIELDS, * PXTIME_FIELDS;
// Content types // Content types
@ -380,10 +331,10 @@ typedef struct _XTIME_FIELDS
typedef struct _XCONTENT_DATA typedef struct _XCONTENT_DATA
{ {
XDWORD DeviceID; be<uint32_t> DeviceID;
XDWORD dwContentType; be<uint32_t> dwContentType;
be<WCHAR> szDisplayName[XCONTENT_MAX_DISPLAYNAME]; be<uint16_t> szDisplayName[XCONTENT_MAX_DISPLAYNAME];
CHAR szFileName[XCONTENT_MAX_FILENAME]; char szFileName[XCONTENT_MAX_FILENAME];
} XCONTENT_DATA, * PXCONTENT_DATA; } XCONTENT_DATA, * PXCONTENT_DATA;
typedef struct _XHOSTCONTENT_DATA : _XCONTENT_DATA typedef struct _XHOSTCONTENT_DATA : _XCONTENT_DATA
@ -398,11 +349,11 @@ typedef struct _XHOSTCONTENT_DATA : _XCONTENT_DATA
typedef struct _XDEVICE_DATA typedef struct _XDEVICE_DATA
{ {
XDWORD DeviceID; be<uint32_t> DeviceID;
XDWORD DeviceType; be<uint32_t> DeviceType;
XQWORD ulDeviceBytes; be<uint64_t> ulDeviceBytes;
XQWORD ulDeviceFreeBytes; be<uint64_t> ulDeviceFreeBytes;
be<WCHAR> wszName[XCONTENTDEVICE_MAX_NAME]; be<uint16_t> wszName[XCONTENTDEVICE_MAX_NAME];
} XDEVICE_DATA, *PXDEVICE_DATA; } XDEVICE_DATA, *PXDEVICE_DATA;
// Direct reflection of XInput structures // Direct reflection of XInput structures
@ -427,32 +378,32 @@ typedef struct _XDEVICE_DATA
typedef struct _XAMINPUT_GAMEPAD typedef struct _XAMINPUT_GAMEPAD
{ {
WORD wButtons; uint16_t wButtons;
BYTE bLeftTrigger; uint8_t bLeftTrigger;
BYTE bRightTrigger; uint8_t bRightTrigger;
SHORT sThumbLX; int16_t sThumbLX;
SHORT sThumbLY; int16_t sThumbLY;
SHORT sThumbRX; int16_t sThumbRX;
SHORT sThumbRY; int16_t sThumbRY;
} XAMINPUT_GAMEPAD, *PXAMINPUT_GAMEPAD; } XAMINPUT_GAMEPAD, *PXAMINPUT_GAMEPAD;
typedef struct _XAMINPUT_VIBRATION typedef struct _XAMINPUT_VIBRATION
{ {
WORD wLeftMotorSpeed; uint16_t wLeftMotorSpeed;
WORD wRightMotorSpeed; uint16_t wRightMotorSpeed;
} XAMINPUT_VIBRATION, * PXAMINPUT_VIBRATION; } XAMINPUT_VIBRATION, * PXAMINPUT_VIBRATION;
typedef struct _XAMINPUT_CAPABILITIES typedef struct _XAMINPUT_CAPABILITIES
{ {
BYTE Type; uint8_t Type;
BYTE SubType; uint8_t SubType;
WORD Flags; uint16_t Flags;
XAMINPUT_GAMEPAD Gamepad; XAMINPUT_GAMEPAD Gamepad;
XAMINPUT_VIBRATION Vibration; XAMINPUT_VIBRATION Vibration;
} XAMINPUT_CAPABILITIES, * PXAMINPUT_CAPABILITIES; } XAMINPUT_CAPABILITIES, * PXAMINPUT_CAPABILITIES;
typedef struct _XAMINPUT_STATE typedef struct _XAMINPUT_STATE
{ {
DWORD dwPacketNumber; uint32_t dwPacketNumber;
XAMINPUT_GAMEPAD Gamepad; XAMINPUT_GAMEPAD Gamepad;
} XAMINPUT_STATE, * PXAMINPUT_STATE; } XAMINPUT_STATE, * PXAMINPUT_STATE;

View File

@ -1,12 +1,116 @@
#include "xex.h" #include "xex.h"
#include "image.h" #include "image.h"
#include <cassert> #include <cassert>
#include <cstring>
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
#define STRINGIFY(X) #X #define STRINGIFY(X) #X
#define XE_EXPORT(MODULE, ORDINAL, NAME, TYPE) { (ORDINAL), "__imp__" STRINGIFY(NAME) } #define XE_EXPORT(MODULE, ORDINAL, NAME, TYPE) { (ORDINAL), "__imp__" STRINGIFY(NAME) }
#ifndef _WIN32
typedef struct _IMAGE_DOS_HEADER {
uint16_t e_magic;
uint16_t e_cblp;
uint16_t e_cp;
uint16_t e_crlc;
uint16_t e_cparhdr;
uint16_t e_minalloc;
uint16_t e_maxalloc;
uint16_t e_ss;
uint16_t e_sp;
uint16_t e_csum;
uint16_t e_ip;
uint16_t e_cs;
uint16_t e_lfarlc;
uint16_t e_ovno;
uint16_t e_res[4];
uint16_t e_oemid;
uint16_t e_oeminfo;
uint16_t e_res2[10];
uint32_t e_lfanew;
} IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER;
typedef struct _IMAGE_FILE_HEADER {
uint16_t Machine;
uint16_t NumberOfSections;
uint32_t TimeDateStamp;
uint32_t PointerToSymbolTable;
uint32_t NumberOfSymbols;
uint16_t SizeOfOptionalHeader;
uint16_t Characteristics;
} IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER;
typedef struct _IMAGE_DATA_DIRECTORY {
uint32_t VirtualAddress;
uint32_t Size;
} IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY;
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
typedef struct _IMAGE_OPTIONAL_HEADER {
uint16_t Magic;
uint8_t MajorLinkerVersion;
uint8_t MinorLinkerVersion;
uint32_t SizeOfCode;
uint32_t SizeOfInitializedData;
uint32_t SizeOfUninitializedData;
uint32_t AddressOfEntryPoint;
uint32_t BaseOfCode;
uint32_t BaseOfData;
uint32_t ImageBase;
uint32_t SectionAlignment;
uint32_t FileAlignment;
uint16_t MajorOperatingSystemVersion;
uint16_t MinorOperatingSystemVersion;
uint16_t MajorImageVersion;
uint16_t MinorImageVersion;
uint16_t MajorSubsystemVersion;
uint16_t MinorSubsystemVersion;
uint32_t Win32VersionValue;
uint32_t SizeOfImage;
uint32_t SizeOfHeaders;
uint32_t CheckSum;
uint16_t Subsystem;
uint16_t DllCharacteristics;
uint32_t SizeOfStackReserve;
uint32_t SizeOfStackCommit;
uint32_t SizeOfHeapReserve;
uint32_t SizeOfHeapCommit;
uint32_t LoaderFlags;
uint32_t NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, * PIMAGE_OPTIONAL_HEADER32;
typedef struct _IMAGE_NT_HEADERS {
uint32_t Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, * PIMAGE_NT_HEADERS32;
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER {
uint8_t Name[IMAGE_SIZEOF_SHORT_NAME];
union {
uint32_t PhysicalAddress;
uint32_t VirtualSize;
} Misc;
uint32_t VirtualAddress;
uint32_t SizeOfRawData;
uint32_t PointerToRawData;
uint32_t PointerToRelocations;
uint32_t PointerToLinenumbers;
uint16_t NumberOfRelocations;
uint16_t NumberOfLinenumbers;
uint32_t Characteristics;
} IMAGE_SECTION_HEADER, * PIMAGE_SECTION_HEADER;
#define IMAGE_SCN_CNT_CODE 0x00000020
#endif
std::unordered_map<size_t, const char*> XamExports = std::unordered_map<size_t, const char*> XamExports =
{ {
#include "xbox/xam_table.inc" #include "xbox/xam_table.inc"

View File

@ -73,46 +73,46 @@ typedef struct _XEX_THUNK_DATA {
{ {
struct struct
{ {
WORD Ordinal : 16; uint16_t Ordinal : 16;
WORD Hint : 8; uint16_t Hint : 8;
WORD Type : 8; uint16_t Type : 8;
} OriginalData; } OriginalData;
XDWORD Ordinal; be<uint32_t> Ordinal;
XDWORD Function; be<uint32_t> Function;
XDWORD AddressOfData; be<uint32_t> AddressOfData;
// For easier swapping // For easier swapping
DWORD Data; uint32_t Data;
}; };
} XEX_THUNK_DATA; } XEX_THUNK_DATA;
typedef struct _XEX_IMPORT_HEADER { typedef struct _XEX_IMPORT_HEADER {
XDWORD SizeOfHeader; be<uint32_t> SizeOfHeader;
XDWORD SizeOfStringTable; be<uint32_t> SizeOfStringTable;
XDWORD NumImports; be<uint32_t> NumImports;
} XEX_IMPORT_HEADER; } XEX_IMPORT_HEADER;
typedef struct _XEX_IMPORT_LIBRARY { typedef struct _XEX_IMPORT_LIBRARY {
XDWORD Size; be<uint32_t> Size;
char NextImportDigest[0x14]; char NextImportDigest[0x14];
XDWORD ID; be<uint32_t> ID;
XDWORD Version; be<uint32_t> Version;
XDWORD MinVersion; be<uint32_t> MinVersion;
XWORD Name; be<uint16_t> Name;
XWORD NumberOfImports; be<uint16_t> NumberOfImports;
} XEX_IMPORT_LIBRARY; } XEX_IMPORT_LIBRARY;
static_assert(sizeof(XEX_IMPORT_LIBRARY) == 0x28); static_assert(sizeof(XEX_IMPORT_LIBRARY) == 0x28);
typedef struct _XEX_IMPORT_DESCRIPTOR { typedef struct _XEX_IMPORT_DESCRIPTOR {
XDWORD FirstThunk; // VA XEX_THUNK_DATA be<uint32_t> FirstThunk; // VA XEX_THUNK_DATA
} XEX_IMPORT_DESCRIPTOR; } XEX_IMPORT_DESCRIPTOR;
typedef struct _XEX_OPTIONAL_HEADER typedef struct _XEX_OPTIONAL_HEADER
{ {
XDWORD Type; be<uint32_t> Type;
XDWORD Address; be<uint32_t> Address;
} XEX_OPTIONAL_HEADER; } XEX_OPTIONAL_HEADER;
typedef struct _XEX2_SECURITY_INFO typedef struct _XEX2_SECURITY_INFO

13
thirdparty/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,13 @@
add_subdirectory(${THIRDPARTY_ROOT}/disasm)
if (NOT TARGET fmt::fmt)
add_subdirectory(${THIRDPARTY_ROOT}/fmt)
endif()
if (NOT TARGET tomlplusplus::tomlplusplus)
add_subdirectory(${THIRDPARTY_ROOT}/tomlplusplus)
endif()
if (NOT TARGET xxHash::xxhash)
add_subdirectory(${THIRDPARTY_ROOT}/xxHash/cmake_unofficial)
endif()

View File

@ -1,5 +1,9 @@
#include "dis-asm.h" #include "dis-asm.h"
#ifndef EIO
#define EIO 5
#endif
/* Get LENGTH bytes from info's buffer, at target address memaddr. /* Get LENGTH bytes from info's buffer, at target address memaddr.
Transfer them to myaddr. */ Transfer them to myaddr. */
int int

1
thirdparty/fmt vendored Submodule

@ -0,0 +1 @@
Subproject commit 873670ba3f9e7bc77ec2c1c94b04f1f8bef77e9f

1
thirdparty/tomlplusplus vendored Submodule

@ -0,0 +1 @@
Subproject commit c4369ae1d8955cae20c4ab40b9813ef4b60e48be

1
thirdparty/xxHash vendored Submodule

@ -0,0 +1 @@
Subproject commit 2bf8313b934633b2a5b7e8fd239645b85e10c852

View File

@ -1,12 +0,0 @@
{
"builtin-baseline": "e63bd09dc0b7204467705c1c7c71d0e2a3f8860b",
"dependencies": [
{
"name": "pkgconf",
"platform": "windows"
},
"fmt",
"tomlplusplus",
"xxhash"
]
}