Removed StackWalker and replaced it with g3log exception handling.

Updated natives for 1.50.
Added settings JSON implementation.
Refactored spawn vehicle bypass to not crash. (removed VMT hook)
This commit is contained in:
gir489 2020-02-22 18:37:42 -05:00
parent 87599327c5
commit 01d48cd314
33 changed files with 13323 additions and 12123 deletions

6
.gitmodules vendored
View File

@ -14,7 +14,7 @@
path = vendor/ImGui
url = https://github.com/ocornut/imgui
ignore = dirty
[submodule "vendor/StackWalker"]
path = vendor/StackWalker
url = https://github.com/JochenKalmbach/StackWalker
[submodule "vendor/g3log"]
path = vendor/g3log
url = https://github.com/KjellKod/g3log.git
ignore = dirty

BIN
BigBaseV2.lnk Normal file

Binary file not shown.

View File

@ -47,10 +47,11 @@
#include <fmt/format.h>
#include <nlohmann/json.hpp>
#include <StackWalker.h>
#include "logger.hpp"
#include "settings.h"
namespace big
{
using namespace std::chrono_literals;
@ -62,16 +63,4 @@ namespace big
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;
}

File diff suppressed because it is too large Load Diff

View File

@ -2,11 +2,11 @@
#include "detour_hook.hpp"
#include "logger.hpp"
#include "memory/handle.hpp"
#include <MinHook.h>
#include <..\MinHook\include\MinHook.h>
namespace big
{
detour_hook::detour_hook(std::string name, void *target, void *detour) :
detour_hook::detour_hook(std::string name, void* target, void* detour) :
m_name(std::move(name)),
m_target(target),
m_detour(detour)
@ -15,12 +15,11 @@ namespace big
if (auto status = MH_CreateHook(m_target, m_detour, &m_original); status == MH_OK)
{
LOG_INFO("Created hook '{}'.", m_name);
LOG(INFO_TO_FILE) << "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)));
}
}
@ -31,14 +30,14 @@ namespace big
MH_RemoveHook(m_target);
}
LOG_INFO("Removed hook '{}',", m_name);
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);
LOG(INFO_TO_FILE) << "Enabled hook '" << m_name << "'.";
}
else
{
@ -50,15 +49,15 @@ namespace big
{
if (auto status = MH_DisableHook(m_target); status == MH_OK)
{
LOG_INFO("Disabled hook '{}'", m_name);
LOG(INFO_TO_FILE) << "Disabled hook '" << m_name << "'.";
}
else
{
LOG_ERROR("Failed to disable hook '{}'.", m_name);
LOG(WARNING) << "Failed to disable hook '" << m_name << "'.";
}
}
DWORD exp_handler(PEXCEPTION_POINTERS exp, std::string const &name)
DWORD exp_handler(PEXCEPTION_POINTERS exp, std::string const& name)
{
return exp->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION
? EXCEPTION_EXECUTE_HANDLER

View File

@ -14,7 +14,11 @@ namespace big
{
while (true)
{
run_tick();
TRY_CLAUSE
{
run_tick();
}
EXCEPT_CLAUSE
script::get_current()->yield();
}
}

View File

@ -78,6 +78,8 @@ using Any = std::uint32_t;
using Hash = std::uint32_t;
using Entity = std::int32_t;
using Player = std::int32_t;
using FireId = std::int32_t;
using Interior = std::int32_t;
using Ped = Entity;
using Vehicle = Entity;
using Cam = std::int32_t;

View File

@ -12,7 +12,8 @@
#include "script.hpp"
#include <imgui.h>
#include <StackWalker.h>
#include "gui/base_tab.h"
namespace big
{
@ -96,56 +97,17 @@ namespace big
void gui::dx_on_tick()
{
if (ImGui::Begin("BigBaseV2"))
TRY_CLAUSE
{
static bool demo_bool = true;
static int demo_int = 1;
static float demo_float = 1.f;
static const char *demo_combo[]
if (ImGui::Begin("BigBaseV2"))
{
"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::BeginTabBar("tabbar");
base_tab::render_base_tab();
ImGui::EndTabBar();
}
ImGui::End();
}
ImGui::End();
EXCEPT_CLAUSE
}
void gui::script_init()
@ -154,10 +116,14 @@ namespace big
void gui::script_on_tick()
{
if (g_gui.m_opened)
TRY_CLAUSE
{
CONTROLS::DISABLE_ALL_CONTROL_ACTIONS(0);
if (g_gui.m_opened)
{
PAD::DISABLE_ALL_CONTROL_ACTIONS(0);
}
}
EXCEPT_CLAUSE
}
void gui::script_func()

View File

@ -0,0 +1,99 @@
#include "common.hpp"
#include "base_tab.h"
#include "imgui.h"
#include "script.hpp"
#include "fiber_pool.hpp"
#include "natives.hpp"
#include "gta_util.hpp"
namespace big
{
void base_tab::render_base_tab()
{
if (ImGui::BeginTabItem("Test"))
{
static const char* demo_combo[]
{
"One",
"Two",
"Three"
};
static double min = 0., max = 10.;
//If you want to add a new option, you have to first declare it in settings.h's default_options, otherwise, this code will crash when trying to access an option that does not exist in memory.
if (ImGui::Checkbox("Bool", g_settings.options["demo bool"].get<bool*>()))
g_settings.save();
if (ImGui::SliderInt("Int", (PINT)g_settings.options["demo int"].get<int64_t*>(), 0, 10))
g_settings.save();
if (ImGui::SliderScalar("Double", ImGuiDataType_Double, g_settings.options["demo double"].get<double*>(), &min, &max)) //JSON does not describe rational numbers as integer/float/double/etc types, it is just "number". See: https://nlohmann.github.io/json/
g_settings.save();
ImGui::Combo("Combo", (PINT)g_settings.options["demo combo"].get<int64_t*>(), demo_combo, sizeof(demo_combo) / sizeof(*demo_combo));
if (ImGui::Button("Spawn an Adder"))
{
QUEUE_JOB_BEGIN_CLAUSE()
{
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);
while (!STREAMING::HAS_MODEL_LOADED(hash))
{
STREAMING::REQUEST_MODEL(hash);
script::get_current()->yield();
}
*(unsigned short*)g_pointers->m_model_spawn_bypass = 0x9090;
Vehicle vehicle = VEHICLE::CREATE_VEHICLE(hash, pos.x, pos.y, pos.z, 0.f, TRUE, FALSE, FALSE);
*(unsigned short*)g_pointers->m_model_spawn_bypass = 0x0574; //By writing the "old" bypass to the function, running CREATE_VEHICLE, then restoring it, the anti-cheat does not have enough time to catch the function in a dirty state.
script::get_current()->yield();
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
if (*g_pointers->m_is_session_started)
{
DECORATOR::DECOR_SET_INT(vehicle, "MPBitset", 0);
ENTITY::_SET_ENTITY_SOMETHING(vehicle, TRUE); //True means it can be deleted by the engine when switching lobbies/missions/etc, false means the script is expected to clean it up.
auto networkId = NETWORK::VEH_TO_NET(vehicle);
if (NETWORK::NETWORK_GET_ENTITY_IS_NETWORKED(vehicle))
NETWORK::SET_NETWORK_ID_EXISTS_ON_ALL_MACHINES(networkId, true);
VEHICLE::SET_VEHICLE_IS_STOLEN(vehicle, FALSE);
}
if (*g_pointers->m_is_session_started)
{
DECORATOR::DECOR_SET_INT(vehicle, "MPBitset", 0);
}
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
}
QUEUE_JOB_END_CLAUSE
}
if (ImGui::Button("Test g3log crash within ImGui"))
{
*((PINT)nullptr) = 0xDEADBEEF;
}
ImGui::SameLine();
if (ImGui::Button("Test g3log crash within GTA V Script"))
{
QUEUE_JOB_BEGIN_CLAUSE()
{
//PED::_0xB782F8238512BAD5(PLAYER::PLAYER_PED_ID(), nullptr); //This causes a crash at GTA5.exe+5845356 and nothing of value was in the log in the stack dump because of the context switch to GTA 5's memory. If you encounter something similar, you will have to figure out where the crash occured in the GTA 5 exe, and trace back that native, and figure out which function is calling the native that is crashing.
*((PINT)nullptr) = 0xDEADBEEF;
}
QUEUE_JOB_END_CLAUSE
}
ImGui::Separator();
if (ImGui::Button("Unload"))
{
g_running = false;
}
}
ImGui::EndTabItem();
}
}

View File

@ -0,0 +1,13 @@
#pragma once
#include "common.hpp"
#include "natives.hpp"
namespace big
{
class base_tab
{
public:
static void render_base_tab();
};
}

View File

@ -63,7 +63,6 @@ namespace big
m_run_script_threads_hook.enable();
m_convert_thread_to_fiber_hook.enable();
ensure_dynamic_hooks();
m_enabled = true;
}
@ -71,11 +70,6 @@ namespace big
{
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();
@ -84,20 +78,6 @@ namespace big
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();
@ -110,85 +90,94 @@ namespace big
bool hooks::run_script_threads(std::uint32_t ops_to_execute)
{
if (g_running)
TRY_CLAUSE
{
g_script_mgr.tick();
}
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);
return g_hooking->m_run_script_threads_hook.get_original<functions::run_script_threads_t>()(ops_to_execute);
} EXCEPT_CLAUSE
return false;
}
void *hooks::convert_thread_to_fiber(void *param)
{
if (IsThreadAFiber())
TRY_CLAUSE
{
return GetCurrentFiber();
}
if (IsThreadAFiber())
{
return GetCurrentFiber();
}
return g_hooking->m_convert_thread_to_fiber_hook.get_original<decltype(&convert_thread_to_fiber)>()(param);
return g_hooking->m_convert_thread_to_fiber_hook.get_original<decltype(&convert_thread_to_fiber)>()(param);
} EXCEPT_CLAUSE
return nullptr;
}
HRESULT hooks::swapchain_present(IDXGISwapChain *this_, UINT sync_interval, UINT flags)
{
if (g_running)
TRY_CLAUSE
{
g_renderer->on_present();
}
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);
return g_hooking->m_swapchain_hook.get_original<decltype(&swapchain_present)>(swapchain_present_index)(this_, sync_interval, flags);
} EXCEPT_CLAUSE
return NULL;
}
HRESULT hooks::swapchain_resizebuffers(IDXGISwapChain * this_, UINT buffer_count, UINT width, UINT height, DXGI_FORMAT new_format, UINT swapchain_flags)
{
if (g_running)
TRY_CLAUSE
{
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))
if (g_running)
{
g_renderer->post_reset();
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 result;
}
return g_hooking->m_swapchain_hook.get_original<decltype(&swapchain_resizebuffers)>(swapchain_resizebuffers_index)
(this_, buffer_count, width, height, new_format, swapchain_flags);
return g_hooking->m_swapchain_hook.get_original<decltype(&swapchain_resizebuffers)>(swapchain_resizebuffers_index)
(this_, buffer_count, width, height, new_format, swapchain_flags);
} EXCEPT_CLAUSE
return NULL;
}
LRESULT hooks::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (g_running)
TRY_CLAUSE
{
g_renderer->wndproc(hwnd, msg, wparam, lparam);
}
if (g_running)
{
g_renderer->wndproc(hwnd, msg, wparam, lparam);
}
return CallWindowProcW(g_hooking->m_og_wndproc, hwnd, msg, wparam, lparam);
return CallWindowProcW(g_hooking->m_og_wndproc, hwnd, msg, wparam, lparam);
} EXCEPT_CLAUSE
return NULL;
}
BOOL hooks::set_cursor_pos(int x, int y)
{
if (g_gui.m_opened)
TRY_CLAUSE
{
return true;
}
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;
return g_hooking->m_set_cursor_pos_hook.get_original<decltype(&set_cursor_pos)>()(x, y);
} EXCEPT_CLAUSE
return FALSE;
}
}

