Skip to content

Commit

Permalink
Merge pull request #366 from WSSDude420/dx-split
Browse files Browse the repository at this point in the history
Split Overlay and Scripting VM by extracting D3D12 interface and calling into both as needed
  • Loading branch information
Yamashi authored Jan 4, 2021
2 parents ae0e100 + 9376c09 commit 3f79c32
Show file tree
Hide file tree
Showing 45 changed files with 2,187 additions and 1,945 deletions.
2 changes: 1 addition & 1 deletion scripts/autoexec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ Game['PlayFinisher'] = Game['PlayFinisher;GameInstance']
Game['PlayFinisherSingle'] = Game['PlayFinisherSingle;GameInstance']
Game['PPS'] = Game['PPS;GameInstance']

print("Cyber Engine Tweaks autoexec.lua execution complete.")
print("Cyber Engine Tweaks startup complete.")
26 changes: 13 additions & 13 deletions src/Image.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@

struct Image
{
void Initialize();
void Initialize();

static uint64_t MakeVersion(uint32_t aMajor, uint16_t aMinor) noexcept
{
return static_cast<uint64_t>(aMajor) << 32 | static_cast<uint64_t>(aMinor) << 16;
}
static uint64_t MakeVersion(uint32_t aMajor, uint16_t aMinor) noexcept
{
return static_cast<uint64_t>(aMajor) << 32 | static_cast<uint64_t>(aMinor) << 16;
}

std::tuple<uint32_t, uint16_t> GetVersion() const noexcept
{
return std::make_tuple(static_cast<uint32_t>(version >> 32), static_cast<uint16_t>((version >> 16) & 0xFFFF));
}
std::tuple<uint32_t, uint16_t> GetVersion() const noexcept
{
return std::make_tuple(static_cast<uint32_t>(version >> 32), static_cast<uint16_t>((version >> 16) & 0xFFFF));
}

uint64_t version{0};
uintptr_t base_address;
uint8_t* pTextStart;
uint8_t* pTextEnd;
uint64_t version{0};
uintptr_t base_address;
uint8_t* pTextStart;
uint8_t* pTextEnd;
};
2 changes: 1 addition & 1 deletion src/Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ Options::Options(HMODULE aModule)

this->DumpGameOptions = config.value("dump_game_options", this->DumpGameOptions);
this->Console = config.value("console", this->Console);
this->ConsoleKey = config.value("console_key", this->ConsoleKey);
this->ConsoleKey = config.value("console_key", this->ConsoleKey);

// check old config names
if (config.value("unlock_menu", false))
Expand Down
52 changes: 26 additions & 26 deletions src/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,35 @@

struct Options
{
static void Initialize(HMODULE aModule);
static Options& Get();
bool IsCyberpunk2077() const noexcept;
static void Initialize(HMODULE aModule);
static Options& Get();
bool IsCyberpunk2077() const noexcept;

bool PatchSMT{ false };
bool PatchVirtualInput{ true };
bool PatchEnableDebug{ false };
bool PatchRemovePedestrians{ false };
bool PatchAsyncCompute{ false };
bool PatchAntialiasing{ false };
bool PatchSkipStartMenu{ true };
bool PatchDisableIntroMovies{ false };
bool PatchDisableVignette{ false };
bool PatchDisableBoundaryTeleport{ false };
bool PatchSMT{ false };
bool PatchVirtualInput{ true };
bool PatchEnableDebug{ false };
bool PatchRemovePedestrians{ false };
bool PatchAsyncCompute{ false };
bool PatchAntialiasing{ false };
bool PatchSkipStartMenu{ true };
bool PatchDisableIntroMovies{ false };
bool PatchDisableVignette{ false };
bool PatchDisableBoundaryTeleport{ false };

bool DumpGameOptions{ false };
bool Console{ true };
int ConsoleKey{ VK_OEM_3 };
int ConsoleChar{ 0 };
float CPUMemoryPoolFraction{ 0.5f };
float GPUMemoryPoolFraction{ 1.f };
std::filesystem::path CETPath;
std::filesystem::path RootPath;
std::filesystem::path ScriptsPath;
Image GameImage;
bool ExeValid{ false };
bool DumpGameOptions{ false };
bool Console{ true };
int ConsoleKey{ VK_OEM_3 };
int ConsoleChar{ 0 };
float CPUMemoryPoolFraction{ 0.5f };
float GPUMemoryPoolFraction{ 1.f };
std::filesystem::path CETPath;
std::filesystem::path RootPath;
std::filesystem::path ScriptsPath;
Image GameImage;
bool ExeValid{ false };

private:

Options(HMODULE aModule);
Options(HMODULE aModule);
};
251 changes: 251 additions & 0 deletions src/console/Console.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
#include <stdafx.h>

#include "Console.h"

#include <Image.h>
#include <Pattern.h>
#include <Options.h>

#include <d3d12/D3D12.h>
#include <scripting/LuaVM.h>

static std::unique_ptr<Console> s_pConsole;

void Console::Initialize()
{
if (!s_pConsole)
{
s_pConsole.reset(new (std::nothrow) Console);
s_pConsole->Hook();
}
}

void Console::Shutdown()
{
s_pConsole = nullptr;
}

Console& Console::Get()
{
return *s_pConsole;
}

