www
www
This commit is contained in:
1 parent
3933cd1901
commit
0aa65c433d
98 files changed
+56670
No files matched your search
@@ -0,0 +1,598 @@
|
||||
#include "helpers.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cwctype>
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
RuntimeConfig g_Runtime;
|
||||
|
||||
namespace {
|
||||
|
||||
std::mutex g_il2cpp_mutex;
|
||||
std::unordered_map<uintptr_t, void*> g_il2cpp_slots;
|
||||
|
||||
void* g_il2cpp_domain_cached = nullptr;
|
||||
void* (*g_il2cpp_domain_get_fn)() = nullptr;
|
||||
void* (*g_il2cpp_thread_attach_fn)(void*) = nullptr;
|
||||
void* (*g_il2cpp_thread_current_fn)() = nullptr;
|
||||
void (*g_il2cpp_thread_detach_fn)(void*) = nullptr;
|
||||
|
||||
thread_local void* g_tls_il2cpp_thread = nullptr;
|
||||
thread_local bool g_tls_il2cpp_attached_by_us = false;
|
||||
thread_local bool g_tls_game_thread_context = false;
|
||||
|
||||
std::mutex g_i18n_mutex;
|
||||
bool g_i18n_initialized = false;
|
||||
std::unordered_map<std::string, std::string> g_en;
|
||||
std::unordered_map<std::string, std::string> g_zh_cn;
|
||||
|
||||
constexpr const char* kI18nBlob = R"json(
|
||||
{
|
||||
"NoClip": {"en":"NoClip", "zh_cn":"NoClip"},
|
||||
"FreeCam": {"en":"FreeCam", "zh_cn":"????"},
|
||||
"Free Camera": {"en":"Free Camera", "zh_cn":"????"},
|
||||
"Fps Unlocker": {"en":"Fps Unlocker", "zh_cn":"????"},
|
||||
"FPSModule": {"en":"FPSModule", "zh_cn":"FPS??"},
|
||||
"SetDither": {"en":"SetDither", "zh_cn":"????"},
|
||||
"Set Dither": {"en":"Set Dither", "zh_cn":"????"},
|
||||
"PlayerProfile": {"en":"PlayerProfile", "zh_cn":"????"},
|
||||
"Vacuum": {"en":"Vacuum", "zh_cn":"??"},
|
||||
"SkillHack": {"en":"SkillHack", "zh_cn":"????"},
|
||||
"Free Skill": {"en":"Free Skill", "zh_cn":"????"},
|
||||
"ESPModule": {"en":"ESPModule", "zh_cn":"ESP??"},
|
||||
"ESP Features": {"en":"ESP Features", "zh_cn":"ESP??"},
|
||||
"Prevent Screenshot": {"en":"Prevent Screenshot", "zh_cn":"???"},
|
||||
"Unity Explorer": {"en":"Unity Explorer", "zh_cn":"Unity???"},
|
||||
"Unity Explorer Window": {"en":"Unity Explorer Window", "zh_cn":"Unity?????"},
|
||||
"ON / OFF": {"en":"ON / OFF", "zh_cn":"? / ?"},
|
||||
"Move Speed": {"en":"Move Speed", "zh_cn":"????"},
|
||||
"Look Sensitivity": {"en":"Look Sensitivity", "zh_cn":"?????"},
|
||||
"Roll Speed": {"en":"Roll Speed", "zh_cn":"????"},
|
||||
"FOV Speed": {"en":"FOV Speed", "zh_cn":"????"},
|
||||
"FOV": {"en":"FOV", "zh_cn":"??"},
|
||||
"Fps Value": {"en":"Fps Value", "zh_cn":"???"},
|
||||
"UID text": {"en":"UID text", "zh_cn":"UID??"},
|
||||
"Name text": {"en":"Name text", "zh_cn":"????"},
|
||||
"Name changer": {"en":"Name changer", "zh_cn":"??"},
|
||||
"Monster": {"en":"Monster", "zh_cn":"??"},
|
||||
"Show Monsters": {"en":"Show Monsters", "zh_cn":"????"},
|
||||
"Show NPC": {"en":"Show NPC", "zh_cn":"??NPC"},
|
||||
"Show Friendly": {"en":"Show Friendly", "zh_cn":"????"},
|
||||
"Show Puzzles": {"en":"Show Puzzles", "zh_cn":"??????"},
|
||||
"Show All": {"en":"Show All", "zh_cn":"????"},
|
||||
"Show Distance": {"en":"Show Distance", "zh_cn":"????"},
|
||||
"Show Name": {"en":"Show Name", "zh_cn":"????"},
|
||||
"Show Type": {"en":"Show Type", "zh_cn":"????"},
|
||||
"Theme": {"en":"Theme", "zh_cn":"??"},
|
||||
"Toggle Console": {"en":"Toggle Console", "zh_cn":"?????"},
|
||||
"About": {"en":"About", "zh_cn":"??"},
|
||||
"Player": {"en":"Player", "zh_cn":"??"},
|
||||
"ESP": {"en":"ESP", "zh_cn":"ESP"},
|
||||
"World": {"en":"World", "zh_cn":"??"},
|
||||
"Visual": {"en":"Visual", "zh_cn":"??"},
|
||||
"Settings": {"en":"Settings", "zh_cn":"??"},
|
||||
"Damagehack Toggle": {"en":"Damagehack Toggle", "zh_cn":"????"},
|
||||
"Damage Multiplier": {"en":"Damage Multiplier", "zh_cn":"????"},
|
||||
"Multiplier Value": {"en":"Multiplier Value", "zh_cn":"???"},
|
||||
"Random Damage Type": {"en":"Random Damage Type", "zh_cn":"??????"},
|
||||
"This is free, if you spend money, then you have been deceived": {
|
||||
"en":"This is free, if you spend money, then you have been deceived",
|
||||
"zh_cn":"?????,??????,?????"
|
||||
}
|
||||
}
|
||||
)json";
|
||||
|
||||
ImVec4 ParseHexColor(const char* rrggbbaa) {
|
||||
unsigned int rgba = 0u;
|
||||
sscanf_s(rrggbbaa, "%x", &rgba);
|
||||
const float r = static_cast<float>((rgba >> 24) & 0xFF) / 255.0f;
|
||||
const float g = static_cast<float>((rgba >> 16) & 0xFF) / 255.0f;
|
||||
const float b = static_cast<float>((rgba >> 8) & 0xFF) / 255.0f;
|
||||
const float a = static_cast<float>(rgba & 0xFF) / 255.0f;
|
||||
return ImVec4(r, g, b, a);
|
||||
}
|
||||
|
||||
void ApplyThemePalette(const std::array<const char*, 11>& colors) {
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.Colors[ImGuiCol_Text] = ParseHexColor(colors[0]);
|
||||
style.Colors[ImGuiCol_WindowBg] = ParseHexColor(colors[1]);
|
||||
style.Colors[ImGuiCol_ChildBg] = ParseHexColor(colors[2]);
|
||||
style.Colors[ImGuiCol_PopupBg] = ParseHexColor(colors[3]);
|
||||
style.Colors[ImGuiCol_Border] = ParseHexColor(colors[4]);
|
||||
style.Colors[ImGuiCol_FrameBg] = ParseHexColor(colors[5]);
|
||||
style.Colors[ImGuiCol_FrameBgHovered] = ParseHexColor(colors[6]);
|
||||
style.Colors[ImGuiCol_FrameBgActive] = ParseHexColor(colors[7]);
|
||||
style.Colors[ImGuiCol_Button] = ParseHexColor(colors[8]);
|
||||
style.Colors[ImGuiCol_ButtonHovered] = ParseHexColor(colors[9]);
|
||||
style.Colors[ImGuiCol_ButtonActive] = ParseHexColor(colors[10]);
|
||||
}
|
||||
|
||||
uintptr_t FindGameAssemblyBaseNow() {
|
||||
HMODULE h = GetModuleHandleW(L"GameAssembly.dll");
|
||||
if (!h) {
|
||||
h = GetModuleHandleW(L"gameassembly.dll");
|
||||
}
|
||||
if (h) {
|
||||
return reinterpret_cast<uintptr_t>(h);
|
||||
}
|
||||
|
||||
HMODULE modules[2048] = {};
|
||||
DWORD needed = 0;
|
||||
if (!K32EnumProcessModules(GetCurrentProcess(), modules, sizeof(modules), &needed)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t count = needed / sizeof(HMODULE);
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
wchar_t path[MAX_PATH] = {};
|
||||
if (K32GetModuleFileNameExW(GetCurrentProcess(), modules[i], path, MAX_PATH) == 0) {
|
||||
continue;
|
||||
}
|
||||
std::wstring name = path;
|
||||
std::transform(name.begin(), name.end(), name.begin(), [](wchar_t c) {
|
||||
return static_cast<wchar_t>(::towlower(c));
|
||||
});
|
||||
if (name.find(L"gameassembly.dll") != std::wstring::npos) {
|
||||
return reinterpret_cast<uintptr_t>(modules[i]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ResolveIl2CppThreadApisOnce() {
|
||||
HMODULE ga = GetModuleHandleW(L"GameAssembly.dll");
|
||||
if (!ga) {
|
||||
ga = GetModuleHandleW(L"gameassembly.dll");
|
||||
}
|
||||
if (!ga) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_il2cpp_domain_get_fn =
|
||||
reinterpret_cast<void* (*)()>(GetProcAddress(ga, "il2cpp_domain_get"));
|
||||
g_il2cpp_thread_attach_fn =
|
||||
reinterpret_cast<void* (*)(void*)>(GetProcAddress(ga, "il2cpp_thread_attach"));
|
||||
g_il2cpp_thread_current_fn =
|
||||
reinterpret_cast<void* (*)()>(GetProcAddress(ga, "il2cpp_thread_current"));
|
||||
g_il2cpp_thread_detach_fn =
|
||||
reinterpret_cast<void (*)(void*)>(GetProcAddress(ga, "il2cpp_thread_detach"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const std::array<Il2cppSlotDefinition, 71> kIl2cppSlotMap = {{
|
||||
{0x1C48, 0x09DC0120, "GameObject.GetComponentByIndex"},
|
||||
{0x1C50, 0x0018CEC0, "il2cpp_domain_get_assemblies_A"},
|
||||
{0x1C58, 0x0B390700, "Component.GetComponent<Transform>"},
|
||||
{0x1C60, 0x0B3A2D20, "Transform.get_localScale"},
|
||||
{0x1C68, 0x0B3A2CB0, "Transform.get_rotation"},
|
||||
{0x1C70, 0x0018AD80, "il2cpp_object_get_class"},
|
||||
{0x1C78, 0x00007480, "il2cpp_class_get_method_from_name"},
|
||||
{0x1C80, 0x0B3A1AE0, "Transform.get_localPosition"},
|
||||
{0x1C88, 0x0B3A1A70, "Transform.get_position"},
|
||||
{0x1C90, 0x0B3A51D0, "Transform.set_localPosition"},
|
||||
{0x1C98, 0x0B398830, "GameObject.SetActive"},
|
||||
{0x1CA0, 0x0B3911F0, "GameObject.get_transform"},
|
||||
{0x1CA8, 0x0B3A59D0, "Transform.set_rotation"},
|
||||
{0x1CB0, 0x0B391D90, "GameObject.get_activeInHierarchy"},
|
||||
{0x1CB8, 0x0B3B2410, "GameObject.get_tag"},
|
||||
{0x1CC0, 0x0B3B2120, "GameObject.get_name"},
|
||||
{0x1CC8, 0x0B3B40B0, "GameObject.get_layer"},
|
||||
{0x1CD0, 0x0B397980, "GameObject.get_scene"},
|
||||
{0x1CD8, 0x02F3DA80, "Game_SkillBuff_A"},
|
||||
{0x1CE0, 0x00F27E10, "GetEntityName"},
|
||||
{0x1CE8, 0x0B329000, "Component.GetComponents"},
|
||||
{0x1CF0, 0x0B329D80, "Component.GetComponentsInChildren"},
|
||||
{0x1CF8, 0x03E9BB50, "Game_SkillSlot_A"},
|
||||
{0x1D00, 0x0B383F60, "Object.get_name"},
|
||||
{0x1D08, 0x0B33CAB0, "Component.GetType_A"},
|
||||
{0x1D10, 0x0B33CB00, "Component.GetType_B"},
|
||||
{0x1D18, 0x039D1AA0, "Game_SkillSlot_B"},
|
||||
{0x1D20, 0x026DE9F0, "Game_Combat_HitA"},
|
||||
{0x1D28, 0x0478E860, "GetEntityManager"},
|
||||
{0x1D30, 0x025E2D40, "Game_Combat_HitB"},
|
||||
{0x1D38, 0x087C2CD0, "Game_Movement_PhysA"},
|
||||
{0x1D40, 0x03419AF0, "Game_Movement_PhysB"},
|
||||
{0x1D48, 0x0B322FB0, "Scene.get_name / Application.set_targetFrameRate ref"},
|
||||
{0x1D50, 0x0B396A20, "SceneManager.GetActiveScene"},
|
||||
{0x1D58, 0x0B397700, "CinemachineBrain.get_ActiveVirtualCamera"},
|
||||
{0x1D60, 0x03766810, "Game_EntityState_A"},
|
||||
{0x1D68, 0x0B3A2A60, "Transform.set_localScale"},
|
||||
{0x1D70, 0x0B326660, "Rigidbody.get_velocity"},
|
||||
{0x1D78, 0x0B3266B0, "Rigidbody.set_velocity"},
|
||||
{0x1D80, 0x0B383200, "Object.Destroy"},
|
||||
{0x1D88, 0x0B3A1A10, "Transform.set_position"},
|
||||
{0x1D90, 0x0B3A2340, "Game_EntityState_B"},
|
||||
{0x1D98, 0x0B421800, "Input.GetAxis(Mouse X)"},
|
||||
{0x1DA0, 0x0B3A26D0, "Game_PlayerState_A"},
|
||||
{0x1DA8, 0x0B3A1FB0, "Game_PlayerState_B"},
|
||||
{0x1DB0, 0x0B32B030, "Game_PlayerHealthStat"},
|
||||
{0x1DB8, 0x0B391240, "GameObject.SetActive (second ref)"},
|
||||
{0x1DC0, 0x0B390440, "Camera.get_main"},
|
||||
{0x1DC8, 0x0B390F80, "GameObject.FindObjectOfType"},
|
||||
{0x1DD0, 0x0B3A19A0, "Transform.get_position (second ref)"},
|
||||
{0x1DD8, 0x03F85430, "Game_SkillAction_C"},
|
||||
{0x1DE0, 0x0B3A1D30, "Transform.set_rotation (second ref)"},
|
||||
{0x1DE8, 0x0B3A1C90, "Camera.get_fieldOfView"},
|
||||
{0x1DF0, 0x00E92CF0, "Game_EntityState_C"},
|
||||
{0x1E00, 0x03DC14C0, "Game_SkillAction_D"},
|
||||
{0x1E08, 0x03E0D2C0, "Game_SkillAction_E"},
|
||||
{0x1E10, 0x03D9DF30, "Game_SkillAction_F"},
|
||||
{0x1E18, 0x00E9E9F0, "Game_SkillAction_G"},
|
||||
{0x1E20, 0x03EA53C0, "Game_SkillAction_H"},
|
||||
{0x1E28, 0x0ACA0EC0, "TMPro.set_text"},
|
||||
{0x1E30, 0x0B391D40, "UnityUI.Text.set_text"},
|
||||
{0x1E38, 0x036AA8F0, "Game_SkillAction_I"},
|
||||
{0x1E40, 0x03EC31C0, "Game_SkillAction_J"},
|
||||
{0x1E48, 0x037F8CD0, "Game_EntityActor_D"},
|
||||
{0x1E50, 0x036EA640, "Game_SkillAction_K"},
|
||||
{0x1E58, 0x03EC30E0, "Game_SkillAction_L"},
|
||||
{0x1E60, 0x037F2A40, "Game_EntityActor_E"},
|
||||
{0x1E68, 0x037FD7E0, "Game_EntityActor_F"},
|
||||
{0x1E70, 0x00D94C10, "il2cpp_domain_get"},
|
||||
{0x1E78, 0x00D94DA0, "il2cpp_assembly_get_image"},
|
||||
{0x1E80, 0x00D93A60, "il2cpp_domain_get_assemblies_B"},
|
||||
}};
|
||||
|
||||
void Log(const char* fmt, ...) {
|
||||
char buffer[2048] = {};
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
std::vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
OutputDebugStringA(buffer);
|
||||
OutputDebugStringA("\n");
|
||||
|
||||
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (h != nullptr && h != INVALID_HANDLE_VALUE) {
|
||||
DWORD written = 0;
|
||||
WriteConsoleA(h, buffer, static_cast<DWORD>(std::strlen(buffer)), &written, nullptr);
|
||||
WriteConsoleA(h, "\n", 1, &written, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring Utf8ToWide(const std::string& value) {
|
||||
if (value.empty()) {
|
||||
return {};
|
||||
}
|
||||
const int size = MultiByteToWideChar(65001, 0, value.c_str(), -1, nullptr, 0);
|
||||
if (size <= 0) {
|
||||
return {};
|
||||
}
|
||||
std::wstring result(static_cast<size_t>(size), L'\0');
|
||||
MultiByteToWideChar(65001, 0, value.c_str(), -1, result.data(), size);
|
||||
if (!result.empty() && result.back() == L'\0') {
|
||||
result.pop_back();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string WideToUtf8(const std::wstring& value) {
|
||||
if (value.empty()) {
|
||||
return {};
|
||||
}
|
||||
const int size = WideCharToMultiByte(65001, 0, value.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
||||
if (size <= 0) {
|
||||
return {};
|
||||
}
|
||||
std::string result(static_cast<size_t>(size), '\0');
|
||||
WideCharToMultiByte(65001, 0, value.c_str(), -1, result.data(), size, nullptr, nullptr);
|
||||
if (!result.empty() && result.back() == '\0') {
|
||||
result.pop_back();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uintptr_t GetGameAssemblyBase() {
|
||||
if (g_Runtime.game_assembly_base != 0) {
|
||||
return g_Runtime.game_assembly_base;
|
||||
}
|
||||
g_Runtime.game_assembly_base = FindGameAssemblyBaseNow();
|
||||
return g_Runtime.game_assembly_base;
|
||||
}
|
||||
|
||||
bool WaitForGameAssembly(uint32_t timeout_ms, uint32_t poll_ms) {
|
||||
const ULONGLONG start = GetTickCount64();
|
||||
while (g_Runtime.running.load(std::memory_order_relaxed) || timeout_ms == 0) {
|
||||
const uintptr_t base = FindGameAssemblyBaseNow();
|
||||
if (base != 0) {
|
||||
g_Runtime.game_assembly_base = base;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (timeout_ms != 0) {
|
||||
const ULONGLONG elapsed = GetTickCount64() - start;
|
||||
if (elapsed >= timeout_ms) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Sleep(poll_ms);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ResolveGABypassSlots() {
|
||||
std::scoped_lock lock(g_il2cpp_mutex);
|
||||
g_il2cpp_slots.clear();
|
||||
|
||||
const uintptr_t base = GetGameAssemblyBase();
|
||||
if (base == 0) {
|
||||
Log("IL2CPP Domain Not Found!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& slot : kIl2cppSlotMap) {
|
||||
g_il2cpp_slots[slot.slot_offset] = reinterpret_cast<void*>(base + slot.gameassembly_offset);
|
||||
}
|
||||
Log("IL2CPP Domain Found: 0x%p", reinterpret_cast<void*>(base));
|
||||
}
|
||||
|
||||
void* GetIl2cppSlot(uintptr_t slot_offset) {
|
||||
std::scoped_lock lock(g_il2cpp_mutex);
|
||||
const auto it = g_il2cpp_slots.find(slot_offset);
|
||||
if (it == g_il2cpp_slots.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool EnsureIl2CppThreadAttached() {
|
||||
if (!g_il2cpp_thread_attach_fn || !g_il2cpp_domain_get_fn) {
|
||||
ResolveIl2CppThreadApisOnce();
|
||||
}
|
||||
|
||||
if (!g_il2cpp_thread_attach_fn || !g_il2cpp_domain_get_fn) {
|
||||
g_Runtime.il2cpp_thread_attached.store(false, std::memory_order_relaxed);
|
||||
return false;
|
||||
}
|
||||
|
||||
void* domain = g_il2cpp_domain_cached;
|
||||
if (!domain) {
|
||||
domain = g_il2cpp_domain_get_fn();
|
||||
g_il2cpp_domain_cached = domain;
|
||||
}
|
||||
|
||||
if (!domain) {
|
||||
g_Runtime.il2cpp_thread_attached.store(false, std::memory_order_relaxed);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_il2cpp_thread_current_fn) {
|
||||
void* current = g_il2cpp_thread_current_fn();
|
||||
if (current) {
|
||||
g_tls_il2cpp_thread = current;
|
||||
g_tls_il2cpp_attached_by_us = false;
|
||||
g_Runtime.il2cpp_thread_attached.store(true, std::memory_order_relaxed);
|
||||
return true;
|
||||
}
|
||||
} else if (g_tls_il2cpp_thread) {
|
||||
g_Runtime.il2cpp_thread_attached.store(true, std::memory_order_relaxed);
|
||||
return true;
|
||||
}
|
||||
|
||||
void* attached = g_il2cpp_thread_attach_fn(domain);
|
||||
if (!attached) {
|
||||
g_Runtime.il2cpp_thread_attached.store(false, std::memory_order_relaxed);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_tls_il2cpp_thread = attached;
|
||||
g_tls_il2cpp_attached_by_us = true;
|
||||
g_Runtime.il2cpp_thread_attached.store(true, std::memory_order_relaxed);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WaitForIl2CppThreadAttach(uint32_t timeout_ms, uint32_t poll_ms) {
|
||||
const ULONGLONG start = GetTickCount64();
|
||||
for (;;) {
|
||||
if (EnsureIl2CppThreadAttached()) {
|
||||
return true;
|
||||
}
|
||||
if (timeout_ms != 0) {
|
||||
const ULONGLONG elapsed = GetTickCount64() - start;
|
||||
if (elapsed >= timeout_ms) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Sleep(poll_ms);
|
||||
}
|
||||
}
|
||||
|
||||
void DetachIl2CppThreadIfAttached() {
|
||||
if (!g_tls_il2cpp_thread || !g_tls_il2cpp_attached_by_us) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_il2cpp_thread_detach_fn) {
|
||||
ResolveIl2CppThreadApisOnce();
|
||||
}
|
||||
if (g_il2cpp_thread_detach_fn) {
|
||||
g_il2cpp_thread_detach_fn(g_tls_il2cpp_thread);
|
||||
}
|
||||
|
||||
g_tls_il2cpp_thread = nullptr;
|
||||
g_tls_il2cpp_attached_by_us = false;
|
||||
g_Runtime.il2cpp_thread_attached.store(false, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void SetGameThreadContext(bool enabled) {
|
||||
g_tls_game_thread_context = enabled;
|
||||
if (enabled) {
|
||||
const DWORD tid = GetCurrentThreadId();
|
||||
DWORD known = g_Runtime.game_thread_id.load(std::memory_order_relaxed);
|
||||
if (known == 0) {
|
||||
g_Runtime.game_thread_id.store(tid, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IsGameThreadContext() {
|
||||
if (g_tls_game_thread_context) {
|
||||
return true;
|
||||
}
|
||||
const DWORD known = g_Runtime.game_thread_id.load(std::memory_order_relaxed);
|
||||
return known != 0 && known == GetCurrentThreadId();
|
||||
}
|
||||
|
||||
bool IsWindowsBuildAtLeast(uint32_t build_number) {
|
||||
using RtlGetVersionFn = LONG(WINAPI*)(PRTL_OSVERSIONINFOW);
|
||||
|
||||
static std::atomic<uint32_t> cached_build{0};
|
||||
uint32_t value = cached_build.load(std::memory_order_acquire);
|
||||
if (value == 0) {
|
||||
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
|
||||
if (!ntdll) {
|
||||
ntdll = LoadLibraryW(L"ntdll.dll");
|
||||
}
|
||||
if (!ntdll) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* rtl_get_version = reinterpret_cast<RtlGetVersionFn>(
|
||||
GetProcAddress(ntdll, "RtlGetVersion"));
|
||||
if (!rtl_get_version) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RTL_OSVERSIONINFOW info{};
|
||||
info.dwOSVersionInfoSize = sizeof(info);
|
||||
if (rtl_get_version(&info) == 0) {
|
||||
value = info.dwBuildNumber;
|
||||
cached_build.store(value, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
return value >= build_number;
|
||||
}
|
||||
|
||||
void ToggleConsole(bool enabled) {
|
||||
if (enabled) {
|
||||
if (GetConsoleWindow() == nullptr) {
|
||||
AllocConsole();
|
||||
FILE* stream = nullptr;
|
||||
freopen_s(&stream, "CONOUT$", "w", stdout);
|
||||
freopen_s(&stream, "CONOUT$", "w", stderr);
|
||||
SetConsoleOutputCP(65001);
|
||||
SetConsoleTitleA("il2cpp Game Console");
|
||||
}
|
||||
} else {
|
||||
if (GetConsoleWindow() != nullptr) {
|
||||
ShowWindow(GetConsoleWindow(), SW_HIDE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ScanLoadedModulesForInjectionMarkers() {
|
||||
static const std::wstring kMarkerA = L"testyip";
|
||||
static const std::wstring kMarkerB = L"gatmp.tmp";
|
||||
static const std::wstring kMarkerC = L"ef-cheeto.dll";
|
||||
|
||||
HMODULE modules[2048] = {};
|
||||
DWORD needed = 0;
|
||||
if (!K32EnumProcessModules(GetCurrentProcess(), modules, sizeof(modules), &needed)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t count = needed / sizeof(HMODULE);
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
wchar_t path[MAX_PATH] = {};
|
||||
if (K32GetModuleFileNameExW(GetCurrentProcess(), modules[i], path, MAX_PATH) == 0) {
|
||||
continue;
|
||||
}
|
||||
std::wstring lower = path;
|
||||
std::transform(lower.begin(), lower.end(), lower.begin(), [](wchar_t c) {
|
||||
return static_cast<wchar_t>(::towlower(c));
|
||||
});
|
||||
if (lower.find(kMarkerA) != std::wstring::npos ||
|
||||
lower.find(kMarkerB) != std::wstring::npos ||
|
||||
lower.find(kMarkerC) != std::wstring::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void InitializeI18N() {
|
||||
std::scoped_lock lock(g_i18n_mutex);
|
||||
if (g_i18n_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nlohmann::json parsed = nlohmann::json::parse(kI18nBlob, nullptr, false);
|
||||
if (!parsed.is_object()) {
|
||||
g_i18n_initialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto it = parsed.begin(); it != parsed.end(); ++it) {
|
||||
const std::string key = it.key();
|
||||
const nlohmann::json& item = it.value();
|
||||
if (!item.is_object()) {
|
||||
continue;
|
||||
}
|
||||
g_en[key] = item.value("en", key);
|
||||
g_zh_cn[key] = item.value("zh_cn", key);
|
||||
}
|
||||
g_i18n_initialized = true;
|
||||
}
|
||||
|
||||
const char* Tr(const char* key) {
|
||||
InitializeI18N();
|
||||
|
||||
std::scoped_lock lock(g_i18n_mutex);
|
||||
const std::string k = key ? key : "";
|
||||
const Language lang = g_Runtime.language.load(std::memory_order_relaxed);
|
||||
|
||||
const auto fallback_it = g_en.find(k);
|
||||
if (lang == Language::ZhCN) {
|
||||
const auto it = g_zh_cn.find(k);
|
||||
if (it != g_zh_cn.end()) {
|
||||
return it->second.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (fallback_it != g_en.end()) {
|
||||
return fallback_it->second.c_str();
|
||||
}
|
||||
return key ? key : "";
|
||||
}
|
||||
|
||||
void SetLanguage(Language language) {
|
||||
g_Runtime.language.store(language, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void ApplyThemeDefault() {
|
||||
ImGui::StyleColorsDark();
|
||||
}
|
||||
|
||||
void ApplyThemeEvangelionUnit01() {
|
||||
static constexpr std::array<const char*, 11> kColors = {{
|
||||
"FFFFFFFF", "7857A7FF", "19171CFF", "2A282EFF", "2A282EE6", "4DE6A5FF",
|
||||
"00000000", "4A455240", "A38CCF80", "7857A780", "4A4552FF"}};
|
||||
ApplyThemePalette(kColors);
|
||||
}
|
||||
|
||||
void ApplyThemeEvangelionUnit02() {
|
||||
static constexpr std::array<const char*, 11> kColors = {{
|
||||
"FFFFFFFF", "D9293BFF", "1E1E1EFF", "3A3A3AFF", "3A3A3AE6", "F7B302FF",
|
||||
"00000000", "4A455240", "F7465880", "D9293B80", "4A4552FF"}};
|
||||
ApplyThemePalette(kColors);
|
||||
}
|
||||
|
||||
void ApplyThemeMatrix() {
|
||||
static constexpr std::array<const char*, 11> kColors = {{
|
||||
"00FF41FF", "00AA2CFF", "000000FF", "0A0A0AFF", "0A0A0AE6", "004400FF",
|
||||
"00000000", "00440040", "00881EFF", "00FF4180", "00FF4180"}};
|
||||
ApplyThemePalette(kColors);
|
||||
}
|
||||
|
||||
bool IsKeyPressedOnce(int vk) {
|
||||
return (GetAsyncKeyState(vk) & 0x1) != 0;
|
||||
}
|
||||
Reference in new issue
Block a user