View File

@ -20,12 +20,6 @@ namespace big
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
@ -44,7 +38,6 @@ namespace big
void enable();
void disable();
void ensure_dynamic_hooks();
private:
bool m_enabled{};
minhook_keepalive m_minhook_keepalive;
@ -55,7 +48,6 @@ namespace big
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{};

View File

@ -14,7 +14,7 @@ namespace big
void native_invoker::cache_handlers()
{
for (const rage::scrNativeMapping &mapping : g_crossmap)
for (const rage::scrNativeMapping& mapping : g_crossmap)
{
rage::scrNativeHandler handler = g_pointers->m_get_native_handler(
g_pointers->m_native_registration_table, mapping.second);
@ -34,19 +34,12 @@ namespace big
{
rage::scrNativeHandler handler = it->second;
__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);
}
handler(&m_call_context);
g_pointers->m_fix_vectors(&m_call_context);
}
else
{
LOG_ERROR("Failed to find 0x{:X} native's handler.", hash);
[hash]() { LOG(WARNING) << "Failed to find " << HEX_TO_UPPER(hash) << " native's handler."; }();
}
}
}

View File

@ -1,188 +1,211 @@
#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__)
}
#pragma once
#include "common.hpp"
#include <g3log/g3log.hpp>
#include <g3log/logworker.hpp>
namespace big
{
template <typename TP>
std::time_t to_time_t(TP tp)
{
using namespace std::chrono;
auto sctp = time_point_cast<system_clock::duration>(tp - TP::clock::now()
+ system_clock::now());
return system_clock::to_time_t(sctp);
}
enum class log_color : std::uint16_t
{
red = FOREGROUND_RED,
green = FOREGROUND_GREEN,
blue = FOREGROUND_BLUE,
intensify = FOREGROUND_INTENSITY
};
enum LOG_FLAGS
{
FLAG_NO_DISK = (1 << 0),
FLAG_NO_CONSOLE = (1 << 1)
};
static const int kEventValue = 400;
static const int kRawValue = 600;
inline constexpr auto max_padding_length = 26;
inline constexpr auto level_padding_length = 8;
const LEVELS INFO_TO_FILE{ INFO.value | FLAG_NO_CONSOLE, {"INFO"} },
HACKER{ INFO.value, {"HACKER"} },
EVENT{ kEventValue | FLAG_NO_CONSOLE, {"EVENT"} },
RAW_GREEN_TO_CONSOLE{ kRawValue | FLAG_NO_DISK, {"RAW_GREEN_TO_CONSOLE"} },
RAW_RED{ kRawValue, {"RAW_RED"} };
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_worker(g3::LogWorker::createLogWorker())
{
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);
}
m_file_path /= "BigBaseV2";
std::filesystem::path m_backup_path = m_file_path;
m_backup_path /= "Backup";
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);
}
if (!std::filesystem::exists(m_backup_path))
{
std::filesystem::create_directory(m_backup_path);
}
else if (!std::filesystem::is_directory(m_backup_path))
{
std::filesystem::remove(m_backup_path);
std::filesystem::create_directory(m_backup_path);
}
m_event_file_path = m_file_path;
m_file_path /= "BigBaseV2.log";
m_event_file_path /= "GTAEvents.log";
if (std::filesystem::exists(m_file_path))
{
auto file_time = std::filesystem::last_write_time(m_file_path);
auto timet = to_time_t(file_time);
auto local_time = std::localtime(&timet);
auto bigbase_timestamp = fmt::format("{:0>2}-{:0>2}-{}-{:0>2}-{:0>2}-{:0>2} BigBaseV2.log", local_time->tm_mon + 1, local_time->tm_mday, local_time->tm_year + 1900, local_time->tm_hour, local_time->tm_min, local_time->tm_sec);
auto gta_events_timestamp = fmt::format("{:0>2}-{:0>2}-{}-{:0>2}-{:0>2}-{:0>2} GTAEvents.log", local_time->tm_mon + 1, local_time->tm_mday, local_time->tm_year + 1900, local_time->tm_hour, local_time->tm_min, local_time->tm_sec);
std::filesystem::copy_file(m_file_path, m_backup_path / bigbase_timestamp);
if (std::filesystem::exists(m_event_file_path) && !std::filesystem::is_empty(m_event_file_path))
std::filesystem::copy_file(m_event_file_path, m_backup_path / gta_events_timestamp);
}
m_file_out.open(m_file_path, std::ios_base::out | std::ios_base::trunc);
m_gta_event_file_out.open(m_event_file_path, std::ios_base::out | std::ios_base::trunc);
m_worker->addSink(std::make_unique<log_sink>(), &log_sink::callback);
g3::initializeLogging(m_worker.get());
g3::installCrashHandler();
}
catch (std::filesystem::filesystem_error const& error)
{
m_console_out << error.what();
}
g_logger = this;
}
~logger()
{
m_worker.reset();
if (!m_did_console_exist)
FreeConsole();
g_logger = nullptr;
}
struct log_sink
{
std::map<std::string, log_color> log_colors = {
{INFO.text, log_color::blue | log_color::intensify},
{WARNING.text, log_color::red},
{HACKER.text, log_color::green | log_color::intensify},
{FATAL.text, log_color::red | log_color::intensify},
{G3LOG_DEBUG.text, log_color::blue},
{RAW_RED.text, log_color::red},
{RAW_GREEN_TO_CONSOLE.text, log_color::green | log_color::intensify}
};
void callback(g3::LogMessageMover log)
{
g3::LogMessage log_message = log.get();
int level_value = log_message._level.value;
bool is_raw = level_value == RAW_RED.value || level_value == RAW_GREEN_TO_CONSOLE.value;
if (!(level_value & FLAG_NO_CONSOLE))
{
SetConsoleTextAttribute(g_logger->m_console_handle, static_cast<std::uint16_t>(log_colors[log_message._level.text]));
g_logger->m_console_out << log_message.toString(is_raw ? format_raw : format_console) << std::flush;
}
if (!(level_value & FLAG_NO_DISK))
{
if (level_value == EVENT.value)
g_logger->m_gta_event_file_out << log_message.toString(format_file) << std::flush;
else
g_logger->m_file_out << log_message.toString(is_raw ? format_raw : format_file) << std::flush;
}
}
static std::string format_file(const g3::LogMessage& msg)
{
std::string file_name_with_line = "[" + msg.file() + ":" + msg.line() + "]";
std::stringstream out;
out << "[" << msg.timestamp("%H:%M:%S") << "] [" << std::left << std::setw(level_padding_length) << msg.level().append("]") << std::setw(max_padding_length) << file_name_with_line;
return out.str();
}
static std::string format_console(const g3::LogMessage& msg)
{
std::stringstream out;
out << "[" << msg.timestamp("%H:%M:%S") << "] ";
return out.str();
}
static std::string format_raw(const g3::LogMessage& msg)
{
return "";
}
};
template <typename ...Args>
inline void log_now(std::string_view format, Args const& ...args)
{
auto message = fmt::format(format, args...);
if (m_file_out)
m_file_out << message << std::endl << std::flush;
}
private:
bool m_did_console_exist{};
HANDLE m_console_handle{};
std::ofstream m_console_out;
std::filesystem::path m_file_path;
std::filesystem::path m_event_file_path;
std::ofstream m_file_out;
std::ofstream m_gta_event_file_out;
std::unique_ptr<g3::LogWorker> m_worker;
};
#define LOG_NOW(format, ...) g_logger->log_now(format, __VA_ARGS__)
#define HEX_TO_UPPER(value) "0x" << std::hex << std::uppercase << (DWORD64)value << std::dec << std::nouppercase
}

