forked from OneshotGH/supremacy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
interfaces.h
111 lines (88 loc) · 2.59 KB
/
interfaces.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#pragma once
class Interfaces {
private:
// used internally to register classes.
class InterfaceReg {
private:
using create_t = void*( __cdecl * )( );
public:
create_t m_create_fn;
const char *m_name;
InterfaceReg *m_next;
};
struct interface_t {
std::string m_name;
Address m_ptr;
};
// holds every interface used by the game.
std::vector< interface_t > m_interfaces;
public:
// ctor.
__forceinline Interfaces( ) : m_interfaces{} {
PE::modules_t modules;
Address ci;
InterfaceReg *reg;
if( !PE::GetAllModules( modules ) )
return;
for( const auto &m : modules ) {
// get CreateInterface export.
ci = PE::GetExport( m, HASH( "CreateInterface" ) );
if( !Address::valid( ci ) )
continue;
// there is a jump to the real CreateInterface function.
if( ci.at< uint8_t >( 0x4 ) == 0xe9 ) {
// displaced jump - take it
ci = ci.rel32( 0x5 );
// we are now in the true CreateInterface function.
// check for ESI register at 5th instruction
// ptr to linked list is after the MOV ESI instruction.
if( ci.at< uint8_t >( 0x5 ) == 0x35 ) {
// get ptr to linked list.
reg = ci.add( 0x6 ).get< InterfaceReg* >( 2 );
// iterate list.
CreateEntries( reg );
}
}
// check for ESI register at 2nd instruction
// ptr to linked list is after the MOV ESI instruction.
else if( ci.at< uint8_t >( 0x2 ) == 0x35 ) {
// get ptr to linked list.
reg = ci.add( 0x3 ).get< InterfaceReg* >( 2 );
// iterate list.
CreateEntries( reg );
}
}
}
__forceinline void CreateEntries( InterfaceReg* list ) {
// iterate single linked list.
for( list; list != nullptr; list = list->m_next ) {
// invalid name.
if( !list->m_name )
continue;
// add to vector.
m_interfaces.push_back( { list->m_name, ( uintptr_t )list->m_create_fn( ) } );
}
}
// get interface.
template< typename t = Address >
__declspec( noinline ) t get( const hash32_t name, size_t skip = 0, bool truncate = true ) {
std::string interface_name;
for( const auto &i : m_interfaces ) {
// make a copy of the interface's name.
interface_name = i.m_name;
// truncate version number.
if( truncate )
interface_name.resize( interface_name.size( ) - 3 );
// compare hash.
if( FNV1a::get( interface_name ) == name ) {
// skip this interface if a newer one is available.
if( skip > 0 ) {
--skip;
continue;
}
return i.m_ptr.as< t >( );
}
}
return t{};
}
};