mirror of
https://github.com/CookiePLMonster/SilentPatch.git
synced 2024-11-21 13:02:36 +01:00
Moved shared stuff to a submodule
This commit is contained in:
parent
19f078bb04
commit
4d02505521
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "SilentPatch/Utils"]
|
||||
path = SilentPatch/Utils
|
||||
url = https://github.com/CookiePLMonster/ModUtils.git
|
@ -168,7 +168,7 @@ copy /y "$(TargetPath)" "D:\Steam\steamapps\common\Grand Theft Auto Vice City\dd
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\SilentPatch\Common_ddraw.cpp" />
|
||||
<ClCompile Include="..\SilentPatch\Patterns.cpp" />
|
||||
<ClCompile Include="..\SilentPatch\Utils\Patterns.cpp" />
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -176,8 +176,8 @@ copy /y "$(TargetPath)" "D:\Steam\steamapps\common\Grand Theft Auto Vice City\dd
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\SilentPatch\Common_ddraw.h" />
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.h" />
|
||||
<ClInclude Include="..\SilentPatch\Patterns.h" />
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.h" />
|
||||
<ClInclude Include="..\SilentPatch\Utils\Patterns.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
@ -13,28 +13,34 @@
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Utils">
|
||||
<UniqueIdentifier>{e6db2444-bfd1-4eb2-a878-7de676789c09}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Utils">
|
||||
<UniqueIdentifier>{53c8e8e5-df13-4831-aa9b-a14b0d0fec04}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Patterns.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Common_ddraw.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Utils\Patterns.cpp">
|
||||
<Filter>Source Files\Utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Patterns.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Common_ddraw.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Utils\Patterns.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\SilentPatch\SilentPatch.rc">
|
||||
|
@ -6,8 +6,8 @@
|
||||
#include <stdio.h>
|
||||
#include <Shlwapi.h>
|
||||
#include <ShlObj.h>
|
||||
#include "MemoryMgr.h"
|
||||
#include "Patterns.h"
|
||||
#include "Utils/MemoryMgr.h"
|
||||
#include "Utils/Patterns.h"
|
||||
|
||||
#include "Common_ddraw.h"
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "Common.h"
|
||||
|
||||
#include "MemoryMgr.h"
|
||||
#include "Patterns.h"
|
||||
#include "Utils/MemoryMgr.h"
|
||||
#include "Utils/Patterns.h"
|
||||
#include "StoredCar.h"
|
||||
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
#include <Shlwapi.h>
|
||||
#include <ShlObj.h>
|
||||
#include "MemoryMgr.h"
|
||||
#include "Patterns.h"
|
||||
#include "Utils/MemoryMgr.h"
|
||||
#include "Utils/Patterns.h"
|
||||
|
||||
#pragma comment(lib, "shlwapi.lib")
|
||||
|
||||
|
@ -1,56 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
template<typename T>
|
||||
class BasicDelimStringReader
|
||||
{
|
||||
public:
|
||||
BasicDelimStringReader( size_t size )
|
||||
: m_buffer( new T[size] ), m_size( size )
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
~BasicDelimStringReader()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
inline T* GetBuffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
inline size_t GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
const T* GetString( size_t* size = nullptr )
|
||||
{
|
||||
if ( *m_cursor == '\0' )
|
||||
{
|
||||
if ( size != nullptr ) *size = 0;
|
||||
return nullptr;
|
||||
}
|
||||
const T* curString = m_cursor;
|
||||
size_t len = 0;
|
||||
|
||||
while ( *m_cursor++ != '\0' ) len++;
|
||||
|
||||
if ( size != nullptr ) *size = len;
|
||||
return curString;
|
||||
}
|
||||
|
||||
inline void Reset()
|
||||
{
|
||||
m_cursor = m_buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
T* const m_buffer;
|
||||
const T* m_cursor;
|
||||
const size_t m_size;
|
||||
};
|
||||
|
||||
typedef BasicDelimStringReader<char> DelimStringReader;
|
||||
typedef BasicDelimStringReader<wchar_t> WideDelimStringReader;
|
@ -1,432 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "MemoryMgr.h"
|
||||
|
||||
#include <variant>
|
||||
#include "Patterns.h"
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
struct PatternAndOffset
|
||||
{
|
||||
PatternAndOffset( std::string_view pattern, ptrdiff_t offset = 0 )
|
||||
: pattern(std::move(pattern)), offset(offset)
|
||||
{
|
||||
}
|
||||
|
||||
std::string_view pattern;
|
||||
ptrdiff_t offset;
|
||||
};
|
||||
|
||||
using AddrVariant = std::variant<uintptr_t, PatternAndOffset>;
|
||||
|
||||
namespace internal
|
||||
{
|
||||
inline signed char* GetVer()
|
||||
{
|
||||
static signed char bVer = -1;
|
||||
return &bVer;
|
||||
}
|
||||
|
||||
inline bool* GetEuropean()
|
||||
{
|
||||
static bool bEuropean;
|
||||
return &bEuropean;
|
||||
}
|
||||
|
||||
inline uintptr_t GetDummy()
|
||||
{
|
||||
static uintptr_t dwDummy;
|
||||
return reinterpret_cast<uintptr_t>(&dwDummy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
inline uintptr_t HandlePattern( const PatternAndOffset& pattern )
|
||||
{
|
||||
void* addr = hook::get_pattern( pattern.pattern, pattern.offset );
|
||||
return reinterpret_cast<uintptr_t>(addr);
|
||||
}
|
||||
|
||||
#if defined _GTA_III
|
||||
inline void InitializeVersions()
|
||||
{
|
||||
signed char* bVer = GetVer();
|
||||
|
||||
if ( *bVer == -1 )
|
||||
{
|
||||
if (*(uint32_t*)0x5C1E75 == 0xB85548EC) *bVer = 0;
|
||||
else if (*(uint32_t*)0x5C2135 == 0xB85548EC) *bVer = 1;
|
||||
else if (*(uint32_t*)0x5C6FD5 == 0xB85548EC) *bVer = 2;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined _GTA_VC
|
||||
|
||||
inline void InitializeVersions()
|
||||
{
|
||||
signed char* bVer = GetVer();
|
||||
|
||||
if ( *bVer == -1 )
|
||||
{
|
||||
if (*(uint32_t*)0x667BF5 == 0xB85548EC) *bVer = 0;
|
||||
else if (*(uint32_t*)0x667C45 == 0xB85548EC) *bVer = 1;
|
||||
else if (*(uint32_t*)0x666BA5 == 0xB85548EC) *bVer = 2;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined _GTA_SA
|
||||
|
||||
inline bool TryMatch_10()
|
||||
{
|
||||
if ( *(uint32_t*)DynBaseAddress(0x82457C) == 0x94BF )
|
||||
{
|
||||
// 1.0 US
|
||||
*GetVer() = 0;
|
||||
*GetEuropean() = false;
|
||||
return true;
|
||||
}
|
||||
if ( *(uint32_t*)DynBaseAddress(0x8245BC) == 0x94BF )
|
||||
{
|
||||
// 1.0 EU
|
||||
*GetVer() = 0;
|
||||
*GetEuropean() = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryMatch_11()
|
||||
{
|
||||
if ( *(uint32_t*)DynBaseAddress(0x8252FC) == 0x94BF )
|
||||
{
|
||||
// 1.01 US
|
||||
*GetVer() = 1;
|
||||
*GetEuropean() = false;
|
||||
return true;
|
||||
}
|
||||
if ( *(uint32_t*)DynBaseAddress(0x82533C) == 0x94BF )
|
||||
{
|
||||
// 1.01 EU
|
||||
*GetVer() = 1;
|
||||
*GetEuropean() = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryMatch_30()
|
||||
{
|
||||
if (*(uint32_t*)DynBaseAddress(0x85EC4A) == 0x94BF )
|
||||
{
|
||||
// 3.0
|
||||
*GetVer() = 2;
|
||||
*GetEuropean() = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryMatch_newsteam_r1()
|
||||
{
|
||||
if ( *(uint32_t*)DynBaseAddress(0x858D21) == 0x3539F633 )
|
||||
{
|
||||
// newsteam r1
|
||||
*GetVer() = 3;
|
||||
*GetEuropean() = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryMatch_newsteam_r2()
|
||||
{
|
||||
if ( *(uint32_t*)DynBaseAddress(0x858D51) == 0x3539F633 )
|
||||
{
|
||||
// newsteam r2
|
||||
*GetVer() = 4;
|
||||
*GetEuropean() = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryMatch_newsteam_r2_lv()
|
||||
{
|
||||
if ( *(uint32_t*)DynBaseAddress(0x858C61) == 0x3539F633 )
|
||||
{
|
||||
// newsteam r2 lv
|
||||
*GetVer() = 5;
|
||||
*GetEuropean() = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void InitializeVersions()
|
||||
{
|
||||
if ( *GetVer() == -1 )
|
||||
{
|
||||
if ( TryMatch_10() ) return;
|
||||
if ( TryMatch_11() ) return;
|
||||
if ( TryMatch_30() ) return;
|
||||
if ( TryMatch_newsteam_r1() ) return;
|
||||
if ( TryMatch_newsteam_r2() ) return;
|
||||
if ( TryMatch_newsteam_r2_lv() ) return;
|
||||
}
|
||||
}
|
||||
|
||||
inline void InitializeRegion_10()
|
||||
{
|
||||
signed char* bVer = GetVer();
|
||||
|
||||
if ( *bVer == -1 )
|
||||
{
|
||||
if ( !TryMatch_10() )
|
||||
{
|
||||
#ifdef assert
|
||||
assert(!"AddressByRegion_10 on non-1.0 EXE!");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void InitializeRegion_11()
|
||||
{
|
||||
signed char* bVer = GetVer();
|
||||
|
||||
if ( *bVer == -1 )
|
||||
{
|
||||
if ( !TryMatch_11() )
|
||||
{
|
||||
#ifdef assert
|
||||
assert(!"AddressByRegion_11 on non-1.01 EXE!");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline uintptr_t AdjustAddress_10(uintptr_t address10)
|
||||
{
|
||||
if ( *GetEuropean() )
|
||||
{
|
||||
if ( address10 >= 0x746720 && address10 < 0x857000 )
|
||||
{
|
||||
if ( address10 >= 0x7BA940 )
|
||||
address10 += 0x40;
|
||||
else
|
||||
address10 += 0x50;
|
||||
}
|
||||
}
|
||||
return address10;
|
||||
}
|
||||
|
||||
inline uintptr_t AdjustAddress_11(uintptr_t address11)
|
||||
{
|
||||
if ( !(*GetEuropean()) && address11 > 0x746FA0 )
|
||||
{
|
||||
if ( address11 < 0x7BB240 )
|
||||
address11 -= 0x50;
|
||||
else
|
||||
address11 -= 0x40;
|
||||
}
|
||||
return address11;
|
||||
}
|
||||
|
||||
inline uintptr_t AddressByVersion(AddrVariant address10, AddrVariant address11, AddrVariant addressSteam, AddrVariant addressNewsteamR2, AddrVariant addressNewsteamR2_LV)
|
||||
{
|
||||
InitializeVersions();
|
||||
|
||||
signed char bVer = *GetVer();
|
||||
|
||||
switch ( bVer )
|
||||
{
|
||||
case 1:
|
||||
if ( auto pao = std::get_if<PatternAndOffset>(&address11) ) return HandlePattern( *pao );
|
||||
else
|
||||
{
|
||||
const uintptr_t addr = *std::get_if<uintptr_t>(&address11);
|
||||
#ifdef assert
|
||||
assert(addr);
|
||||
#endif
|
||||
|
||||
// Safety measures - if null, return dummy var pointer to prevent a crash
|
||||
if ( addr == 0 )
|
||||
return GetDummy();
|
||||
|
||||
// Adjust to US if needed
|
||||
return AdjustAddress_11(addr);
|
||||
}
|
||||
case 2:
|
||||
if ( auto pao = std::get_if<PatternAndOffset>(&addressSteam) ) return HandlePattern( *pao );
|
||||
else
|
||||
{
|
||||
const uintptr_t addr = *std::get_if<uintptr_t>(&addressSteam);
|
||||
#ifdef assert
|
||||
assert(addr);
|
||||
#endif
|
||||
// Safety measures - if null, return dummy var pointer to prevent a crash
|
||||
if ( addr == 0 )
|
||||
return GetDummy();
|
||||
|
||||
return addr;
|
||||
}
|
||||
case 3:
|
||||
return GetDummy();
|
||||
case 4:
|
||||
if ( auto pao = std::get_if<PatternAndOffset>(&addressNewsteamR2) ) return HandlePattern( *pao );
|
||||
else
|
||||
{
|
||||
const uintptr_t addr = *std::get_if<uintptr_t>(&addressNewsteamR2);
|
||||
#ifdef assert
|
||||
assert(addr);
|
||||
#endif
|
||||
if ( addr == 0 )
|
||||
return GetDummy();
|
||||
|
||||
return DynBaseAddress(addr);
|
||||
}
|
||||
case 5:
|
||||
if ( auto pao = std::get_if<PatternAndOffset>(&addressNewsteamR2) ) return HandlePattern( *pao );
|
||||
else
|
||||
{
|
||||
const uintptr_t addr = *std::get_if<uintptr_t>(&addressNewsteamR2_LV);
|
||||
#ifdef assert
|
||||
assert(addr);
|
||||
#endif
|
||||
if ( addr == 0 )
|
||||
return GetDummy();
|
||||
|
||||
return DynBaseAddress(addr);
|
||||
}
|
||||
default:
|
||||
if ( auto pao = std::get_if<PatternAndOffset>(&address10) ) return HandlePattern( *pao );
|
||||
else
|
||||
{
|
||||
const uintptr_t addr = *std::get_if<uintptr_t>(&address10);
|
||||
#ifdef assert
|
||||
assert(addr);
|
||||
#endif
|
||||
// Adjust to EU if needed
|
||||
return AdjustAddress_10(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline uintptr_t AddressByRegion_10(uintptr_t address10)
|
||||
{
|
||||
InitializeRegion_10();
|
||||
|
||||
// Adjust to EU if needed
|
||||
return AdjustAddress_10(address10);
|
||||
}
|
||||
|
||||
inline uintptr_t AddressByRegion_11(uintptr_t address11)
|
||||
{
|
||||
InitializeRegion_11();
|
||||
|
||||
// Adjust to US if needed
|
||||
return AdjustAddress_11(address11);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void InitializeVersions()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined _GTA_III || defined _GTA_VC
|
||||
|
||||
inline uintptr_t AddressByVersion(uintptr_t address10, uintptr_t address11, uintptr_t addressSteam)
|
||||
{
|
||||
InitializeVersions();
|
||||
|
||||
signed char bVer = *GetVer();
|
||||
|
||||
switch ( bVer )
|
||||
{
|
||||
case 1:
|
||||
#ifdef assert
|
||||
assert(address11);
|
||||
#endif
|
||||
return address11;
|
||||
case 2:
|
||||
#ifdef assert
|
||||
assert(addressSteam);
|
||||
#endif
|
||||
return addressSteam;
|
||||
default:
|
||||
#ifdef assert
|
||||
assert(address10);
|
||||
#endif
|
||||
return address10;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#if defined _GTA_III || defined _GTA_VC
|
||||
|
||||
template<typename T>
|
||||
inline T AddressByVersion(uintptr_t address10, uintptr_t address11, uintptr_t addressSteam)
|
||||
{
|
||||
return T(Memory::internal::AddressByVersion( address10, address11, addressSteam ));
|
||||
}
|
||||
|
||||
#elif defined _GTA_SA
|
||||
|
||||
template<typename T>
|
||||
inline T AddressByVersion(Memory::AddrVariant address10, Memory::AddrVariant address11, Memory::AddrVariant addressSteam)
|
||||
{
|
||||
return T(Memory::internal::AddressByVersion( std::move(address10), std::move(address11), std::move(addressSteam), 0, 0 ));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T AddressByVersion(Memory::AddrVariant address10, Memory::AddrVariant address11, Memory::AddrVariant addressSteam, Memory::AddrVariant addressNewsteamR2, Memory::AddrVariant addressNewsteamR2_LV)
|
||||
{
|
||||
return T(Memory::internal::AddressByVersion( std::move(address10), std::move(address11), std::move(addressSteam), std::move(addressNewsteamR2), std::move(addressNewsteamR2_LV) ));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T AddressByVersion(Memory::AddrVariant address10, Memory::AddrVariant addressNewsteam)
|
||||
{
|
||||
return T(Memory::internal::AddressByVersion( std::move(address10), 0, 0, addressNewsteam, addressNewsteam ));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T AddressByRegion_10(uintptr_t address10)
|
||||
{
|
||||
return T(Memory::internal::AddressByRegion_10(address10));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T AddressByRegion_11(uintptr_t address11)
|
||||
{
|
||||
return T(Memory::internal::AddressByRegion_11(address11));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
struct VersionInfo
|
||||
{
|
||||
int8_t version;
|
||||
bool european;
|
||||
};
|
||||
|
||||
inline VersionInfo GetVersion()
|
||||
{
|
||||
Memory::internal::InitializeVersions();
|
||||
return { *Memory::internal::GetVer(), *Memory::internal::GetEuropean() };
|
||||
}
|
||||
};
|
@ -1,429 +0,0 @@
|
||||
#ifndef __MEMORYMGR
|
||||
#define __MEMORYMGR
|
||||
|
||||
// Switches:
|
||||
// _MEMORY_NO_CRT - don't include anything "complex" like ScopedUnprotect or memset
|
||||
// _MEMORY_DECLS_ONLY - don't include anything but macroes
|
||||
|
||||
#define WRAPPER __declspec(naked)
|
||||
#define DEPRECATED __declspec(deprecated)
|
||||
#define EAXJMP(a) { _asm mov eax, a _asm jmp eax }
|
||||
#define VARJMP(a) { _asm jmp a }
|
||||
#define WRAPARG(a) ((int)a)
|
||||
|
||||
#define NOVMT __declspec(novtable)
|
||||
#define SETVMT(a) *((uintptr_t*)this) = (uintptr_t)a
|
||||
|
||||
#ifndef _MEMORY_DECLS_ONLY
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
|
||||
#ifndef _MEMORY_NO_CRT
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
PATCH_CALL,
|
||||
PATCH_JUMP
|
||||
};
|
||||
|
||||
template<typename AT>
|
||||
inline AT DynBaseAddress(AT address)
|
||||
{
|
||||
return (ptrdiff_t)GetModuleHandle(nullptr) - 0x400000 + address;
|
||||
}
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
template<typename T, typename AT>
|
||||
inline void Patch(AT address, T value)
|
||||
{*(T*)address = value; }
|
||||
|
||||
#ifndef _MEMORY_NO_CRT
|
||||
template<typename AT>
|
||||
inline void Patch(AT address, std::initializer_list<uint8_t> list )
|
||||
{
|
||||
uint8_t* addr = reinterpret_cast<uint8_t*>(address);
|
||||
std::copy( list.begin(), list.end(), stdext::make_checked_array_iterator(addr, list.size()) );
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename AT>
|
||||
inline void Nop(AT address, size_t count)
|
||||
#ifndef _MEMORY_NO_CRT
|
||||
{ memset((void*)address, 0x90, count); }
|
||||
#else
|
||||
{ do {
|
||||
*(uint8_t*)address++ = 0x90;
|
||||
} while ( --count != 0 ); }
|
||||
#endif
|
||||
|
||||
template<typename AT, typename Func>
|
||||
inline void InjectHook(AT address, Func hook)
|
||||
{
|
||||
union member_cast
|
||||
{
|
||||
intptr_t addr;
|
||||
Func funcPtr;
|
||||
} cast;
|
||||
static_assert( sizeof(cast.addr) == sizeof(cast.funcPtr), "member_cast failure!" );
|
||||
cast.funcPtr = hook;
|
||||
|
||||
*(int32_t*)((intptr_t)address + 1) = static_cast<int32_t>(cast.addr - (intptr_t)address - 5);
|
||||
}
|
||||
|
||||
template<typename AT, typename Func>
|
||||
inline void InjectHook(AT address, Func hook, unsigned int nType)
|
||||
{
|
||||
*(uint8_t*)address = nType == PATCH_JUMP ? 0xE9 : 0xE8;
|
||||
InjectHook(address, hook);
|
||||
}
|
||||
|
||||
template<typename Func, typename AT>
|
||||
inline void ReadCall(AT address, Func& func)
|
||||
{
|
||||
union member_cast
|
||||
{
|
||||
intptr_t addr;
|
||||
Func funcPtr;
|
||||
} cast;
|
||||
static_assert( sizeof(cast.addr) == sizeof(cast.funcPtr), "member_cast failure!" );
|
||||
|
||||
cast.addr = (intptr_t)address + 5 + *(int32_t*)((intptr_t)address+1);
|
||||
func = cast.funcPtr;
|
||||
}
|
||||
|
||||
template<typename AT>
|
||||
inline void* ReadCallFrom(AT address, ptrdiff_t offset = 0)
|
||||
{
|
||||
uintptr_t addr;
|
||||
ReadCall( address, addr );
|
||||
return reinterpret_cast<void*>( addr + offset );
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_NO_CRT
|
||||
inline bool MemEquals(uintptr_t address, std::initializer_list<uint8_t> val)
|
||||
{
|
||||
const uint8_t* mem = reinterpret_cast<const uint8_t*>(address);
|
||||
return std::equal( val.begin(), val.end(), stdext::make_checked_array_iterator(mem, val.size()) );
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename AT>
|
||||
inline AT Verify(AT address, uintptr_t expected)
|
||||
{
|
||||
assert( uintptr_t(address) == expected );
|
||||
return address;
|
||||
}
|
||||
|
||||
namespace DynBase
|
||||
{
|
||||
template<typename T, typename AT>
|
||||
inline void Patch(AT address, T value)
|
||||
{
|
||||
Memory::Patch(DynBaseAddress(address), value);
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_NO_CRT
|
||||
template<typename AT>
|
||||
inline void Patch(AT address, std::initializer_list<uint8_t> list )
|
||||
{
|
||||
Memory::Patch(DynBaseAddress(address), std::move(list));
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename AT>
|
||||
inline void Nop(AT address, size_t count)
|
||||
{
|
||||
Memory::Nop(DynBaseAddress(address), count);
|
||||
}
|
||||
|
||||
template<typename AT, typename HT>
|
||||
inline void InjectHook(AT address, HT hook)
|
||||
{
|
||||
Memory::InjectHook(DynBaseAddress(address), hook);
|
||||
}
|
||||
|
||||
template<typename AT, typename HT>
|
||||
inline void InjectHook(AT address, HT hook, unsigned int nType)
|
||||
{
|
||||
Memory::InjectHook(DynBaseAddress(address), hook, nType);
|
||||
}
|
||||
|
||||
template<typename Func, typename AT>
|
||||
inline void ReadCall(AT address, Func& func)
|
||||
{
|
||||
Memory::ReadCall(DynBaseAddress(address), func);
|
||||
}
|
||||
|
||||
template<typename AT>
|
||||
inline void* ReadCallFrom(AT address, ptrdiff_t offset = 0)
|
||||
{
|
||||
return Memory::ReadCallFrom(DynBaseAddress(address), offset);
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_NO_CRT
|
||||
inline bool MemEquals(uintptr_t address, std::initializer_list<uint8_t> val)
|
||||
{
|
||||
return Memory::MemEquals(DynBaseAddress(address), std::move(val));
|
||||
}
|
||||
|
||||
template<typename AT>
|
||||
inline AT Verify(AT address, uintptr_t expected)
|
||||
{
|
||||
return Memory::Verify(address, DynBaseAddress(expected));
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace VP
|
||||
{
|
||||
template<typename T, typename AT>
|
||||
inline void Patch(AT address, T value)
|
||||
{
|
||||
DWORD dwProtect[2];
|
||||
VirtualProtect((void*)address, sizeof(T), PAGE_EXECUTE_READWRITE, &dwProtect[0]);
|
||||
Memory::Patch( address, value );
|
||||
VirtualProtect((void*)address, sizeof(T), dwProtect[0], &dwProtect[1]);
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_NO_CRT
|
||||
template<typename AT>
|
||||
inline void Patch(AT address, std::initializer_list<uint8_t> list )
|
||||
{
|
||||
DWORD dwProtect[2];
|
||||
VirtualProtect((void*)address, list.size(), PAGE_EXECUTE_READWRITE, &dwProtect[0]);
|
||||
Memory::Patch(address, std::move(list));
|
||||
VirtualProtect((void*)address, list.size(), dwProtect[0], &dwProtect[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename AT>
|
||||
inline void Nop(AT address, size_t count)
|
||||
{
|
||||
DWORD dwProtect[2];
|
||||
VirtualProtect((void*)address, count, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
|
||||
Memory::Nop( address, count );
|
||||
VirtualProtect((void*)address, count, dwProtect[0], &dwProtect[1]);
|
||||
}
|
||||
|
||||
template<typename AT, typename HT>
|
||||
inline void InjectHook(AT address, HT hook)
|
||||
{
|
||||
DWORD dwProtect[2];
|
||||
|
||||
VirtualProtect((void*)((DWORD_PTR)address + 1), 4, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
|
||||
Memory::InjectHook( address, hook );
|
||||
VirtualProtect((void*)((DWORD_PTR)address + 1), 4, dwProtect[0], &dwProtect[1]);
|
||||
}
|
||||
|
||||
template<typename AT, typename HT>
|
||||
inline void InjectHook(AT address, HT hook, unsigned int nType)
|
||||
{
|
||||
DWORD dwProtect[2];
|
||||
|
||||
VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
|
||||
Memory::InjectHook( address, hook, nType );
|
||||
VirtualProtect((void*)address, 5, dwProtect[0], &dwProtect[1]);
|
||||
}
|
||||
|
||||
template<typename Func, typename AT>
|
||||
inline void ReadCall(AT address, Func& func)
|
||||
{
|
||||
Memory::ReadCall(address, func);
|
||||
}
|
||||
|
||||
template<typename AT>
|
||||
inline void* ReadCallFrom(AT address, ptrdiff_t offset = 0)
|
||||
{
|
||||
return Memory::ReadCallFrom(address, offset);
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_NO_CRT
|
||||
inline bool MemEquals(uintptr_t address, std::initializer_list<uint8_t> val)
|
||||
{
|
||||
return Memory::MemEquals(address, std::move(val));
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename AT>
|
||||
inline AT Verify(AT address, uintptr_t expected)
|
||||
{
|
||||
return Memory::Verify(address, expected);
|
||||
}
|
||||
|
||||
namespace DynBase
|
||||
{
|
||||
template<typename T, typename AT>
|
||||
inline void Patch(AT address, T value)
|
||||
{
|
||||
VP::Patch(DynBaseAddress(address), value);
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_NO_CRT
|
||||
template<typename AT>
|
||||
inline void Patch(AT address, std::initializer_list<uint8_t> list )
|
||||
{
|
||||
VP::Patch(DynBaseAddress(address), std::move(list));
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename AT>
|
||||
inline void Nop(AT address, size_t count)
|
||||
{
|
||||
VP::Nop(DynBaseAddress(address), count);
|
||||
}
|
||||
|
||||
template<typename AT, typename HT>
|
||||
inline void InjectHook(AT address, HT hook)
|
||||
{
|
||||
VP::InjectHook(DynBaseAddress(address), hook);
|
||||
}
|
||||
|
||||
template<typename AT, typename HT>
|
||||
inline void InjectHook(AT address, HT hook, unsigned int nType)
|
||||
{
|
||||
VP::InjectHook(DynBaseAddress(address), hook, nType);
|
||||
}
|
||||
|
||||
template<typename Func, typename AT>
|
||||
inline void ReadCall(AT address, Func& func)
|
||||
{
|
||||
Memory::ReadCall(DynBaseAddress(address), func);
|
||||
}
|
||||
|
||||
template<typename AT>
|
||||
inline void* ReadCallFrom(AT address, ptrdiff_t offset = 0)
|
||||
{
|
||||
Memory::ReadCallFrom(DynBaseAddress(address), offset);
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_NO_CRT
|
||||
inline bool MemEquals(uintptr_t address, std::initializer_list<uint8_t> val)
|
||||
{
|
||||
return Memory::MemEquals(DynBaseAddress(address), std::move(val));
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename AT>
|
||||
inline AT Verify(AT address, uintptr_t expected)
|
||||
{
|
||||
return Memory::Verify(address, DynBaseAddress(expected));
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#ifndef _MEMORY_NO_CRT
|
||||
|
||||
#include <forward_list>
|
||||
#include <tuple>
|
||||
#include <memory>
|
||||
|
||||
namespace ScopedUnprotect
|
||||
{
|
||||
class Unprotect
|
||||
{
|
||||
public:
|
||||
~Unprotect()
|
||||
{
|
||||
for ( auto& it : m_queriedProtects )
|
||||
{
|
||||
DWORD dwOldProtect;
|
||||
VirtualProtect( std::get<0>(it), std::get<1>(it), std::get<2>(it), &dwOldProtect );
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Unprotect() = default;
|
||||
|
||||
void UnprotectRange( DWORD_PTR BaseAddress, SIZE_T Size )
|
||||
{
|
||||
SIZE_T QueriedSize = 0;
|
||||
while ( QueriedSize < Size )
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION MemoryInf;
|
||||
DWORD dwOldProtect;
|
||||
|
||||
VirtualQuery( (LPCVOID)(BaseAddress + QueriedSize), &MemoryInf, sizeof(MemoryInf) );
|
||||
if ( MemoryInf.State == MEM_COMMIT && (MemoryInf.Type & MEM_IMAGE) != 0 &&
|
||||
(MemoryInf.Protect & (PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY|PAGE_READWRITE|PAGE_WRITECOPY)) == 0 )
|
||||
{
|
||||
const bool wasExecutable = (MemoryInf.Protect & (PAGE_EXECUTE|PAGE_EXECUTE_READ)) != 0;
|
||||
VirtualProtect( MemoryInf.BaseAddress, MemoryInf.RegionSize, wasExecutable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &dwOldProtect );
|
||||
m_queriedProtects.emplace_front( MemoryInf.BaseAddress, MemoryInf.RegionSize, MemoryInf.Protect );
|
||||
}
|
||||
QueriedSize += MemoryInf.RegionSize;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::forward_list< std::tuple< LPVOID, SIZE_T, DWORD > > m_queriedProtects;
|
||||
};
|
||||
|
||||
class Section : public Unprotect
|
||||
{
|
||||
public:
|
||||
Section( HINSTANCE hInstance, const char* name )
|
||||
{
|
||||
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)hInstance + ((PIMAGE_DOS_HEADER)hInstance)->e_lfanew);
|
||||
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(ntHeader);
|
||||
|
||||
DWORD_PTR VirtualAddress = DWORD_PTR(-1);
|
||||
SIZE_T VirtualSize = SIZE_T(-1);
|
||||
for ( SIZE_T i = 0, j = ntHeader->FileHeader.NumberOfSections; i < j; ++i, ++pSection )
|
||||
{
|
||||
if ( strncmp( (const char*)pSection->Name, name, IMAGE_SIZEOF_SHORT_NAME ) == 0 )
|
||||
{
|
||||
VirtualAddress = (DWORD_PTR)hInstance + pSection->VirtualAddress;
|
||||
VirtualSize = pSection->Misc.VirtualSize;
|
||||
m_locatedSection = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( VirtualAddress == DWORD_PTR(-1) )
|
||||
return;
|
||||
|
||||
UnprotectRange( VirtualAddress, VirtualSize );
|
||||
};
|
||||
|
||||
bool SectionLocated() const { return m_locatedSection; }
|
||||
|
||||
private:
|
||||
bool m_locatedSection = false;
|
||||
};
|
||||
|
||||
class FullModule : public Unprotect
|
||||
{
|
||||
public:
|
||||
FullModule( HINSTANCE hInstance )
|
||||
{
|
||||
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)hInstance + ((PIMAGE_DOS_HEADER)hInstance)->e_lfanew);
|
||||
UnprotectRange( (DWORD_PTR)hInstance, ntHeader->OptionalHeader.SizeOfImage );
|
||||
}
|
||||
};
|
||||
|
||||
inline std::unique_ptr<Unprotect> UnprotectSectionOrFullModule( HINSTANCE hInstance, const char* name )
|
||||
{
|
||||
std::unique_ptr<Section> section = std::make_unique<Section>( hInstance, name );
|
||||
if ( !section->SectionLocated() )
|
||||
{
|
||||
return std::make_unique<FullModule>( hInstance );
|
||||
}
|
||||
return section;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,212 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
// Stores a list of loaded modules with their names, WITHOUT extension
|
||||
class ModuleList
|
||||
{
|
||||
public:
|
||||
struct LazyEnumerateTag {};
|
||||
|
||||
ModuleList()
|
||||
{
|
||||
Enumerate();
|
||||
}
|
||||
|
||||
explicit ModuleList( LazyEnumerateTag )
|
||||
{
|
||||
}
|
||||
|
||||
// Initializes module list
|
||||
// Needs to be called before any calls to Get or GetAll
|
||||
void Enumerate()
|
||||
{
|
||||
// Cannot enumerate twice without cleaing
|
||||
assert( m_moduleList.size() == 0 );
|
||||
|
||||
constexpr size_t INITIAL_SIZE = sizeof(HMODULE) * 256;
|
||||
HMODULE* modules = static_cast<HMODULE*>(malloc( INITIAL_SIZE ));
|
||||
if ( modules != nullptr )
|
||||
{
|
||||
typedef BOOL (WINAPI * Func)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded);
|
||||
|
||||
HMODULE hLib = LoadLibrary( TEXT("kernel32") );
|
||||
assert( hLib != nullptr ); // If this fails then everything is probably broken anyway
|
||||
|
||||
Func pEnumProcessModules = reinterpret_cast<Func>(GetProcAddress( hLib, "K32EnumProcessModules" ));
|
||||
if ( pEnumProcessModules == nullptr )
|
||||
{
|
||||
// Try psapi
|
||||
FreeLibrary( hLib );
|
||||
hLib = LoadLibrary( TEXT("psapi") );
|
||||
if ( hLib != nullptr )
|
||||
{
|
||||
pEnumProcessModules = reinterpret_cast<Func>(GetProcAddress( hLib, "EnumProcessModules" ));
|
||||
}
|
||||
}
|
||||
|
||||
if ( pEnumProcessModules != nullptr )
|
||||
{
|
||||
const HANDLE currentProcess = GetCurrentProcess();
|
||||
DWORD cbNeeded = 0;
|
||||
if ( pEnumProcessModules( currentProcess, modules, INITIAL_SIZE, &cbNeeded ) != 0 )
|
||||
{
|
||||
if ( cbNeeded > INITIAL_SIZE )
|
||||
{
|
||||
HMODULE* newModules = static_cast<HMODULE*>(realloc( modules, cbNeeded ));
|
||||
if ( newModules != nullptr )
|
||||
{
|
||||
modules = newModules;
|
||||
|
||||
if ( pEnumProcessModules( currentProcess, modules, cbNeeded, &cbNeeded ) != 0 )
|
||||
{
|
||||
EnumerateInternal( modules, cbNeeded / sizeof(HMODULE) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnumerateInternal( modules, INITIAL_SIZE / sizeof(HMODULE) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnumerateInternal( modules, cbNeeded / sizeof(HMODULE) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( hLib != nullptr )
|
||||
{
|
||||
FreeLibrary( hLib );
|
||||
}
|
||||
|
||||
free( modules );
|
||||
}
|
||||
}
|
||||
|
||||
// Recreates module list
|
||||
void ReEnumerate()
|
||||
{
|
||||
Clear();
|
||||
Enumerate();
|
||||
}
|
||||
|
||||
// Clears module list
|
||||
void Clear()
|
||||
{
|
||||
m_moduleList.clear();
|
||||
}
|
||||
|
||||
// Gets handle of a loaded module with given name, NULL otherwise
|
||||
HMODULE Get( const wchar_t* moduleName ) const
|
||||
{
|
||||
// If vector is empty then we're trying to call it without calling Enumerate first
|
||||
assert( m_moduleList.size() != 0 );
|
||||
|
||||
auto it = std::find_if( m_moduleList.begin(), m_moduleList.end(), [&]( const auto& e ) {
|
||||
return _wcsicmp( moduleName, e.second.c_str() ) == 0;
|
||||
} );
|
||||
return it != m_moduleList.end() ? it->first : nullptr;
|
||||
}
|
||||
|
||||
// Gets handles to all loaded modules with given name
|
||||
std::vector<HMODULE> GetAll( const wchar_t* moduleName ) const
|
||||
{
|
||||
// If vector is empty then we're trying to call it without calling Enumerate first
|
||||
assert( m_moduleList.size() != 0 );
|
||||
|
||||
std::vector<HMODULE> results;
|
||||
for ( auto& e : m_moduleList )
|
||||
{
|
||||
if ( _wcsicmp( moduleName, e.second.c_str() ) == 0 )
|
||||
{
|
||||
results.push_back( e.first );
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
// Gets handle of a loaded module with given prefix, NULL otherwise
|
||||
HMODULE GetByPrefix( const wchar_t* modulePrefix ) const
|
||||
{
|
||||
// If vector is empty then we're trying to call it without calling Enumerate first
|
||||
assert( m_moduleList.size() != 0 );
|
||||
|
||||
const size_t len = wcslen( modulePrefix );
|
||||
auto it = std::find_if( m_moduleList.begin(), m_moduleList.end(), [&]( const auto& e ) {
|
||||
return _wcsnicmp( modulePrefix, e.second.c_str(), len ) == 0;
|
||||
} );
|
||||
return it != m_moduleList.end() ? it->first : nullptr;
|
||||
}
|
||||
|
||||
// Gets handles to all loaded modules with given prefix
|
||||
std::vector<HMODULE> GetAllByPrefix( const wchar_t* modulePrefix ) const
|
||||
{
|
||||
// If vector is empty then we're trying to call it without calling Enumerate first
|
||||
assert( m_moduleList.size() != 0 );
|
||||
|
||||
const size_t len = wcslen( modulePrefix );
|
||||
std::vector<HMODULE> results;
|
||||
for ( auto& e : m_moduleList )
|
||||
{
|
||||
if ( _wcsnicmp( modulePrefix, e.second.c_str(), len ) == 0 )
|
||||
{
|
||||
results.push_back( e.first );
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private:
|
||||
void EnumerateInternal( HMODULE* modules, size_t numModules )
|
||||
{
|
||||
size_t moduleNameLength = MAX_PATH;
|
||||
wchar_t* moduleName = static_cast<wchar_t*>( malloc( moduleNameLength * sizeof(moduleName[0]) ) );
|
||||
if ( moduleName != nullptr )
|
||||
{
|
||||
m_moduleList.reserve( numModules );
|
||||
for ( size_t i = 0; i < numModules; i++ )
|
||||
{
|
||||
// Obtain module name, with resizing if necessary
|
||||
DWORD size;
|
||||
while ( size = GetModuleFileNameW( *modules, moduleName, moduleNameLength ), size == moduleNameLength )
|
||||
{
|
||||
wchar_t* newName = static_cast<wchar_t*>( realloc( moduleName, 2 * moduleNameLength * sizeof(moduleName[0]) ) );
|
||||
if ( newName != nullptr )
|
||||
{
|
||||
moduleName = newName;
|
||||
moduleNameLength *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( size != 0 )
|
||||
{
|
||||
const wchar_t* nameBegin = wcsrchr( moduleName, '\\' ) + 1;
|
||||
const wchar_t* dotPos = wcsrchr( nameBegin, '.' );
|
||||
if ( dotPos != nullptr )
|
||||
{
|
||||
m_moduleList.emplace_back( *modules, std::wstring( nameBegin, dotPos ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_moduleList.emplace_back( *modules, nameBegin );
|
||||
}
|
||||
}
|
||||
modules++;
|
||||
}
|
||||
|
||||
free( moduleName );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector< std::pair<HMODULE, std::wstring> > m_moduleList;
|
||||
};
|
@ -1,274 +0,0 @@
|
||||
/*
|
||||
* This file is part of the CitizenFX project - http://citizen.re/
|
||||
*
|
||||
* See LICENSE and MENTIONS in the root of the source tree for information
|
||||
* regarding licensing.
|
||||
*/
|
||||
|
||||
#include "Patterns.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#include <algorithm>
|
||||
|
||||
#if PATTERNS_USE_HINTS
|
||||
#include <map>
|
||||
#endif
|
||||
|
||||
|
||||
#if PATTERNS_USE_HINTS
|
||||
|
||||
// from boost someplace
|
||||
template <std::uint64_t FnvPrime, std::uint64_t OffsetBasis>
|
||||
struct basic_fnv_1
|
||||
{
|
||||
std::uint64_t operator()(std::string_view text) const
|
||||
{
|
||||
std::uint64_t hash = OffsetBasis;
|
||||
for (auto it : text)
|
||||
{
|
||||
hash *= FnvPrime;
|
||||
hash ^= it;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr std::uint64_t fnv_prime = 1099511628211u;
|
||||
static constexpr std::uint64_t fnv_offset_basis = 14695981039346656037u;
|
||||
|
||||
typedef basic_fnv_1<fnv_prime, fnv_offset_basis> fnv_1;
|
||||
|
||||
#endif
|
||||
|
||||
namespace hook
|
||||
{
|
||||
ptrdiff_t pattern::get_process_base()
|
||||
{
|
||||
return ptrdiff_t(GetModuleHandle(nullptr));
|
||||
}
|
||||
|
||||
|
||||
#if PATTERNS_USE_HINTS
|
||||
static auto& getHints()
|
||||
{
|
||||
static std::multimap<uint64_t, uintptr_t> hints;
|
||||
return hints;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void TransformPattern(std::string_view pattern, std::basic_string<uint8_t>& data, std::basic_string<uint8_t>& mask)
|
||||
{
|
||||
uint8_t tempDigit = 0;
|
||||
bool tempFlag = false;
|
||||
|
||||
auto tol = [] (char ch) -> uint8_t
|
||||
{
|
||||
if (ch >= 'A' && ch <= 'F') return uint8_t(ch - 'A' + 10);
|
||||
if (ch >= 'a' && ch <= 'f') return uint8_t(ch - 'a' + 10);
|
||||
return uint8_t(ch - '0');
|
||||
};
|
||||
|
||||
for (auto ch : pattern)
|
||||
{
|
||||
if (ch == ' ')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (ch == '?')
|
||||
{
|
||||
data.push_back(0);
|
||||
mask.push_back(0);
|
||||
}
|
||||
else if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f'))
|
||||
{
|
||||
uint8_t thisDigit = tol(ch);
|
||||
|
||||
if (!tempFlag)
|
||||
{
|
||||
tempDigit = thisDigit << 4;
|
||||
tempFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempDigit |= thisDigit;
|
||||
tempFlag = false;
|
||||
|
||||
data.push_back(tempDigit);
|
||||
mask.push_back(0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class executable_meta
|
||||
{
|
||||
private:
|
||||
uintptr_t m_begin;
|
||||
uintptr_t m_end;
|
||||
|
||||
template<typename TReturn, typename TOffset>
|
||||
TReturn* getRVA(TOffset rva)
|
||||
{
|
||||
return (TReturn*)(m_begin + rva);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit executable_meta(uintptr_t module)
|
||||
: m_begin(module)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dosHeader = getRVA<IMAGE_DOS_HEADER>(0);
|
||||
PIMAGE_NT_HEADERS ntHeader = getRVA<IMAGE_NT_HEADERS>(dosHeader->e_lfanew);
|
||||
|
||||
m_end = m_begin + ntHeader->OptionalHeader.SizeOfImage;
|
||||
}
|
||||
|
||||
executable_meta(uintptr_t begin, uintptr_t end)
|
||||
: m_begin(begin), m_end(end)
|
||||
{
|
||||
}
|
||||
|
||||
inline uintptr_t begin() const { return m_begin; }
|
||||
inline uintptr_t end() const { return m_end; }
|
||||
};
|
||||
|
||||
void pattern::Initialize(std::string_view pattern)
|
||||
{
|
||||
// get the hash for the base pattern
|
||||
#if PATTERNS_USE_HINTS
|
||||
m_hash = fnv_1()(pattern);
|
||||
#endif
|
||||
|
||||
// transform the base pattern from IDA format to canonical format
|
||||
TransformPattern(pattern, m_bytes, m_mask);
|
||||
|
||||
#if PATTERNS_USE_HINTS
|
||||
// if there's hints, try those first
|
||||
#if PATTERNS_CAN_SERIALIZE_HINTS
|
||||
if (m_rangeStart == reinterpret_cast<uintptr_t>(GetModuleHandle(nullptr)))
|
||||
#endif
|
||||
{
|
||||
auto range = getHints().equal_range(m_hash);
|
||||
|
||||
if (range.first != range.second)
|
||||
{
|
||||
std::for_each(range.first, range.second, [&] (const auto& hint)
|
||||
{
|
||||
ConsiderHint(hint.second);
|
||||
});
|
||||
|
||||
// if the hints succeeded, we don't need to do anything more
|
||||
if (!m_matches.empty())
|
||||
{
|
||||
m_matched = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void pattern::EnsureMatches(uint32_t maxCount)
|
||||
{
|
||||
if (m_matched)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// scan the executable for code
|
||||
executable_meta executable = m_rangeStart != 0 && m_rangeEnd != 0 ? executable_meta(m_rangeStart, m_rangeEnd) : executable_meta(m_rangeStart);
|
||||
|
||||
auto matchSuccess = [&] (uintptr_t address)
|
||||
{
|
||||
#if PATTERNS_USE_HINTS
|
||||
getHints().emplace(m_hash, address);
|
||||
#else
|
||||
(void)address;
|
||||
#endif
|
||||
|
||||
return (m_matches.size() == maxCount);
|
||||
};
|
||||
|
||||
const uint8_t* pattern = m_bytes.data();
|
||||
const uint8_t* mask = m_mask.data();
|
||||
const size_t maskSize = m_mask.size();
|
||||
const size_t lastWild = m_mask.find_last_not_of(uint8_t(0xFF));
|
||||
|
||||
ptrdiff_t Last[256];
|
||||
|
||||
std::fill(std::begin(Last), std::end(Last), lastWild == std::string::npos ? -1 : static_cast<ptrdiff_t>(lastWild) );
|
||||
|
||||
for ( ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(maskSize); ++i )
|
||||
{
|
||||
if ( Last[ pattern[i] ] < i )
|
||||
{
|
||||
Last[ pattern[i] ] = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (uintptr_t i = executable.begin(), end = executable.end() - maskSize; i <= end;)
|
||||
{
|
||||
uint8_t* ptr = reinterpret_cast<uint8_t*>(i);
|
||||
ptrdiff_t j = maskSize - 1;
|
||||
|
||||
while((j >= 0) && pattern[j] == (ptr[j] & mask[j])) j--;
|
||||
|
||||
if(j < 0)
|
||||
{
|
||||
m_matches.emplace_back(ptr);
|
||||
|
||||
if (matchSuccess(i))
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
else i += std::max(ptrdiff_t(1), j - Last[ ptr[j] ]);
|
||||
}
|
||||
|
||||
m_matched = true;
|
||||
}
|
||||
|
||||
bool pattern::ConsiderHint(uintptr_t offset)
|
||||
{
|
||||
uint8_t* ptr = reinterpret_cast<uint8_t*>(offset);
|
||||
|
||||
#if PATTERNS_CAN_SERIALIZE_HINTS
|
||||
const uint8_t* pattern = m_bytes.data();
|
||||
const uint8_t* mask = m_mask.data();
|
||||
|
||||
for (size_t i = 0, j = m_mask.size(); i < j; i++)
|
||||
{
|
||||
if (pattern[i] != (ptr[i] & mask[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m_matches.emplace_back(ptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if PATTERNS_USE_HINTS && PATTERNS_CAN_SERIALIZE_HINTS
|
||||
void pattern::hint(uint64_t hash, uintptr_t address)
|
||||
{
|
||||
auto& hints = getHints();
|
||||
|
||||
auto range = hints.equal_range(hash);
|
||||
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
{
|
||||
if (it->second == address)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
hints.emplace(hash, address);
|
||||
}
|
||||
#endif
|
||||
}
|
@ -1,181 +0,0 @@
|
||||
/*
|
||||
* This file is part of the CitizenFX project - http://citizen.re/
|
||||
*
|
||||
* See LICENSE and MENTIONS in the root of the source tree for information
|
||||
* regarding licensing.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4201)
|
||||
|
||||
namespace hook
|
||||
{
|
||||
class pattern_match
|
||||
{
|
||||
private:
|
||||
void* m_pointer;
|
||||
|
||||
public:
|
||||
inline pattern_match(void* pointer)
|
||||
: m_pointer(pointer)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* get(ptrdiff_t offset = 0) const
|
||||
{
|
||||
char* ptr = reinterpret_cast<char*>(m_pointer);
|
||||
return reinterpret_cast<T*>(ptr + offset);
|
||||
}
|
||||
};
|
||||
|
||||
class pattern
|
||||
{
|
||||
private:
|
||||
std::basic_string<uint8_t> m_bytes;
|
||||
std::basic_string<uint8_t> m_mask;
|
||||
|
||||
#if PATTERNS_USE_HINTS
|
||||
uint64_t m_hash;
|
||||
#endif
|
||||
|
||||
std::vector<pattern_match> m_matches;
|
||||
|
||||
bool m_matched = false;
|
||||
|
||||
uintptr_t m_rangeStart;
|
||||
uintptr_t m_rangeEnd;
|
||||
|
||||
private:
|
||||
static ptrdiff_t get_process_base();
|
||||
|
||||
void Initialize(std::string_view pattern);
|
||||
|
||||
bool ConsiderHint(uintptr_t offset);
|
||||
|
||||
void EnsureMatches(uint32_t maxCount);
|
||||
|
||||
inline pattern_match _get_internal(size_t index) const
|
||||
{
|
||||
return m_matches[index];
|
||||
}
|
||||
|
||||
inline pattern(uintptr_t module)
|
||||
: pattern( module, 0 )
|
||||
{
|
||||
}
|
||||
|
||||
inline pattern(uintptr_t begin, uintptr_t end)
|
||||
: m_rangeStart(begin), m_rangeEnd(end)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
pattern(std::string_view pattern)
|
||||
: pattern(get_process_base())
|
||||
{
|
||||
Initialize(std::move(pattern));
|
||||
}
|
||||
|
||||
inline pattern(void* module, std::string_view pattern)
|
||||
: pattern(reinterpret_cast<uintptr_t>(module))
|
||||
{
|
||||
Initialize(std::move(pattern));
|
||||
}
|
||||
|
||||
inline pattern(uintptr_t begin, uintptr_t end, std::string_view pattern)
|
||||
: m_rangeStart(begin), m_rangeEnd(end)
|
||||
{
|
||||
Initialize(std::move(pattern));
|
||||
}
|
||||
|
||||
inline pattern&& count(uint32_t expected)
|
||||
{
|
||||
EnsureMatches(expected);
|
||||
assert(m_matches.size() == expected);
|
||||
return std::forward<pattern>(*this);
|
||||
}
|
||||
|
||||
inline pattern&& count_hint(uint32_t expected)
|
||||
{
|
||||
EnsureMatches(expected);
|
||||
return std::forward<pattern>(*this);
|
||||
}
|
||||
|
||||
inline pattern&& clear()
|
||||
{
|
||||
m_matches.clear();
|
||||
m_matched = false;
|
||||
return std::forward<pattern>(*this);
|
||||
}
|
||||
|
||||
inline size_t size()
|
||||
{
|
||||
EnsureMatches(UINT32_MAX);
|
||||
return m_matches.size();
|
||||
}
|
||||
|
||||
inline bool empty()
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
inline pattern_match get(size_t index)
|
||||
{
|
||||
EnsureMatches(UINT32_MAX);
|
||||
return _get_internal(index);
|
||||
}
|
||||
|
||||
inline pattern_match get_one()
|
||||
{
|
||||
return std::forward<pattern>(*this).count(1)._get_internal(0);
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
inline auto get_first(ptrdiff_t offset = 0)
|
||||
{
|
||||
return get_one().get<T>(offset);
|
||||
}
|
||||
|
||||
template <typename Pred>
|
||||
inline Pred for_each_result(Pred&& pred)
|
||||
{
|
||||
EnsureMatches(UINT32_MAX);
|
||||
for ( auto it : m_matches )
|
||||
{
|
||||
std::forward<Pred>(pred)(it);
|
||||
}
|
||||
return std::forward<Pred>(pred);
|
||||
}
|
||||
|
||||
public:
|
||||
#if PATTERNS_USE_HINTS && PATTERNS_CAN_SERIALIZE_HINTS
|
||||
// define a hint
|
||||
static void hint(uint64_t hash, uintptr_t address);
|
||||
#endif
|
||||
};
|
||||
|
||||
inline pattern make_module_pattern(void* module, std::string_view bytes)
|
||||
{
|
||||
return pattern(module, std::move(bytes));
|
||||
}
|
||||
|
||||
inline pattern make_range_pattern(uintptr_t begin, uintptr_t end, std::string_view bytes)
|
||||
{
|
||||
return pattern(begin, end, std::move(bytes));
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
inline auto get_pattern(std::string_view pattern_string, ptrdiff_t offset = 0)
|
||||
{
|
||||
return pattern(std::move(pattern_string)).get_first<T>(offset);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning(pop)
|
@ -8,7 +8,7 @@
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
#include "MemoryMgr.h"
|
||||
#include "MemoryMgr.GTA.h"
|
||||
#include "Utils/MemoryMgr.h"
|
||||
#include "Utils/MemoryMgr.GTA.h"
|
||||
|
||||
#define DISABLE_FLA_DONATION_WINDOW 0
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "StoredCar.h"
|
||||
#include "Patterns.h"
|
||||
#include "Utils/Patterns.h"
|
||||
|
||||
#if _GTA_III
|
||||
static auto FindPlayerPed = hook::get_pattern<class CEntity*()>( "6B C0 4F 8B 04 85 ? ? ? ? C3", -7 );
|
||||
|
@ -3,7 +3,7 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
#include "ModuleList.hpp"
|
||||
#include "Utils/ModuleList.hpp"
|
||||
|
||||
int32_t (*FLAUtils::GetExtendedID8Func)(const uint8_t* ptr) = FLAUtils::GetExtendedID8_Stock;
|
||||
int32_t (*FLAUtils::GetExtendedID16Func)(const uint16_t* ptr) = FLAUtils::GetExtendedID16_Stock;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "StdAfx.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include "Patterns.h"
|
||||
#include "Utils/Patterns.h"
|
||||
|
||||
int& CTimer::m_snTimeInMilliseconds = **hook::get_pattern<int*>( "83 E4 F8 89 44 24 08 C7 44 24 0C 00 00 00 00 DF 6C 24 08", -20 + 1 );
|
||||
|
||||
|
1
SilentPatch/Utils
Submodule
1
SilentPatch/Utils
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 43e545d9fe2caa609579dd3936702a4566b71258
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "General.h"
|
||||
#include "Timer.h"
|
||||
#include "Patterns.h"
|
||||
#include "Utils/Patterns.h"
|
||||
#include "Common.h"
|
||||
#include "Common_ddraw.h"
|
||||
|
||||
|
@ -25,13 +25,13 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Master|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Patterns.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Master|Win32'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\StoredCar.cpp" />
|
||||
<ClCompile Include="..\SilentPatch\Timer.cpp" />
|
||||
<ClCompile Include="..\SilentPatch\Utils\Patterns.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Master|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SilentPatchIII.cpp" />
|
||||
<ClCompile Include="StdAfxIII.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
@ -43,12 +43,12 @@
|
||||
<ClInclude Include="..\SilentPatch\Common.h" />
|
||||
<ClInclude Include="..\SilentPatch\Common_ddraw.h" />
|
||||
<ClInclude Include="..\SilentPatch\General.h" />
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.GTA.h" />
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.h" />
|
||||
<ClInclude Include="..\SilentPatch\Patterns.h" />
|
||||
<ClInclude Include="..\SilentPatch\StdAfx.h" />
|
||||
<ClInclude Include="..\SilentPatch\StoredCar.h" />
|
||||
<ClInclude Include="..\SilentPatch\Timer.h" />
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.GTA.h" />
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.h" />
|
||||
<ClInclude Include="..\SilentPatch\Utils\Patterns.h" />
|
||||
<ClInclude Include="VehicleIII.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -13,6 +13,12 @@
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Utils">
|
||||
<UniqueIdentifier>{6f7b5bc0-8528-4f8e-a767-183d8c1abb17}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Utils">
|
||||
<UniqueIdentifier>{66df9142-3ab6-4f22-aca5-69b4c3d9b475}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\SilentPatch\Timer.cpp">
|
||||
@ -24,9 +30,6 @@
|
||||
<ClCompile Include="StdAfxIII.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Patterns.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Common.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -36,11 +39,11 @@
|
||||
<ClCompile Include="..\SilentPatch\StoredCar.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Utils\Patterns.cpp">
|
||||
<Filter>Source Files\Utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -50,9 +53,6 @@
|
||||
<ClInclude Include="..\SilentPatch\StdAfx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Patterns.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VehicleIII.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -65,8 +65,14 @@
|
||||
<ClInclude Include="..\SilentPatch\StoredCar.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.GTA.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.GTA.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Utils\Patterns.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -21,9 +21,9 @@
|
||||
#include "WaveDecoderSA.h"
|
||||
#include "FLACDecoderSA.h"
|
||||
|
||||
#include "Patterns.h"
|
||||
#include "DelimStringReader.h"
|
||||
#include "ModuleList.hpp"
|
||||
#include "Utils/Patterns.h"
|
||||
#include "Utils/DelimStringReader.h"
|
||||
#include "Utils/ModuleList.hpp"
|
||||
|
||||
#include "debugmenu_public.h"
|
||||
#include "resource.h"
|
||||
|
@ -186,16 +186,16 @@ copy /y "$(TargetPath)" "D:\gry\GTA San Andreas clean\scripts\newsteam_r2_lowvio
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\SilentPatch\Patterns.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Master|Win32'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\TheFLAUtils.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Master|Win32'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Utils\Patterns.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Master|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AudioHardwareSA.cpp" />
|
||||
<ClCompile Include="FireManagerSA.cpp" />
|
||||
<ClCompile Include="FLACDecoderSA.cpp" />
|
||||
@ -218,19 +218,18 @@ copy /y "$(TargetPath)" "D:\gry\GTA San Andreas clean\scripts\newsteam_r2_lowvio
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\SilentPatch\debugmenu_public.h" />
|
||||
<ClInclude Include="..\SilentPatch\DelimStringReader.h" />
|
||||
<ClInclude Include="..\SilentPatch\FLAC\callback.h" />
|
||||
<ClInclude Include="..\SilentPatch\FLAC\export.h" />
|
||||
<ClInclude Include="..\SilentPatch\FLAC\format.h" />
|
||||
<ClInclude Include="..\SilentPatch\FLAC\metadata.h" />
|
||||
<ClInclude Include="..\SilentPatch\FLAC\ordinals.h" />
|
||||
<ClInclude Include="..\SilentPatch\FLAC\stream_decoder.h" />
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.GTA.h" />
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.h" />
|
||||
<ClInclude Include="..\SilentPatch\ModuleList.hpp" />
|
||||
<ClInclude Include="..\SilentPatch\Patterns.h" />
|
||||
<ClInclude Include="..\SilentPatch\resource1.h" />
|
||||
<ClInclude Include="..\SilentPatch\TheFLAUtils.h" />
|
||||
<ClInclude Include="..\SilentPatch\Utils\DelimStringReader.h" />
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.GTA.h" />
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.h" />
|
||||
<ClInclude Include="..\SilentPatch\Utils\Patterns.h" />
|
||||
<ClInclude Include="AudioHardwareSA.h" />
|
||||
<ClInclude Include="FireManagerSA.h" />
|
||||
<ClInclude Include="FLACDecoderSA.h" />
|
||||
|
@ -19,6 +19,12 @@
|
||||
<Filter Include="Source Files\decoders">
|
||||
<UniqueIdentifier>{f4ecbe23-228b-461b-b37f-d718e7ca92ae}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Utils">
|
||||
<UniqueIdentifier>{d46aa122-7a45-44f2-a031-ad8e9b946ed2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Utils">
|
||||
<UniqueIdentifier>{09c5ceab-2ac8-4111-b2d1-d2c7379cb5c1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SilentPatchSA.cpp">
|
||||
@ -57,9 +63,6 @@
|
||||
<ClCompile Include="FLACDecoderSA.cpp">
|
||||
<Filter>Source Files\decoders</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Patterns.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\TheFLAUtils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -72,11 +75,11 @@
|
||||
<ClCompile Include="FireManagerSA.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Utils\Patterns.cpp">
|
||||
<Filter>Source Files\Utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\FLAC\callback.h">
|
||||
<Filter>Header Files\FLAC</Filter>
|
||||
</ClInclude>
|
||||
@ -137,15 +140,9 @@
|
||||
<ClInclude Include="FLACDecoderSA.h">
|
||||
<Filter>Source Files\decoders</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Patterns.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\resource1.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\DelimStringReader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\TheFLAUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -155,21 +152,27 @@
|
||||
<ClInclude Include="..\SilentPatch\debugmenu_public.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\ModuleList.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PlayerInfoSA.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FireManagerSA.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.GTA.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RWUtils.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Utils\DelimStringReader.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.GTA.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Utils\Patterns.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\SilentPatch\SilentPatch.rc">
|
||||
|
@ -17,8 +17,8 @@
|
||||
#include <rphanim.h>
|
||||
#include <rtpng.h>
|
||||
|
||||
#include "MemoryMgr.h"
|
||||
#include "MemoryMgr.GTA.h"
|
||||
#include "Utils/MemoryMgr.h"
|
||||
#include "Utils/MemoryMgr.GTA.h"
|
||||
#include "Maths.h"
|
||||
#include "rwutils.hpp"
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "VehicleSA.h"
|
||||
#include "TimerSA.h"
|
||||
#include "PedSA.h"
|
||||
#include "DelimStringReader.h"
|
||||
#include "Utils/DelimStringReader.h"
|
||||
#include "PlayerInfoSA.h"
|
||||
|
||||
static constexpr float PHOENIX_FLUTTER_PERIOD = 70.0f;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Timer.h"
|
||||
#include "Patterns.h"
|
||||
#include "Utils/Patterns.h"
|
||||
#include "Common.h"
|
||||
#include "Common_ddraw.h"
|
||||
#include "General.h"
|
||||
|
@ -173,12 +173,12 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\SilentPatch\Common_ddraw.h" />
|
||||
<ClInclude Include="..\SilentPatch\General.h" />
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.GTA.h" />
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.h" />
|
||||
<ClInclude Include="..\SilentPatch\Patterns.h" />
|
||||
<ClInclude Include="..\SilentPatch\StdAfx.h" />
|
||||
<ClInclude Include="..\SilentPatch\StoredCar.h" />
|
||||
<ClInclude Include="..\SilentPatch\Timer.h" />
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.GTA.h" />
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.h" />
|
||||
<ClInclude Include="..\SilentPatch\Utils\Patterns.h" />
|
||||
<ClInclude Include="ModelInfoVC.h" />
|
||||
<ClInclude Include="VehicleVC.h" />
|
||||
</ItemGroup>
|
||||
@ -193,13 +193,13 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Master|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Patterns.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Master|Win32'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\StoredCar.cpp" />
|
||||
<ClCompile Include="..\SilentPatch\Timer.cpp" />
|
||||
<ClCompile Include="..\SilentPatch\Utils\Patterns.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Master|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ModelInfoVC.cpp" />
|
||||
<ClCompile Include="SilentPatchVC.cpp" />
|
||||
<ClCompile Include="StdAfxVC.cpp">
|
||||
|
@ -13,11 +13,14 @@
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Utils">
|
||||
<UniqueIdentifier>{e3c269eb-37ad-4a59-a26c-cb1547484475}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Utils">
|
||||
<UniqueIdentifier>{42382fee-b609-4a36-9bef-fa812755d623}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -27,9 +30,6 @@
|
||||
<ClInclude Include="..\SilentPatch\StdAfx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Patterns.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\StoredCar.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -42,8 +42,14 @@
|
||||
<ClInclude Include="ModelInfoVC.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\MemoryMgr.GTA.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.GTA.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SilentPatch\Utils\Patterns.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -56,9 +62,6 @@
|
||||
<ClCompile Include="SilentPatchVC.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Patterns.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Common.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -71,6 +74,9 @@
|
||||
<ClCompile Include="ModelInfoVC.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SilentPatch\Utils\Patterns.cpp">
|
||||
<Filter>Source Files\Utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\SilentPatch\SilentPatch.rc">
|
||||
|
Loading…
Reference in New Issue
Block a user