View File

@ -21,102 +21,83 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
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");
LOG(RAW_GREEN_TO_CONSOLE) << u8R"kek(
______ _ ______ ______
(____ \(_) (____ \ (_____ \
____) )_ ____ ____) ) ____ ___ ____ _ _ ____) )
| __ (| |/ _ | __ ( / _ |/___)/ _ ) | | /_____/
| |__) ) ( ( | | |__) | ( | |___ ( (/ / \ V /_______
|______/|_|\_|| |______/ \_||_(___/ \____) \_/(_______)
(_____|)kek";
auto pointers_instance = std::make_unique<pointers>();
LOG_INFO("Pointers initialized.");
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.");
}
//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.");
LOG(INFO) << "Renderer initialized.";
auto fiber_pool_instance = std::make_unique<fiber_pool>(10);
LOG_INFO("Fiber pool initialized.");
LOG(INFO) << "Fiber pool initialized.";
auto hooking_instance = std::make_unique<hooking>();
LOG_INFO("Hooking initialized.");
LOG(INFO) << "Hooking initialized.";
g_settings.load();
LOG(INFO) << "Settings Loaded.";
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.");
LOG(INFO) << "Scripts registered.";
g_hooking->enable();
LOG_INFO("Hooking enabled.");
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);
std::this_thread::sleep_for(500ms);
}
g_hooking->disable();
LOG_INFO("Hooking disabled.");
LOG(INFO) << "Hooking disabled.";
std::this_thread::sleep_for(1000ms);
g_script_mgr.remove_all_scripts();
LOG_INFO("Scripts unregistered.");
LOG(INFO) << "Scripts unregistered.";
hooking_instance.reset();
LOG_INFO("Hooking uninitialized.");
LOG(INFO) << "Hooking uninitialized.";
fiber_pool_instance.reset();
LOG_INFO("Fiber pool uninitialized.");
LOG(INFO) << "Fiber pool uninitialized.";
renderer_instance.reset();
LOG_INFO("Renderer uninitialized.");
LOG(INFO) << "Renderer uninitialized.";
pointers_instance.reset();
LOG_INFO("Pointers uninitialized.");
LOG(INFO) << "Pointers uninitialized.";
}
catch (std::exception const &ex)
{
LOG_ERROR("{}", ex.what());
LOG(WARNING) << ex.what();
MessageBoxA(nullptr, ex.what(), nullptr, MB_OK | MB_ICONEXCLAMATION);
}
LOG_INFO("Farewell!");
LOG(INFO) << "Farewell!";
logger_instance.reset();
CloseHandle(g_main_thread);

