From 43a9a323af8cc110ccba45a7ffea55a59af48636 Mon Sep 17 00:00:00 2001
From: arol <completionoftime@gmail.com>
Date: Tue, 23 Jul 2024 00:37:22 -0600
Subject: [PATCH] Revamped API for main, new imgui style, etc.

---
 mod-demo/include/api.h |  26 ++++++--
 src/api.cpp            | 139 ++++++++++++++++++++++++++++++++++++++---
 src/include/api.h      |  22 +++++--
 src/main.cpp           |  32 ++++++----
 src/menu.cpp           | 133 ++++++++++++++++++++++++++++++++-------
 src/mod_loader.cpp     |   9 ++-
 6 files changed, 302 insertions(+), 59 deletions(-)

diff --git a/mod-demo/include/api.h b/mod-demo/include/api.h
index 368254c..2c60096 100644
--- a/mod-demo/include/api.h
+++ b/mod-demo/include/api.h
@@ -36,12 +36,28 @@ class ModApi {
     uintptr_t GetSkyBase();
     uintptr_t GetSkySize();
 
-    uintptr_t Scan(const char *signature);
-    uintptr_t Scan(const char *signature, uintptr_t start, size_t size);
-    
-    void Hook(uintptr_t addr, void* newFn, void** oldFn);
+    uintptr_t Scan(const char* signature);
+    uintptr_t Scan(const char* signature, uintptr_t start, size_t size);
 
-    void UnHook(uintptr_t addr);
+    uintptr_t ScanPattern(lm_bytearr_t pattern, const char* masking);
+    uintptr_t ScanPattern(lm_bytearr_t pattern, const char* masking, uintptr_t start, size_t size);
+
+    uintptr_t ScanData(lm_bytearr_t data, size_t scansize);
+    uintptr_t ScanData(lm_bytearr_t data, size_t size, uintptr_t start, size_t scansize);
+
+    bool Hook(uintptr_t addr, void* newFn, void** oldFn);
+    bool Patch(uintptr_t address, const std::vector<unsigned char>& patchBytes, bool toggle = true);
+    bool Unpatch(uintptr_t address, const std::vector<unsigned char>& unpatchBytes);
+    bool Restore(uintptr_t address);
+    bool SetByte(uintptr_t address, std::vector<unsigned char> setByte);
+
+    bool FastHook(uintptr_t addr, void* newFn, void** oldFn);
+    bool FastPatch(uintptr_t address, const std::vector<unsigned char>& patchBytes, bool toggle = true);
+    bool FastUnpatch(uintptr_t address, const std::vector<unsigned char>& unpatchBytes);
+    bool FastRestore(uintptr_t address);
+    bool FastSetByte(uintptr_t address, std::vector<unsigned char> setByte);
+
+    bool UnHook(uintptr_t addr);
 };
 
 #define API ModApi::Instance()
\ No newline at end of file
diff --git a/src/api.cpp b/src/api.cpp
index b754643..41104e8 100644
--- a/src/api.cpp
+++ b/src/api.cpp
@@ -56,26 +56,43 @@ uintptr_t ModApi::Scan(const char *signature, uintptr_t start, size_t size){
     return LM_SigScan(signature, start, size);
 }
 
+uintptr_t ModApi::ScanPattern(lm_bytearr_t pattern, const char* masking) {
+    return LM_PatternScan(pattern, masking, skyBase, skySize);
+}
+
+uintptr_t ModApi::ScanPattern(lm_bytearr_t pattern, const char* masking, uintptr_t start, size_t size) {
+    return LM_PatternScan(pattern, masking, start, size);
+}
+
+uintptr_t ModApi::ScanData(lm_bytearr_t data, size_t scansize) {
+    return LM_DataScan(data, skySize, skyBase, scansize);
+}
 
