Skip to content

Commit 7075f37

Browse files
committed
feat: REX 2
1 parent f6e9dce commit 7075f37

File tree

14 files changed

+1153
-279
lines changed

14 files changed

+1153
-279
lines changed

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
cmake_minimum_required(VERSION 3.19)
22

3+
option(REX_OPTION_INI "Enables ini config support for REX." OFF)
4+
option(REX_OPTION_JSON "Enables json config support for REX." OFF)
5+
option(REX_OPTION_TOML "Enables toml config support for REX." OFF)
36
option(SKSE_SUPPORT_XBYAK "Enables trampoline support for Xbyak." OFF)
47
option(SKYRIM_SUPPORT_AE "Enables support for Skyrim AE" OFF)
58

@@ -39,6 +42,9 @@ target_compile_definitions(
3942
PUBLIC
4043
WINVER=0x0601 # windows 7, minimum supported version by skyrim special edition
4144
_WIN32_WINNT=0x0601
45+
"$<$<BOOL:${REX_OPTION_INI}>:REX_OPTION_INI=1>"
46+
"$<$<BOOL:${REX_OPTION_JSON}>:REX_OPTION_JSON=1>"
47+
"$<$<BOOL:${REX_OPTION_TOML}>:REX_OPTION_TOML=1>"
4248
"$<$<BOOL:${SKSE_SUPPORT_XBYAK}>:SKSE_SUPPORT_XBYAK=1>"
4349
"$<$<BOOL:${SKYRIM_SUPPORT_AE}>:SKYRIM_SUPPORT_AE=1>"
4450
)

