-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: improve logging performance, refactor code, and add console colors
- perf: submit logs once per millisecond and in a separate thread - refactor: overhaul the codebase with a major cleanup - feat: add colors to the console output
- Loading branch information
Showing
11 changed files
with
409 additions
and
233 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ | |
|
||
namespace Carbon { | ||
struct LogMessage { | ||
int colour; | ||
std::string message; | ||
std::string time; | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#pragma once | ||
|
||
#define WIN32_LEAN_AND_MEAN | ||
#include <Windows.h> | ||
|
||
#include <string> | ||
#include <queue> | ||
|
||
struct LogMessage { | ||
WORD colour; | ||
std::string message; | ||
}; | ||
|
||
class Globals_t { | ||
public: | ||
std::queue<LogMessage> logMessages = {}; | ||
|
||
static Globals_t* GetInstance() { | ||
static Globals_t instance; | ||
return &instance; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#pragma once | ||
|
||
#define WIN32_LEAN_AND_MEAN | ||
|
||
#include <string> | ||
#include <Windows.h> | ||
|
||
#include <spdlog/spdlog.h> | ||
|
||
enum ContraptionState { | ||
LOADING = 1, | ||
IN_GAME = 2, | ||
MAIN_MENU = 3 | ||
}; | ||
|
||
namespace SM { | ||
const uintptr_t ContraptionOffset = 0x1267538; | ||
|
||
struct LogMessage { | ||
int colour; | ||
std::string message; | ||
}; | ||
|
||
class Console { | ||
virtual ~Console() {} | ||
virtual void Log(const std::string&, WORD colour, WORD LogType) = 0; | ||
virtual void LogNoRepeat(const std::string&, WORD colour, WORD LogType) = 0; | ||
|
||
public: | ||
void Hook(); | ||
}; | ||
|
||
class Contraption { | ||
private: | ||
/* 0x0000 */ char pad_0x0000[0x58]; | ||
public: | ||
/* 0x0058 */ Console* console; | ||
private: | ||
/* 0x0060 */ char pad_0x0060[0x11C]; | ||
public: | ||
/* 0x017C */ int state; | ||
|
||
public: | ||
static Contraption* GetInstance() { | ||
// TODO sig scan for this (90 48 89 05 ? ? ? ? + 0x4 @ Contraption) | ||
auto contraption = *reinterpret_cast<Contraption**>((uintptr_t)GetModuleHandle(nullptr) + ContraptionOffset); | ||
while (contraption == nullptr || contraption->state < LOADING || contraption->state > 3) { | ||
std::this_thread::sleep_for(std::chrono::milliseconds(100)); | ||
contraption = SM::Contraption::GetInstance(); | ||
|
||
static int i = 0; | ||
if (i++ % 30 == 0) { // Every 3 seconds | ||
spdlog::warn("Waiting for Contraption..."); | ||
} | ||
} | ||
|
||
return contraption; | ||
} | ||
|
||
void WaitForStateEgress(ContraptionState state) const { | ||
while (this->state == (int)state) { | ||
std::this_thread::sleep_for(std::chrono::milliseconds(100)); | ||
} | ||
} | ||
|
||
void OnStateChange(std::function<void(ContraptionState)> callback) const { | ||
while (true) { | ||
std::this_thread::sleep_for(std::chrono::milliseconds(100)); | ||
static int lastState = 0; | ||
if (lastState != this->state) { | ||
lastState = this->state; | ||
callback((ContraptionState)lastState); | ||
} | ||
} | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#pragma once | ||
|
||
#include <spdlog/spdlog.h> | ||
#include <spdlog/sinks/stdout_color_sinks.h> | ||
|
||
enum PacketType { | ||
LOADED, | ||
STATECHANGE, | ||
LOG, | ||
UNKNOWNTYPE | ||
}; | ||
|
||
namespace Utils { | ||
void InitLogging(); | ||
|
||
class Pipe { | ||
public: | ||
Pipe() = default; | ||
|
||
static Pipe* GetInstance() { | ||
static Pipe instance; | ||
return &instance; | ||
} | ||
|
||
// Delete copy constructor and assignment operator | ||
Pipe(Pipe const&) = delete; | ||
void operator=(Pipe const&) = delete; | ||
|
||
void ResetPipe(bool reInformLauncher = false); | ||
|
||
void SendPacket(PacketType packetType, const std::string& data); | ||
void SendPacket(PacketType packetType, int data); | ||
void SendPacket(PacketType packetType); | ||
|
||
void ValidatePipe(); | ||
|
||
private: | ||
std::mutex logMutex{}; | ||
HANDLE pipe = INVALID_HANDLE_VALUE; | ||
}; | ||
} // namespace Utils |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
#include "sm.h" | ||
#include "utils.h" | ||
#include "globals.h" | ||
|
||
using LogFunction = void(SM::Console::*)(const std::string&, WORD, WORD); | ||
LogFunction oLogFunction; | ||
LogFunction oLogNoRepeatFunction; | ||
|
||
static void LogPacket(const std::string& message, WORD colour, WORD type) { | ||
static Utils::Pipe* pipe = Utils::Pipe::GetInstance(); | ||
pipe->SendPacket(LOG, fmt::format("{}-|-{}", colour, message)); | ||
} | ||
|
||
static void HookedLog(SM::Console* console, const std::string& message, WORD colour, WORD type) { | ||
static Globals_t* globals = Globals_t::GetInstance(); | ||
globals->logMessages.push({ colour, message }); | ||
(console->*oLogFunction)(message, colour, type); | ||
} | ||
|
||
static void HookVTableFunc(void** vtable, int index, void* newFunction, void** originalFunction) { | ||
DWORD oldProtect; | ||
VirtualProtect(&vtable[index], sizeof(void*), PAGE_EXECUTE_READWRITE, &oldProtect); | ||
*originalFunction = vtable[index]; | ||
vtable[index] = newFunction; | ||
VirtualProtect(&vtable[index], sizeof(void*), oldProtect, &oldProtect); | ||
} | ||
|
||
void SM::Console::Hook() { | ||
spdlog::info("Hooking console functions"); | ||
|
||
// Hook the consoles `Log` and `LogNoRepeat` functions (to the same thing) | ||
// Make them send a packet to the pipe with LOG:-:<message> | ||
void** vtable = *reinterpret_cast<void***>(this); | ||
HookVTableFunc(vtable, 1, HookedLog, reinterpret_cast<void**>(&oLogFunction)); | ||
HookVTableFunc(vtable, 2, HookedLog, nullptr); | ||
|
||
// Start a thread to send log messages to the launcher | ||
std::thread([]() { | ||
auto pipe = Utils::Pipe::GetInstance(); | ||
static Globals_t* globals = Globals_t::GetInstance(); | ||
auto& logMessages = globals->logMessages; | ||
|
||
while (true) { | ||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); | ||
if (!logMessages.empty()) { | ||
auto& message = logMessages.front(); | ||
pipe->SendPacket(LOG, fmt::format("{}-|-{}", message.colour, message.message)); | ||
logMessages.pop(); | ||
} | ||
} | ||
}).detach(); | ||
} | ||
|
||
void Utils::InitLogging() { | ||
AllocConsole(); | ||
freopen_s(reinterpret_cast<FILE**>(stdout), "CONOUT$", "w", stdout); | ||
|
||
auto console = spdlog::stdout_color_mt("carbon"); | ||
spdlog::set_default_logger(console); | ||
spdlog::set_level(spdlog::level::trace); | ||
spdlog::set_pattern("%^[ %H:%M:%S | %-8l] %n: %v%$"); | ||
} |
Oops, something went wrong.