Premake, Gitmodules, Readme

This commit is contained in:
Pocakking
2019-06-23 22:00:18 +02:00
parent 1ec1716c2e
commit 17fe337342
108 changed files with 303 additions and 68667 deletions

1
BigBaseV2/src/common.cpp Normal file
View File

@ -0,0 +1 @@
#include "common.hpp"

77
BigBaseV2/src/common.hpp Normal file
View File

@ -0,0 +1,77 @@
#pragma once
#include <SDKDDKVer.h>
#include <Windows.h>
#include <D3D11.h>
#include <wrl/client.h>
#include <cinttypes>
#include <cstddef>
#include <cstdint>
#include <chrono>
#include <ctime>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <atomic>
#include <mutex>
#include <thread>
#include <memory>
#include <new>
#include <sstream>
#include <string>
#include <string_view>
#include <algorithm>
#include <functional>
#include <utility>
#include <stack>
#include <vector>
#include <typeinfo>
#include <type_traits>
#include <exception>
#include <stdexcept>
#include <any>
#include <optional>
#include <variant>
#include <fmt/format.h>
#include <nlohmann/json.hpp>
#include <StackWalker.h>
#include "logger.hpp"
namespace big
{
using namespace std::chrono_literals;
template <typename T>
using comptr = Microsoft::WRL::ComPtr<T>;
inline HMODULE g_hmodule{};
inline HANDLE g_main_thread{};
inline DWORD g_main_thread_id{};
inline std::atomic_bool g_running{ true };
struct stackwalker : public StackWalker
{
using StackWalker::StackWalker;
void OnOutput(LPCSTR szText) override
{
g_logger->raw(log_color::red, szText);
}
};
inline stackwalker g_stackwalker;
}

5846
BigBaseV2/src/crossmap.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
#include "common.hpp"
#include "detour_hook.hpp"
#include "logger.hpp"
#include "memory/handle.hpp"
#include <MinHook.h>
namespace big
{
detour_hook::detour_hook(std::string name, void *target, void *detour) :
m_name(std::move(name)),
m_target(target),
m_detour(detour)
{
fix_hook_address();
if (auto status = MH_CreateHook(m_target, m_detour, &m_original); status == MH_OK)
{
LOG_INFO("Created hook '{}'.", m_name);
}
else
{
throw std::runtime_error(fmt::format("Failed to create hook '{}' at 0x{:X} (error: {})", m_name, reinterpret_cast<std::uintptr_t>(m_target), MH_StatusToString(status)));
}
}
detour_hook::~detour_hook() noexcept
{
if (m_target)
{
MH_RemoveHook(m_target);
}
LOG_INFO("Removed hook '{}',", m_name);
}
void detour_hook::enable()
{
if (auto status = MH_EnableHook(m_target); status == MH_OK)
{
LOG_INFO("Enabled hook '{}'.", m_name);
}
else
{
throw std::runtime_error(fmt::format("Failed to enable hook 0x{:X} ({})", reinterpret_cast<std::uintptr_t>(m_target), MH_StatusToString(status)));
}
}
void detour_hook::disable()
{
if (auto status = MH_DisableHook(m_target); status == MH_OK)
{
LOG_INFO("Disabled hook '{}'", m_name);
}
else
{
LOG_ERROR("Failed to disable hook '{}'.", m_name);
}
}
DWORD exp_handler(PEXCEPTION_POINTERS exp, std::string const &name)
{
return exp->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH;
}
void detour_hook::fix_hook_address()
{
__try
{
auto ptr = memory::handle(m_target);
while (ptr.as<std::uint8_t&>() == 0xE9)
{
ptr = ptr.add(1).rip();
}
m_target = ptr.as<void*>();
}
__except (exp_handler(GetExceptionInformation(), m_name))
{
[this]()
{
throw std::runtime_error(fmt::format("Failed to fix hook address for '{}'", m_name));
}();
}
}
}

View File

@ -0,0 +1,35 @@
#pragma once
namespace big
{
class detour_hook
{
public:
explicit detour_hook(std::string name, void *target, void *detour);
~detour_hook() noexcept;
detour_hook(detour_hook&& that) = delete;
detour_hook& operator=(detour_hook&& that) = delete;
detour_hook(detour_hook const&) = delete;
detour_hook& operator=(detour_hook const&) = delete;
void enable();
void disable();
template <typename T>
T get_original();
void fix_hook_address();
private:
std::string m_name;
void *m_target;
void *m_detour;
void *m_original{};
};
template <typename T>
inline T detour_hook::get_original()
{
return static_cast<T>(m_original);
}
}

View File

@ -0,0 +1,21 @@
#include "common.hpp"
#include "features.hpp"
#include "logger.hpp"
#include "natives.hpp"
#include "script.hpp"
namespace big
{
void features::run_tick()
{
}
void features::script_func()
{
while (true)
{
run_tick();
script::get_current()->yield();
}
}
}

View File

@ -0,0 +1,8 @@
#pragma once
#include "common.hpp"
namespace big::features
{
void run_tick();
void script_func();
}

View File

