mirror of
https://github.com/Mr-X-GTA/YimMenu.git
synced 2025-06-22 08:42:44 +08:00
Premake, Gitmodules, Readme
This commit is contained in:
1
BigBaseV2/src/common.cpp
Normal file
1
BigBaseV2/src/common.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "common.hpp"
|
77
BigBaseV2/src/common.hpp
Normal file
77
BigBaseV2/src/common.hpp
Normal 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
5846
BigBaseV2/src/crossmap.hpp
Normal file
File diff suppressed because it is too large
Load Diff
88
BigBaseV2/src/detour_hook.cpp
Normal file
88
BigBaseV2/src/detour_hook.cpp
Normal 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));
|
||||
}();
|
||||
}
|
||||
}
|
||||
}
|
35
BigBaseV2/src/detour_hook.hpp
Normal file
35
BigBaseV2/src/detour_hook.hpp
Normal 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);
|
||||
}
|
||||
}
|
21
BigBaseV2/src/features.cpp
Normal file
21
BigBaseV2/src/features.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
8
BigBaseV2/src/features.hpp
Normal file
8
BigBaseV2/src/features.hpp
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "common.hpp"
|
||||
|
||||
namespace big::features
|
||||
{
|
||||
void run_tick();
|
||||
void script_func();
|
||||
}
|
53
BigBaseV2/src/fiber_pool.cpp
Normal file
53
BigBaseV2/src/fiber_pool.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
22
BigBaseV2/src/fiber_pool.hpp
Normal file
22
BigBaseV2/src/fiber_pool.hpp
Normal 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
11734
BigBaseV2/src/fonts.cpp
Normal file
File diff suppressed because it is too large
Load Diff
4
BigBaseV2/src/fonts.hpp
Normal file
4
BigBaseV2/src/fonts.hpp
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
extern const std::uint8_t font_rubik[140732];
|
11
BigBaseV2/src/function_types.hpp
Normal file
11
BigBaseV2/src/function_types.hpp
Normal 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*);
|
||||
}
|
65
BigBaseV2/src/gta/array.hpp
Normal file
65
BigBaseV2/src/gta/array.hpp
Normal 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;
|
||||
};
|
||||
}
|
18
BigBaseV2/src/gta/base.hpp
Normal file
18
BigBaseV2/src/gta/base.hpp
Normal 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;
|
||||
};
|
||||
}
|
19
BigBaseV2/src/gta/color.hpp
Normal file
19
BigBaseV2/src/gta/color.hpp
Normal 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);
|
||||
}
|
7
BigBaseV2/src/gta/enums.hpp
Normal file
7
BigBaseV2/src/gta/enums.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
enum eGameState : std::uint32_t
|
||||
{
|
||||
Playing = 0
|
||||
};
|
44
BigBaseV2/src/gta/extensible.hpp
Normal file
44
BigBaseV2/src/gta/extensible.hpp
Normal 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);
|
||||
}
|
68
BigBaseV2/src/gta/fwddec.hpp
Normal file
68
BigBaseV2/src/gta/fwddec.hpp
Normal 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;
|
84
BigBaseV2/src/gta/joaat.hpp
Normal file
84
BigBaseV2/src/gta/joaat.hpp
Normal 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)
|
22
BigBaseV2/src/gta/matrix.hpp
Normal file
22
BigBaseV2/src/gta/matrix.hpp
Normal 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] = {};
|
||||
};
|
||||
};
|
||||
}
|
89
BigBaseV2/src/gta/natives.hpp
Normal file
89
BigBaseV2/src/gta/natives.hpp
Normal 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;
|
58
BigBaseV2/src/gta/net_game_event.hpp
Normal file
58
BigBaseV2/src/gta/net_game_event.hpp
Normal 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)
|
23
BigBaseV2/src/gta/node_list.hpp
Normal file
23
BigBaseV2/src/gta/node_list.hpp
Normal 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;
|
||||
};
|
||||
}
|
18
BigBaseV2/src/gta/ped_factory.hpp
Normal file
18
BigBaseV2/src/gta/ped_factory.hpp
Normal 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;
|
||||
};
|
112
BigBaseV2/src/gta/player.hpp
Normal file
112
BigBaseV2/src/gta/player.hpp
Normal 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)
|
18
BigBaseV2/src/gta/ref_aware.hpp
Normal file
18
BigBaseV2/src/gta/ref_aware.hpp
Normal 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);
|
||||
}
|
185
BigBaseV2/src/gta/script_handler.hpp
Normal file
185
BigBaseV2/src/gta/script_handler.hpp
Normal 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)
|
72
BigBaseV2/src/gta/script_id.hpp
Normal file
72
BigBaseV2/src/gta/script_id.hpp
Normal 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)
|
145
BigBaseV2/src/gta/script_program.hpp
Normal file
145
BigBaseV2/src/gta/script_program.hpp
Normal 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)
|
||||
|
79
BigBaseV2/src/gta/script_thread.hpp
Normal file
79
BigBaseV2/src/gta/script_thread.hpp
Normal 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);
|
23
BigBaseV2/src/gta/tls_context.hpp
Normal file
23
BigBaseV2/src/gta/tls_context.hpp
Normal 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);
|
||||
}
|
49
BigBaseV2/src/gta/vector.hpp
Normal file
49
BigBaseV2/src/gta/vector.hpp
Normal 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)
|
||||
}
|
57
BigBaseV2/src/gta_util.hpp
Normal file
57
BigBaseV2/src/gta_util.hpp
Normal 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
172
BigBaseV2/src/gui.cpp
Normal 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
20
BigBaseV2/src/gui.hpp
Normal 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
194
BigBaseV2/src/hooking.cpp
Normal 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
62
BigBaseV2/src/hooking.hpp
Normal 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
54
BigBaseV2/src/invoker.cpp
Normal 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
43
BigBaseV2/src/invoker.hpp
Normal 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
188
BigBaseV2/src/logger.hpp
Normal 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
128
BigBaseV2/src/main.cpp
Normal 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;
|
||||
}
|
7
BigBaseV2/src/memory/all.hpp
Normal file
7
BigBaseV2/src/memory/all.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "handle.hpp"
|
||||
#include "module.hpp"
|
||||
#include "pattern.hpp"
|
||||
#include "pattern_batch.hpp"
|
||||
#include "range.hpp"
|
10
BigBaseV2/src/memory/fwddec.hpp
Normal file
10
BigBaseV2/src/memory/fwddec.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
namespace memory
|
||||
{
|
||||
class handle;
|
||||
class range;
|
||||
class module;
|
||||
class pattern;
|
||||
class pattern_batch;
|
||||
}
|
96
BigBaseV2/src/memory/handle.hpp
Normal file
96
BigBaseV2/src/memory/handle.hpp
Normal 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;
|
||||
}
|
||||
}
|
33
BigBaseV2/src/memory/module.cpp
Normal file
33
BigBaseV2/src/memory/module.cpp
Normal 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());
|
||||
}
|
||||
}
|
16
BigBaseV2/src/memory/module.hpp
Normal file
16
BigBaseV2/src/memory/module.hpp
Normal 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);
|
||||
};
|
||||
}
|
90
BigBaseV2/src/memory/pattern.cpp
Normal file
90
BigBaseV2/src/memory/pattern.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
25
BigBaseV2/src/memory/pattern.hpp
Normal file
25
BigBaseV2/src/memory/pattern.hpp
Normal 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;
|
||||
};
|
||||
}
|
39
BigBaseV2/src/memory/pattern_batch.cpp
Normal file
39
BigBaseV2/src/memory/pattern_batch.cpp
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
33
BigBaseV2/src/memory/pattern_batch.hpp
Normal file
33
BigBaseV2/src/memory/pattern_batch.hpp
Normal 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;
|
||||
};
|
||||
}
|
74
BigBaseV2/src/memory/range.cpp
Normal file
74
BigBaseV2/src/memory/range.cpp
Normal 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);
|
||||
}
|
||||
}
|
25
BigBaseV2/src/memory/range.hpp
Normal file
25
BigBaseV2/src/memory/range.hpp
Normal 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
5372
BigBaseV2/src/natives.hpp
Normal file
File diff suppressed because it is too large
Load Diff
82
BigBaseV2/src/pointers.cpp
Normal file
82
BigBaseV2/src/pointers.cpp
Normal 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;
|
||||
}
|
||||
}
|
38
BigBaseV2/src/pointers.hpp
Normal file
38
BigBaseV2/src/pointers.hpp
Normal 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
100
BigBaseV2/src/renderer.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
29
BigBaseV2/src/renderer.hpp
Normal file
29
BigBaseV2/src/renderer.hpp
Normal 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
92
BigBaseV2/src/script.cpp
Normal 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
25
BigBaseV2/src/script.hpp
Normal 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;
|
||||
};
|
||||
}
|
26
BigBaseV2/src/script_global.cpp
Normal file
26
BigBaseV2/src/script_global.cpp
Normal 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);
|
||||
}
|
||||
}
|
29
BigBaseV2/src/script_global.hpp
Normal file
29
BigBaseV2/src/script_global.hpp
Normal 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;
|
||||
};
|
||||
}
|
107
BigBaseV2/src/script_hook.cpp
Normal file
107
BigBaseV2/src/script_hook.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
29
BigBaseV2/src/script_hook.hpp
Normal file
29
BigBaseV2/src/script_hook.hpp
Normal 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;
|
||||
};
|
||||
}
|
38
BigBaseV2/src/script_mgr.cpp
Normal file
38
BigBaseV2/src/script_mgr.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
25
BigBaseV2/src/script_mgr.hpp
Normal file
25
BigBaseV2/src/script_mgr.hpp
Normal 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;
|
||||
}
|
34
BigBaseV2/src/vmt_hook.cpp
Normal file
34
BigBaseV2/src/vmt_hook.cpp
Normal 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;
|
||||
}
|
||||
}
|
37
BigBaseV2/src/vmt_hook.hpp
Normal file
37
BigBaseV2/src/vmt_hook.hpp
Normal 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]);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user