diff --git a/BigBaseV2/src/common.hpp b/BigBaseV2/src/common.hpp index e4465b5f..7b9c41cb 100644 --- a/BigBaseV2/src/common.hpp +++ b/BigBaseV2/src/common.hpp @@ -53,6 +53,7 @@ #include "core/globals.hpp" #include "CPed.hpp" +#include "services/globals_service.hpp" #include "services/vehicle_service.hpp" namespace big diff --git a/BigBaseV2/src/gui/window/dbg/debug_globals.cpp b/BigBaseV2/src/gui/window/dbg/debug_globals.cpp index 866b59ef..6a80ecd2 100644 --- a/BigBaseV2/src/gui/window/dbg/debug_globals.cpp +++ b/BigBaseV2/src/gui/window/dbg/debug_globals.cpp @@ -1,4 +1,6 @@ #include "debug_tabs.hpp" +#include "services/globals_service.hpp" +#include "thread_pool.hpp" namespace big { @@ -6,7 +8,55 @@ namespace big { if (ImGui::BeginTabItem("Globals")) { - ImGui::Text("Coming soon..."); + if (ImGui::Checkbox("Enable Freezing", &g_globals_service->m_running) && !g_globals_service->m_running) + g_thread_pool->push([&]() { g_globals_service->loop(); }); + + if (ImGui::Button("Load")) + g_globals_service->load(); + ImGui::SameLine(); + if (ImGui::Button("Save")) + g_globals_service->save(); + + ImGui::SameLine(); + if (ImGui::Button("Add Global")) + { + ImGui::OpenPopup("New Global"); + } + + modal_debug::modal_new_global(); + + for (auto& global : g_globals_service->m_globals) + { + ImGui::Separator(); + + char label[64]; + sprintf(label, "Freeze###freeze_%d", global.m_base_address); + ImGui::Checkbox(label, &global.m_freeze); + ImGui::SameLine(); + + ImGui::Text(global.m_name.c_str()); + ImGui::SameLine(); + + sprintf(label, "###input_%d", global.m_base_address); + ImGui::PushItemWidth(200.f); + ImGui::InputInt(label, global.get()); + ImGui::PopItemWidth(); + + sprintf(label, "Write###btn_%d", global.m_base_address); + if (ImGui::Button(label)) + global.write(); + + ImGui::SameLine(); + sprintf(label, "Delete##delet_%d", global.m_base_address); + if (ImGui::Button(label)) + { + for (int i = 0; i < g_globals_service->m_globals.size(); i++) + if (const auto& it = g_globals_service->m_globals.at(i); it.m_base_address == global.m_base_address && it.m_name == global.m_name) + g_globals_service->m_globals.erase(g_globals_service->m_globals.begin() + i); + + break; + } + } ImGui::EndTabItem(); } diff --git a/BigBaseV2/src/gui/window/dbg/debug_tabs.hpp b/BigBaseV2/src/gui/window/dbg/debug_tabs.hpp index 344d3743..787594d1 100644 --- a/BigBaseV2/src/gui/window/dbg/debug_tabs.hpp +++ b/BigBaseV2/src/gui/window/dbg/debug_tabs.hpp @@ -4,8 +4,13 @@ namespace big { - class tab_debug { - public: + struct modal_debug + { + static void modal_new_global(); + }; + + struct tab_debug + { static void tab_globals(); static void tab_script_events(); static void _tab_debug(); diff --git a/BigBaseV2/src/gui/window/dbg/modals/new_globals.cpp b/BigBaseV2/src/gui/window/dbg/modals/new_globals.cpp new file mode 100644 index 00000000..402311f8 --- /dev/null +++ b/BigBaseV2/src/gui/window/dbg/modals/new_globals.cpp @@ -0,0 +1,97 @@ +#include "../debug_tabs.hpp" +#include "fiber_pool.hpp" +#include "thread_pool.hpp" +#include "natives.hpp" +#include "script.hpp" + +namespace big +{ + void modal_debug::modal_new_global() + { + ImGui::SetNextWindowSize({ 520, 325 }, ImGuiCond_FirstUseEver); + if (ImGui::BeginPopupModal("New Global")) + { + static int base_address = 0; + static bool freeze = false; + static char name[32] = ""; + static int (*offsets)[2] = nullptr; + static int offset_count = 0; + static int previous_offset_count = 0; + + QUEUE_JOB_BEGIN_CLAUSE() + { + PAD::DISABLE_ALL_CONTROL_ACTIONS(0); + }QUEUE_JOB_END_CLAUSE + + ImGui::Text("Name:"); + ImGui::InputText("##modal_global_name", name, sizeof(name)); + ImGui::Text("Base Address:"); + ImGui::InputInt("##modal_global_base_addr", &base_address); + ImGui::Text("Freeze:"); + ImGui::Checkbox("##modal_global_freeze", &freeze); + ImGui::Text("Number of Offsets:"); + ImGui::InputInt("##modal_offset_count", &offset_count); + + if (offset_count < 0) offset_count; + else if (offset_count > 10) offset_count = 10; + + if (offset_count != previous_offset_count) + { + int(*new_offsets)[2] = new int[offset_count][2]{ 0 }; + memcpy(new_offsets, offsets, sizeof(int) * std::min(offset_count, previous_offset_count) * 2); + + delete[] offsets; + offsets = new_offsets; + + previous_offset_count = offset_count; + } + + ImGui::PushItemWidth(320.f); + for (int i = 0; i < offset_count; i++) + { + char id[32]; + + ImGui::Separator(); + + ImGui::Text("Offset: %d", i + 1); + + sprintf(id, "##offset_%d", i); + ImGui::InputInt(id, &offsets[i][0]); + + ImGui::Text("Size:"); + ImGui::SameLine(); + sprintf(id, "##size_%d", i); + ImGui::InputInt(id, &offsets[i][1]); + } + ImGui::PopItemWidth(); + + if (ImGui::Button("Cancel")) + { + strcpy(name, ""); + freeze = false; + delete[] offsets; + offsets = nullptr; + offset_count = 0; + previous_offset_count = 0; + + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(); + if (ImGui::Button("Save")) + { + g_globals_service->m_globals.push_back(global(name, base_address, freeze, offsets, offset_count)); + + strcpy(name, ""); + freeze = false; + delete[] offsets; + offsets = nullptr; + offset_count = 0; + previous_offset_count = 0; + + ImGui::CloseCurrentPopup(); + } + + ImGui::EndPopup(); + } + } +} \ No newline at end of file diff --git a/BigBaseV2/src/main.cpp b/BigBaseV2/src/main.cpp index c0199a52..99256ccc 100644 --- a/BigBaseV2/src/main.cpp +++ b/BigBaseV2/src/main.cpp @@ -51,6 +51,8 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) g_hooking->enable(); LOG(INFO) << "Hooking enabled."; + LOG(INFO) << "Registering service instances..."; + auto globals_service_instace = std::make_unique(); auto vehicle_service_instance = std::make_unique(); while (g_running) @@ -58,6 +60,12 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) std::this_thread::sleep_for(500ms); } + LOG(INFO) << "Serviceses uninitialized."; + vehicle_service_instance.reset(); + globals_service_instace.reset(); + + // Make sure that all threads created don't have any blocking loops + // otherwise make sure that they have stopped executing g_thread_pool->destroy(); LOG(INFO) << "Destroyed thread pool."; @@ -83,8 +91,6 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) pointers_instance.reset(); LOG(INFO) << "Pointers uninitialized."; - - vehicle_service_instance.reset(); } catch (std::exception const &ex) { diff --git a/BigBaseV2/src/services/globals_service.cpp b/BigBaseV2/src/services/globals_service.cpp new file mode 100644 index 00000000..aea4c6b3 --- /dev/null +++ b/BigBaseV2/src/services/globals_service.cpp @@ -0,0 +1,89 @@ +#include "globals_service.hpp" +#include "thread_pool.hpp" + +namespace big +{ + globals_service::globals_service() + { + g_globals_service = this; + } + + globals_service::~globals_service() + { + g_globals_service = nullptr; + + m_running = false; + + this->save(); + } + + void globals_service::build(nlohmann::json& data) + { + m_globals.clear(); + + for (auto& offset : data) + m_globals.push_back(global(offset)); + + for (auto& global : m_globals) + global.build_cache(); + } + + bool globals_service::load() + { + std::string path = std::getenv("appdata"); + path += this->file_location; + + std::ifstream file(path); + + if (!file.is_open()) + return false; + + try + { + nlohmann::json j; + j << file; + + this->build(j); + } + catch (const std::exception&) + { + LOG(WARNING) << "Failure to parse globals.json, aborting..."; + + return false; + } + + return true; + } + + void globals_service::loop() + { + // Don't start loop if it's already running... + if (m_running) return; + + while (m_running) + for (auto& global : m_globals) + if (global.m_freeze) global.write(); + } + + void globals_service::save() + { + nlohmann::json j = nlohmann::json::array(); + for (auto& global : m_globals) + j.push_back(global.to_json()); + + std::string path = std::getenv("appdata"); + path += this->file_location; + std::ofstream file(path, std::ios::out | std::ios::trunc); + + try + { + file << j.dump(4); + + file.close(); + } + catch (const std::exception&) + { + LOG(WARNING) << "Failed to write to globals.json"; + } + } +} \ No newline at end of file diff --git a/BigBaseV2/src/services/globals_service.hpp b/BigBaseV2/src/services/globals_service.hpp new file mode 100644 index 00000000..994ac5a1 --- /dev/null +++ b/BigBaseV2/src/services/globals_service.hpp @@ -0,0 +1,143 @@ +#pragma once +#include "script_global.hpp" + +namespace big +{ + struct global_offset + { + global_offset(nlohmann::json data) + { + m_offset = data["offset"]; + + if (data.contains("size")) + m_size = data["size"]; + } + + global_offset(int offset, int size = 0) + { + m_offset = offset; + + if (size) + m_size = size; + } + + script_global apply(script_global internal_cache) + { + return m_size ? internal_cache.at(m_offset, m_size) : internal_cache.at(m_offset); + } + + nlohmann::json to_json() + { + nlohmann::json j; + + j["offset"] = m_offset; + if (m_size) + j["size"] = m_size; + + return j; + } + + private: + int m_offset = 0; + int m_size = 0; + }; + + struct global + { + int m_base_address; + bool m_freeze = false; + std::string m_name; + std::vector m_offsets; + int m_value; + + global(nlohmann::json data) + { + m_base_address = data["base_address"]; + m_freeze = data["freeze"]; + m_name = data["name"]; + m_value = data["value"]; + + for (auto& offset : data["offsets"]) + m_offsets.push_back(global_offset(offset)); + } + + global(const char* name, const int base_address, const bool freeze, const int(*offsets)[2], int offset_count) + { + m_base_address = base_address; + m_freeze = freeze; + m_name = std::string(name); + m_value = 0; + + for (int i = 0; i < offset_count; i++) + m_offsets.push_back(global_offset(offsets[i][0], offsets[i][1])); + } + + void build_cache() + { + script_global internal_cache(m_base_address); + + for (auto& offset : m_offsets) + internal_cache = offset.apply(internal_cache); + + m_internal_addr = internal_cache.as(); + } + + int* get() + { + if (m_freeze) + return &m_value; + return m_internal_addr; + } + + void set(int value) + { + m_value = value; + if (!m_freeze) + this->write(); + } + + nlohmann::json to_json() + { + nlohmann::json j; + + j["base_address"] = m_base_address; + j["freeze"] = m_freeze; + j["name"] = m_name; + j["value"] = m_value; + + j["offsets"] = nlohmann::json::array(); + for (auto& offset : m_offsets) + j["offsets"].push_back(offset.to_json()); + + return j; + } + + void write() + { + *m_internal_addr = m_value; + } + + private: + int* m_internal_addr; + }; + + class globals_service + { + const char* file_location = "\\BigBaseV2\\globals.json"; + + public: + globals_service(); + ~globals_service(); + + bool load(); + void loop(); + void save(); + + std::vector m_globals; + bool m_running = false;; + private: + void build(nlohmann::json& data); + }; + + inline globals_service* g_globals_service{}; +} \ No newline at end of file