@ -0,0 +1,53 @@
#include "common.hpp"
#include "fiber_pool.hpp"
#include "script.hpp"
#include "script_mgr.hpp"
namespace big
{
fiber_pool::fiber_pool(std::size_t num_fibers)
{
for (std::size_t i = 0; i < num_fibers; ++i)
{
g_script_mgr.add_script(std::make_unique<script>(&fiber_func));
}
g_fiber_pool = this;
}
fiber_pool::~fiber_pool()
{
g_fiber_pool = nullptr;
}
void fiber_pool::queue_job(std::function<void()> func)
{
if (func)
{
std::lock_guard lock(m_mutex);
m_jobs.push(std::move(func));
}
}
void fiber_pool::fiber_tick()
{
std::unique_lock lock(m_mutex);
if (!m_jobs.empty())
{
auto job = std::move(m_jobs.top());
m_jobs.pop();
lock.unlock();
std::invoke(std::move(job));
}
}
void fiber_pool::fiber_func()
{
while (true)
{
g_fiber_pool->fiber_tick();
script::get_current()->yield();
}
}
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "common.hpp"
namespace big
{
class fiber_pool
{
public:
explicit fiber_pool(std::size_t num_fibers);
~fiber_pool();
void queue_job(std::function<void()> func);
void fiber_tick();
static void fiber_func();
private:
std::recursive_mutex m_mutex;
std::stack<std::function<void()>> m_jobs;
};
inline fiber_pool *g_fiber_pool{};
}

11734
BigBaseV2/src/fonts.cpp Normal file

File diff suppressed because it is too large Load Diff

4
BigBaseV2/src/fonts.hpp Normal file
View File

@ -0,0 +1,4 @@
#pragma once
#include <cstdint>
extern const std::uint8_t font_rubik[140732];

View File

@ -0,0 +1,11 @@
#pragma once
#include "common.hpp"
#include "gta/fwddec.hpp"
#include "gta/natives.hpp"
namespace big::functions
{
using run_script_threads_t = bool(*)(std::uint32_t ops_to_execute);
using get_native_handler_t = rage::scrNativeHandler(*)(rage::scrNativeRegistrationTable*, rage::scrNativeHash);
using fix_vectors_t = void(*)(rage::scrNativeCallContext*);
}

View File

@ -0,0 +1,65 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
namespace rage
{
template <typename T>
class atArray
{
public:
T *begin()
{
return m_data;
}
T *end()
{
return m_data + m_size;
}
const T *begin() const
{
return m_data;
}
const T *end() const
{
return m_data + m_size;
}
T *data()
{
return m_data;
}
const T *data() const
{
return m_data;
}
std::uint16_t size() const
{
return m_size;
}
std::uint16_t capacity() const
{
return m_capacity;
}
T &operator[](std::uint16_t index)
{
return m_data[index];
}
const T &operator[](std::uint16_t index) const
{
return m_data[index];
}
private:
T *m_data;
std::uint16_t m_size;
std::uint16_t m_capacity;
};
}

View File

@ -0,0 +1,18 @@
#pragma once
namespace rage
{
class datBase
{
public:
virtual ~datBase() = default;
};
class pgBase
{
public:
virtual ~pgBase() = default;
private:
void *m_pgunk;
};
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <cstdint>
namespace rage
{
struct rgbaColor
{
rgbaColor(std::uint8_t r = 0, std::uint8_t g = 0, std::uint8_t b = 0, std::uint8_t a = 255) :
r(r), g(g), b(b), a(a)
{}
std::uint8_t r;
std::uint8_t g;
std::uint8_t b;
std::uint8_t a;
};
static_assert(sizeof(rgbaColor) == sizeof(std::uint8_t) * 4);
}

View File

@ -0,0 +1,7 @@
#pragma once
#include <cstdint>
enum eGameState : std::uint32_t
{
Playing = 0
};

View File

@ -0,0 +1,44 @@
#pragma once
#include <cstdint>
#include "ref_aware.hpp"
namespace rage
{
class fwExtension
{
public:
virtual ~fwExtension() = default;
virtual void unk_0x08() = 0;
virtual void unk_0x10() = 0;
virtual std::uint32_t get_id() = 0;
};
class fwExtensionContainer
{
public:
fwExtension *m_entry;
fwExtensionContainer* m_next;
};
class fwExtensibleBase : public fwRefAwareBase
{
public:
virtual bool is_of_type(std::uint32_t hash) = 0;
virtual std::uint32_t const &get_type() = 0;
public:
fwExtensionContainer* m_extension_container; // 0x10
private:
void *m_extensible_unk; // 0x18
public:
template <typename T>
bool is_of_type()
{
static auto name = (typeid(T).name()) + 6; // Skip "class "
static auto name_hash = util::joaat(name);
return is_of_type(name_hash);
}
};
static_assert(sizeof(fwExtensibleBase) == 0x20);
}

View File

@ -0,0 +1,68 @@
#pragma once
namespace rage
{
template <typename T>
class atArray;
class datBitBuffer;
class sysMemAllocator;
class scriptIdBase;
class scriptId;
class scriptHandler;
class scriptHandlerNetComponent;
class scriptHandlerObject;
class scriptHandlerMgr;
class scrProgram;
class scrProgramTable;
class scrThreadContext;
class scrThread;
class tlsContext;
class netLoggingInterface;
class netLogStub;
class netPlayer;
class netPlayerMgr;
class netGameEvent;
class netEventMgr;
class netObject;
class netObjectMgrBase;
class scrNativeCallContext;
class scrNativeRegistration;
class scrNativeRegistrationTable;
class fwRefAwareBase;
class fwExtensibleBase;
class fwEntity;
class fwArchetype;
}
class GtaThread;
class CGameScriptId;
class CGameScriptHandler;
class CGameScriptHandlerNetwork;
class CGameScriptHandlerMgr;
class CEntity;
class CDynamicEntity;
class CPhysical;
class CPed;
class CVehicle;
class CObject;
class CPickup;
class CPedFactory;
class CVehicleFactory;
class CNetGamePlayer;
class CNetworkPlayerMgr;
class CPlayerInfo;

View File

@ -0,0 +1,84 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <string_view>
#include <type_traits>
namespace rage
{
using joaat_t = std::uint32_t;
inline constexpr char joaat_to_lower(char c)
{
return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
}
template <std::size_t CharCount>
struct constexpr_joaat
{
char data[CharCount];
template <std::size_t... Indices>
constexpr constexpr_joaat(const char *str, std::index_sequence<Indices...>) :
data{ (str[Indices])... }
{
}
constexpr joaat_t operator()()
{
joaat_t hash = 0;
for (std::size_t i = 0; i < CharCount; ++i)
{
hash += joaat_to_lower(data[i]);
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
};
inline joaat_t joaat(std::string_view str)
{
joaat_t hash = 0;
for (char c : str)
{
hash += joaat_to_lower(c);
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
inline joaat_t joaat(const char *str)
{
joaat_t hash = 0;
while (*str)
{
hash += joaat_to_lower(*(str++));
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
}
#define RAGE_JOAAT_IMPL(str) (::rage::constexpr_joaat<sizeof(str) - 1>((str), std::make_index_sequence<sizeof(str) - 1>())())
#define RAGE_JOAAT(str) (std::integral_constant<rage::joaat_t, RAGE_JOAAT_IMPL(str)>::value)

View File

@ -0,0 +1,22 @@
#pragma once
#include "vector.hpp"
namespace rage
{
class matrix4x4
{
public:
union
{
struct
{
vector4 _1;
vector4 _2;
vector4 _3;
vector4 _4;
};
float raw[4 * 4] = {};
};
};
}

View File

@ -0,0 +1,89 @@
#pragma once
#include <cstdint>
#include <utility>
#include "fwddec.hpp"
#include "vector.hpp"
namespace rage
{
class scrNativeCallContext
{
public:
void reset()
{
m_arg_count = 0;
m_data_count = 0;
}
template <typename T>
void push_arg(T &&value)
{
static_assert(sizeof(T) <= sizeof(std::uint64_t));
*reinterpret_cast<std::remove_cv_t<std::remove_reference_t<T>>*>(reinterpret_cast<std::uint64_t*>(m_args) + (m_arg_count++)) = std::forward<T>(value);
}
template <typename T>
T &get_arg(std::size_t index)
{
static_assert(sizeof(T) <= sizeof(std::uint64_t));
return *reinterpret_cast<T*>(reinterpret_cast<std::uint64_t*>(m_args) + index);
}
template <typename T>
void set_arg(std::size_t index, T &&value)
{
static_assert(sizeof(T) <= sizeof(std::uint64_t));
*reinterpret_cast<std::remove_cv_t<std::remove_reference_t<T>>*>(reinterpret_cast<std::uint64_t*>(m_args) + index) = std::forward<T>(value);
}
template <typename T>
T *get_return_value()
{
return reinterpret_cast<T*>(m_return_value);
}
template <typename T>
void set_return_value(T &&value)
{
*reinterpret_cast<std::remove_cv_t<std::remove_reference_t<T>>*>(m_return_value) = std::forward<T>(value);
}
protected:
void *m_return_value;
std::uint32_t m_arg_count;
void *m_args;
std::int32_t m_data_count;
std::uint32_t m_data[48];
};
using scrNativeHash = std::uint64_t;
using scrNativeMapping = std::pair<scrNativeHash, scrNativeHash>;
using scrNativeHandler = void(*)(scrNativeCallContext*);
class scrNativeRegistration;
#pragma pack(push, 1)
class scrNativeRegistrationTable
{
scrNativeRegistration *m_entries[0xFF];
std::uint32_t m_unk;
bool m_initialized;
};
#pragma pack(pop)
static_assert(sizeof(scrNativeCallContext) == 0xE0);
}
using Void = void;
using Any = std::uint32_t;
using Hash = std::uint32_t;
using Entity = std::int32_t;
using Player = std::int32_t;
using Ped = Entity;
using Vehicle = Entity;
using Cam = std::int32_t;
using Object = Entity;
using Pickup = Object;
using Blip = std::int32_t;
using Camera = Entity;
using ScrHandle = Entity;
using Vector3 = rage::scrVector;

View File

@ -0,0 +1,58 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
#pragma pack(push, 1)
namespace rage
{
class netGameEvent
{
public:
virtual ~netGameEvent() = default;
virtual const char *get_name() const = 0;
virtual bool is_applicable_to_player(netPlayer *player) = 0;
virtual bool time_to_resend(std::uint32_t time) = 0;
virtual bool needs_reply() = 0;
virtual void serialize(datBitBuffer *buffer, netPlayer* source_player, netPlayer* target_player) = 0;
virtual void deserialize(datBitBuffer *buffer, netPlayer* source_player, netPlayer* target_player) = 0;
virtual bool handle(netPlayer* source_player, netPlayer* target_player) = 0;
virtual void deserialize_reply(datBitBuffer *buffer, netPlayer* reply_player) = 0;
virtual void serialize_reply(datBitBuffer *buffer, netPlayer* souce_player) = 0;
virtual void deserialize_extra_data(datBitBuffer *buffer, bool is_reply, netPlayer *player, netPlayer *player2) = 0;
virtual void serialize_extra_data(datBitBuffer *buffer, bool is_reply, netPlayer *player, netPlayer *player2) = 0;
virtual void _0x60() = 0;
virtual void _0x68() = 0;
virtual void _0x70() = 0;
virtual void _0x78() = 0;
virtual bool operator==(netGameEvent const& other) = 0;
virtual bool operator!=(netGameEvent const& other) = 0;
virtual bool must_persist() = 0;
virtual bool must_persist_when_out_of_scope() = 0;
virtual bool has_timed_out() = 0;
public:
std::uint16_t m_id; // 0x08
bool m_requires_reply; // 0x0A
private:
char m_padding1[0x05]; // 0x0B
public:
netPlayer* m_source_player; // 0x10
netPlayer* m_target_player; // 0x18
std::uint32_t m_resend_time; // 0x20
std::uint16_t m_0x24; // 0x24
std::uint8_t m_0x26; // 0x26
std::uint8_t m_0x27; // 0x27
std::uint32_t m_0x28; // 0x28
char m_padding2[0x04]; // 0x2C
};
static_assert(sizeof(netGameEvent) == 0x30);
}
#pragma pack(pop)

View File

@ -0,0 +1,23 @@
#pragma once
#include "fwddec.hpp"
#include "base.hpp"
namespace rage
{
template <typename T, typename Base = datBase>
class atDNode : public Base
{
public:
T m_data;
void *m_unk;
atDNode<T, Base> *m_next;
};
template <typename Node>
class atDList
{
public:
Node *m_head;
Node *m_tail;
};
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "fwddec.hpp"
#pragma pack(push, 1)
class CPed
{
public:
char m_padding[0x10B8];
CPlayerInfo *m_playerinfo;
};
#pragma pack(pop)
class CPedFactory
{
public:
virtual ~CPedFactory() = default;
CPed *m_local_ped;
};

View File

@ -0,0 +1,112 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
#include "extensible.hpp"
#include "vector.hpp"
#pragma pack(push, 1)
namespace rage
{
# pragma warning(push)
# pragma warning(disable : 4201) // nonstandard extension used: nameless struct/union
union netAddress
{
std::uint32_t m_raw;
struct
{
std::uint8_t m_field4;
std::uint8_t m_field3;
std::uint8_t m_field2;
std::uint8_t m_field1;
};
};
# pragma warning(pop)
class netPlayerData
{
public:
std::uint64_t m_unk1; // 0x00
std::uint64_t m_unk2; // 0x08
std::uint32_t m_sec_key_time; // 0x10
netAddress m_lan_ip; // 0x14
std::uint16_t m_lan_port; // 0x18
char m_pad1[0x02]; // 0x1A
netAddress m_relay_ip; // 0x1C
std::uint16_t m_relay_port; // 0x20
char m_pad2[0x02]; // 0x22
netAddress m_online_ip; // 0x24
std::uint16_t m_online_port; // 0x26
char m_pad3[0x1E]; // 0x28
std::uint64_t m_rockstar_id; // 0x48
bool m_id_flag; // 0x50
char m_pad4[0x0B]; // 0x51
char m_name[0x14]; // 0x5C
};
class nonPhysicalPlayerDataBase
{
public:
virtual ~nonPhysicalPlayerDataBase() = default; // 0 (0x00)
virtual void unk_0x08() = 0; // 1 (0x08)
virtual void unk_0x10() = 0; // 2 (0x10)
virtual void unk_0x18() = 0; // 3 (0x18)
virtual void log(netLoggingInterface* logger) = 0; // 4 (0x20)
};
class netPlayer
{
public:
virtual ~netPlayer() = default; // 0 (0x00)
virtual void reset() = 0; // 1 (0x08)
virtual bool is_valid() const = 0; // 2 (0x10)
virtual const char *get_name() const = 0; // 3 (0x18)
virtual void _0x20() = 0; // 4 (0x20)
virtual bool is_host() = 0; // 5 (0x28)
virtual netPlayerData *get_net_data() = 0; // 6 (0x30)
virtual void _0x38() = 0; // 7 (0x38)
};
class netPlayerMgrBase
{
public:
virtual ~netPlayerMgrBase() = default; // 0 (0x00)
};
}
namespace gta
{
inline constexpr auto num_players = 32;
}
class CNonPhysicalPlayerData : public rage::nonPhysicalPlayerDataBase
{
public:
std::int32_t m_bubble_id; // 0x08
std::int32_t m_player_id; // 0x0C
rage::vector3 m_position; // 0x10
};
class CNetGamePlayer : public rage::netPlayer
{
public:
};
class CWantedData
{
public:
char m_padding[0x98];
std::int32_t m_wanted_level;
};
class CPlayerInfo : public rage::fwExtensibleBase
{
public:
char m_padding1[0x1D8]; // 0x20
std::uint32_t m_frame_flags; // 0x1F8
char m_padding2[0x584]; // 0x1FC
CWantedData m_wanted_data; // 0x780
};
static_assert(sizeof(CNonPhysicalPlayerData) == 0x1C);
#pragma pack(pop)

View File

@ -0,0 +1,18 @@
#pragma once
#include "base.hpp"
namespace rage
{
template <typename T>
class fwRefAwareBaseImpl : public T
{
private:
void *m_ref; // 0x08
};
class fwRefAwareBase : public fwRefAwareBaseImpl<datBase>
{
};
static_assert(sizeof(fwRefAwareBase) == 0x10);
}

View File

@ -0,0 +1,185 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
#include "node_list.hpp"
#include "script_id.hpp"
#pragma pack(push, 1)
namespace rage
{
class scriptResource
{
public:
virtual ~scriptResource() = default;
};
class scriptResourceEntry
{
public:
scriptResource *m_data; // 0x00
std::uint32_t m_unk; // 0x04
char m_padding[0x0C]; // 0x0C
scriptResourceEntry *m_next; // 0x18
};
class scriptHandlerNetComponent
{
public:
virtual ~scriptHandlerNetComponent() = default;
public:
scriptHandler *m_script_handler; // 0x08
};
class scriptHandler
{
public:
class atDScriptObjectNode : public atDNode<scriptHandlerObject*>
{
};
public:
virtual ~scriptHandler() = default; // 0 (0x00)
virtual bool _0x08() = 0; // 1 (0x08)
virtual void _0x10() = 0; // 2 (0x10)
virtual void cleanup_objects() = 0; // 3 (0x18)
virtual scriptId *_0x20() = 0; // 4 (0x20)
virtual scriptId *get_id() = 0; // 5 (0x28)
// Returns whether the script handler belongs to a networked script.
virtual bool is_networked() = 0; // 6 (0x30)
// Initializes the network component for the script handler.
virtual void init_net_component() = 0; // 7 (0x38)
// Deletes the script handler's network component, if it exists.
virtual void reset_net_component() = 0; // 8 (0x40)
// Destroys the script handler.
virtual bool destroy() = 0; // 9 (0x48)
// Adds the object to the script handler's list of objects.
virtual void add_object(scriptHandlerObject*, bool is_network, bool is_network_and_scriptcheck) = 0; // 10 (0x50)
// Something related to reservations.
virtual void _0x58(void*) = 0; // 11 (0x58)
virtual void register_resource(scriptResource*, void*) = 0; // 12 (0x60)
virtual void _0x68() = 0; // 13 (0x68)
virtual void _0x70() = 0; // 14 (0x70)
virtual void _0x78() = 0; // 15 (0x78)
virtual void _0x80() = 0; // 16 (0x80)
virtual void _0x88() = 0; // 17 (0x88)
virtual void _0x90() = 0; // 18 (0x90)
virtual void _0x98() = 0; // 19 (0x98)
public:
void *m_0x08; // 0x08
void *m_0x10; // 0x10
scrThread *m_script_thread; // 0x18
atDList<atDScriptObjectNode> m_objects; // 0x20
scriptResource *m_resource_list_head; // 0x30
scriptResource *m_resource_list_tail; // 0x38
void *m_0x40; // 0x40
scriptHandlerNetComponent *m_net_component; // 0x48
std::uint32_t m_0x50; // 0x50
std::uint32_t m_0x54; // 0x54
std::uint32_t m_0x58; // 0x58
std::uint32_t m_0x60; // 0x5C
};
class scriptHandlerMgr
{
public:
virtual ~scriptHandlerMgr() = default;
// Initializes some scripting-related pools.
virtual bool initialize() = 0; // 1 (0x08)
// Called every tick.
virtual void _0x10() = 0; // 2 (0x10)
// Frees some scripting-related pools.
virtual void shutdown() = 0; // 3 (0x18)
virtual void _0x20() = 0; // 4 (0x20)
virtual void _0x28() = 0; // 5 (0x28)
virtual void _0x30() = 0; // 6 (0x30)
// Generates a rage::scriptId from the thread and copies it over to a global structure.
virtual void _0x38(scrThread*) = 0; // 7 (0x38)
// Allocates and constructs a script handler.
virtual scriptHandler *create_script_handler() = 0; // 8 (0x40)
// Finds the script handler for a given script id.
virtual scriptHandler *get_script_handler(scriptId*) = 0; // 9 (0x48)
// Attaches a script thread.
virtual void attach_thread(scrThread*) = 0; // 10 (0x50)
// Detaches a script thread.
virtual void detach_thread(scrThread*) = 0; // 11 (0x58)
// Called when a player joins.
virtual void on_player_join(netPlayer*) = 0; // 12 (0x60)
// Called when a player leaves.
virtual void on_player_left(netPlayer*) = 0; // 13 (0x68)
virtual std::int32_t _0x70() = 0; // 14 (0x70)
virtual void *_0x78() = 0; // 15 (0x78)
public:
char m_padding1[0x28]; // 0x08
bool m_initialized; // 0x30
bool m_initialized2; // 0x31
char m_padding2[0x0E]; // 0x32
rage::netLoggingInterface *m_logger; // 0x40
};
}
class CGameScriptHandler : public rage::scriptHandler
{
public:
CGameScriptId m_script_id; // 0x60
};
class CGameScriptHandlerNetwork : public CGameScriptHandler
{
public:
std::uint8_t m_0xA0; // 0xA0
std::uint8_t m_0xA1; // 0xA1
std::uint8_t m_0xA2; // 0xA2
std::uint8_t m_0xA3; // 0xA3
std::uint8_t m_num_players; // 0xA4
std::uint8_t m_0xA5; // 0xA5
std::uint8_t m_0xA6; // 0xA6
std::uint8_t m_0xA7; // 0xA7
std::uint8_t m_0xA8; // 0xA8
std::uint8_t m_0xA9; // 0xA9
std::uint8_t m_0xAA; // 0xAA
std::uint8_t m_0xAB; // 0xAB
std::uint8_t m_0xAC; // 0xAC
std::uint8_t m_0xAD; // 0xAD
std::uint8_t m_0xAE; // 0xAE
std::uint8_t m_0xAF; // 0xAF
};
class CGameScriptHandlerMgr : public rage::scriptHandlerMgr
{
};
static_assert(sizeof(rage::scriptHandler) == 0x60);
static_assert(sizeof(CGameScriptHandler) == 0xA0);
static_assert(sizeof(CGameScriptHandlerNetwork) == 0xB0);
#pragma pack(pop)

View File

@ -0,0 +1,72 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
#include "joaat.hpp"
#pragma pack(push, 1)
namespace rage
{
class scriptIdBase
{
public:
virtual ~scriptIdBase() = default; // 0 (0x00)
// Assumes the script thread's identity.
virtual void assume_thread_identity(scrThread*) {}; // 1 (0x08)
// Returns whether the hash of the script id is valid.
virtual bool is_valid() {}; // 2 (0x10)
// Gets the hash of the script id.
virtual joaat_t *get_hash(joaat_t *out) {}; // 3 (0x18)
// Gets an unknown value from the script id.
virtual std::uint32_t *get_hash2(std::uint32_t *out) {}; // 4 (0x20)
// Gets the name of the script id.
virtual const char *get_name() {}; // 5 (0x28)
// Serializes the script id from the buffer.
virtual void deserialize(datBitBuffer* buffer) {}; // 6 (0x30)
// Serializes the script id to the buffer.
virtual void serialize(datBitBuffer* buffer) {}; // 7 (0x38)
// Calculates some information with the position hash & instance id.
virtual std::uint32_t _0x40() {}; // 8 (0x40)
// Calls _0x40 and returns it's value added to another value.
virtual std::uint32_t _0x48() {}; // 9 (0x48)
// Logs some information about the script id.
virtual void log_information(netLoggingInterface* logger) {}; // 10 (0x50)
// Copies the information of other to this object.
virtual void copy_data(scriptIdBase *other) {} // 11 (0x58)
// Returns whether the other script id is equal.
virtual bool operator==(scriptIdBase*) {}; // 12 (0x60)
virtual bool _0x68(void*) {}; // 13 (0x68)
};
class scriptId : public scriptIdBase
{
public:
joaat_t m_hash; // 0x08
char m_name[0x20]; // 0x0C
};
}
class CGameScriptId : public rage::scriptId
{
public:
char m_padding[0x04]; // 0x2C
std::int32_t m_timestamp; // 0x30
std::int32_t m_position_hash; // 0x34
std::int32_t m_instance_id; // 0x38
std::int32_t m_unk; // 0x3C
};
static_assert(sizeof(CGameScriptId) == 0x40);
#pragma pack(pop)

View File

@ -0,0 +1,145 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
#include "base.hpp"
#include "joaat.hpp"
#include "script_id.hpp"
#pragma pack(push, 1)
namespace rage
{
class scrProgram : public pgBase
{
public:
std::uint8_t** m_code_blocks; // 0x10
std::uint32_t m_hash; // 0x18
std::uint32_t m_code_size; // 0x1C
std::uint32_t m_arg_count; // 0x20
std::uint32_t m_local_count; // 0x24
std::uint32_t m_global_count; // 0x28
std::uint32_t m_native_count; // 0x2C
void *m_local_data; // 0x30
std::int64_t **m_global_data; // 0x38
void **m_native_entrypoints; // 0x40
char m_padding6[0x10]; // 0x48
std::uint32_t m_name_hash; // 0x58
char m_padding7[0x04]; // 0x5C
const char* m_name; // 0x60
const char** m_strings_data; // 0x68
std::uint32_t m_strings_count; // 0x70
char m_padding8[0x0C]; // 0x74
bool is_valid() const
{
return m_code_size != 0;
}
std::uint32_t get_num_code_pages() const
{
return (m_code_size + 0x3FFF) >> 14;
}
std::uint32_t get_code_page_size(std::uint32_t page) const
{
auto num = get_num_code_pages();
if (page < num)
{
if (page == num - 1)
return m_code_size & 0x3FFF;
return 0x4000;
}
return 0;
}
std::uint32_t get_full_code_size() const
{
auto numPages = get_num_code_pages();
if (!numPages)
return 0;
if (numPages == 1)
--numPages;
return (numPages * 0x4000) + (m_code_size & 0x3FFF);
}
std::uint8_t* get_code_page(std::uint32_t page) const
{
return m_code_blocks[page];
}
std::uint8_t* get_code_address(std::uint32_t index) const
{
if (index < m_code_size)
return &m_code_blocks[index >> 14][index & 0x3FFF];
return nullptr;
}
const char* get_string(std::uint32_t index) const
{
if (index < m_strings_count)
return &m_strings_data[index >> 14][index & 0x3FFF];
return nullptr;
}
void** get_address_of_native_entrypoint(void* entrypoint)
{
for (std::uint32_t i = 0; i < m_native_count; ++i)
{
if (m_native_entrypoints[i] == entrypoint)
{
return m_native_entrypoints + i;
}
}
return nullptr;
}
};
class scrProgramTableEntry
{
public:
scrProgram* m_program; // 0x00
char m_Pad1[0x04]; // 0x08
joaat_t m_hash; // 0x0C
};
class scrProgramTable
{
public:
scrProgramTableEntry* m_data; // 0x00
char m_padding[0x10]; // 0x08
std::uint32_t m_size; // 0x18
scrProgram* find_script(joaat_t hash)
{
for (std::uint32_t i = 0; i < m_size; ++i)
{
if (m_data[i].m_hash == hash)
{
return m_data[i].m_program;
}
}
return nullptr;
}
scrProgramTableEntry* begin()
{
return m_data;
}
scrProgramTableEntry* end()
{
return m_data + m_size;
}
};
static_assert(sizeof(scrProgram) == 0x80);
static_assert(sizeof(scrProgramTableEntry) == 0x10);
static_assert(sizeof(scrProgramTable) == 0x1C);
}
#pragma pack(pop)

View File

@ -0,0 +1,79 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
#include "joaat.hpp"
#include "tls_context.hpp"
namespace rage
{
enum class eThreadState : std::uint32_t
{
idle,
running,
killed,
unk_3,
unk_4,
};
class scrThreadContext
{
public:
std::uint32_t m_thread_id; // 0x00
joaat_t m_script_hash; // 0x04
eThreadState m_state; // 0x08
std::uint32_t m_instruction_pointer; // 0x0C
std::uint32_t m_frame_pointer; // 0x10
std::uint32_t m_stack_pointer; // 0x14
float m_timer_a; // 0x18
float m_timer_b; // 0x1C
float m_timer_c; // 0x20
char m_padding1[0x2C]; // 0x24
std::uint32_t m_stack_size; // 0x50
char m_padding2[0x54]; // 0x54
};
class scrThread
{
public:
virtual ~scrThread() = default; // 0 (0x00)
virtual void reset(std::uint32_t script_hash, void *args, std::uint32_t arg_count) = 0; // 1 (0x08)
virtual eThreadState run() = 0; // 2 (0x10)
virtual eThreadState tick(std::uint32_t ops_to_execute) = 0; // 3 (0x18)
virtual void kill() = 0; // 4 (0x20)
static scrThread* get()
{
return rage::tlsContext::get()->m_script_thread;
}
public:
scrThreadContext m_context; // 0x08
void *m_stack; // 0xB0
char m_padding[0x10]; // 0xB8
const char *m_exit_message; // 0xC8
char m_name[0x40]; // 0xD0
scriptHandler *m_handler; // 0x110
scriptHandlerNetComponent *m_net_component; // 0x118
};
static_assert(sizeof(scrThreadContext) == 0xA8);
static_assert(sizeof(scrThread) == 0x120);
}
class GtaThread : public rage::scrThread
{
public:
rage::joaat_t m_script_hash; // 0x120
char m_padding3[0x14]; // 0x124
std::int32_t m_instance_id; // 0x138
char m_padding4[0x04]; // 0x13C
std::uint8_t m_flag1; // 0x140
bool m_safe_for_network_game; // 0x141
char m_padding5[0x02]; // 0x142
bool m_is_minigame_script; // 0x144
char m_padding6[0x02]; // 0x145
bool m_can_be_paused; // 0x147
bool m_can_remove_blips_from_other_scripts; // 0x148
char m_padding7[0x0F]; // 0x149
};
static_assert(sizeof(GtaThread) == 0x158);

View File

@ -0,0 +1,23 @@
#pragma once
#include <intrin.h>
#include "fwddec.hpp"
namespace rage
{
class tlsContext
{
public:
char m_padding1[0xC8]; // 0x00
sysMemAllocator *m_allocator; // 0xC8
char m_padding2[0x760]; // 0xD0
scrThread *m_script_thread; // 0x830
bool m_is_script_thread_active; // 0x838
static tlsContext *get()
{
return *reinterpret_cast<tlsContext**>(__readgsqword(0x58));
}
};
static_assert(sizeof(tlsContext) == 0x840);
}

View File

@ -0,0 +1,49 @@
#pragma once
namespace rage
{
struct vector2
{
float x{};
float y{};
};
struct vector3
{
float x{};
float y{};
float z{};
};
struct vector4
{
float x{};
float y{};
float z{};
float w{};
};
#pragma pack(push, 1)
class scrVector
{
public:
scrVector() = default;
scrVector(float x, float y, float z) :
x(x), y(y), z(z)
{}
public:
float x{};
private:
char m_padding1[0x04];
public:
float y{};
private:
char m_padding2[0x04];
public:
float z{};
private:
char m_padding3[0x04];
};
#pragma pack(pop)
}

View File

@ -0,0 +1,57 @@
#pragma once
#include "common.hpp"
#include "gta/array.hpp"
#include "gta/ped_factory.hpp"
#include "gta/player.hpp"
#include "gta/script_thread.hpp"
#include "gta/tls_context.hpp"
#include "pointers.hpp"
namespace big::gta_util
{
inline CPed *get_local_ped()
{
if (auto ped_factory = *g_pointers->m_ped_factory)
{
return ped_factory->m_local_ped;
}
return nullptr;
}
inline CPlayerInfo *get_local_playerinfo()
{
if (auto ped_factory = *g_pointers->m_ped_factory)
{
if (auto ped = ped_factory->m_local_ped)
{
return ped->m_playerinfo;
}
}
return nullptr;
}
template <typename F, typename ...Args>
void execute_as_script(rage::joaat_t script_hash, F &&callback, Args &&...args)
{
auto tls_ctx = rage::tlsContext::get();
for (auto thread : *g_pointers->m_script_threads)
{
if (!thread || !thread->m_context.m_thread_id || thread->m_context.m_script_hash != script_hash)
continue;
auto og_thread = tls_ctx->m_script_thread;
tls_ctx->m_script_thread = thread;
tls_ctx->m_is_script_thread_active = true;
std::invoke(std::forward<F>(callback), std::forward<Args>(args)...);
tls_ctx->m_script_thread = og_thread;
tls_ctx->m_is_script_thread_active = og_thread != nullptr;
return;
}
}
}

172
BigBaseV2/src/gui.cpp Normal file
View File

@ -0,0 +1,172 @@
#include "common.hpp"
#include "fiber_pool.hpp"
#include "gta/player.hpp"
#include "gta_util.hpp"
#include "gui.hpp"
#include "logger.hpp"
#include "memory/module.hpp"
#include "memory/pattern.hpp"
#include "natives.hpp"
#include "pointers.hpp"
#include "renderer.hpp"
#include "script.hpp"
#include <imgui.h>
#include <StackWalker.h>
namespace big
{
void gui::dx_init()
{
auto &style = ImGui::GetStyle();
style.WindowPadding = { 10.f, 10.f };
style.PopupRounding = 0.f;
style.FramePadding = { 8.f, 4.f };
style.ItemSpacing = { 10.f, 8.f };
style.ItemInnerSpacing = { 6.f, 6.f };
style.TouchExtraPadding = { 0.f, 0.f };
style.IndentSpacing = 21.f;
style.ScrollbarSize = 15.f;
style.GrabMinSize = 8.f;
style.WindowBorderSize = 1.f;
style.ChildBorderSize = 0.f;
style.PopupBorderSize = 1.f;
style.FrameBorderSize = 0.f;
style.TabBorderSize = 0.f;
style.WindowRounding = 0.f;
style.ChildRounding = 0.f;
style.FrameRounding = 0.f;
style.ScrollbarRounding = 0.f;
style.GrabRounding = 0.f;
style.TabRounding = 0.f;
style.WindowTitleAlign = { 0.5f, 0.5f };
style.ButtonTextAlign = { 0.5f, 0.5f };
style.DisplaySafeAreaPadding = { 3.f, 3.f };
auto &colors = style.Colors;
colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(1.00f, 0.90f, 0.19f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 1.00f);
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
colors[ImGuiCol_Border] = ImVec4(0.30f, 0.30f, 0.30f, 0.50f);
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_FrameBg] = ImVec4(0.21f, 0.21f, 0.21f, 0.54f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.21f, 0.21f, 0.21f, 0.78f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.28f, 0.27f, 0.27f, 0.54f);
colors[ImGuiCol_TitleBg] = ImVec4(0.17f, 0.17f, 0.17f, 1.00f);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
colors[ImGuiCol_CheckMark] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.34f, 0.34f, 0.34f, 1.00f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.39f, 0.38f, 0.38f, 1.00f);
colors[ImGuiCol_Button] = ImVec4(0.41f, 0.41f, 0.41f, 0.74f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.41f, 0.41f, 0.41f, 0.78f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.41f, 0.41f, 0.41f, 0.87f);
colors[ImGuiCol_Header] = ImVec4(0.37f, 0.37f, 0.37f, 0.31f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.38f, 0.38f, 0.38f, 0.37f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.37f, 0.37f, 0.37f, 0.51f);
colors[ImGuiCol_Separator] = ImVec4(0.38f, 0.38f, 0.38f, 0.50f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.46f, 0.46f, 0.46f, 0.50f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.46f, 0.46f, 0.46f, 0.64f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.26f, 0.26f, 1.00f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f);
colors[ImGuiCol_Tab] = ImVec4(0.21f, 0.21f, 0.21f, 0.86f);
colors[ImGuiCol_TabHovered] = ImVec4(0.27f, 0.27f, 0.27f, 0.86f);
colors[ImGuiCol_TabActive] = ImVec4(0.34f, 0.34f, 0.34f, 0.86f);
colors[ImGuiCol_TabUnfocused] = ImVec4(0.10f, 0.10f, 0.10f, 0.97f);
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.15f, 0.15f, 0.15f, 1.00f);
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
}
void gui::dx_on_tick()
{
if (ImGui::Begin("BigBaseV2"))
{
static bool demo_bool = true;
static int demo_int = 1;
static float demo_float = 1.f;
static const char *demo_combo[]
{
"One",
"Two",
"Three"
};
static int demo_combo_pos = 0;
ImGui::Checkbox("Bool", &demo_bool);
ImGui::SliderInt("Int", &demo_int, 0, 10);
ImGui::SliderFloat("Float", &demo_float, 0.f, 10.f);
ImGui::Combo("Combo", &demo_combo_pos, demo_combo, sizeof(demo_combo) / sizeof(*demo_combo));
if (ImGui::Button("Spawn a vehicle"))
{
g_fiber_pool->queue_job([]
{
constexpr auto hash = RAGE_JOAAT("adder");
while (!STREAMING::HAS_MODEL_LOADED(hash))
{
STREAMING::REQUEST_MODEL(hash);
script::get_current()->yield();
}
auto pos = ENTITY::GET_ENTITY_COORDS(PLAYER::PLAYER_PED_ID(), true);
auto vehicle = VEHICLE::CREATE_VEHICLE(hash, pos.x, pos.y, pos.z, 0.f, true, true);
if (*g_pointers->m_is_session_started)
{
DECORATOR::DECOR_SET_INT(vehicle, "MPBitset", 0);
}
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
});
}
ImGui::Separator();
if (ImGui::Button("Unload"))
{
g_running = false;
}
}
ImGui::End();
}
void gui::script_init()
{
}
void gui::script_on_tick()
{
if (g_gui.m_opened)
{
CONTROLS::DISABLE_ALL_CONTROL_ACTIONS(0);
}
}
void gui::script_func()
{
g_gui.script_init();
while (true)
{
g_gui.script_on_tick();
script::get_current()->yield();
}
}
}

20
BigBaseV2/src/gui.hpp Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include "common.hpp"
namespace big
{
class gui
{
public:
void dx_init();
void dx_on_tick();
void script_init();
void script_on_tick();
static void script_func();
public:
bool m_opened{};
};
inline gui g_gui;
}

194
BigBaseV2/src/hooking.cpp Normal file
View File

@ -0,0 +1,194 @@
#include "common.hpp"
#include "function_types.hpp"
#include "logger.hpp"
#include "gta/array.hpp"
#include "gta/player.hpp"
#include "gta/script_thread.hpp"
#include "gui.hpp"
#include "hooking.hpp"
#include "memory/module.hpp"
#include "natives.hpp"
#include "pointers.hpp"
#include "renderer.hpp"
#include "script_mgr.hpp"
#include <MinHook.h>
namespace big
{
static GtaThread *find_script_thread(rage::joaat_t hash)
{
for (auto thread : *g_pointers->m_script_threads)
{
if (thread
&& thread->m_context.m_thread_id
&& thread->m_handler
&& thread->m_script_hash == hash)
{
return thread;
}
}
return nullptr;
}
hooking::hooking() :
m_swapchain_hook(*g_pointers->m_swapchain, hooks::swapchain_num_funcs),
m_set_cursor_pos_hook("SetCursorPos", memory::module("user32.dll").get_export("SetCursorPos").as<void*>(), &hooks::set_cursor_pos),
m_run_script_threads_hook("Script hook", g_pointers->m_run_script_threads, &hooks::run_script_threads),
m_convert_thread_to_fiber_hook("ConvertThreadToFiber", memory::module("kernel32.dll").get_export("ConvertThreadToFiber").as<void*>(), &hooks::convert_thread_to_fiber)
{
m_swapchain_hook.hook(hooks::swapchain_present_index, &hooks::swapchain_present);
m_swapchain_hook.hook(hooks::swapchain_resizebuffers_index, &hooks::swapchain_resizebuffers);
g_hooking = this;
}
hooking::~hooking()
{
if (m_enabled)
disable();
g_hooking = nullptr;
}
void hooking::enable()
{
m_swapchain_hook.enable();
m_og_wndproc = reinterpret_cast<WNDPROC>(SetWindowLongPtrW(g_pointers->m_hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&hooks::wndproc)));
m_set_cursor_pos_hook.enable();
m_run_script_threads_hook.enable();
m_convert_thread_to_fiber_hook.enable();
ensure_dynamic_hooks();
m_enabled = true;
}
void hooking::disable()
{
m_enabled = false;
if (m_main_persistent_hook)
{
m_main_persistent_hook->disable();
}
m_convert_thread_to_fiber_hook.disable();
m_run_script_threads_hook.disable();
m_set_cursor_pos_hook.disable();
SetWindowLongPtrW(g_pointers->m_hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(m_og_wndproc));
m_swapchain_hook.disable();
}
void hooking::ensure_dynamic_hooks()
{
if (!m_main_persistent_hook)
{
if (auto main_persistent = find_script_thread(RAGE_JOAAT("main_persistent")))
{
m_main_persistent_hook = std::make_unique<vmt_hook>(main_persistent->m_handler, hooks::main_persistent_num_funcs);
m_main_persistent_hook->hook(hooks::main_persistent_dtor_index, &hooks::main_persistent_dtor);
m_main_persistent_hook->hook(hooks::main_persistent_is_networked_index, &hooks::main_persistent_is_networked);
m_main_persistent_hook->enable();
}
}
}
minhook_keepalive::minhook_keepalive()
{
MH_Initialize();
}
minhook_keepalive::~minhook_keepalive()
{
MH_Uninitialize();
}
bool hooks::run_script_threads(std::uint32_t ops_to_execute)
{
if (g_running)
{
g_script_mgr.tick();
}
return g_hooking->m_run_script_threads_hook.get_original<functions::run_script_threads_t>()(ops_to_execute);
}
void *hooks::convert_thread_to_fiber(void *param)
{
if (IsThreadAFiber())
{
return GetCurrentFiber();
}
return g_hooking->m_convert_thread_to_fiber_hook.get_original<decltype(&convert_thread_to_fiber)>()(param);
}
HRESULT hooks::swapchain_present(IDXGISwapChain *this_, UINT sync_interval, UINT flags)
{
if (g_running)
{
g_renderer->on_present();
}
return g_hooking->m_swapchain_hook.get_original<decltype(&swapchain_present)>(swapchain_present_index)(this_, sync_interval, flags);
}
HRESULT hooks::swapchain_resizebuffers(IDXGISwapChain * this_, UINT buffer_count, UINT width, UINT height, DXGI_FORMAT new_format, UINT swapchain_flags)
{
if (g_running)
{
g_renderer->pre_reset();
auto result = g_hooking->m_swapchain_hook.get_original<decltype(&swapchain_resizebuffers)>(swapchain_resizebuffers_index)
(this_, buffer_count, width, height, new_format, swapchain_flags);
if (SUCCEEDED(result))
{
g_renderer->post_reset();
}
return result;
}
return g_hooking->m_swapchain_hook.get_original<decltype(&swapchain_resizebuffers)>(swapchain_resizebuffers_index)
(this_, buffer_count, width, height, new_format, swapchain_flags);
}
LRESULT hooks::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (g_running)
{
g_renderer->wndproc(hwnd, msg, wparam, lparam);
}
return CallWindowProcW(g_hooking->m_og_wndproc, hwnd, msg, wparam, lparam);
}
BOOL hooks::set_cursor_pos(int x, int y)
{
if (g_gui.m_opened)
{
return true;
}
return g_hooking->m_set_cursor_pos_hook.get_original<decltype(&set_cursor_pos)>()(x, y);
}
void hooks::main_persistent_dtor(CGameScriptHandler *this_, bool free_memory)
{
auto og_func = g_hooking->m_main_persistent_hook->get_original<decltype(&main_persistent_dtor)>(main_persistent_dtor_index);
g_hooking->m_main_persistent_hook->disable();
g_hooking->m_main_persistent_hook.reset();
return og_func(this_, free_memory);
}
bool hooks::main_persistent_is_networked(CGameScriptHandler *this_)
{
return *g_pointers->m_is_session_started;
}
}

62
BigBaseV2/src/hooking.hpp Normal file
View File

@ -0,0 +1,62 @@
#pragma once
#include "common.hpp"
#include "detour_hook.hpp"
#include "gta/fwddec.hpp"
#include "script_hook.hpp"
#include "vmt_hook.hpp"
namespace big
{
struct hooks
{
static bool run_script_threads(std::uint32_t ops_to_execute);
static void *convert_thread_to_fiber(void *param);
static constexpr auto swapchain_num_funcs = 19;
static constexpr auto swapchain_present_index = 8;
static constexpr auto swapchain_resizebuffers_index = 13;
static HRESULT swapchain_present(IDXGISwapChain *this_, UINT sync_interval, UINT flags);
static HRESULT swapchain_resizebuffers(IDXGISwapChain *this_, UINT buffer_count, UINT width, UINT height, DXGI_FORMAT new_format, UINT swapchain_flags);
static LRESULT wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
static BOOL set_cursor_pos(int x, int y);
static constexpr auto main_persistent_num_funcs = 16;
static constexpr auto main_persistent_dtor_index = 0;
static constexpr auto main_persistent_is_networked_index = 6;
static void main_persistent_dtor(CGameScriptHandler *this_, bool free_memory);
static bool main_persistent_is_networked(CGameScriptHandler *this_);
};
struct minhook_keepalive
{
minhook_keepalive();
~minhook_keepalive();
};
class hooking
{
friend hooks;
public:
explicit hooking();
~hooking();
void enable();
void disable();
void ensure_dynamic_hooks();
private:
bool m_enabled{};
minhook_keepalive m_minhook_keepalive;
vmt_hook m_swapchain_hook;
WNDPROC m_og_wndproc;
detour_hook m_set_cursor_pos_hook;
detour_hook m_run_script_threads_hook;
detour_hook m_convert_thread_to_fiber_hook;
std::unique_ptr<vmt_hook> m_main_persistent_hook;
};
inline hooking *g_hooking{};
}

54
BigBaseV2/src/invoker.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "common.hpp"
#include "crossmap.hpp"
#include "invoker.hpp"
#include "logger.hpp"
#include "pointers.hpp"
namespace big
{
native_call_context::native_call_context()
{
m_return_value = &m_return_stack[0];
m_args = &m_arg_stack[0];
}
bool native_invoker::map_native(rage::scrNativeHash *hash)
{
for (auto const &mapping : g_crossmap)
{
if (mapping.first == *hash)
{
*hash = mapping.second;
return true;
}
}
return false;
}
void native_invoker::begin_call()
{
m_call_context.reset();
}
void native_invoker::end_call(rage::scrNativeHash hash)
{
map_native(&hash);
if (auto handler = g_pointers->m_get_native_handler(g_pointers->m_native_registration_table, hash))
{
__try
{
handler(&m_call_context);
g_pointers->m_fix_vectors(&m_call_context);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
LOG_ERROR("Exception caught while trying to call 0x{:X} native.", hash);
}
}
else
{
LOG_ERROR("Failed to find 0x{:X} native's handler.", hash);
}
}
}

43
BigBaseV2/src/invoker.hpp Normal file
View File

@ -0,0 +1,43 @@
#pragma once
#include "common.hpp"
#include "gta/natives.hpp"
namespace big
{
class native_call_context : public rage::scrNativeCallContext
{
public:
native_call_context();
private:
std::uint64_t m_return_stack[10];
std::uint64_t m_arg_stack[100];
};
class native_invoker
{
public:
explicit native_invoker() = default;
~native_invoker() = default;
bool map_native(rage::scrNativeHash *hash);
void begin_call();
void end_call(rage::scrNativeHash hash);
template <typename T>
void push_arg(T &&value)
{
m_call_context.push_arg(std::forward<T>(value));
}
template <typename T>
T &get_return_value()
{
return *m_call_context.get_return_value<T>();
}
private:
native_call_context m_call_context;
};
inline native_invoker g_native_invoker;
}

188
BigBaseV2/src/logger.hpp Normal file
View File

@ -0,0 +1,188 @@
#pragma once
#include "common.hpp"
namespace big
{
enum class log_color : std::uint16_t
{
red = FOREGROUND_RED,
green = FOREGROUND_GREEN,
blue = FOREGROUND_BLUE,
intensify = FOREGROUND_INTENSITY
};
inline log_color operator|(log_color a, log_color b)
{
return static_cast<log_color>(static_cast<std::underlying_type_t<log_color>>(a) | static_cast<std::underlying_type_t<log_color>>(b));
}
class logger;
inline logger *g_logger{};
class logger
{
public:
explicit logger() :
m_file_path(std::getenv("appdata"))
{
m_file_path /= "BigBaseV2";
try
{
if (!std::filesystem::exists(m_file_path))
{
std::filesystem::create_directory(m_file_path);
}
else if (!std::filesystem::is_directory(m_file_path))
{
std::filesystem::remove(m_file_path);
std::filesystem::create_directory(m_file_path);
}
m_file_path /= "BigBaseV2.log";
m_file_out.open(m_file_path, std::ios_base::out | std::ios_base::app);
}
catch (std::filesystem::filesystem_error const&)
{
}
if ((m_did_console_exist = AttachConsole(GetCurrentProcessId())) == false)
AllocConsole();
if ((m_console_handle = GetStdHandle(STD_OUTPUT_HANDLE)) != nullptr)
{
SetConsoleTitleA("BigBaseV2");
SetConsoleOutputCP(CP_UTF8);
m_console_out.open("CONOUT$", std::ios_base::out | std::ios_base::app);
}
g_logger = this;
}
~logger()
{
if (!m_did_console_exist)
FreeConsole();
g_logger = nullptr;
}
template <typename ...Args>
void raw(log_color color, Args const &...args)
{
raw_to_console(color, args...);
raw_to_file(args...);
}
template <typename ...Args>
void log(log_color color, std::string_view prefix, std::string_view format, Args const &...args)
{
auto message = fmt::format(format, args...);
auto time_since_epoch = std::time(nullptr);
auto local_time = std::localtime(&time_since_epoch);
auto console_timestamp = fmt::format("[{:0>2}:{:0>2}:{:0>2}]", local_time->tm_hour, local_time->tm_min, local_time->tm_sec);
auto file_timestamp = fmt::format("[{}-{}-{} {:0>2}:{:0>2}:{:0>2}]", local_time->tm_year + 1900, local_time->tm_mon + 1, local_time->tm_mday, local_time->tm_hour, local_time->tm_min, local_time->tm_sec);
raw_to_console(color, console_timestamp, " [", prefix, "] ", message, "\n");
raw_to_file(file_timestamp, " [", prefix, "] ", message, "\n");
}
private:
template <typename ...Args>
void raw_to_console(log_color color, Args const &...args)
{
if (m_console_handle)
{
SetConsoleTextAttribute(m_console_handle, static_cast<std::uint16_t>(color));
}
if (m_console_out)
{
((m_console_out << args), ...);
m_console_out << std::flush;
}
}
template <typename ...Args>
void raw_to_file(Args const &...args)
{
if (m_file_out)
{
((m_file_out << args), ...);
m_file_out << std::flush;
}
}
private:
bool m_did_console_exist{};
HANDLE m_console_handle{};
std::ofstream m_console_out;
std::filesystem::path m_file_path;
std::ofstream m_file_out;
};
template <typename ...Args>
inline void log_info(std::string_view format, Args const &...args)
{
if (g_logger)
{
g_logger->log(log_color::blue | log_color::intensify, "Info", format, args...);
}
else
{
DebugBreak();
}
}
template <typename ...Args>
inline void log_error(std::string_view format, Args const &...args)
{
if (g_logger)
{
g_logger->log(log_color::green | log_color::intensify, "Error", format, args...);
}
else
{
DebugBreak();
}
}
template <typename ...Args>
inline void log_trace(std::string_view format, Args const &...args)
{
if (g_logger)
{
g_logger->log(log_color::green | log_color::intensify, "Trace", format, args...);
}
else
{
DebugBreak();
}
}
template <typename ...Args>
inline void log_raw(log_color color, Args const &...args)
{
if (g_logger)
{
g_logger->raw(color, args...);
}
else
{
DebugBreak();
}
}
#define LOG_INFO_IMPL(format, ...) (::big::log_info(format, __VA_ARGS__))
#define LOG_INFO(format, ...) LOG_INFO_IMPL(format, __VA_ARGS__)
#define LOG_ERROR_IMPL(format, ...) (::big::log_error(format, __VA_ARGS__))
#define LOG_ERROR(format, ...) LOG_ERROR_IMPL(format, __VA_ARGS__)
#define LOG_TRACE_IMPL(format, ...) (::big::log_trace(format, __VA_ARGS__))
#define LOG_TRACE(format, ...) LOG_TRACE_IMPL(format, __VA_ARGS__)
#define LOG_RAW_IMPL(color, ...) (::big::log_raw(color, __VA_ARGS__))
#define LOG_RAW(color, ...) LOG_RAW_IMPL(color, __VA_ARGS__)
}

128
BigBaseV2/src/main.cpp Normal file
View File

@ -0,0 +1,128 @@
#include "common.hpp"
#include "features.hpp"
#include "fiber_pool.hpp"
#include "gui.hpp"
#include "logger.hpp"
#include "hooking.hpp"
#include "pointers.hpp"
#include "renderer.hpp"
#include "script_mgr.hpp"
BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
{
using namespace big;
if (reason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hmod);
g_hmodule = hmod;
g_main_thread = CreateThread(nullptr, 0, [](PVOID) -> DWORD
{
auto logger_instance = std::make_unique<logger>();
try
{
LOG_RAW(log_color::green | log_color::intensify,
u8R"kek( ...
;::::;
;::::; :;
;:::::' :;
;:::::; ;.
,:::::' ; OOO\
::::::; ; OOOOO\
;:::::; ; OOOOOOOO
,;::::::; ;' / OOOOOOO
;:::::::::`. ,,,;. / / DOOOOOO
.';:::::::::::::::::;, / / DOOOO
,::::::;::::::;;;;::::;, / / DOOO
;`::::::`'::::::;;;::::: ,#/ / DOOO
:`:::::::`;::::::;;::: ;::# / DOOO
::`:::::::`;:::::::: ;::::# / DOO
`:`:::::::`;:::::: ;::::::#/ DOO
:::`:::::::`;; ;:::::::::## OO
::::`:::::::`;::::::::;:::# OO
`:::::`::::::::::::;'`:;::# O
`:::::`::::::::;' / / `:#
::::::`:::::;' / / `#
)kek");
auto pointers_instance = std::make_unique<pointers>();
LOG_INFO("Pointers initialized.");
if (*g_pointers->m_game_state != eGameState::Playing)
{
LOG_INFO("Waiting for the game to load.");
do
{
std::this_thread::sleep_for(100ms);
} while (*g_pointers->m_game_state != eGameState::Playing);
LOG_INFO("The game has loaded.");
}
else
{
LOG_INFO("The game is already loaded.");
}
auto renderer_instance = std::make_unique<renderer>();
LOG_INFO("Renderer initialized.");
auto fiber_pool_instance = std::make_unique<fiber_pool>(10);
LOG_INFO("Fiber pool initialized.");
auto hooking_instance = std::make_unique<hooking>();
LOG_INFO("Hooking initialized.");
g_script_mgr.add_script(std::make_unique<script>(&features::script_func));
g_script_mgr.add_script(std::make_unique<script>(&gui::script_func));
LOG_INFO("Scripts registered.");
g_hooking->enable();
LOG_INFO("Hooking enabled.");
while (g_running)
{
if (GetAsyncKeyState(VK_END) & 0x8000)
g_running = false;
g_hooking->ensure_dynamic_hooks();
std::this_thread::sleep_for(10ms);
}
g_hooking->disable();
LOG_INFO("Hooking disabled.");
std::this_thread::sleep_for(1000ms);
g_script_mgr.remove_all_scripts();
LOG_INFO("Scripts unregistered.");
hooking_instance.reset();
LOG_INFO("Hooking uninitialized.");
fiber_pool_instance.reset();
LOG_INFO("Fiber pool uninitialized.");
renderer_instance.reset();
LOG_INFO("Renderer uninitialized.");
pointers_instance.reset();
LOG_INFO("Pointers uninitialized.");
}
catch (std::exception const &ex)
{
LOG_ERROR("{}", ex.what());
MessageBoxA(nullptr, ex.what(), nullptr, MB_OK | MB_ICONEXCLAMATION);
}
LOG_INFO("Farewell!");
logger_instance.reset();
CloseHandle(g_main_thread);
FreeLibraryAndExitThread(g_hmodule, 0);
}, nullptr, 0, &g_main_thread_id);
}
return true;
}

View File

@ -0,0 +1,7 @@
#pragma once
#include "handle.hpp"
#include "module.hpp"
#include "pattern.hpp"
#include "pattern_batch.hpp"
#include "range.hpp"

View File

@ -0,0 +1,10 @@
#pragma once
namespace memory
{
class handle;
class range;
class module;
class pattern;
class pattern_batch;
}

View File

@ -0,0 +1,96 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <type_traits>
namespace memory
{
class handle
{
public:
handle(void* ptr = nullptr);
explicit handle(std::uintptr_t ptr);
template <typename T>
std::enable_if_t<std::is_pointer_v<T>, T> as();
template <typename T>
std::enable_if_t<std::is_lvalue_reference_v<T>, T> as();
template <typename T>
std::enable_if_t<std::is_same_v<T, std::uintptr_t>, T> as();
template <typename T>
handle add(T offset);
template <typename T>
handle sub(T offset);
handle rip();
explicit operator bool();
friend bool operator==(handle a, handle b);
friend bool operator!=(handle a, handle b);
private:
void* ptr;
};
inline handle::handle(void* ptr) :
ptr(ptr)
{}
inline handle::handle(std::uintptr_t ptr) :
ptr(reinterpret_cast<void*>(ptr))
{}
template <typename T>
inline std::enable_if_t<std::is_pointer_v<T>, T> handle::as()
{
return static_cast<T>(ptr);
}
template <typename T>
inline std::enable_if_t<std::is_lvalue_reference_v<T>, T> handle::as()
{
return *static_cast<std::add_pointer_t<std::remove_reference_t<T>>>(ptr);
}
template <typename T>
inline std::enable_if_t<std::is_same_v<T, std::uintptr_t>, T> handle::as()
{
return reinterpret_cast<std::uintptr_t>(ptr);
}
template <typename T>
inline handle handle::add(T offset)
{
return handle(as<std::uintptr_t>() + offset);
}
template <typename T>
inline handle handle::sub(T offset)
{
return handle(as<std::uintptr_t>() - offset);
}
inline handle handle::rip()
{
return add(as<std::int32_t&>()).add(4);
}
inline bool operator==(handle a, handle b)
{
return a.ptr == b.ptr;
}
inline bool operator!=(handle a, handle b)
{
return a.ptr != b.ptr;
}
inline handle::operator bool()
{
return ptr != nullptr;
}
}

View File

@ -0,0 +1,33 @@
#include "../common.hpp"
#include "module.hpp"
namespace memory
{
module::module(HMODULE mod) :
range(mod, 0)
{
auto dosHeader = m_base.as<IMAGE_DOS_HEADER*>();
auto ntHeader = m_base.add(dosHeader->e_lfanew).as<IMAGE_NT_HEADERS*>();
m_size = ntHeader->OptionalHeader.SizeOfImage;
}
module::module(std::nullptr_t) :
module(GetModuleHandle(nullptr))
{
}
module::module(std::string_view name) :
module(GetModuleHandleA(name.data()))
{
}
module::module(std::wstring_view name) :
module(GetModuleHandleW(name.data()))
{
}
handle module::get_export(std::string_view symbol_name)
{
return GetProcAddress(m_base.as<HMODULE>(), symbol_name.data());
}
}

View File

@ -0,0 +1,16 @@
#pragma once
#include "range.hpp"
namespace memory
{
class module : public range
{
public:
module(HMODULE mod);
explicit module(std::nullptr_t);
explicit module(std::string_view name);
explicit module(std::wstring_view name);
memory::handle get_export(std::string_view symbol_name);
};
}

View File

@ -0,0 +1,90 @@
#include "../common.hpp"
#include "pattern.hpp"
namespace memory
{
pattern::pattern(std::string_view ida_sig)
{
auto to_upper = [](char c) -> char
{
return c >= 'a' && c <= 'z' ? static_cast<char>(c + ('A' - 'a')) : static_cast<char>(c);
};
auto to_hex = [&](char c) -> std::optional<std::uint8_t>
{
switch (to_upper(c))
{
case '0':
return static_cast<std::uint8_t>(0);
case '1':
return static_cast<std::uint8_t>(1);
case '2':
return static_cast<std::uint8_t>(2);
case '3':
return static_cast<std::uint8_t>(3);
case '4':
return static_cast<std::uint8_t>(4);
case '5':
return static_cast<std::uint8_t>(5);
case '6':
return static_cast<std::uint8_t>(6);
case '7':
return static_cast<std::uint8_t>(7);
case '8':
return static_cast<std::uint8_t>(8);
case '9':
return static_cast<std::uint8_t>(9);
case 'A':
return static_cast<std::uint8_t>(10);
case 'B':
return static_cast<std::uint8_t>(11);
case 'C':
return static_cast<std::uint8_t>(12);
case 'D':
return static_cast<std::uint8_t>(13);
case 'E':
return static_cast<std::uint8_t>(14);
case 'F':
return static_cast<std::uint8_t>(15);
default:
return std::nullopt;
}
};
for (std::size_t i = 0; i < ida_sig.size(); ++i)
{
if (ida_sig[i] == ' ')
continue;
bool last = (i == ida_sig.size() - 1);
if (ida_sig[i] != '?')
{
if (!last)
{
auto c1 = to_hex(ida_sig[i]);
auto c2 = to_hex(ida_sig[i + 1]);
if (c1 && c2)
{
m_bytes.emplace_back(static_cast<std::uint8_t>((*c1 * 0x10) + *c2));
}
}
}
else
{
m_bytes.push_back(std::nullopt);
}
}
}
pattern::pattern(const void *bytes, std::string_view mask)
{
for (std::size_t i = 0; i < mask.size(); ++i)
{
if (mask[i] != '?')
m_bytes.emplace_back(static_cast<const std::uint8_t*>(bytes)[i]);
else
m_bytes.push_back(std::nullopt);
}
}
}

View File

@ -0,0 +1,25 @@
#pragma once
#include <cstdint>
#include <optional>
#include <string_view>
#include <vector>
#include "fwddec.hpp"
#include "handle.hpp"
namespace memory
{
class pattern
{
friend pattern_batch;
friend range;
public:
pattern(std::string_view ida_sig);
explicit pattern(const void *bytes, std::string_view mask);
inline pattern(const char* ida_sig) :
pattern(std::string_view(ida_sig))
{}
private:
std::vector<std::optional<std::uint8_t>> m_bytes;
};
}

View File

@ -0,0 +1,39 @@
#include "../common.hpp"
#include "../logger.hpp"
#include "pattern_batch.hpp"
#include "range.hpp"
namespace memory
{
void pattern_batch::add(std::string name, pattern pattern, std::function<void(handle)> callback)
{
m_entries.emplace_back(std::move(name), std::move(pattern), std::move(callback));
}
void pattern_batch::run(range region)
{
bool all_found = true;
for (auto &entry : m_entries)
{
if (auto result = region.scan(entry.m_pattern))
{
if (entry.m_callback)
{
std::invoke(std::move(entry.m_callback), result);
LOG_INFO("Found '{}'.", entry.m_name);
}
else
{
all_found = false;
LOG_ERROR("Failed to find '{}'.", entry.m_name);
}
}
}
m_entries.clear();
if (!all_found)
{
throw std::runtime_error("Failed to find some patterns.");
}
}
}

View File

@ -0,0 +1,33 @@
#pragma once
#include <functional>
#include <vector>
#include "pattern.hpp"
namespace memory
{
class pattern_batch
{
public:
explicit pattern_batch() = default;
~pattern_batch() noexcept = default;
void add(std::string name, pattern pattern, std::function<void(memory::handle)> callback);
void run(range region);
struct entry
{
std::string m_name;
pattern m_pattern;
std::function<void(memory::handle)> m_callback;
explicit entry(std::string name, pattern pattern, std::function<void(memory::handle)> callback) :
m_name(std::move(name)),
m_pattern(std::move(pattern)),
m_callback(std::move(callback))
{}
};
private:
std::vector<entry> m_entries;
};
}

View File

@ -0,0 +1,74 @@
#include "../common.hpp"
#include "range.hpp"
#include "pattern.hpp"
namespace memory
{
range::range(handle base, std::size_t size) :
m_base(base), m_size(size)
{
}
handle range::begin()
{
return m_base;
}
handle range::end()
{
return m_base.add(m_size);
}
std::size_t range::size()
{
return m_size;
}
bool range::contains(handle h)
{
return h.as<std::uintptr_t>() >= begin().as<std::uintptr_t>() && h.as<std::uintptr_t>() <= end().as<std::uintptr_t>();
}
static bool pattern_matches(std::uint8_t* target, const std::optional<std::uint8_t>* sig, std::size_t length)
{
for (std::size_t i = 0; i < length; ++i)
{
if (sig[i] && *sig[i] != target[i])
return false;
}
return true;
};
handle range::scan(pattern const &sig)
{
auto data = sig.m_bytes.data();
auto length = sig.m_bytes.size();
for (std::uintptr_t i = 0; i < m_size - length; ++i)
{
if (pattern_matches(m_base.add(i).as<std::uint8_t*>(), data, length))
{
return m_base.add(i);
}
}
return nullptr;
}
std::vector<handle> range::scan_all(pattern const &sig)
{
std::vector<handle> result;
auto data = sig.m_bytes.data();
auto length = sig.m_bytes.size();
for (std::uintptr_t i = 0; i < m_size - length; ++i)
{
if (pattern_matches(m_base.add(i).as<std::uint8_t*>(), data, length))
{
result.push_back(m_base.add(i));
}
}
return std::move(result);
}
}

View File

@ -0,0 +1,25 @@
#pragma once
#include <vector>
#include "fwddec.hpp"
#include "handle.hpp"
namespace memory
{
class range
{
public:
range(handle base, std::size_t size);
handle begin();
handle end();
std::size_t size();
bool contains(handle h);
handle scan(pattern const& sig);
std::vector<handle> scan_all(pattern const& sig);
protected:
handle m_base;
std::size_t m_size;
};
}

5372
BigBaseV2/src/natives.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,82 @@
#include "common.hpp"
#include "logger.hpp"
#include "pointers.hpp"
#include "memory/all.hpp"
namespace big
{
pointers::pointers()
{
memory::pattern_batch main_batch;
main_batch.add("Game state", "83 3D ? ? ? ? ? 75 17 8B 42 20 25", [this](memory::handle ptr)
{
m_game_state = ptr.add(2).rip().as<eGameState*>();
});
main_batch.add("Is session started", "40 38 35 ? ? ? ? 75 0E 4C 8B C3 49 8B D7 49 8B CE", [this](memory::handle ptr)
{
m_is_session_started = ptr.add(3).rip().as<bool*>();
});
main_batch.add("Ped factory", "48 8B 05 ? ? ? ? 48 8B 48 08 48 85 C9 74 52 8B 81", [this](memory::handle ptr)
{
m_ped_factory = ptr.add(3).rip().as<CPedFactory**>();
});
main_batch.add("Network player manager", "48 8B 0D ? ? ? ? 8A D3 48 8B 01 FF 50 ? 4C 8B 07 48 8B CF", [this](memory::handle ptr)
{
m_network_player_mgr = ptr.add(3).rip().as<CNetworkPlayerMgr**>();
});
main_batch.add("Native handlers", "48 8D 0D ? ? ? ? 48 8B 14 FA E8 ? ? ? ? 48 85 C0 75 0A", [this](memory::handle ptr)
{
m_native_registration_table = ptr.add(3).rip().as<rage::scrNativeRegistrationTable*>();
m_get_native_handler = ptr.add(12).rip().as<functions::get_native_handler_t>();
});
main_batch.add("Fix vectors", "83 79 18 00 48 8B D1 74 4A FF 4A 18 48 63 4A 18 48 8D 41 04 48 8B 4C CA", [this](memory::handle ptr)
{
m_fix_vectors = ptr.as<functions::fix_vectors_t>();
});
main_batch.add("Script threads", "45 33 F6 8B E9 85 C9 B8", [this](memory::handle ptr)
{
m_script_threads = ptr.sub(4).rip().sub(8).as<decltype(m_script_threads)>();
m_run_script_threads = ptr.sub(0x1F).as<functions::run_script_threads_t>();
});
main_batch.add("Script programs", "44 8B 0D ? ? ? ? 4C 8B 1D ? ? ? ? 48 8B 1D ? ? ? ? 41 83 F8 FF 74 3F 49 63 C0 42 0F B6 0C 18 81 E1", [this](memory::handle ptr)
{
m_script_program_table = ptr.add(17).rip().as<decltype(m_script_program_table)>();
});
main_batch.add("Script globals", "48 8D 15 ? ? ? ? 4C 8B C0 E8 ? ? ? ? 48 85 FF 48 89 1D", [this](memory::handle ptr)
{
m_script_globals = ptr.add(3).rip().as<std::int64_t**>();
});
main_batch.add("CGameScriptHandlerMgr", "48 8B 0D ? ? ? ? 4C 8B CE E8 ? ? ? ? 48 85 C0 74 05 40 32 FF", [this](memory::handle ptr)
{
m_script_handler_mgr = ptr.add(3).rip().as<CGameScriptHandlerMgr**>();
});
main_batch.add("Swapchain", "48 8B 0D ? ? ? ? 48 8B 01 44 8D 43 01 33 D2 FF 50 40 8B C8", [this](memory::handle ptr)
{
m_swapchain = ptr.add(3).rip().as<IDXGISwapChain**>();
});
main_batch.run(memory::module(nullptr));
m_hwnd = FindWindowW(L"grcWindow", nullptr);
if (!m_hwnd)
throw std::runtime_error("Failed to find the game's window.");
g_pointers = this;
}
pointers::~pointers()
{
g_pointers = nullptr;
}
}

View File

@ -0,0 +1,38 @@
#pragma once
#include "common.hpp"
#include "gta/fwddec.hpp"
#include "gta/enums.hpp"
#include "function_types.hpp"
namespace big
{
class pointers
{
public:
explicit pointers();
~pointers();
public:
HWND m_hwnd{};
eGameState *m_game_state{};
bool *m_is_session_started{};
CPedFactory **m_ped_factory{};
CNetworkPlayerMgr **m_network_player_mgr{};
rage::scrNativeRegistrationTable *m_native_registration_table{};
functions::get_native_handler_t m_get_native_handler{};
functions::fix_vectors_t m_fix_vectors{};
rage::atArray<GtaThread*> *m_script_threads{};
rage::scrProgramTable *m_script_program_table{};
functions::run_script_threads_t m_run_script_threads{};
std::int64_t **m_script_globals{};
CGameScriptHandlerMgr **m_script_handler_mgr{};
IDXGISwapChain **m_swapchain{};
};
inline pointers *g_pointers{};
}

100
BigBaseV2/src/renderer.cpp Normal file
View File

@ -0,0 +1,100 @@
#include "common.hpp"
#include "fonts.hpp"
#include "logger.hpp"
#include "gui.hpp"
#include "pointers.hpp"
#include "renderer.hpp"
#include <imgui.h>
#include <imgui_impl_dx11.h>
#include <imgui_impl_win32.h>
IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
namespace big
{
renderer::renderer() :
m_dxgi_swapchain(*g_pointers->m_swapchain)
{
void *d3d_device{};
if (SUCCEEDED(m_dxgi_swapchain->GetDevice(__uuidof(ID3D11Device), &d3d_device)))
{
m_d3d_device.Attach(static_cast<ID3D11Device*>(d3d_device));
}
else
{
throw std::runtime_error("Failed to get D3D device.");
}
m_d3d_device->GetImmediateContext(m_d3d_device_context.GetAddressOf());
ImGui::CreateContext();
ImGui_ImplDX11_Init(m_d3d_device.Get(), m_d3d_device_context.Get());
ImGui_ImplWin32_Init(g_pointers->m_hwnd);
ImFontConfig font_cfg{};
font_cfg.FontDataOwnedByAtlas = false;
std::strcpy(font_cfg.Name, "Rubik");
m_font = ImGui::GetIO().Fonts->AddFontFromMemoryTTF(const_cast<std::uint8_t*>(font_rubik), sizeof(font_rubik), 20.f, &font_cfg);
m_monospace_font = ImGui::GetIO().Fonts->AddFontDefault();
g_gui.dx_init();
g_renderer = this;
}
renderer::~renderer()
{
ImGui_ImplWin32_Shutdown();
ImGui_ImplDX11_Shutdown();
ImGui::DestroyContext();
g_renderer = nullptr;
}
void renderer::on_present()
{
if (g_gui.m_opened)
{
ImGui::GetIO().MouseDrawCursor = true;
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
}
else
{
ImGui::GetIO().MouseDrawCursor = false;
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouse;
}
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
if (g_gui.m_opened)
{
g_gui.dx_on_tick();
}
ImGui::Render();
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
}
void renderer::pre_reset()
{
ImGui_ImplDX11_InvalidateDeviceObjects();
}
void renderer::post_reset()
{
ImGui_ImplDX11_CreateDeviceObjects();
}
void renderer::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (msg == WM_KEYUP && wparam == VK_INSERT)
g_gui.m_opened ^= true;
if (g_gui.m_opened)
{
ImGui_ImplWin32_WndProcHandler(hwnd, msg, wparam, lparam);
}
}
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "common.hpp"
#include <imgui.h>
namespace big
{
class renderer
{
public:
explicit renderer();
~renderer();
void on_present();
void pre_reset();
void post_reset();
void wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
public:
ImFont *m_font;
ImFont *m_monospace_font;
private:
comptr<IDXGISwapChain> m_dxgi_swapchain;
comptr<ID3D11Device> m_d3d_device;
comptr<ID3D11DeviceContext> m_d3d_device_context;
};
inline renderer *g_renderer{};
}

92
BigBaseV2/src/script.cpp Normal file
View File

@ -0,0 +1,92 @@
#pragma once
#include "common.hpp"
#include "logger.hpp"
#include "script.hpp"
namespace big
{
static void script_exception_handler(PEXCEPTION_POINTERS exp)
{
LOG_ERROR("Script threw an exception!");
g_stackwalker.ShowCallstack(GetCurrentThread(), exp->ContextRecord);
}
script::script(func_t func, std::optional<std::size_t> stack_size) :
m_func(func),
m_script_fiber(nullptr),
m_main_fiber(nullptr)
{
m_script_fiber = CreateFiber(stack_size.has_value() ? stack_size.value() : 0, [](void* param)
{
auto this_script = static_cast<script*>(param);
this_script->fiber_func();
}, this);
}
script::~script()
{
if (m_script_fiber)
DeleteFiber(m_script_fiber);
}
void script::tick()
{
m_main_fiber = GetCurrentFiber();
if (!m_wake_time.has_value() || m_wake_time.value() <= std::chrono::high_resolution_clock::now())
{
SwitchToFiber(m_script_fiber);
}
}
void script::yield(std::optional<std::chrono::high_resolution_clock::duration> time)
{
if (time.has_value())
{
m_wake_time = std::chrono::high_resolution_clock::now() + time.value();
}
else
{
m_wake_time = std::nullopt;
}
SwitchToFiber(m_main_fiber);
}
script *script::get_current()
{
return static_cast<script*>(GetFiberData());
}
void script::fiber_func()
{
__try
{
[this]()
{
try
{
m_func();
}
catch (std::exception const &ex)
{
auto ex_class = typeid(ex).name() + 6;
LOG_INFO("Script threw an C++ expection! {}: {}", ex_class, ex.what());
}
catch (...)
{
LOG_INFO("Script threw a C++ exception!");
}
}();
}
__except (script_exception_handler(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER)
{
LOG_INFO("Script threw an exception!");
}
LOG_INFO("Script finished!");
while (true)
{
yield();
}
}
}

25
BigBaseV2/src/script.hpp Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include "common.hpp"
namespace big
{
class script
{
public:
using func_t = void(*)();
public:
explicit script(func_t func, std::optional<std::size_t> stack_size = std::nullopt);
~script();
void tick();
void yield(std::optional<std::chrono::high_resolution_clock::duration> time = std::nullopt);
static script *get_current();
private:
void fiber_func();
private:
void *m_script_fiber;
void *m_main_fiber;
func_t m_func;
std::optional<std::chrono::high_resolution_clock::time_point> m_wake_time;
};
}

View File

@ -0,0 +1,26 @@
#include "common.hpp"
#include "pointers.hpp"
#include "script_global.hpp"
namespace big
{
script_global::script_global(std::size_t index) :
m_index(index)
{
}
script_global script_global::at(std::ptrdiff_t index)
{
return script_global(m_index + index);
}
script_global script_global::at(std::ptrdiff_t index, std::size_t size)
{
return script_global(m_index + 1 + (index * size));
}
void *script_global::get()
{
return g_pointers->m_script_globals[m_index >> 0x12 & 0x3F] + (m_index & 0x3FFFF);
}
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "common.hpp"
namespace big
{
class script_global
{
public:
explicit script_global(std::size_t index);
script_global at(std::ptrdiff_t index);
script_global at(std::ptrdiff_t index, std::size_t size);
template <typename T>
std::enable_if_t<std::is_pointer_v<T>, T> as()
{
return static_cast<T>(get());
}
template <typename T>
std::enable_if_t<std::is_lvalue_reference_v<T>, T> as()
{
return *static_cast<std::add_pointer_t<std::remove_reference_t<T>>>(get());
}
private:
void *get();
std::size_t m_index;
};
}

View File

@ -0,0 +1,107 @@
#include "common.hpp"
#include "crossmap.hpp"
#include "gta/script_program.hpp"
#include "logger.hpp"
#include "pointers.hpp"
#include "script_hook.hpp"
namespace big
{
inline std::unordered_map<rage::scrProgram*, script_hook*> script_hook::s_map;
static bool map_native(rage::scrNativeHash *hash)
{
for (auto const &mapping : g_crossmap)
{
if (mapping.first == *hash)
{
*hash = mapping.second;
return true;
}
}
return false;
}
script_hook::script_hook(rage::joaat_t script_hash, std::unordered_map<rage::scrNativeHash, rage::scrNativeHandler> native_replacements) :
m_script_hash(script_hash),
m_native_replacements(std::move(native_replacements))
{
ensure();
}
script_hook::~script_hook()
{
if (m_program)
{
for (auto[hash, handler_ptr] : m_native_handler_ptrs)
{
auto og_handler = g_pointers->m_get_native_handler(g_pointers->m_native_registration_table, hash);
*handler_ptr = og_handler;
}
}
if (m_vmt_hook)
{
m_vmt_hook->disable();
s_map.erase(m_program);
}
}
void script_hook::ensure()
{
if (m_vmt_hook)
return;
if (auto program = g_pointers->m_script_program_table->find_script(m_script_hash))
{
if (program->is_valid())
{
hook_instance(program);
LOG_INFO("Hooked {} script ({})", program->m_name, static_cast<void*>(program));
}
}
}
void script_hook::hook_instance(rage::scrProgram *program)
{
m_program = program;
s_map.emplace(m_program, this);
m_vmt_hook = std::make_unique<vmt_hook>(m_program, 3);
m_vmt_hook->hook(0, &scrprogram_dtor);
for (auto [replacement_hash, replacement_handler] : m_native_replacements)
{
auto hash = replacement_hash;
map_native(&hash);
auto og_handler = g_pointers->m_get_native_handler(g_pointers->m_native_registration_table, hash);
if (!og_handler)
continue;
auto handler_ptr = m_program->get_address_of_native_entrypoint(og_handler);
if (!handler_ptr)
continue;
m_native_handler_ptrs.emplace(hash, reinterpret_cast<rage::scrNativeHandler*>(handler_ptr));
*handler_ptr = replacement_handler;
}
}
void script_hook::scrprogram_dtor(rage::scrProgram *this_, bool free_memory)
{
if (auto it = s_map.find(this_); it != s_map.end())
{
auto hook = it->second;
hook->m_program = nullptr;
s_map.erase(it);
auto og_func = hook->m_vmt_hook->get_original<decltype(&scrprogram_dtor)>(0);
hook->m_vmt_hook->disable();
hook->m_vmt_hook.reset();
og_func(this_, free_memory);
}
}
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "common.hpp"
#include "gta/fwddec.hpp"
#include "gta/joaat.hpp"
#include "gta/natives.hpp"
#include "vmt_hook.hpp"
namespace big
{
class script_hook
{
public:
explicit script_hook(rage::joaat_t script_hash, std::unordered_map<rage::scrNativeHash, rage::scrNativeHandler> native_replacements);
~script_hook();
void ensure();
private:
void hook_instance(rage::scrProgram *program);
static void scrprogram_dtor(rage::scrProgram *this_, bool free_memory);
static std::unordered_map<rage::scrProgram*, script_hook*> s_map;
rage::joaat_t m_script_hash;
rage::scrProgram* m_program;
std::unique_ptr<vmt_hook> m_vmt_hook;
std::unordered_map<rage::scrNativeHash, rage::scrNativeHandler> m_native_replacements;
std::unordered_map<rage::scrNativeHash, rage::scrNativeHandler*> m_native_handler_ptrs;
};
}

View File

@ -0,0 +1,38 @@
#include "common.hpp"
#include "gta/array.hpp"
#include "gta/script_thread.hpp"
#include "gta/tls_context.hpp"
#include "gta_util.hpp"
#include "pointers.hpp"
#include "script_mgr.hpp"
namespace big
{
void script_mgr::add_script(std::unique_ptr<script> script)
{
std::lock_guard lock(m_mutex);
m_scripts.push_back(std::move(script));
}
void script_mgr::remove_all_scripts()
{
std::lock_guard lock(m_mutex);
m_scripts.clear();
}
void script_mgr::tick()
{
gta_util::execute_as_script(RAGE_JOAAT("main_persistent"), std::mem_fn(&script_mgr::tick_internal), this);
}
void script_mgr::tick_internal()
{
static bool ensure_main_fiber = (ConvertThreadToFiber(nullptr), true);
std::lock_guard lock(m_mutex);
for (auto const &script : m_scripts)
{
script->tick();
}
}
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "common.hpp"
#include "script.hpp"
namespace big
{
class script_mgr
{
public:
explicit script_mgr() = default;
~script_mgr() = default;
void add_script(std::unique_ptr<script> script);
void remove_all_scripts();
void tick();
private:
void tick_internal();
private:
std::recursive_mutex m_mutex;
std::vector<std::unique_ptr<script>> m_scripts;
};
inline script_mgr g_script_mgr;
}

View File

@ -0,0 +1,34 @@
#include "common.hpp"
#include "vmt_hook.hpp"
namespace big
{
vmt_hook::vmt_hook(void* obj, std::size_t num_funcs) :
m_object(static_cast<void***>(obj)),
m_num_funcs(num_funcs + 1),
m_original_table(*m_object),
m_new_table(std::make_unique<void*[]>(m_num_funcs))
{
std::copy_n(m_original_table - 1, m_num_funcs, m_new_table.get());
}
void vmt_hook::hook(std::size_t index, void* func)
{
m_new_table[index + 1] = func;
}
void vmt_hook::unhook(std::size_t index)
{
m_new_table[index + 1] = m_original_table[index];
}
void vmt_hook::enable()
{
*m_object = m_new_table.get() + 1;
}
void vmt_hook::disable()
{
*m_object = m_original_table;
}
}

View File

@ -0,0 +1,37 @@
#pragma once
#include "common.hpp"
namespace big
{
class vmt_hook
{
public:
explicit vmt_hook(void* obj, std::size_t num_funcs);
vmt_hook(vmt_hook&& that) = delete;
vmt_hook& operator=(vmt_hook&& that) = delete;
vmt_hook(vmt_hook const&) = delete;
vmt_hook& operator=(vmt_hook const&) = delete;
void hook(std::size_t index, void* func);
void unhook(std::size_t index);
template <typename T>
T get_original(std::size_t index);
void enable();
void disable();
private:
void*** m_object;
std::size_t m_num_funcs;
void** m_original_table;
std::unique_ptr<void*[]> m_new_table;
};
template<typename T>
inline T vmt_hook::get_original(std::size_t index)
{
return static_cast<T>(m_original_table[index]);
}
}