void Console::Update()
{
if (this == nullptr)
return;

if (!IsEnabled())
return;

SIZE resolution = D3D12::Get().GetResolution();

ImGui::SetNextWindowPos(ImVec2(0.f, 0.f), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(resolution.cx, resolution.cy * 0.3f), ImGuiCond_FirstUseEver);

ImGui::Begin("Cyber Engine Tweaks");

auto [major, minor] = Options::Get().GameImage.GetVersion();

if (major == 1 && (minor >= 4 && minor <= 6))
{
ImGui::Checkbox("Clear Input", &m_inputClear);
ImGui::SameLine();
if (ImGui::Button("Clear Output"))
{
std::lock_guard<std::recursive_mutex> _{ m_outputLock };
m_outputLines.clear();
}
ImGui::SameLine();
ImGui::Checkbox("Scroll Output", &m_outputShouldScroll);
ImGui::SameLine();
ImGui::Checkbox("Disable Game Log", &m_disabledGameLog);

static char command[200000] = { 0 };

{
std::lock_guard<std::recursive_mutex> _{ m_outputLock };

ImVec2 listboxSize = ImGui::GetContentRegionAvail();
listboxSize.y -= ImGui::GetFrameHeightWithSpacing();
const auto result = ImGui::ListBoxHeader("##ConsoleHeader", listboxSize);
ImGuiListClipper clipper;
clipper.Begin(m_outputLines.size());
while (clipper.Step())
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; ++i)
{
auto& item = m_outputLines[i];
ImGui::PushID(i);
if (ImGui::Selectable(item.c_str()))
{
auto str = item;
if (item[0] == '>' && item[1] == ' ')
str = str.substr(2);

std::strncpy(command, str.c_str(), sizeof(command) - 1);
m_focusConsoleInput = true;
}
ImGui::PopID();
}

if (m_outputScroll)
{
if (m_outputShouldScroll)
ImGui::SetScrollHereY();
m_outputScroll = false;
}
if (result)
ImGui::ListBoxFooter();
}

ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (m_focusConsoleInput)
{
ImGui::SetKeyboardFocusHere();
m_focusConsoleInput = false;
}
const auto execute = ImGui::InputText("##InputCommand", command, std::size(command), ImGuiInputTextFlags_EnterReturnsTrue);
ImGui::SetItemDefaultFocus();
if (execute)
{
Log(std::string("> ") + command);

if (!LuaVM::Get().ExecuteLua(command))
Log("Command failed to execute!");

if (m_inputClear)
std::memset(command, 0, sizeof(command));
}
}
else
ImGui::Text("Unknown version, please update your game and the mod");

ImGui::End();
}

void Console::Toggle()
{
m_enabled = !m_enabled;

auto& d3d12 = D3D12::Get();
d3d12.PassInputToImGui(m_enabled);
d3d12.CatchInputInImGui(m_enabled);

while(true)
{
if (m_enabled && ShowCursor(TRUE) >= 0)
{
m_focusConsoleInput = true;
break;
}
if (!m_enabled && ShowCursor(FALSE) < 0)
break;
}

ClipToCenter(RED4ext::CGameEngine::Get()->unkC0);
}

bool Console::IsEnabled() const
{
return m_enabled;
}

void Console::Log(const std::string& acpText)
{
if (this == nullptr)
return;

std::lock_guard<std::recursive_mutex> _{ m_outputLock };
std::istringstream lines(acpText);
std::string line;

while (std::getline(lines, line))
{
m_outputLines.emplace_back(line);
}
m_outputScroll = true;
}

LRESULT Console::OnWndProc(HWND, UINT auMsg, WPARAM awParam, LPARAM)
{
if (this == nullptr)
return 0;

auto& options = Options::Get();
if (auMsg == WM_KEYDOWN && awParam == options.ConsoleKey)
{
Toggle();
return 1;
}

switch (auMsg)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
if (awParam == options.ConsoleKey)
return 1;
break;
case WM_CHAR:
if (options.ConsoleChar && awParam == options.ConsoleChar)
return 1;
break;
}

if (IsEnabled())
{
if (auMsg == WM_KEYUP && awParam == VK_RETURN)
m_focusConsoleInput = true;
}

return 0;
}

BOOL Console::ClipToCenter(RED4ext::CGameEngine::UnkC0* apThis)
{
HWND wnd = (HWND)apThis->hWnd;
HWND foreground = GetForegroundWindow();

if(wnd == foreground && apThis->unk164 && !apThis->unk140 && !Get().IsEnabled())
{
RECT rect;
GetClientRect(wnd, &rect);
ClientToScreen(wnd, reinterpret_cast<POINT*>(&rect.left));
ClientToScreen(wnd, reinterpret_cast<POINT*>(&rect.right));
rect.left = (rect.left + rect.right) / 2;
rect.right = rect.left;
rect.bottom = (rect.bottom + rect.top) / 2;
rect.top = rect.bottom;
apThis->isClipped = true;
ShowCursor(FALSE);
return ClipCursor(&rect);
}

if(apThis->isClipped)
{
apThis->isClipped = false;
return ClipCursor(nullptr);
}

return 1;
}

void Console::Hook()
{
uint8_t* pLocation = FindSignature({
0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8B,
0x99, 0x68, 0x01, 0x00, 0x00, 0x48, 0x8B, 0xF9, 0xFF });

if (pLocation)
{
if (MH_CreateHook(pLocation, &ClipToCenter, reinterpret_cast<void**>(&m_realClipToCenter)) != MH_OK || MH_EnableHook(pLocation) != MH_OK)
spdlog::error("Could not hook mouse clip function!");
else
spdlog::info("Hook mouse clip function!");
}
}

Console::Console() = default;

Console::~Console() = default;
Loading

0 comments on commit 3f79c32

Please sign in to comment.