2024-09-07 18:00:09 +06:00
|
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
|
|
#include <type_traits>
|
|
|
|
#include <bit>
|
2024-09-30 10:55:30 +06:00
|
|
|
#include <string>
|
2024-12-13 18:31:55 +03:00
|
|
|
#include "byteswap.h"
|
2024-09-07 18:00:09 +06:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
2024-09-07 18:21:08 +06:00
|
|
|
#include <windows.h>
|
2024-09-07 18:00:09 +06:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// real win32 handles will never use the upper bits unless something goes really wrong
|
|
|
|
#define CHECK_GUEST_HANDLE(HANDLE) (((HANDLE) & 0x80000000) == 0x80000000)
|
|
|
|
#define GUEST_HANDLE(HANDLE) ((HANDLE) | 0x80000000)
|
|
|
|
#define HOST_HANDLE(HANDLE) ((HANDLE) & ~0x80000000)
|
|
|
|
|
2024-09-30 10:55:30 +06:00
|
|
|
// Return true to free the associated memory
|
|
|
|
typedef bool(*TypeDestructor_t)(void*);
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
bool DestroyObject(void* obj)
|
|
|
|
{
|
|
|
|
static_cast<T*>(obj)->~T();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-09-07 18:00:09 +06:00
|
|
|
template<typename T>
|
|
|
|
struct be
|
|
|
|
{
|
|
|
|
T value;
|
|
|
|
|
|
|
|
be() : value(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
be(const T v)
|
|
|
|
{
|
|
|
|
set(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
static T byteswap(T value)
|
|
|
|
{
|
|
|
|
if constexpr (std::is_same_v<T, double>)
|
|
|
|
{
|
2024-12-13 18:31:55 +03:00
|
|
|
const uint64_t swapped = ByteSwap(*reinterpret_cast<uint64_t*>(&value));
|
2024-09-07 18:00:09 +06:00
|
|
|
return *reinterpret_cast<const T*>(&swapped);
|
|
|
|
}
|
|
|
|
else if constexpr (std::is_same_v<T, float>)
|
|
|
|
{
|
2024-12-13 18:31:55 +03:00
|
|
|
const uint32_t swapped = ByteSwap(*reinterpret_cast<uint32_t*>(&value));
|
2024-09-07 18:00:09 +06:00
|
|
|
return *reinterpret_cast<const T*>(&swapped);
|
|
|
|
}
|
2024-11-21 01:47:03 +00:00
|
|
|
else if constexpr (std::is_enum_v<T>)
|
|
|
|
{
|
2024-12-13 18:31:55 +03:00
|
|
|
const std::underlying_type_t<T> swapped = ByteSwap(*reinterpret_cast<std::underlying_type_t<T>*>(&value));
|
2024-11-21 01:47:03 +00:00
|
|
|
return *reinterpret_cast<const T*>(&swapped);
|
|
|
|
}
|
2024-09-07 18:00:09 +06:00
|
|
|
else
|
|
|
|
{
|
2024-12-13 18:31:55 +03:00
|
|
|
return ByteSwap(value);
|
2024-09-07 18:00:09 +06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void set(const T v)
|
|
|
|
{
|
|
|
|
value = byteswap(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
T get() const
|
|
|
|
{
|
|
|
|
return byteswap(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
be& operator| (T value)
|
|
|
|
{
|
|
|
|
set(get() | value);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
be& operator& (T value)
|
|
|
|
{
|
|
|
|
set(get() & value);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
operator T() const
|
|
|
|
{
|
|
|
|
return get();
|
|
|
|
}
|
|
|
|
|
|
|
|
be& operator=(T v)
|
|
|
|
{
|
|
|
|
set(v);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-09-30 10:55:30 +06:00
|
|
|
extern "C" void* MmGetHostAddress(uint32_t ptr);
|
2024-09-07 18:00:09 +06:00
|
|
|
template<typename T>
|
|
|
|
struct xpointer
|
|
|
|
{
|
|
|
|
be<uint32_t> ptr;
|
|
|
|
|
2024-11-24 09:25:22 +00:00
|
|
|
xpointer() : ptr(0)
|
2024-09-07 18:00:09 +06:00
|
|
|
{
|
2024-11-24 09:25:22 +00:00
|
|
|
}
|
2024-09-07 18:00:09 +06:00
|
|
|
|
2025-01-28 18:34:39 +03:00
|
|
|
xpointer(T* p) : ptr(p != nullptr ? (reinterpret_cast<size_t>(p) - reinterpret_cast<size_t>(MmGetHostAddress(0))) : 0)
|
2024-11-24 09:25:22 +00:00
|
|
|
{
|
2024-09-07 18:00:09 +06:00
|
|
|
}
|
|
|
|
|
|
|
|
T* get() const
|
|
|
|
{
|
|
|
|
if (!ptr.value)
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-09-30 10:55:30 +06:00
|
|
|
return reinterpret_cast<T*>(MmGetHostAddress(ptr));
|
2024-09-07 18:00:09 +06:00
|
|
|
}
|
|
|
|
|
|
|
|
operator T* () const
|
|
|
|
{
|
|
|
|
return get();
|
|
|
|
}
|
|
|
|
|
|
|
|
T* operator->() const
|
|
|
|
{
|
|
|
|
return get();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-09-30 10:55:30 +06:00
|
|
|
template<typename TGuest>
|
|
|
|
struct HostObject
|
|
|
|
{
|
|
|
|
typedef TGuest guest_type;
|
|
|
|
};
|
|
|
|
|
2024-09-07 18:00:09 +06:00
|
|
|
struct _XLIST_ENTRY;
|
|
|
|
typedef _XLIST_ENTRY XLIST_ENTRY;
|
|
|
|
typedef xpointer<XLIST_ENTRY> PXLIST_ENTRY;
|
|
|
|
|
2024-09-11 22:06:01 +06:00
|
|
|
typedef struct _IMAGE_CE_RUNTIME_FUNCTION
|
2024-09-11 21:21:23 +06:00
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
uint32_t BeginAddress;
|
2024-09-11 21:21:23 +06:00
|
|
|
|
|
|
|
union
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
uint32_t Data;
|
2024-09-11 21:21:23 +06:00
|
|
|
struct
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
uint32_t PrologLength : 8;
|
|
|
|
uint32_t FunctionLength : 22;
|
|
|
|
uint32_t ThirtyTwoBit : 1;
|
|
|
|
uint32_t ExceptionFlag : 1;
|
2024-09-11 21:21:23 +06:00
|
|
|
};
|
|
|
|
};
|
2024-09-11 22:06:01 +06:00
|
|
|
} IMAGE_CE_RUNTIME_FUNCTION;
|
2024-09-11 21:21:23 +06:00
|
|
|
|
2024-09-11 22:06:01 +06:00
|
|
|
static_assert(sizeof(IMAGE_CE_RUNTIME_FUNCTION) == 8);
|
2024-09-11 21:21:23 +06:00
|
|
|
|
2024-09-07 18:00:09 +06:00
|
|
|
typedef struct _XLIST_ENTRY
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint32_t> Flink;
|
|
|
|
be<uint32_t> Blink;
|
2024-09-07 18:00:09 +06:00
|
|
|
} XLIST_ENTRY;
|
|
|
|
|
|
|
|
typedef struct _XDISPATCHER_HEADER
|
|
|
|
{
|
|
|
|
union
|
|
|
|
{
|
|
|
|
struct
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
uint8_t Type;
|
2024-09-07 18:00:09 +06:00
|
|
|
union
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
uint8_t Abandoned;
|
|
|
|
uint8_t Absolute;
|
|
|
|
uint8_t NpxIrql;
|
|
|
|
uint8_t Signalling;
|
2024-09-07 18:00:09 +06:00
|
|
|
};
|
|
|
|
union
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
uint8_t Size;
|
|
|
|
uint8_t Hand;
|
2024-09-07 18:00:09 +06:00
|
|
|
};
|
|
|
|
union
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
uint8_t Inserted;
|
|
|
|
uint8_t DebugActive;
|
|
|
|
uint8_t DpcActive;
|
2024-09-07 18:00:09 +06:00
|
|
|
};
|
|
|
|
};
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint32_t> Lock;
|
2024-09-07 18:00:09 +06:00
|
|
|
};
|
|
|
|
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint32_t> SignalState;
|
2024-09-07 18:00:09 +06:00
|
|
|
XLIST_ENTRY WaitListHead;
|
|
|
|
} XDISPATCHER_HEADER, * XPDISPATCHER_HEADER;
|
|
|
|
|
|
|
|
// These variables are never accessed in guest code, we can safely use them in little endian
|
|
|
|
typedef struct _XRTL_CRITICAL_SECTION
|
|
|
|
{
|
|
|
|
XDISPATCHER_HEADER Header;
|
2024-12-21 00:49:06 +03:00
|
|
|
int32_t LockCount;
|
2024-09-07 18:00:09 +06:00
|
|
|
int32_t RecursionCount;
|
|
|
|
uint32_t OwningThread;
|
|
|
|
} XRTL_CRITICAL_SECTION;
|
|
|
|
|
|
|
|
typedef struct _XANSI_STRING {
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint16_t> Length;
|
|
|
|
be<uint16_t> MaximumLength;
|
2024-09-07 18:00:09 +06:00
|
|
|
xpointer<char> Buffer;
|
|
|
|
} XANSI_STRING;
|
|
|
|
|
|
|
|
typedef struct _XOBJECT_ATTRIBUTES
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint32_t> RootDirectory;
|
2024-09-07 18:00:09 +06:00
|
|
|
xpointer<XANSI_STRING> Name;
|
|
|
|
xpointer<void> Attributes;
|
|
|
|
} XOBJECT_ATTRIBUTES;
|
|
|
|
|
|
|
|
typedef XDISPATCHER_HEADER XKEVENT;
|
|
|
|
|
|
|
|
typedef struct _XIO_STATUS_BLOCK
|
|
|
|
{
|
|
|
|
union {
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint32_t> Status;
|
|
|
|
be<uint32_t> Pointer;
|
2024-09-07 18:00:09 +06:00
|
|
|
};
|
|
|
|
be<uint32_t> Information;
|
|
|
|
} XIO_STATUS_BLOCK;
|
|
|
|
|
|
|
|
typedef struct _XOVERLAPPED {
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint32_t> Internal;
|
|
|
|
be<uint32_t> InternalHigh;
|
|
|
|
be<uint32_t> Offset;
|
|
|
|
be<uint32_t> OffsetHigh;
|
|
|
|
be<uint32_t> hEvent;
|
2024-09-07 18:00:09 +06:00
|
|
|
} XOVERLAPPED;
|
|
|
|
|
|
|
|
// this name is so dumb
|
|
|
|
typedef struct _XXOVERLAPPED {
|
|
|
|
union
|
|
|
|
{
|
|
|
|
struct
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint32_t> Error;
|
|
|
|
be<uint32_t> Length;
|
2024-09-07 18:00:09 +06:00
|
|
|
};
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
uint32_t InternalLow;
|
|
|
|
uint32_t InternalHigh;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
uint32_t InternalContext;
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint32_t> hEvent;
|
|
|
|
be<uint32_t> pCompletionRoutine;
|
|
|
|
be<uint32_t> dwCompletionContext;
|
|
|
|
be<uint32_t> dwExtendedError;
|
2024-09-07 18:00:09 +06:00
|
|
|
} XXOVERLAPPED, *PXXOVERLAPPED;
|
|
|
|
|
|
|
|
static_assert(sizeof(_XXOVERLAPPED) == 0x1C);
|
|
|
|
|
2024-10-01 15:24:43 +06:00
|
|
|
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-memorystatus
|
|
|
|
typedef struct _XMEMORYSTATUS {
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint32_t> dwLength;
|
|
|
|
be<uint32_t> dwMemoryLoad;
|
|
|
|
be<uint32_t> dwTotalPhys;
|
|
|
|
be<uint32_t> dwAvailPhys;
|
|
|
|
be<uint32_t> dwTotalPageFile;
|
|
|
|
be<uint32_t> dwAvailPageFile;
|
|
|
|
be<uint32_t> dwTotalVirtual;
|
|
|
|
be<uint32_t> dwAvailVirtual;
|
2024-10-01 15:24:43 +06:00
|
|
|
} XMEMORYSTATUS, * XLPMEMORYSTATUS;
|
|
|
|
|
2024-09-07 18:00:09 +06:00
|
|
|
typedef struct _XVIDEO_MODE
|
|
|
|
{
|
|
|
|
be<uint32_t> DisplayWidth;
|
|
|
|
be<uint32_t> DisplayHeight;
|
|
|
|
be<uint32_t> IsInterlaced;
|
|
|
|
be<uint32_t> IsWidescreen;
|
|
|
|
be<uint32_t> IsHighDefinition;
|
|
|
|
be<uint32_t> RefreshRate;
|
|
|
|
be<uint32_t> VideoStandard;
|
|
|
|
be<uint32_t> Unknown4A;
|
|
|
|
be<uint32_t> Unknown01;
|
|
|
|
be<uint32_t> reserved[3];
|
|
|
|
} XVIDEO_MODE;
|
|
|
|
|
|
|
|
typedef struct _XKSEMAPHORE
|
|
|
|
{
|
|
|
|
XDISPATCHER_HEADER Header;
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint32_t> Limit;
|
2024-09-11 21:21:23 +06:00
|
|
|
} XKSEMAPHORE;
|
2024-09-30 10:55:30 +06:00
|
|
|
|
|
|
|
typedef struct _XUSER_SIGNIN_INFO {
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint64_t> xuid;
|
|
|
|
be<uint32_t> dwField08;
|
|
|
|
be<uint32_t> SigninState;
|
|
|
|
be<uint32_t> dwField10;
|
|
|
|
be<uint32_t> dwField14;
|
|
|
|
char Name[16];
|
2024-09-30 10:55:30 +06:00
|
|
|
} XUSER_SIGNIN_INFO;
|
|
|
|
|
2024-11-24 11:25:45 +01:00
|
|
|
typedef struct _XTIME_FIELDS
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint16_t> Year;
|
|
|
|
be<uint16_t> Month;
|
|
|
|
be<uint16_t> Day;
|
|
|
|
be<uint16_t> Hour;
|
|
|
|
be<uint16_t> Minute;
|
|
|
|
be<uint16_t> Second;
|
|
|
|
be<uint16_t> Milliseconds;
|
|
|
|
be<uint16_t> Weekday;
|
2024-11-24 11:25:45 +01:00
|
|
|
} XTIME_FIELDS, * PXTIME_FIELDS;
|
|
|
|
|
2024-09-30 10:55:30 +06:00
|
|
|
// Content types
|
|
|
|
#define XCONTENTTYPE_SAVEDATA 1
|
|
|
|
#define XCONTENTTYPE_DLC 2
|
|
|
|
#define XCONTENTTYPE_RESERVED 3
|
|
|
|
|
|
|
|
#define XCONTENT_NEW 1
|
|
|
|
#define XCONTENT_EXISTING 2
|
|
|
|
|
|
|
|
#define XCONTENT_MAX_DISPLAYNAME 128
|
|
|
|
#define XCONTENT_MAX_FILENAME 42
|
|
|
|
#define XCONTENTDEVICE_MAX_NAME 27
|
|
|
|
|
|
|
|
typedef struct _XCONTENT_DATA
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint32_t> DeviceID;
|
|
|
|
be<uint32_t> dwContentType;
|
|
|
|
be<uint16_t> szDisplayName[XCONTENT_MAX_DISPLAYNAME];
|
|
|
|
char szFileName[XCONTENT_MAX_FILENAME];
|
2024-09-30 10:55:30 +06:00
|
|
|
} XCONTENT_DATA, * PXCONTENT_DATA;
|
|
|
|
|
|
|
|
typedef struct _XHOSTCONTENT_DATA : _XCONTENT_DATA
|
|
|
|
{
|
|
|
|
// This is a host exclusive type so we don't care what goes on
|
|
|
|
std::string szRoot{};
|
|
|
|
} XHOSTCONTENT_DATA, *PXHOSTCONTENT_DATA;
|
|
|
|
|
|
|
|
|
|
|
|
#define XCONTENTDEVICETYPE_HDD 1
|
|
|
|
#define XCONTENTDEVICETYPE_MU 2
|
|
|
|
|
|
|
|
typedef struct _XDEVICE_DATA
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
be<uint32_t> DeviceID;
|
|
|
|
be<uint32_t> DeviceType;
|
|
|
|
be<uint64_t> ulDeviceBytes;
|
|
|
|
be<uint64_t> ulDeviceFreeBytes;
|
|
|
|
be<uint16_t> wszName[XCONTENTDEVICE_MAX_NAME];
|
2024-09-30 10:55:30 +06:00
|
|
|
} XDEVICE_DATA, *PXDEVICE_DATA;
|
|
|
|
|
|
|
|
// Direct reflection of XInput structures
|
|
|
|
|
2024-10-01 15:24:43 +06:00
|
|
|
#define XAMINPUT_DEVTYPE_GAMEPAD 0x01
|
|
|
|
#define XAMINPUT_DEVSUBTYPE_GAMEPAD 0x01
|
|
|
|
|
2024-09-30 10:55:30 +06:00
|
|
|
#define XAMINPUT_GAMEPAD_DPAD_UP 0x0001
|
|
|
|
#define XAMINPUT_GAMEPAD_DPAD_DOWN 0x0002
|
|
|
|
#define XAMINPUT_GAMEPAD_DPAD_LEFT 0x0004
|
|
|
|
#define XAMINPUT_GAMEPAD_DPAD_RIGHT 0x0008
|
|
|
|
#define XAMINPUT_GAMEPAD_START 0x0010
|
|
|
|
#define XAMINPUT_GAMEPAD_BACK 0x0020
|
|
|
|
#define XAMINPUT_GAMEPAD_LEFT_THUMB 0x0040
|
|
|
|
#define XAMINPUT_GAMEPAD_RIGHT_THUMB 0x0080
|
|
|
|
#define XAMINPUT_GAMEPAD_LEFT_SHOULDER 0x0100
|
|
|
|
#define XAMINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200
|
|
|
|
#define XAMINPUT_GAMEPAD_A 0x1000
|
|
|
|
#define XAMINPUT_GAMEPAD_B 0x2000
|
|
|
|
#define XAMINPUT_GAMEPAD_X 0x4000
|
|
|
|
#define XAMINPUT_GAMEPAD_Y 0x8000
|
|
|
|
|
|
|
|
typedef struct _XAMINPUT_GAMEPAD
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
uint16_t wButtons;
|
|
|
|
uint8_t bLeftTrigger;
|
|
|
|
uint8_t bRightTrigger;
|
|
|
|
int16_t sThumbLX;
|
|
|
|
int16_t sThumbLY;
|
|
|
|
int16_t sThumbRX;
|
|
|
|
int16_t sThumbRY;
|
2024-09-30 10:55:30 +06:00
|
|
|
} XAMINPUT_GAMEPAD, *PXAMINPUT_GAMEPAD;
|
|
|
|
|
|
|
|
typedef struct _XAMINPUT_VIBRATION
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
uint16_t wLeftMotorSpeed;
|
|
|
|
uint16_t wRightMotorSpeed;
|
2024-09-30 10:55:30 +06:00
|
|
|
} XAMINPUT_VIBRATION, * PXAMINPUT_VIBRATION;
|
|
|
|
|
|
|
|
typedef struct _XAMINPUT_CAPABILITIES
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
uint8_t Type;
|
|
|
|
uint8_t SubType;
|
|
|
|
uint16_t Flags;
|
2024-09-30 10:55:30 +06:00
|
|
|
XAMINPUT_GAMEPAD Gamepad;
|
|
|
|
XAMINPUT_VIBRATION Vibration;
|
|
|
|
} XAMINPUT_CAPABILITIES, * PXAMINPUT_CAPABILITIES;
|
|
|
|
|
|
|
|
typedef struct _XAMINPUT_STATE
|
|
|
|
{
|
2024-12-21 00:49:06 +03:00
|
|
|
uint32_t dwPacketNumber;
|
2024-09-30 10:55:30 +06:00
|
|
|
XAMINPUT_GAMEPAD Gamepad;
|
|
|
|
} XAMINPUT_STATE, * PXAMINPUT_STATE;
|