View File

@ -13,21 +13,26 @@ namespace memory
void pattern_batch::run(range region)
{
bool all_found = true;
for (auto &entry : m_entries)
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);
LOG(big::INFO_TO_FILE) << "Found '" << entry.m_name << "' GTA5.exe+" << HEX_TO_UPPER(result.as<DWORD64>() - region.begin().as<DWORD64>());
}
else
{
all_found = false;
LOG_ERROR("Failed to find '{}'.", entry.m_name);
LOG(WARNING) << "Failed to find '" << entry.m_name << "'.";
}
}
else
{
all_found = false;
LOG(WARNING) << "Failed to find '" << entry.m_name << "'.";
}
}
m_entries.clear();

File diff suppressed because it is too large Load Diff

View File

@ -66,6 +66,11 @@ namespace big
m_swapchain = ptr.add(3).rip().as<IDXGISwapChain**>();
});
main_batch.add("Model Spawn Bypass", "48 8B C8 FF 52 30 84 C0 74 05 48", [this](memory::handle ptr)
{
m_model_spawn_bypass = ptr.add(8).as<PVOID>();
});
main_batch.run(memory::module(nullptr));
m_hwnd = FindWindowW(L"grcWindow", nullptr);

View File

@ -32,6 +32,8 @@ namespace big
CGameScriptHandlerMgr **m_script_handler_mgr{};
IDXGISwapChain **m_swapchain{};
PVOID m_model_spawn_bypass;
};
inline pointers *g_pointers{};

