Skip to content

Commit

Permalink
Merge pull request #296 from UE4SS-RE/kismet-debugger
Browse files Browse the repository at this point in the history
Add KismetDebugger cppmod; add cpp mod packaging to build script
  • Loading branch information
narknon authored May 30, 2024
2 parents 8ff121a + 3efb0b2 commit dfd715d
Show file tree
Hide file tree
Showing 8 changed files with 1,600 additions and 11 deletions.
2 changes: 1 addition & 1 deletion assets/Mods/mods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ ConsoleCommandsMod : 1
ConsoleEnablerMod : 1
SplitScreenMod : 0
LineTraceMod : 1
BPModLoaderMod : 1
BPML_GenericFunctions : 1
BPModLoaderMod : 1
jsbLuaProfilerMod : 0


Expand Down
129 changes: 129 additions & 0 deletions cppmods/KismetDebuggerMod/include/KismetDebugger.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#pragma once

#include <unordered_map>
#include <unordered_set>

#include <Unreal/FFrame.hpp>
#include <Unreal/UStruct.hpp>
#include <Unreal/UObject.hpp>

namespace RC::GUI::KismetDebuggerMod
{
using namespace RC::Unreal;

typedef void (*FNativeFuncPtr)(UObject* Context, FFrame& Stack, void* RESULT_DECL);

auto expr_to_string(EExprToken expr) -> const char*;

struct PausedContext
{
EExprToken expr{};
UObject* context{};
FFrame* stack{};
};

class BreakpointStore
{
public:
BreakpointStore();
~BreakpointStore();

auto load(std::filesystem::path& path) -> void;
auto save() -> void;

auto has_breakpoint(UFunction* fn, size_t index) -> bool;
auto add_breakpoint(UFunction* fn, size_t index) -> void;
auto add_breakpoint(const std::wstring& fn, size_t index) -> void;
auto remove_breakpoint(UFunction* fn, size_t index) -> void;

private:
typedef std::unordered_set<size_t> FunctionBreakpoints;

std::unordered_map<UFunction*, std::shared_ptr<FunctionBreakpoints> > m_breakpoints_by_function{};
std::unordered_map<std::wstring, std::shared_ptr<FunctionBreakpoints> > m_breakpoints_by_name{};
};

class Debugger
{
public:
Debugger();
~Debugger();

auto enable() -> void;
auto disable() -> void;

auto render() -> void;
auto render_nav_bar(float width) -> void;

auto nav_to_function(UFunction* fn) -> void;
auto nav_to_function(std::string full_name) -> void;

private:
bool m_paused{};

// std::string because it's used primarily with ImGui
std::unordered_map<std::string, UFunction*> m_function_name_map{};
std::vector<std::string> m_nav_history{};
int m_nav_history_index{-1};
std::string m_nav_function{""};

// layout
float m_split_right{400.0};
float m_split_left{400.0};

uint8_t* m_last_code{nullptr}; // pointer to last stack instruction, used to know if it's advanced since last frame
BreakpointStore& m_breakpoints;

public:
static inline std::filesystem::path m_save_path;
};

class ScriptRenderContext
{
public:
ScriptRenderContext(std::optional<PausedContext>& paused_context, UFunction* fn, bool scroll_to_active, BreakpointStore& breakpoints);
~ScriptRenderContext();

auto render() -> void;

private:
auto render_property();
auto render_expr() -> EExprToken;

template<typename T>
auto read() -> T
{
T t;
memcpy(&t, &m_script[m_index], sizeof(T));
m_index += sizeof(T);
return t;
}

auto read_object() -> UObject*
{
return (UObject*)this->read<uint64_t>();
}
auto read_name() -> FName
{
FName n = read<FName>();
read<uint32_t>(); // not sure what this is for
return n;
}


private:
std::optional<PausedContext>& m_paused_context;
UFunction* m_fn{};

bool m_scroll_to_active{};
BreakpointStore& m_breakpoints;

int m_indent{0};

uint8_t* m_script{};
int m_script_size{};
int m_index{};
int m_cur{}; // or -1
EExprToken m_current_expr{};
};
}
Loading

0 comments on commit dfd715d

Please sign in to comment.