-
Notifications
You must be signed in to change notification settings - Fork 26
/
MatrixList.cpp
152 lines (120 loc) · 5.08 KB
/
MatrixList.cpp
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
* Matrices Limit Adjuster
* Copyright (C) 2014 LINK/2012 <[email protected]>
* Licensed under the MIT License (http://opensource.org/licenses/MIT)
*/
#include "LimitAdjuster.h"
#include "utility/dummy_object.hpp"
#include <injector/utility.hpp>
#include <memory>
/*
* Key: MatrixList
* Value: Integer
* Game: SA
*/
struct MatrixList : public SimpleAdjuster
{
typedef dummy_object<0x54> CMatrixLink; // dummy CMatrixLink
injector::hook_back<void*(__fastcall*)(void*)> hbRemoveMatrix_1S;
injector::hook_back<void*(__fastcall*)(void*)> hbRemoveMatrix_1T;
// Additional matrices, if asked for unlimited storage
int total; // Total amount of allocated matrices (by the game and by ourselves)
std::vector<std::unique_ptr<CMatrixLink[]>> matrices; // Our additional matrices
// Limit Name
const char* GetLimitName()
{
return (IsSA()? "MatrixList" : nullptr);
}
// Sets the limit
void ChangeLimit(int, const std::string& value)
{
if(Adjuster::IsUnlimited(value))
{
total = -1; // We don't know how much yet
hbRemoveMatrix_1T.fun = injector::MakeCALL(0x54F5B6, CheckMatrix1T).get();
hbRemoveMatrix_1S.fun = injector::MakeCALL(0x54F548, CheckMatrix1S).get();
}
else
{
injector::WriteMemory(0x54F3A0 + 0x1, std::stoi(value), true);
}
}
// Get matrices usage
bool GetUsage(int, std::string& output)
{
auto nUsed = GetTotalUsage(); // Amount of used matrices
auto nFree = GetNumFree(); // Amount of free matrices
return Adjuster::GetUsage(output, nUsed, nUsed + nFree);
}
// Allocates more free matrices
void* GrowFreeLinkedList()
{
// If this is the first time we run, we still don't know the amount of matrices allocated, get it
if(total == -1) total = GetTotalUsage();
// Grow the linked list by 100%
auto grow_by = total;
total += grow_by;
// We'll need to insert more CMatrixLinkz to the FreeMatrices linked list, get necessary pointers to perform this operation
auto FreeMatricesHead = (CMatrixLink*)((uintptr_t)(gMatrixList()) + 0x150);
auto CMatrixLink__Insert = (CMatrixLink* (__thiscall*)(CMatrixLink*, CMatrixLink*)) injector::lazy_pointer<0x54E8F0>().get<void>();
// Allocate more matrices
matrices.push_back(std::unique_ptr<CMatrixLink[]>( new CMatrixLink[grow_by] ));
CMatrixLink *last = nullptr, *m = matrices.back().get();
// Initialise and insert the newly allocated matrices into the free matrices linked list
for(int i = 0; i < grow_by; ++i)
{
last = &m[i];
std::memset(last, 0, sizeof(CMatrixLink)); // Barely constructs CMatrixLink, we won't destruct it =////
CMatrixLink__Insert(FreeMatricesHead, last);
}
return last;
}
// Hooks at call to CPlaceable::RemoveMatrix to check if no more matrices available
// When there are no more matrices available the game end up sending a null CPlaceable as the this pointer
// because it gets a null CMatrixLink::m_pPlaceable from the temp matrix list since there's no more temp matrices to be used
// So whenever this happens we should add more matrices to the free matrix list
static void* __fastcall CheckMatrix1T(void* placeable) // @CPlaceable::AllocateMatrix
{
if(placeable == nullptr && GetTempMatrixUsage() == 0)
return adjuster_MatrixList.GrowFreeLinkedList();
else
return adjuster_MatrixList.hbRemoveMatrix_1T.fun(placeable);
}
static void* __fastcall CheckMatrix1S(void* placeable) // @CPlaceable::AllocateStaticMatrix
{
if(placeable == nullptr && GetTempMatrixUsage() == 0)
return adjuster_MatrixList.GrowFreeLinkedList();
else
return adjuster_MatrixList.hbRemoveMatrix_1S.fun(placeable);
}
//////// Game Information ////////
// Gets the CMatrixLinkList object
static void* gMatrixList()
{
return injector::lazy_pointer<0xB74288>::get<void>();
}
// Gets the number of free matrices
static uint32_t GetNumFree()
{
uint32_t (__fastcall *GetNumFree)(void*) = injector::lazy_pointer<0x54EB10>::get();
return GetNumFree(gMatrixList());
}
// Gets the usage of temp matrices
static uint32_t GetTempMatrixUsage()
{
uint32_t (__fastcall *GetNumUsed1)(void*) = injector::lazy_pointer<0x54EB30>::get();
return GetNumUsed1(gMatrixList());
}
// Gets the usage of static matrices
static uint32_t GetStaticMatrixUsage()
{
uint32_t (__fastcall *GetNumUsed2)(void*) = injector::lazy_pointer<0x54EB50>::get();
return GetNumUsed2(gMatrixList());
}
// Gets the total usage of matrices (temp matrices + static matrices)
static uint32_t GetTotalUsage()
{
return GetTempMatrixUsage() + GetStaticMatrixUsage();
}
// Instantiate the adjuster on the global scope
} adjuster_MatrixList;