View File

@ -1,100 +1,132 @@
#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);
}
}
}
#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>
#include <imgui_internal.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());
auto file_path = std::filesystem::path(std::getenv("appdata"));
file_path /= "BigBaseV2";
if (!std::filesystem::exists(file_path))
{
std::filesystem::create_directory(file_path);
}
else if (!std::filesystem::is_directory(file_path))
{
std::filesystem::remove(file_path);
std::filesystem::create_directory(file_path);
}
file_path /= "imgui.ini";
ImGuiContext* ctx = ImGui::CreateContext();
static std::string path = file_path.make_preferred().string();
ctx->IO.IniFilename = path.c_str();
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)
{
//Persist and restore the cursor position between menu instances.
static POINT cursor_coords{};
if (g_gui.m_opened)
{
GetCursorPos(&cursor_coords);
}
else if (cursor_coords.x + cursor_coords.y != 0)
{
SetCursorPos(cursor_coords.x, cursor_coords.y);
}
g_gui.m_opened ^= true;
}
if (g_gui.m_opened)
{
ImGui_ImplWin32_WndProcHandler(hwnd, msg, wparam, lparam);
}
}
}

View File

@ -5,10 +5,17 @@
namespace big
{
static void script_exception_handler(PEXCEPTION_POINTERS exp)
void script::script_exception_handler(PEXCEPTION_POINTERS exp)
{
LOG_ERROR("Script threw an exception!");
g_stackwalker.ShowCallstack(GetCurrentThread(), exp->ContextRecord);
HMODULE mod{};
DWORD64 offset{};
char buffer[MAX_PATH]{};
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)exp->ExceptionRecord->ExceptionAddress, &mod) == TRUE && mod != nullptr)
{
offset = ((DWORD64)exp->ExceptionRecord->ExceptionAddress - (DWORD64)mod);
GetModuleFileNameA(mod, buffer, MAX_PATH - 1);
}
LOG(FATAL) << "Exception Code: " << HEX_TO_UPPER(exp->ExceptionRecord->ExceptionCode) << " Exception Offset: " << HEX_TO_UPPER(offset) << " Fault Module Name: " << buffer;
}
script::script(func_t func, std::optional<std::size_t> stack_size) :
@ -52,38 +59,23 @@ namespace big
SwitchToFiber(m_main_fiber);
}
script *script::get_current()
script* script::get_current()
{
return static_cast<script*>(GetFiberData());
}
void script::fiber_func()
{
__try
TRY_CLAUSE
{
[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!");
m_func();
}
EXCEPT_CLAUSE
[]() {
LOG(INFO) << "Script finished!";
}();
LOG_INFO("Script finished!");
while (true)
{
yield();

View File

@ -13,13 +13,20 @@ namespace big
void tick();
void yield(std::optional<std::chrono::high_resolution_clock::duration> time = std::nullopt);
static script *get_current();
static script* get_current();
static void script_exception_handler(PEXCEPTION_POINTERS exp);
private:
void fiber_func();
private:
void *m_script_fiber;
void *m_main_fiber;
void* m_script_fiber;
void* m_main_fiber;
func_t m_func;
std::optional<std::chrono::high_resolution_clock::time_point> m_wake_time;
};
#define TRY_CLAUSE __try
#define EXCEPT_CLAUSE __except (script::script_exception_handler(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) { }
#define QUEUE_JOB_BEGIN_CLAUSE(...) g_fiber_pool->queue_job([__VA_ARGS__] { __try
#define QUEUE_JOB_END_CLAUSE __except (script::script_exception_handler(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) {} });
}

View File

@ -9,9 +9,9 @@ namespace big
{
inline std::unordered_map<rage::scrProgram*, script_hook*> script_hook::s_map;
static bool map_native(rage::scrNativeHash *hash)
static bool map_native(rage::scrNativeHash* hash)
{
for (auto const &mapping : g_crossmap)
for (auto const& mapping : g_crossmap)
{
if (mapping.first == *hash)
{
@ -34,7 +34,7 @@ namespace big
{
if (m_program)
{
for (auto[hash, handler_ptr] : m_native_handler_ptrs)
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;
@ -58,12 +58,12 @@ namespace big
if (program->is_valid())
{
hook_instance(program);
LOG_INFO("Hooked {} script ({})", program->m_name, static_cast<void*>(program));
LOG(INFO) << "Hooked " << program->m_name << " script (" << HEX_TO_UPPER(static_cast<void*>(program)) << ")";
}
}
}
void script_hook::hook_instance(rage::scrProgram *program)
void script_hook::hook_instance(rage::scrProgram* program)
{
m_program = program;
s_map.emplace(m_program, this);
@ -88,7 +88,7 @@ namespace big
}
}
void script_hook::scrprogram_dtor(rage::scrProgram *this_, bool free_memory)
void script_hook::scrprogram_dtor(rage::scrProgram* this_, bool free_memory)
{
if (auto it = s_map.find(this_); it != s_map.end())
{

86
BigBaseV2/src/settings.h Normal file
View File

@ -0,0 +1,86 @@
#pragma once
#include "common.hpp"
#include "gta/player.hpp"
namespace big
{
class settings
{
public:
explicit settings() = default;
~settings() = default;
nlohmann::json options;
nlohmann::json default_options =
R"({
"demo bool": false,
"demo int": 1,
"demo double": 1.0,
"demo combo": 0
})"_json;
bool save()
{
std::string settings_file = std::getenv("appdata");
settings_file += "\\BigBaseV2\\settings.json";
std::ofstream file(settings_file, std::ios::out | std::ios::trunc);
file << options.dump(4);
file.close();
return true;
}
bool load()
{
std::string settings_file = std::getenv("appdata");
settings_file += "\\BigBaseV2\\settings.json";
std::ifstream file(settings_file);
if (!file.is_open())
{
write_default_config();
file.open(settings_file);
}
file >> options;
bool should_save = false;
for (auto& e : default_options.items())
{
if (options.count(e.key()) == 0)
{
should_save = true;
options[e.key()] = e.value();
}
}
if (should_save)
{
LOG(INFO) << "Updating settings.";
save();
}
return true;
}
private:
bool write_default_config()
{
std::string settings_file = std::getenv("appdata");
settings_file += "\\BigBaseV2\\settings.json";
std::ofstream file(settings_file, std::ios::out);
file << default_options.dump(4);
file.close();
options.clear();
options = default_options;
return true;
}
};
inline settings g_settings;
}

5
GenerateProjects.bat Normal file
View File

@ -0,0 +1,5 @@
@echo off
premake5 vs2019
IF %ERRORLEVEL% NEQ 0 (
PAUSE
)

View File

@ -20,6 +20,15 @@ To set up the build environment, run the following commands in a terminal:
```dos
git clone https://github.com/Pocakking/BigBaseV2.git --recurse-submodules
cd BigBaseV2
premake5 vs2019
GenerateProjects.bat
```
Now, you will be able to open the solution, and simply build it in Visual Studio.
It is reccomended you generate the project each time you add a file instead of adding it directly to Visual Studio.
## Credits
Pocakking - Original creator.
gir489 - Implementer and wrote the g3log crash handler and added test cases.
datlimabean04 - Wrote the g3log and settings implementation.

View File

@ -17,7 +17,7 @@ workspace "BigBaseV2"
IncludeDir["MinHook"] = "vendor/MinHook/include"
IncludeDir["ImGui"] = "vendor/ImGui"
IncludeDir["ImGuiImpl"] = "vendor/ImGui/examples"
IncludeDir["StackWalker"] = "vendor/StackWalker/Main/StackWalker/"
IncludeDir["g3log"] = "vendor/g3log/src"
CppVersion = "C++17"
MsvcToolset = "v142"
@ -26,6 +26,8 @@ workspace "BigBaseV2"
function DeclareMSVCOptions()
filter "system:windows"
staticruntime "Off"
floatingpoint "Fast"
vectorextensions "AVX2"
systemversion (WindowsSdkVersion)
toolset (MsvcToolset)
cppdialect (CppVersion)
@ -45,6 +47,11 @@ workspace "BigBaseV2"
"4307" -- C4307: integral constant overflow
}
end
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
function DeclareDebugOptions()
filter "configurations:Debug"
@ -102,27 +109,6 @@ workspace "BigBaseV2"
DeclareMSVCOptions()
DeclareDebugOptions()
project "StackWalker"
location "vendor/%{prj.name}"
kind "StaticLib"
language "C++"
targetdir ("bin/lib/" .. outputdir)
objdir ("bin/lib/int/" .. outputdir .. "/%{prj.name}")
files
{
"vendor/%{prj.name}/Main/StackWalker/StackWalker.cpp"
}
includedirs
{
"vendor/%{prj.name}/include"
}
DeclareMSVCOptions()
DeclareDebugOptions()
project "MinHook"
location "vendor/%{prj.name}"
kind "StaticLib"
@ -140,6 +126,38 @@ workspace "BigBaseV2"
DeclareMSVCOptions()
DeclareDebugOptions()
project "g3log"
location "vendor/%{prj.name}"
kind "StaticLib"
language "C++"
targetdir ("bin/lib/" .. outputdir)
objdir ("bin/lib/int/" .. outputdir .. "/%{prj.name}")
includedirs
{
"vendor/%{prj.name}/src"
}
if(file_exists("vendor\\g3log\\src\\g3log\\generated_definitions.hpp") == false) then
file = io.open("vendor\\g3log\\src\\g3log\\generated_definitions.hpp", "w")
file:write("// AUTO GENERATED MACRO DEFINITIONS FOR G3LOG\n\n\n/* ==========================================================================\n*2015 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes\n* with no warranties. This code is yours to share, use and modify with no\n\n*strings attached and no restrictions or obligations.\n* \n* For more information see g3log/LICENSE or refer refer to http://unlicense.org\n\n*============================================================================*/\n#pragma once\n\n\n// CMake induced definitions below. See g3log/Options.cmake for details.");
end
files
{
"vendor/%{prj.name}/src/**.hpp",
"vendor/%{prj.name}/src/**.cpp"
}
removefiles
{
"vendor/%{prj.name}/src/crashhandler_unix.cpp"
}
DeclareMSVCOptions()
DeclareDebugOptions()
project "BigBaseV2"
location "BigBaseV2"
@ -155,6 +173,7 @@ workspace "BigBaseV2"
files
{
"%{prj.name}/src/**.hpp",
"%{prj.name}/src/**.h",
"%{prj.name}/src/**.cpp",
"%{prj.name}/src/**.asm"
}
@ -166,7 +185,7 @@ workspace "BigBaseV2"
"%{IncludeDir.MinHook}",
"%{IncludeDir.ImGui}",
"%{IncludeDir.ImGuiImpl}",
"%{IncludeDir.StackWalker}",
"%{IncludeDir.g3log}",
"%{prj.name}/src"
}
@ -180,7 +199,7 @@ workspace "BigBaseV2"
"fmtlib",
"MinHook",
"ImGui",
"StackWalker"
"g3log"
}
pchheader "%{PrecompiledHeaderInclude}"
@ -197,12 +216,14 @@ workspace "BigBaseV2"
flags { "NoImportLib", "Maps" }
filter "configurations:Debug"
flags { "LinkTimeOptimization", "MultiProcessorCompile" }
defines { "BIGBASEV2_DEBUG" }
filter "configurations:Release"
flags { "LinkTimeOptimization", "NoManifest", "MultiProcessorCompile" }
defines { "BIGBASEV2_RELEASE" }
optimize "speed"
filter "configurations:Dist"
flags { "LinkTimeOptimization", "FatalCompileWarnings" }
flags { "LinkTimeOptimization", "FatalWarnings", "NoManifest", "MultiProcessorCompile" }
defines { "BIGBASEV2_DIST" }
optimize "speed"

2
vendor/ImGui vendored

@ -1 +1 @@
Subproject commit 6a0d0dab5a9f0b9518a2bc9bb456a69895ae0962
Subproject commit 03453246464cdd414c2f76d4a2569d2d5511870b

2
vendor/MinHook vendored

@ -1 +1 @@
Subproject commit 9fbd087432700d73fc571118d6a9697a36443d88
Subproject commit 8fda4f5481fed5797dc2651cd91e238e9b3928c6

1
vendor/StackWalker vendored

@ -1 +0,0 @@
Subproject commit 42e7a6e056a9e7aca911a7e9e54e2e4f90bc2652

2
vendor/fmtlib vendored

@ -1 +1 @@
Subproject commit 9e554999ce02cf86fcdfe74fe740c4fe3f5a56d5
Subproject commit e00997b004713a8de4ea480d7dfb3abb11d07852

1
vendor/g3log vendored Submodule

@ -0,0 +1 @@
Subproject commit 3ffc36a3a2d07e2c1e51acfe5e04856f87639488

2
vendor/json vendored

@ -1 +1 @@
Subproject commit 53c3eefa2cf790a7130fed3e13a3be35c2f2ace2
Subproject commit 456478b3c50d60100dbb1fb9bc931f370a2c1c28