+uintptr_t ModApi::ScanData(lm_bytearr_t data, size_t size, uintptr_t start, size_t scansize) {
+    return LM_DataScan(data, size, start, scansize);
+}
 
 bool ModApi::Hook(uintptr_t addr, void* newFn, void** oldFn) {
-    //todo: check if already hooked,Multiple modification hooks for the same function
     HookDef hook;
-    hook.addr = addr;
-    hook.newFn = newFn;
-    hook.oldFn = oldFn;
+
+    if (hooks.contains(addr)) { // dogshit_check.cpp
+        printf("hooking : function is already hooked!");
+        return true;
+    }
+    hook.addr = addr; hook.newFn = newFn; hook.oldFn = oldFn;
+
     hook.size = LM_HookCode(addr, (lm_address_t)newFn, (lm_address_t*)oldFn);
-    if(!hook.size)
+    if (!hook.size)
         return false;
+
     hooks[addr] = hook;
     return true;
 }
 
 bool ModApi::UnHook(uintptr_t addr) {
-    //todo:
     auto it = hooks.begin();
-	if ((it = hooks.find(addr)) != hooks.end()) {
-        if(LM_UnhookCode(addr, (lm_address_t )*(it->second.oldFn), it->second.size)){
+    if ((it = hooks.find(addr)) != hooks.end()) {
+        if (LM_UnhookCode(addr, (lm_address_t) * (it->second.oldFn), it->second.size)) {
             hooks.erase(addr);
             return true;
         }
@@ -92,7 +109,7 @@ bool ModApi::Patch(uintptr_t address, const std::vector<unsigned char>& patchByt
     if (it == OriginalBytes.end()) {
         size_t size = patchBytes.size();
         // Change the protection to ReadWriteable
-        if (!LM_ProtMemory(address, size,LM_PROT_XRW, NULL)) {
+        if (!LM_ProtMemory(address, size, LM_PROT_XRW, NULL)) {
             std::cerr << "Failed to Change protection at address: " << std::hex << address << std::endl;
             return false;
         }
@@ -114,5 +131,109 @@ bool ModApi::Patch(uintptr_t address, const std::vector<unsigned char>& patchByt
         return false;
     }
 
+    return true;
+}
+
+bool ModApi::Unpatch(uintptr_t address, const std::vector<unsigned char>& unpatchBytes) {
+    size_t size = unpatchBytes.size();
+    if (!LM_FreeMemory(address, size)) {
+        std::cerr << "Failed to free memory at address: " << std::hex << address << std::endl;
+        return true;
+    }
+
+    return false;
+}
+
+bool ModApi::Restore(uintptr_t address) {
+    auto it = OriginalBytes.find(address);
+    if (it == OriginalBytes.end()) {
+        std::cerr << "Original bytes not found for address: " << std::hex << address << std::endl;
+        return false;
+    }
+
+    const std::vector<unsigned char>& OriginalBytes = it->second;
+    if (!LM_WriteMemory(address, OriginalBytes.data(), OriginalBytes.size())) {
+        std::cerr << "Failed to restore memory at address: " << std::hex << address << std::endl;
+        return false;
+    }
+
+    return true;
+}
+
+bool ModApi::SetByte(uintptr_t address, std::vector<unsigned char> setByte) {
+    address += skyBase; // Ensure address is relative to Sky_Base
+
+    if (OriginalBytes.find(address) == OriginalBytes.end()) {
+        if (!LM_ProtMemory(address, setByte.size(), LM_PROT_XRW, NULL)) {
+            std::cerr << "Failed to Change protection at address: " << std::hex << address << std::endl;
+            return false;
+        }
+    }
+
+    lm_byte_t* byte = setByte.data();
+    if (!LM_SetMemory(address, *(byte), OriginalBytes[address].size())) {
+        std::cerr << "Failed to set memory at address: " << std::hex << address << std::endl;
+        return false;
+    }
+
+    return true;
+}
+
+// fastfunctions (basically functions checkless counterparts)
+// WARNING : fastfunctions should only be used for patches if you are extremely confident that it wont kill your game.
+bool ModApi::FastHook(uintptr_t addr, void* newFn, void** oldFn) {
+    HookDef hook;
+
+    hook.addr = addr; hook.newFn = newFn; hook.oldFn = oldFn;
+    hook.size = LM_HookCode(addr, (lm_address_t)newFn, (lm_address_t*)oldFn);
+
+    hooks[addr] = hook;
+    return true;
+}
+
+bool ModApi::FastPatch(uintptr_t address, const std::vector<unsigned char>& patchBytes, bool toggle) {
+    address += skyBase;
+
+    auto it = OriginalBytes.find(address);
+    if (it == OriginalBytes.end()) {
+        size_t size = patchBytes.size();
+        LM_ProtMemory(address, size, LM_PROT_XRW, NULL);
+
+        std::vector<unsigned char> originalBytes(size);
+        LM_ReadMemory(address, originalBytes.data(), size);
+    }
+
+    const unsigned char* dataPtr = toggle ? patchBytes.data() : OriginalBytes[address].data();
+    LM_WriteMemory(address, dataPtr, OriginalBytes[address].size());
+    return true;
+}
+
+
+bool ModApi::FastUnpatch(uintptr_t address, const std::vector<unsigned char>& unpatchBytes) {
+    size_t size = unpatchBytes.size();
+    LM_FreeMemory(address, size);
+
+    return false;
+}
+
+bool ModApi::FastRestore(uintptr_t address) {
+    auto it = OriginalBytes.find(address);
+
+    const std::vector<unsigned char>& OriginalBytes = it->second;
+    LM_WriteMemory(address, OriginalBytes.data(), OriginalBytes.size());
+
+    return true;
+}
+
+bool ModApi::FastSetByte(uintptr_t address, std::vector<unsigned char> setByte) {
+    address += skyBase; // Ensure address is relative to Sky_Base
+
+    if (OriginalBytes.find(address) == OriginalBytes.end()) {
+        LM_ProtMemory(address, setByte.size(), LM_PROT_XRW, NULL);
+    }
+
+    lm_byte_t* byte = setByte.data();
+    LM_SetMemory(address, *(byte), OriginalBytes[address].size());
+
     return true;
 }
\ No newline at end of file
diff --git a/src/include/api.h b/src/include/api.h
index 54ac943..5b07c0c 100644
--- a/src/include/api.h
+++ b/src/include/api.h
@@ -4,6 +4,7 @@
 #include <cstdint>
 #include <string>
 #include <vector>
+#include <libmem.h>
 
 #ifdef _MSC_VER
     #define MOD_API __declspec(dllexport)
@@ -41,13 +42,26 @@ class MOD_API ModApi {
     uintptr_t GetSkyBase();
     uintptr_t GetSkySize();
 
-    uintptr_t Scan(const char *signature);
-    uintptr_t Scan(const char *signature, uintptr_t start, size_t size);
+    uintptr_t Scan(const char* signature);
+    uintptr_t Scan(const char* signature, uintptr_t start, size_t size);
 
-    bool Hook(uintptr_t addr, void* newFn, void** oldFn);
+    uintptr_t ScanPattern(lm_bytearr_t pattern, const char* masking);
+    uintptr_t ScanPattern(lm_bytearr_t pattern, const char* masking, uintptr_t start, size_t size);
 
-    bool UnHook(uintptr_t addr);
+    uintptr_t ScanData(lm_bytearr_t data, size_t scansize);
+    uintptr_t ScanData(lm_bytearr_t data, size_t size, uintptr_t start, size_t scansize);
 
+    bool Hook(uintptr_t addr, void* newFn, void** oldFn);
     bool Patch(uintptr_t address, const std::vector<unsigned char>& patchBytes, bool toggle = true);
+    bool Unpatch(uintptr_t address, const std::vector<unsigned char>& unpatchBytes);
+    bool Restore(uintptr_t address);
+    bool SetByte(uintptr_t address, std::vector<unsigned char> setByte);
 
+    bool FastHook(uintptr_t addr, void* newFn, void** oldFn);
+    bool FastPatch(uintptr_t address, const std::vector<unsigned char>& patchBytes, bool toggle = true);
+    bool FastUnpatch(uintptr_t address, const std::vector<unsigned char>& unpatchBytes);
+    bool FastRestore(uintptr_t address);
+    bool FastSetByte(uintptr_t address, std::vector<unsigned char> setByte);
+
+    bool UnHook(uintptr_t addr);
 };
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 94dbde1..60e623a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -47,7 +47,7 @@ __declspec(dllexport) POWER_PLATFORM_ROLE PowerDeterminePlatformRole(){
 void InitConsole(){
     FreeConsole();
     AllocConsole();
-    SetConsoleTitle("SML Console");
+    SetConsoleTitle("SML Console - 0.1.2 - TgcMainWindow::VulkanRendering");
 
     if (IsValidCodePage(CP_UTF8)) {
         SetConsoleCP(CP_UTF8);
@@ -88,6 +88,8 @@ void loadWrapper(){
         dllHandle = LoadLibrary("C:\\Windows\\System32\\POWRPROF.dll");
     }
 
+    printf("Loading powrprof.dll symbols...");
+
     if (dllHandle != NULL) {
         o_GetPwrCapabilities = (BOOLEAN(*)(PSYSTEM_POWER_CAPABILITIES))GetProcAddress(dllHandle, "GetPwrCapabilities");
         o_CallNtPowerInformation = (NTSTATUS (*)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG))GetProcAddress(dllHandle, "CallNtPowerInformation");
@@ -127,18 +129,19 @@ static LRESULT WINAPI WndProc(const HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
 
 
 void terminateCrashpadHandler() {
-
     PROCESSENTRY32 entry;
     entry.dwSize = sizeof(PROCESSENTRY32);
+
     HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
     if (Process32First(snapshot, &entry) == TRUE) {
         while (Process32Next(snapshot, &entry) == TRUE) {
             if (lstrcmp(entry.szExeFile, "crashpad_handler.exe") == 0) {
                 HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, entry.th32ProcessID);
 
-                if (hProcess!= NULL) {
+                if (hProcess != NULL) {
                     TerminateProcess(hProcess, 0);
                     CloseHandle(hProcess);
+                    printf("Detected and closed crashpad_handler.exe");
                 }
             }
         }
@@ -237,18 +240,21 @@ LSTATUS hkRegEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpValueName, LPDWORD lpc
 }
 
 
-DWORD WINAPI hook_thread(PVOID lParam){
-    HWND window = nullptr; 
-    printf("Searching for window...\n");
-    while(!window){
+DWORD WINAPI hook_thread(PVOID lParam) {
+    HWND window = nullptr;
+    printf("Searching for TgcMainWindow...\n");
+    while (!window) {
         std::this_thread::sleep_for(std::chrono::milliseconds(100));
         window = FindWindowA("TgcMainWindow", "Sky");
-    } 
-    printf("Window Found: %p\n", window);
-    layer::setup(window);      
+    }
+    printf("Complete! info: %p\n", window);
+
+    // todo: add something a little special here.
+    layer::setup(window);
     oWndProc = reinterpret_cast<WNDPROC>(SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(WndProc)));
     InitConsole();
     Sleep(3000);
+    printf("Finished hook_thread routine, loading mods.");
     //clear_screen();
     return EXIT_SUCCESS;
 }
@@ -259,7 +265,7 @@ DWORD WINAPI console_thread(LPVOID lpParam){
 }
 
 
-void onAttach(){
+void onAttach() {
     loadWrapper();
     WCHAR path[MAX_PATH];
     GetModuleFileNameW(NULL, path, MAX_PATH);
@@ -267,9 +273,9 @@ void onAttach(){
     std::string _path(ws.begin(), ws.end());
     g_path = _path.substr(0, _path.find_last_of("\\/"));
     HMODULE handle = LoadLibrary("advapi32.dll");
-    if(handle!= NULL){
+    if (handle != NULL) {
         lm_address_t fnRegEnumValue = (lm_address_t)GetProcAddress(handle, "RegEnumValueA");
-        LM_HookCode(fnRegEnumValue, (lm_address_t)&hkRegEnumValueA, (lm_address_t *)&oRegEnumValueA);
+        LM_HookCode(fnRegEnumValue, (lm_address_t)&hkRegEnumValueA, (lm_address_t*)&oRegEnumValueA);
         InitConsole();
         terminateCrashpadHandler();
         ModApi::Instance().InitSkyBase();
diff --git a/src/menu.cpp b/src/menu.cpp
index a47eaff..784c6c6 100644
--- a/src/menu.cpp
+++ b/src/menu.cpp
@@ -105,6 +105,91 @@ namespace Menu {
         ImGui::CreateContext( );
         ImGui_ImplWin32_Init(hwnd);
 
+#pragma region imgui-style
+        ImGuiStyle* style = &ImGui::GetStyle();
+        style->WindowPadding = ImVec2(9, 9);
+        style->FramePadding = ImVec2(9, 4);
+        style->ItemSpacing = ImVec2(6, 4);
+        style->ItemInnerSpacing = ImVec2(4, 4);
+        style->IndentSpacing = 20;
+        style->ScrollbarSize = 8;
+        style->ScrollbarRounding = 12;
+        style->GrabMinSize = 15;
+        style->WindowBorderSize = 1;
+        style->ChildBorderSize = 1;
+        style->PopupBorderSize = 1;
+        style->FrameBorderSize = 0; // ??
+        style->TabBorderSize = 1;
+        style->TabBarBorderSize = 1;
+        style->WindowRounding = 6;
+        style->ChildRounding = 6;
+        style->FrameRounding = 3;
+        style->PopupRounding = 6;
+        style->GrabRounding = 4;
+        style->TabRounding = 4;
+        style->CellPadding = ImVec2(2, 2);
+        style->WindowTitleAlign = ImVec2(0.02f, 0.50f);
+        style->SeparatorTextBorderSize = 2;
+        style->SeparatorTextPadding = ImVec2(8, 0);
+
+        ImVec4* colors = style->Colors;
+        colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
+        colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
+        colors[ImGuiCol_WindowBg] = ImVec4(0.08f, 0.08f, 0.08f, 1.00f);
+        colors[ImGuiCol_ChildBg] = ImVec4(0.21f, 0.21f, 0.21f, 0.18f);
+        colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.05f, 0.73f);
+        colors[ImGuiCol_Border] = ImVec4(1.00f, 1.00f, 1.00f, 0.50f);
+        colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+        colors[ImGuiCol_FrameBg] = ImVec4(0.18f, 0.18f, 0.18f, 0.54f);
+        colors[ImGuiCol_FrameBgHovered] = ImVec4(0.29f, 0.29f, 0.29f, 0.40f);
+        colors[ImGuiCol_FrameBgActive] = ImVec4(0.53f, 0.53f, 0.53f, 0.67f);
+        colors[ImGuiCol_TitleBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
+        colors[ImGuiCol_TitleBgActive] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
+        colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
+        colors[ImGuiCol_MenuBarBg] = ImVec4(0.12f, 0.12f, 0.12f, 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(0.65f, 0.65f, 0.65f, 1.00f);
+        colors[ImGuiCol_Button] = ImVec4(0.21f, 0.21f, 0.21f, 1.00f);
+        colors[ImGuiCol_ButtonHovered] = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
+        colors[ImGuiCol_ButtonActive] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f);
+        colors[ImGuiCol_Header] = ImVec4(0.54f, 0.54f, 0.54f, 0.31f);
+        colors[ImGuiCol_HeaderHovered] = ImVec4(0.69f, 0.69f, 0.69f, 0.80f);
+        colors[ImGuiCol_HeaderActive] = ImVec4(0.83f, 0.83f, 0.83f, 1.00f);
+        colors[ImGuiCol_Separator] = ImVec4(0.29f, 0.29f, 0.29f, 0.50f);
+        colors[ImGuiCol_SeparatorHovered] = ImVec4(0.29f, 0.29f, 0.29f, 0.50f);
+        colors[ImGuiCol_SeparatorActive] = ImVec4(0.29f, 0.29f, 0.29f, 0.50f);
+        colors[ImGuiCol_ResizeGrip] = ImVec4(0.52f, 0.52f, 0.52f, 0.50f);
+        colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.67f, 0.67f, 0.67f, 0.50f);
+        colors[ImGuiCol_ResizeGripActive] = ImVec4(0.74f, 0.74f, 0.74f, 0.95f);
+        colors[ImGuiCol_Tab] = ImVec4(0.19f, 0.19f, 0.19f, 0.86f);
+        colors[ImGuiCol_TabHovered] = ImVec4(0.27f, 0.27f, 0.27f, 0.80f);
+        colors[ImGuiCol_TabActive] = ImVec4(0.46f, 0.46f, 0.46f, 1.00f);
+        colors[ImGuiCol_TabUnfocused] = ImVec4(0.27f, 0.27f, 0.27f, 0.80f);
+        colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.37f, 0.37f, 0.37f, 1.00f);
+        colors[ImGuiCol_DockingPreview] = ImVec4(0.46f, 0.46f, 0.46f, 0.70f);
+        colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f);
+        colors[ImGuiCol_PlotLines] = ImVec4(0.77f, 0.77f, 0.77f, 1.00f);
+        colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.91f, 0.91f, 0.91f, 1.00f);
+        colors[ImGuiCol_PlotHistogram] = ImVec4(0.49f, 0.49f, 0.49f, 1.00f);
+        colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.62f, 0.62f, 0.62f, 1.00f);
+        colors[ImGuiCol_TableHeaderBg] = ImVec4(0.21f, 0.21f, 0.21f, 1.00f);
+        colors[ImGuiCol_TableBorderStrong] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f);
+        colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.23f, 1.00f);
+        colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+        colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
+        colors[ImGuiCol_TextSelectedBg] = ImVec4(0.72f, 0.72f, 0.72f, 0.35f);
+        colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f);
+        colors[ImGuiCol_NavHighlight] = ImVec4(0.66f, 0.66f, 0.66f, 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);
+        colors[ImGuiCol_SliderGrab] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f);
+        colors[ImGuiCol_SliderGrabActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f);
+#pragma endregion
+
         loadFontConfig("sml_config.json", fontconfig);
         LoadFontsFromFolder(fontconfig);
 
@@ -114,7 +199,7 @@ namespace Menu {
 
 
     void HelpMarker(const char* description){ 
-        ImGui::TextDisabled("(?)");
+        ImGui::TextDisabled("<?>");
         if (ImGui::IsItemHovered())
         {
             ImGui::BeginTooltip();
@@ -128,45 +213,47 @@ namespace Menu {
 
     void SMLMainMenu() {
         char buf[64];
-        ig::SetNextWindowSize({200, 0}, ImGuiCond_Once);
-        if(ig::Begin("SML Main",nullptr,ImGuiWindowFlags_AlwaysAutoResize)) {
+        ImGuiIO& io = ImGui::GetIO();
+
+        ig::SetNextWindowSize({ 200, 0 }, ImGuiCond_Once);
+        if (ig::Begin("SML Main", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
             ImGui::SeparatorText(("Mods (" + std::to_string(ModLoader::GetModCount()) + ")").c_str());
             ig::BeginTable("##mods", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBody);
             ig::TableSetupColumn("Mod", ImGuiTableColumnFlags_WidthStretch);
-            ig::TableSetupColumn( "Info", ImGuiTableColumnFlags_WidthFixed, ImGui::CalcTextSize("Info").x);
-
-            for(int i = 0; i < ModLoader::GetModCount(); i++) {
-                    snprintf(buf, 64, "%s##check%d", ModLoader::GetModName(i).data(), i);
-                    ig::TableNextColumn();
-                    if(ig::Checkbox(buf, &ModLoader::GetModEnabled(i))) {
-                        if(ModLoader::GetModEnabled(i)) {
-                            ModLoader::EnableMod(i);
-                        } else {
-                            ModLoader::DisableMod(i);
-                        }
+            ig::TableSetupColumn("Info", ImGuiTableColumnFlags_WidthFixed, ImGui::CalcTextSize("Info").x);
+
+            for (int i = 0; i < ModLoader::GetModCount(); i++) {
+                snprintf(buf, 64, "%s##check%d", ModLoader::GetModName(i).data(), i);
+                ig::TableNextColumn();
+                if (ig::Checkbox(buf, &ModLoader::GetModEnabled(i))) {
+                    if (ModLoader::GetModEnabled(i)) {
+                        ModLoader::EnableMod(i);
                     }
-                    ig::TableNextColumn();
-                    HelpMarker(ModLoader::toString(i).c_str());
+                    else {
+                        ModLoader::DisableMod(i);
+                    }
+                }
+                ig::TableNextColumn();
+                HelpMarker(ModLoader::toString(i).c_str());
             }
             ig::EndTable();
             ImGui::SeparatorText("Settings");
-            ImGuiIO& io = ImGui::GetIO();
             ShowFontSelector();
             ImGui::SameLine();
-            HelpMarker(std::format("Total: {}\nPath: {}\nStart Range: {}\nEnd Range: {}\nSize: {}W / {}H\nConfig: sml_config.json", io.Fonts->Fonts.Size, fontconfig.fontPath.c_str(), fontconfig.unicodeRangeStart, fontconfig.unicodeRangeEnd,  io.Fonts->TexWidth, io.Fonts->TexHeight).c_str());
-            
+            HelpMarker(std::format("Total: {}\nPath: {}\nStart Range: {}\nEnd Range: {}\nSize: {}W / {}H\nConfig: sml_config.json", io.Fonts->Fonts.Size, fontconfig.fontPath.c_str(), fontconfig.unicodeRangeStart, fontconfig.unicodeRangeEnd, io.Fonts->TexWidth, io.Fonts->TexHeight).c_str());
+
             const float MIN_SCALE = 0.3f;
             const float MAX_SCALE = 3.0f;
             static float window_scale = 1.0f;
-            if (ImGui::DragFloat("Window scale", &window_scale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp))
+            if (ImGui::DragFloat("Window Scale", &window_scale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp))
                 ImGui::SetWindowFontScale(window_scale);
-            ImGui::DragFloat("Global scale", &io.FontGlobalScale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp);
-            
+            ImGui::DragFloat("Global Scale", &io.FontGlobalScale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp);
+
             ImGui::Spacing();
             ImGui::Separator();
             ImGui::Spacing();
 
-            ImGui::Text("FPS: %.1f | %.3f ms/frame", io.Framerate, 1000.0f / io.Framerate);
+            ImGui::Text("FPS: %.f | %.2f ms | DeltaTime: %.2f | amb", io.Framerate, 1000.0f / io.Framerate, io.DeltaTime);
         }
         ig::End();
     }
diff --git a/src/mod_loader.cpp b/src/mod_loader.cpp
index 0da8653..993c89c 100644
--- a/src/mod_loader.cpp
+++ b/src/mod_loader.cpp
@@ -90,14 +90,13 @@ void ModLoader::RenderAll() {
 }
 std::string ModLoader::toString(int index) {
     std::stringstream ss;
-    
-    ss << "Mod Information" << "\n";
+
+    ss << "Information" << "\n";
     ss << "Name: " << mods[index].info.name << "\n";
     ss << "Version: " << mods[index].info.version << "\n";
     ss << "Author: " << mods[index].info.author << "\n";
-    ss << "Description: " << mods[index].info.description << "\n";
-    // ss << "GetModInfo: " << mods[index].getInfo << "\n";
+    ss << "Details: " << mods[index].info.description << "\n";
+    //ss << "GetModInfo: " << mods[index].getInfo << "\n";
     // ss << "Render: " << mods[index].render << "\n";
     return ss.str();
 }
-