feat: added rage header
This commit is contained in:
235
src/detail/rage.hpp
Normal file
235
src/detail/rage.hpp
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace fxn::rage
|
||||||
|
{
|
||||||
|
namespace sysObfuscatedTypes
|
||||||
|
{
|
||||||
|
std::uint32_t obfuscatedRandom()
|
||||||
|
{
|
||||||
|
static std::uint32_t next = 0xCB536E6A;
|
||||||
|
next = next * 214013 + 2531011;
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, bool TMutate = true>
|
||||||
|
class sysObfuscated
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
sysObfuscated()
|
||||||
|
{
|
||||||
|
static_assert((sizeof(T) & 3) == 0, "Size of T must be a multiple of 4");
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
sysObfuscated(const sysObfuscated<T, TMutate>& rhs)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
Set(rhs.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<bool TMutateOther>
|
||||||
|
sysObfuscated(const sysObfuscated<T, TMutateOther>& rhs)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
Set(rhs.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit sysObfuscated(const T& data)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
Set(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
~sysObfuscated() {}
|
||||||
|
public:
|
||||||
|
T Get() const;
|
||||||
|
void Set(const T& data);
|
||||||
|
operator T() const { return Get(); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<bool TMutateOther> bool operator==(const sysObfuscated<T, TMutateOther>& rhs) const { return Get() == rhs.Get(); }
|
||||||
|
template<bool TMutateOther> bool operator!=(const sysObfuscated<T, TMutateOther>& rhs) const { return Get() != rhs.Get(); }
|
||||||
|
template<bool TMutateOther> bool operator<(const sysObfuscated<T, TMutateOther>& rhs) const { return Get() < rhs.Get(); }
|
||||||
|
template<bool TMutateOther> bool operator<=(const sysObfuscated<T, TMutateOther>& rhs) const { return Get() <= rhs.Get(); }
|
||||||
|
template<bool TMutateOther> bool operator>(const sysObfuscated<T, TMutateOther>& rhs) const { return Get() > rhs.Get(); }
|
||||||
|
template<bool TMutateOther> bool operator>=(const sysObfuscated<T, TMutateOther>& rhs) const { return Get() >= rhs.Get(); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<bool TMutateOther> sysObfuscated<T, TMutate>& operator=(const sysObfuscated<T, TMutateOther>& rhs) { Set(rhs.Get()); return *this; }
|
||||||
|
sysObfuscated<T, TMutate>& operator=(const T& data) { Set(data); return *this; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<bool TMutateOther> sysObfuscated<T, TMutate>& operator+=(const sysObfuscated<T, TMutateOther>& rhs) { Set(Get()+rhs.Get()); return *this; }
|
||||||
|
sysObfuscated<T, TMutate>& operator+=(const T& data) { Set(Get()+data); return *this; }
|
||||||
|
template<bool TMutateOther> sysObfuscated<T, TMutate>& operator-=(const sysObfuscated<T, TMutateOther>& rhs) { Set(Get()-rhs.Get()); return *this; }
|
||||||
|
sysObfuscated<T, TMutate>& operator-=(const T& data) { Set(Get()-data); return *this; }
|
||||||
|
template<bool TMutateOther> sysObfuscated<T, TMutate>& operator*=(const sysObfuscated<T, TMutateOther>& rhs) { Set(Get()*rhs.Get()); return *this; }
|
||||||
|
sysObfuscated<T, TMutate>& operator*=(const T& data) { Set(Get()*data); return *this; }
|
||||||
|
template<bool TMutateOther> sysObfuscated<T, TMutate>& operator/=(const sysObfuscated<T, TMutateOther>& rhs) { Set(Get()/rhs.Get()); return *this; }
|
||||||
|
sysObfuscated<T, TMutate>& operator/=(const T& data) { Set(Get()/data); return *this; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
mutable std::uint32_t m_data[(TMutate ? sizeof(T)*2 : sizeof(T)) / sizeof(std::uint32_t)];
|
||||||
|
mutable std::uint32_t m_xor;
|
||||||
|
mutable std::uint32_t m_mutate;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, bool TMutate> __forceinline void sysObfuscated<T, TMutate>::Init()
|
||||||
|
{
|
||||||
|
m_xor = sysObfuscatedTypes::obfuscatedRandom();
|
||||||
|
if(TMutate)
|
||||||
|
{
|
||||||
|
m_mutate = sysObfuscatedTypes::obfuscatedRandom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, bool TMutate> __forceinline T sysObfuscated<T, TMutate>::Get() const
|
||||||
|
{
|
||||||
|
std::uint32_t xorVal = m_xor ^ (std::uint32_t)(size_t)this;
|
||||||
|
std::uint32_t ret[sizeof(T)/sizeof(std::uint32_t)];
|
||||||
|
std::uint32_t* src = const_cast<std::uint32_t*>(&m_data[0]);
|
||||||
|
std::uint32_t* dest = (std::uint32_t*)&ret;
|
||||||
|
for(size_t i=0; i<sizeof(T)/4; ++i)
|
||||||
|
{
|
||||||
|
if(TMutate)
|
||||||
|
{
|
||||||
|
// Extract valid data from two words of storage
|
||||||
|
std::uint32_t a = *src & m_mutate;
|
||||||
|
std::uint32_t b = src[sizeof(T)/4] & (~m_mutate);
|
||||||
|
|
||||||
|
// Apply entropy in the unused bits: Just flip the two u16's in the std::uint32_t. We can't do a
|
||||||
|
// huge amount more without knowledge of the mutation mask.
|
||||||
|
std::uint32_t entropyA = ((*src & (~m_mutate)) << 16) | ((*src & (~m_mutate)) >> 16);
|
||||||
|
std::uint32_t entropyB = ((src[sizeof(T)/4] & m_mutate) << 16) | ((src[sizeof(T)/4] & m_mutate) >> 16);
|
||||||
|
*src = (*src & m_mutate) | entropyA;
|
||||||
|
src[sizeof(T)/4] = (src[sizeof(T)/4] & (~m_mutate)) | entropyB;
|
||||||
|
|
||||||
|
*dest++ = a | b;
|
||||||
|
++src;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*dest++ = *src++ ^ xorVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call Set() to reset the xor and mutate keys on every call to Get()
|
||||||
|
if(TMutate)
|
||||||
|
{
|
||||||
|
const_cast<sysObfuscated<T, TMutate>*>(this)->Set(*(T*)&ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *(T*)&ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, bool TMutate> __forceinline void sysObfuscated<T, TMutate>::Set(const T& data)
|
||||||
|
{
|
||||||
|
// Reset xor and mutate keys
|
||||||
|
Init();
|
||||||
|
|
||||||
|
std::uint32_t xorVal = m_xor ^ (std::uint32_t)(size_t)this;
|
||||||
|
std::uint32_t* src = (std::uint32_t*)&data;
|
||||||
|
std::uint32_t* dest = &m_data[0];
|
||||||
|
for(size_t i=0; i<sizeof(T)/4; ++i)
|
||||||
|
{
|
||||||
|
if(TMutate)
|
||||||
|
{
|
||||||
|
std::uint32_t a = *src & m_mutate;
|
||||||
|
std::uint32_t b = *src & (~m_mutate);
|
||||||
|
++src;
|
||||||
|
|
||||||
|
*dest = a;
|
||||||
|
dest[sizeof(T)/4] = b;
|
||||||
|
++dest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*dest++ = *src++ ^ xorVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename _T>
|
||||||
|
class scrCommandHash
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static const int ToplevelSize = 256;
|
||||||
|
static const int PerBucket = 7;
|
||||||
|
|
||||||
|
struct Bucket
|
||||||
|
{
|
||||||
|
sysObfuscated<Bucket *, false> obf_Next;
|
||||||
|
_T Data[PerBucket];
|
||||||
|
sysObfuscated<std::uint32_t, false> obf_Count;
|
||||||
|
sysObfuscated<std::uint64_t, false> obf_Hashes[PerBucket];
|
||||||
|
std::uint64_t plainText_Hashes[PerBucket];
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
void RegistrationComplete(bool val)
|
||||||
|
{
|
||||||
|
m_bRegistrationComplete = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
m_Occupancy = 0;
|
||||||
|
m_bRegistrationComplete = false;
|
||||||
|
for (int i=0; i<ToplevelSize; i++)
|
||||||
|
m_Buckets[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kill()
|
||||||
|
{
|
||||||
|
for (int i=0; i<ToplevelSize; i++) {
|
||||||
|
Bucket *b = m_Buckets[i];
|
||||||
|
while (b) {
|
||||||
|
char *old = (char*) b;
|
||||||
|
b = b->obf_Next.Get();
|
||||||
|
delete[] old;
|
||||||
|
}
|
||||||
|
m_Buckets[i] = NULL;
|
||||||
|
}
|
||||||
|
m_Occupancy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Insert(std::uint64_t hashcode,_T cmd)
|
||||||
|
{
|
||||||
|
Bucket * b = m_Buckets[hashcode & (ToplevelSize-1)];
|
||||||
|
// If this chain is empty, or the first bucket is full, allocate and patch in a new bucket
|
||||||
|
if (!b || b->obf_Count.Get() == PerBucket) {
|
||||||
|
Bucket *nb = (Bucket*) new char[sizeof(Bucket)];
|
||||||
|
nb->obf_Next.Set(m_Buckets[hashcode & (ToplevelSize-1)]);
|
||||||
|
nb->obf_Count.Set(0);
|
||||||
|
b = m_Buckets[hashcode & (ToplevelSize-1)] = nb;
|
||||||
|
}
|
||||||
|
b->obf_Hashes[b->obf_Count.Get()].Set(hashcode);
|
||||||
|
b->plainText_Hashes[b->obf_Count.Get()] = 0; //hashcode;
|
||||||
|
b->Data[b->obf_Count] = cmd;
|
||||||
|
b->obf_Count.Set(b->obf_Count.Get()+1); //inc count
|
||||||
|
}
|
||||||
|
|
||||||
|
_T Lookup(std::uint64_t hashcode)
|
||||||
|
{
|
||||||
|
Bucket *b = m_Buckets[hashcode & (ToplevelSize-1)];
|
||||||
|
while (b) {
|
||||||
|
for (std::uint32_t i=0; i<b->obf_Count.Get(); i++)
|
||||||
|
if (b->obf_Hashes[i].Get() == hashcode)
|
||||||
|
return b->Data[i];
|
||||||
|
b = b->obf_Next.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Bucket* m_Buckets[ToplevelSize];
|
||||||
|
int m_Occupancy;
|
||||||
|
bool m_bRegistrationComplete;
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user