cmake/sourcelist.cmake

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,6 +1671,13 @@ set(SOURCES
16711671
include/REX/PS4.h
16721672
include/REX/PS4/SCEPAD.h
16731673
include/REX/REX.h
1674+
include/REX/REX/Enum.h
1675+
include/REX/REX/EnumSet.h
1676+
include/REX/REX/INI.h
1677+
include/REX/REX/JSON.h
1678+
include/REX/REX/Setting.h
1679+
include/REX/REX/Singleton.h
1680+
include/REX/REX/TOML.h
16741681
include/REX/W32.h
16751682
include/REX/W32/ADVAPI32.h
16761683
include/REX/W32/BASE.h
@@ -2046,6 +2053,7 @@ set(SOURCES
20462053
src/REL/Module.cpp
20472054
src/REL/Relocation.cpp
20482055
src/REL/Version.cpp
2056+
src/REX/REX.cpp
20492057
src/REX/W32.cpp
20502058
src/SKSE/API.cpp
20512059
src/SKSE/IAT.cpp

include/REL/Relocation.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,37 @@ namespace REL
282282
return stl::unrestricted_cast<value_type>(_impl);
283283
}
284284

285+
template <std::ptrdiff_t O = 0>
286+
void replace_func(const std::size_t a_count, const std::uintptr_t a_dst) requires(std::same_as<value_type, std::uintptr_t>)
287+
{
288+
#pragma pack(push, 1)
289+
struct Assembly
290+
{
291+
std::uint8_t jmp;
292+
std::uint8_t modrm;
293+
std::int32_t disp;
294+
std::uint64_t addr;
295+
};
296+
static_assert(sizeof(Assembly) == 0xE);
297+
#pragma pack(pop)
298+
299+
Assembly assembly{
300+
.jmp = static_cast<std::uint8_t>(0xFF),
301+
.modrm = static_cast<std::uint8_t>(0x25),
302+
.disp = static_cast<std::int32_t>(0),
303+
.addr = static_cast<std::uint64_t>(a_dst),
304+
};
305+
306+
safe_fill(address() + O, INT3, a_count);
307+
safe_write(address() + O, &assembly, sizeof(assembly));
308+
}
309+
310+
template <std::ptrdiff_t O = 0, class F>
311+
void replace_func(const std::size_t a_count, const F a_dst) requires(std::same_as<value_type, std::uintptr_t>)
312+
{
313+
replace_func<O>(a_count, stl::unrestricted_cast<std::uintptr_t>(a_dst));
314+
}
315+
285316
template <std::integral U>
286317
void write(const U& a_data) requires(std::same_as<value_type, std::uintptr_t>)
287318
{

include/REX/REX.h

Lines changed: 7 additions & 270 deletions
Original file line numberDiff line numberDiff line change
@@ -1,272 +1,9 @@
11
#pragma once
22

3-
namespace REX
4-
{
5-
template <
6-
class E,
7-
class U = std::underlying_type_t<E>>
8-
class Enum
9-
{
10-
public:
11-
using enum_type = E;
12-
using underlying_type = U;
13-
14-
static_assert(std::is_enum_v<E>, "Enum<E, ...> must be an enum");
15-
static_assert(std::is_integral_v<U>, "Enum<..., U> must be an integral");
16-
17-
constexpr Enum() noexcept = default;
18-
constexpr Enum(const Enum&) noexcept = default;
19-
constexpr Enum(Enum&&) noexcept = default;
20-
21-
template <class U2> // NOLINTNEXTLINE(google-explicit-constructor)
22-
constexpr Enum(Enum<E, U2> a_rhs) noexcept :
23-
_impl(static_cast<U>(a_rhs.get()))
24-
{}
25-
26-
constexpr Enum(E a_value) noexcept :
27-
_impl(static_cast<U>(a_value))
28-
{}
29-
30-
~Enum() noexcept = default;
31-
32-
constexpr Enum& operator=(const Enum&) noexcept = default;
33-
constexpr Enum& operator=(Enum&&) noexcept = default;
34-
35-
template <class U2>
36-
constexpr Enum& operator=(Enum<E, U2> a_rhs) noexcept
37-
{
38-
_impl = static_cast<U>(a_rhs.get());
39-
}
40-
41-
constexpr Enum& operator=(E a_value) noexcept
42-
{
43-
_impl = static_cast<U>(a_value);
44-
return *this;
45-
}
46-
47-
public:
48-
[[nodiscard]] explicit constexpr operator bool() const noexcept { return _impl != static_cast<U>(0); }
49-
50-
[[nodiscard]] constexpr E operator*() const noexcept { return get(); }
51-
[[nodiscard]] constexpr E get() const noexcept { return static_cast<E>(_impl); }
52-
[[nodiscard]] constexpr U underlying() const noexcept { return _impl; }
53-
54-
public:
55-
friend constexpr bool operator==(Enum a_lhs, Enum a_rhs) noexcept { return a_lhs.underlying() == a_rhs.underlying(); }
56-
friend constexpr bool operator==(Enum a_lhs, E a_rhs) noexcept { return a_lhs.underlying() == static_cast<U>(a_rhs); }
57-
friend constexpr bool operator==(E a_lhs, Enum a_rhs) noexcept { return static_cast<U>(a_lhs) == a_rhs.underlying(); }
58-
59-
private:
60-
U _impl{ 0 };
61-
};
62-
63-
template <class... Args>
64-
Enum(Args...) -> Enum<
65-
std::common_type_t<Args...>,
66-
std::underlying_type_t<
67-
std::common_type_t<Args...>>>;
68-
}
69-
70-
namespace REX
71-
{
72-
template <
73-
class E,
74-
class U = std::underlying_type_t<E>>
75-
class EnumSet
76-
{
77-
public:
78-
using enum_type = E;
79-
using underlying_type = U;
80-
81-
static_assert(std::is_enum_v<E>, "EnumSet<E, ...> must be an enum");
82-
static_assert(std::is_integral_v<U>, "EnumSet<..., U> must be an integral");
83-
84-
constexpr EnumSet() noexcept = default;
85-
constexpr EnumSet(const EnumSet&) noexcept = default;
86-
constexpr EnumSet(EnumSet&&) noexcept = default;
87-
88-
template <class U2> // NOLINTNEXTLINE(google-explicit-constructor)
89-
constexpr EnumSet(EnumSet<E, U2> a_rhs) noexcept :
90-
_impl(static_cast<U>(a_rhs.get()))
91-
{}
92-
93-
template <class... Args>
94-
constexpr EnumSet(Args... a_values) noexcept
95-
requires(std::same_as<Args, E>&&...) :
96-
_impl((static_cast<U>(a_values) | ...))
97-
{}
98-
99-
~EnumSet() noexcept = default;
100-
101-
constexpr EnumSet& operator=(const EnumSet&) noexcept = default;
102-
constexpr EnumSet& operator=(EnumSet&&) noexcept = default;
103-
104-
template <class U2>
105-
constexpr EnumSet& operator=(EnumSet<E, U2> a_rhs) noexcept
106-
{
107-
_impl = static_cast<U>(a_rhs.get());
108-
}
109-
110-
constexpr EnumSet& operator=(E a_value) noexcept
111-
{
112-
_impl = static_cast<U>(a_value);
113-
return *this;
114-
}
115-
116-
public:
117-
[[nodiscard]] explicit constexpr operator bool() const noexcept { return _impl != static_cast<U>(0); }
118-
119-
[[nodiscard]] constexpr E operator*() const noexcept { return get(); }
120-
[[nodiscard]] constexpr E get() const noexcept { return static_cast<E>(_impl); }
121-
[[nodiscard]] constexpr U underlying() const noexcept { return _impl; }
122-
123-
public:
124-
template <class... Args>
125-
constexpr EnumSet& set(Args... a_args) noexcept
126-
requires(std::same_as<Args, E>&&...)
127-
{
128-
_impl |= (static_cast<U>(a_args) | ...);
129-
return *this;
130-
}
131-
132-
template <class... Args>
133-
constexpr EnumSet& set(bool a_set, Args... a_args) noexcept
134-
requires(std::same_as<Args, E>&&...)
135-
{
136-
if (a_set)
137-
_impl |= (static_cast<U>(a_args) | ...);
138-
else
139-
_impl &= ~(static_cast<U>(a_args) | ...);
140-
141-
return *this;
142-
}
143-
144-
template <class... Args>
145-
constexpr EnumSet& reset(Args... a_args) noexcept
146-
requires(std::same_as<Args, E>&&...)
147-
{
148-
_impl &= ~(static_cast<U>(a_args) | ...);
149-
return *this;
150-
}
151-
152-
constexpr EnumSet& reset() noexcept
153-
{
154-
_impl = 0;
155-
return *this;
156-
}
157-
158-
template <class... Args>
159-
[[nodiscard]] constexpr bool any(Args... a_args) const noexcept
160-
requires(std::same_as<Args, E>&&...)
161-
{
162-
return (_impl & (static_cast<U>(a_args) | ...)) != static_cast<U>(0);
163-
}
164-
165-
template <class... Args>
166-
[[nodiscard]] constexpr bool all(Args... a_args) const noexcept
167-
requires(std::same_as<Args, E>&&...)
168-
{
169-
return (_impl & (static_cast<U>(a_args) | ...)) == (static_cast<U>(a_args) | ...);
170-
}
171-
172-
template <class... Args>
173-
[[nodiscard]] constexpr bool none(Args... a_args) const noexcept
174-
requires(std::same_as<Args, E>&&...)
175-
{
176-
return (_impl & (static_cast<U>(a_args) | ...)) == static_cast<U>(0);
177-
}
178-
179-
public:
180-
friend constexpr bool operator==(EnumSet a_lhs, EnumSet a_rhs) noexcept { return a_lhs.underlying() == a_rhs.underlying(); }
181-
friend constexpr bool operator==(EnumSet a_lhs, E a_rhs) noexcept { return a_lhs.underlying() == static_cast<U>(a_rhs); }
182-
friend constexpr bool operator==(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<U>(a_lhs) == a_rhs.underlying(); }
183-
184-
friend constexpr std::strong_ordering operator<=>(EnumSet a_lhs, EnumSet a_rhs) noexcept { return a_lhs.underlying() <=> a_rhs.underlying(); }
185-
friend constexpr std::strong_ordering operator<=>(EnumSet a_lhs, E a_rhs) noexcept { return a_lhs.underlying() <=> static_cast<U>(a_rhs); }
186-
friend constexpr std::strong_ordering operator<=>(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<U>(a_lhs) <=> a_rhs.underlying(); }
187-
188-
friend constexpr EnumSet operator&(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() & a_rhs.underlying()); }
189-
friend constexpr EnumSet operator&(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() & static_cast<U>(a_rhs)); }
190-
friend constexpr EnumSet operator&(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) & a_rhs.underlying()); }
191-
192-
friend constexpr EnumSet& operator&=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs & a_rhs; }
193-
friend constexpr EnumSet& operator&=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs & a_rhs; }
194-
195-
friend constexpr EnumSet operator|(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() | a_rhs.underlying()); }
196-
friend constexpr EnumSet operator|(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() | static_cast<U>(a_rhs)); }
197-
friend constexpr EnumSet operator|(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) | a_rhs.underlying()); }
198-
199-
friend constexpr EnumSet& operator|=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs | a_rhs; }
200-
friend constexpr EnumSet& operator|=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs | a_rhs; }
201-
202-
friend constexpr EnumSet operator^(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() ^ a_rhs.underlying()); }
203-
friend constexpr EnumSet operator^(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() ^ static_cast<U>(a_rhs)); }
204-
friend constexpr EnumSet operator^(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) ^ a_rhs.underlying()); }
205-
206-
friend constexpr EnumSet& operator^=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs ^ a_rhs; }
207-
friend constexpr EnumSet& operator^=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs ^ a_rhs; }
208-
209-
friend constexpr EnumSet operator+(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() + a_rhs.underlying()); }
210-
friend constexpr EnumSet operator+(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() + static_cast<U>(a_rhs)); }
211-
friend constexpr EnumSet operator+(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) + a_rhs.underlying()); }
212-
213-
friend constexpr EnumSet& operator+=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs + a_rhs; }
214-
friend constexpr EnumSet& operator+=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs + a_rhs; }
215-
216-
friend constexpr EnumSet operator-(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() - a_rhs.underlying()); }
217-
friend constexpr EnumSet operator-(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() - static_cast<U>(a_rhs)); }
218-
friend constexpr EnumSet operator-(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) - a_rhs.underlying()); }
219-
220-
friend constexpr EnumSet& operator-=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs - a_rhs; }
221-
friend constexpr EnumSet& operator-=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs - a_rhs; }
222-
223-
friend constexpr EnumSet operator<<(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() << a_rhs.underlying()); }
224-
friend constexpr EnumSet operator<<(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() << static_cast<U>(a_rhs)); }
225-
friend constexpr EnumSet operator<<(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) << a_rhs.underlying()); }
226-
227-
friend constexpr EnumSet& operator<<=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs << a_rhs; }
228-
friend constexpr EnumSet& operator<<=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs << a_rhs; }
229-
230-
friend constexpr EnumSet operator>>(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() >> a_rhs.underlying()); }
231-
friend constexpr EnumSet operator>>(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() >> static_cast<U>(a_rhs)); }
232-
friend constexpr EnumSet operator>>(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) >> a_rhs.underlying()); }
233-
234-
friend constexpr EnumSet& operator>>=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs >> a_rhs; }
235-
friend constexpr EnumSet& operator>>=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs >> a_rhs; }
236-
237-
friend constexpr EnumSet& operator~(EnumSet& a_lhs) noexcept { return a_lhs = ~a_lhs.underlying(); }
238-
239-
private:
240-
U _impl{ 0 };
241-
};
242-
243-
template <class... Args>
244-
EnumSet(Args...) -> EnumSet<
245-
std::common_type_t<Args...>,
246-
std::underlying_type_t<
247-
std::common_type_t<Args...>>>;
248-
}
249-
250-
namespace REX
251-
{
252-
template <class T>
253-
class Singleton
254-
{
255-
public:
256-
static T* GetSingleton()
257-
{
258-
static T singleton;
259-
return std::addressof(singleton);
260-
}
261-
262-
protected:
263-
Singleton() = default;
264-
~Singleton() = default;
265-
266-
Singleton(const Singleton&) = delete;
267-
Singleton(Singleton&&) = delete;
268-
269-
Singleton& operator=(const Singleton&) = delete;
270-
Singleton& operator=(Singleton&&) = delete;
271-
};
272-
}
3+
#include "REX/REX/Enum.h"
4+
#include "REX/REX/EnumSet.h"
5+
#include "REX/REX/INI.h"
6+
#include "REX/REX/JSON.h"
7+
#include "REX/REX/Setting.h"
8+
#include "REX/REX/Singleton.h"
9+
#include "REX/REX/TOML.h"

0 commit comments

Comments
 (0)