Skip to content
This repository has been archived by the owner on Jun 21, 2024. It is now read-only.

Commit

Permalink
Reduce errors, add advanced options
Browse files Browse the repository at this point in the history
  • Loading branch information
axstin committed Feb 13, 2020
1 parent 165cca8 commit 5b891b6
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 32 deletions.
86 changes: 63 additions & 23 deletions injector/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <vector>
#include <codecvt>
#include <unordered_map>
#include <chrono>
#include <TlHelp32.h>

#pragma comment(lib, "Shlwapi.lib")
Expand Down Expand Up @@ -44,7 +45,7 @@ HANDLE GetRobloxProcess()
if (processes.size() == 1)
return processes[0];

printf("Multiple processes found! Select a process to inject into (%d - %d):\n", 1, processes.size());
printf("Multiple processes found! Select a process to inject into (%u - %zu):\n", 1, processes.size());
for (int i = 0; i < processes.size(); i++)
{
try
Expand Down Expand Up @@ -75,7 +76,7 @@ HANDLE GetRobloxProcess()

if (selection < 1 || selection > processes.size())
{
printf("Please enter a number between %d and %d\n", 1, processes.size());
printf("Please enter a number between %u and %zu\n", 1, processes.size());
continue;
}

Expand Down Expand Up @@ -134,13 +135,13 @@ size_t FindTaskSchedulerFrameDelayOffset(HANDLE process, const void *scheduler)
return -1;

/* Find the frame delay variable inside TaskScheduler (ugly, but it should survive updates unless the variable is removed or shifted)
(variable was at +0x150 (32-bit) and +0x2B8 (studio 64-bit) as of 11/13/2019) */
(variable was at +0x150 (32-bit) and +0x180 (studio 64-bit) as of 2/13/2020) */
for (int i = 0; i < sizeof(buffer) - sizeof(double); i += 4)
{
static const double frame_delay = 1.0 / 60.0;
double difference = *(double *)(buffer + i) - frame_delay;
difference = difference < 0 ? -difference : difference;
if (difference < 0.004) return search_offset + i;
if (difference < std::numeric_limits<double>::epsilon()) return search_offset + i;
}

return -1;
Expand All @@ -152,6 +153,7 @@ const void *FindTaskScheduler(HANDLE process, const char **error = nullptr)
{
ProcUtil::ProcessInfo info;

// TODO: remove this retry code? (see RobloxProcess::Tick)
int tries = 5;
int wait_time = 100;

Expand Down Expand Up @@ -226,32 +228,69 @@ const void *FindTaskScheduler(HANDLE process, const char **error = nullptr)
return nullptr;
}

void NotifyError(const char* title, const char* error)
{
if (Settings::SilentErrors || Settings::NonBlockingErrors)
{
// lol
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO info{};
GetConsoleScreenBufferInfo(console, &info);

WORD color = (info.wAttributes & 0xFF00) | FOREGROUND_RED | FOREGROUND_INTENSITY;
SetConsoleTextAttribute(console, color);

printf("[ERROR] %s\n", error);

SetConsoleTextAttribute(console, info.wAttributes);

if (!Settings::SilentErrors)
{
UI::SetConsoleVisible(true);
}
}
else
{
MessageBoxA(UI::Window, error, title, MB_OK);
}
}

struct RobloxProcess
{
HANDLE handle = NULL;
const void *ts_ptr = nullptr; // task scheduler pointer
const void *fd_ptr = nullptr; // frame delay pointer

bool Attach(HANDLE process)
int retries_left = 0;

bool Attach(HANDLE process, int retry_count)
{
handle = process;

const char *error = nullptr;
ts_ptr = FindTaskScheduler(process, &error);

if (!ts_ptr)
{
MessageBoxA(UI::Window, error ? error : "Unable to find TaskScheduler! This is probably due to a Roblox update-- watch the github for any patches or a fix.", "rbxfpsunlocker Error", MB_OK);
return false;
}
retries_left = retry_count;

Tick();

return true;
return ts_ptr != nullptr && fd_ptr != nullptr;
}

void Tick()
{
if (retries_left < 0) return; // we tried

if (!ts_ptr)
{
const char* error = nullptr;
ts_ptr = FindTaskScheduler(handle, &error);

if (!ts_ptr)
{
if (error) retries_left = 0; // if FindTaskScheduler returned an error it already retried 5 times. TODO: remove
if (retries_left-- <= 0)
NotifyError("rbxfpsunlocker Error", error ? error : "Unable to find TaskScheduler! This is probably due to a Roblox update-- watch the github for any patches or a fix.");
return;
}
}

if (ts_ptr && !fd_ptr)
{
try
Expand All @@ -263,12 +302,12 @@ struct RobloxProcess
size_t delay_offset = FindTaskSchedulerFrameDelayOffset(handle, scheduler);
if (delay_offset == -1)
{
MessageBoxA(UI::Window, "Variable scan failed! This is probably due to a Roblox update-- watch the github for any patches or a fix.", "rbxfpsunlocker Error", MB_OK);
ts_ptr = nullptr;
if (retries_left-- <= 0)
NotifyError("rbxfpsunlocker Error", "Variable scan failed! This is probably due to a Roblox update-- watch the github for any patches or a fix.");
return;
}

printf("[%p] Frame Delay Offset: %d\n", handle, delay_offset);
printf("[%p] Frame Delay Offset: %zu\n", handle, delay_offset);

fd_ptr = scheduler + delay_offset;

Expand All @@ -278,7 +317,8 @@ struct RobloxProcess
catch (ProcUtil::WindowsException& e)
{
printf("[%p] RobloxProcess::Tick failed: %s (%d)\n", handle, e.what(), e.GetLastError());
ts_ptr = nullptr;
if (retries_left-- <= 0)
NotifyError("rbxfpsunlocker Error", "An exception occurred while performing the variable scan.");
}
}
}
Expand Down Expand Up @@ -358,12 +398,12 @@ DWORD WINAPI WatchThread(LPVOID)
MessageBoxA(UI::Window, "Failed to inject rbxfpsunlocker.dll", "Error", MB_OK);
}
#else
roblox_process.Attach(process);
roblox_process.Attach(process, 2);
#endif

AttachedProcesses[id] = roblox_process;

printf("New size: %d\n", AttachedProcesses.size());
printf("New size: %zu\n", AttachedProcesses.size());
}
else
{
Expand All @@ -383,7 +423,7 @@ DWORD WINAPI WatchThread(LPVOID)
printf("Purging dead process %p (pid %d) (code %X)\n", process, GetProcessId(process), code);
it = AttachedProcesses.erase(it);
CloseHandle(process);
printf("New size: %d\n", AttachedProcesses.size());
printf("New size: %zu\n", AttachedProcesses.size());
}
else
{
Expand Down Expand Up @@ -480,7 +520,7 @@ int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
#else
printf("Attaching...\n");

if (!RobloxProcess().Attach(process))
if (!RobloxProcess().Attach(process, 0))
{
printf("\nERROR: unable to attach to process\n");
pause();
Expand Down
2 changes: 1 addition & 1 deletion injector/rfu.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#define RFU_VERSION "4.1.1"
#define RFU_VERSION "4.2.0"
#define RFU_GITHUB_REPO "axstin/rbxfpsunlocker"

bool CheckForUpdates();
Expand Down
8 changes: 8 additions & 0 deletions injector/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace Settings
double FPSCap = 0.0;
bool UnlockStudio = false;
bool CheckForUpdates = true;
bool NonBlockingErrors = true;
bool SilentErrors = false;

bool Init()
{
Expand Down Expand Up @@ -58,6 +60,10 @@ namespace Settings
UnlockStudio = std::stoi(value) != 0;
else if (key == "CheckForUpdates")
CheckForUpdates = std::stoi(value) != 0;
else if (key == "NonBlockingErrors")
NonBlockingErrors = std::stoi(value) != 0;
else if (key == "SilentErrors")
SilentErrors = std::stoi(value) != 0;
}
catch (std::exception& e)
{
Expand Down Expand Up @@ -85,6 +91,8 @@ namespace Settings
file << "FPSCapSelection=" << std::to_string(FPSCapSelection) << std::endl;
file << "FPSCap=" << std::to_string(FPSCap) << std::endl;
file << "CheckForUpdates=" << std::to_string(CheckForUpdates) << std::endl;
file << "NonBlockingErrors=" << std::to_string(NonBlockingErrors) << std::endl;
file << "SilentErrors=" << std::to_string(SilentErrors) << std::endl;

return true;
}
Expand Down
2 changes: 2 additions & 0 deletions injector/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ namespace Settings
extern double FPSCap;
extern bool UnlockStudio;
extern bool CheckForUpdates;
extern bool NonBlockingErrors;
extern bool SilentErrors;

bool Init();
bool Load();
Expand Down
39 changes: 31 additions & 8 deletions injector/ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
#define RFU_TRAYMENU_GITHUB WM_APP + 7
#define RFU_TRAYMENU_STUDIO WM_APP + 8
#define RFU_TRAYMENU_CFU WM_APP + 9
#define RFU_TRAYMENU_ADV_NBE WM_APP + 10
#define RFU_TRAYMENU_ADV_SE WM_APP + 11

#define RFU_FCS_FIRST (WM_APP + 10)
#define RFU_FCS_FIRST (WM_APP + 20)
#define RFU_FCS_NONE RFU_FCS_FIRST + 0
#define RFU_FCS_30 RFU_FCS_FIRST + 1
#define RFU_FCS_60 RFU_FCS_FIRST + 2
Expand Down Expand Up @@ -71,8 +73,13 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
AppendMenu(submenu, MF_STRING, RFU_FCS_144, "144");
AppendMenu(submenu, MF_STRING, RFU_FCS_240, "240");
CheckMenuRadioItem(submenu, RFU_FCS_FIRST, RFU_FCS_LAST, RFU_FCS_FIRST + Settings::FPSCapSelection, MF_BYCOMMAND);

AppendMenu(popup, MF_POPUP, (UINT_PTR)submenu, "FPS Cap");

HMENU advanced = CreatePopupMenu();
AppendMenu(advanced, MF_STRING | (Settings::SilentErrors ? MF_CHECKED : 0), RFU_TRAYMENU_ADV_SE, "Silent Errors");
AppendMenu(advanced, MF_STRING | (Settings::SilentErrors ? MF_GRAYED : 0) | (Settings::NonBlockingErrors ? MF_CHECKED : 0), RFU_TRAYMENU_ADV_NBE, "Use Console Errors");
AppendMenu(popup, MF_POPUP, (UINT_PTR)advanced, "Advanced");

AppendMenu(popup, MF_SEPARATOR, 0, NULL);
AppendMenu(popup, MF_STRING, RFU_TRAYMENU_LOADSET, "Load Settings");
AppendMenu(popup, MF_STRING, RFU_TRAYMENU_CONSOLE, "Toggle Console");
Expand Down Expand Up @@ -125,6 +132,17 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
CheckMenuItem(popup, RFU_TRAYMENU_CFU, Settings::CheckForUpdates ? MF_CHECKED : MF_UNCHECKED);
break;

case RFU_TRAYMENU_ADV_NBE:
Settings::NonBlockingErrors = !Settings::NonBlockingErrors;
CheckMenuItem(popup, RFU_TRAYMENU_ADV_NBE, Settings::NonBlockingErrors ? MF_CHECKED : MF_UNCHECKED);
break;

case RFU_TRAYMENU_ADV_SE:
Settings::SilentErrors = !Settings::SilentErrors;
CheckMenuItem(popup, RFU_TRAYMENU_ADV_SE, Settings::SilentErrors ? MF_CHECKED : MF_UNCHECKED);
if (Settings::SilentErrors) CheckMenuItem(popup, RFU_TRAYMENU_ADV_NBE, MF_GRAYED);
break;

default:
if (result >= RFU_FCS_FIRST
&& result <= RFU_FCS_LAST)
Expand Down Expand Up @@ -157,6 +175,14 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
return 0;
}

bool IsConsoleVisible = false;

void UI::SetConsoleVisible(bool visible)
{
IsConsoleVisible = visible;
ShowWindow(GetConsoleWindow(), visible ? SW_SHOWNORMAL : SW_HIDE);
}

void UI::CreateHiddenConsole()
{
AllocConsole();
Expand All @@ -176,20 +202,17 @@ void UI::CreateHiddenConsole()
SetConsoleTitleA("Roblox FPS Unlocker " RFU_VERSION " (32-bit) Console");
#endif

ShowWindow(GetConsoleWindow(), SW_HIDE);
SetConsoleVisible(false);
}

bool UI::ToggleConsole()
{
static bool toggle = false;

if (!GetConsoleWindow())
UI::CreateHiddenConsole();

toggle = !toggle;
ShowWindow(GetConsoleWindow(), toggle ? SW_SHOWNORMAL : SW_HIDE);
SetConsoleVisible(!IsConsoleVisible);

return toggle;
return IsConsoleVisible;
}

int UI::Start(HINSTANCE instance, LPTHREAD_START_ROUTINE watchthread)
Expand Down
1 change: 1 addition & 0 deletions injector/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace UI
{
void CreateHiddenConsole();
void SetConsoleVisible(bool visible);
bool ToggleConsole();
int Start(HINSTANCE instance, LPTHREAD_START_ROUTINE watchthread);

Expand Down

0 comments on commit 5b891b6

Please sign in to comment.