Skip to content

Commit

Permalink
Uncharted 4 Debug Menu from SunBeam
Browse files Browse the repository at this point in the history
so its not lost in some discord message
  • Loading branch information
illusion0001 committed Nov 29, 2023
1 parent d44b2be commit a456f12
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 31 deletions.
16 changes: 15 additions & 1 deletion .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,23 @@
</details>
<details><summary>

### Uncharted 4 & The Lost Legacy
### Uncharted 4 + The Lost Legacy
</summary>

- Debug Menu (by SunBeam)
- Controls:
- Joypad:
- `L3 + X`: Open Quick Menu
- `L3 + Circle`: Open Dev Menu
- `L3 + Square`: Debug Pause
- `Circle`: Back submenu
- `X`: Enter\Select Dev Menu Entry
- Keyboard:
- `Alt + Tilde`: Open Dev Menu
- `Tilde + 1`: Open Quick Menu
- `Tilde`: Back submenu
- `Enter`: Enter\Select Dev Menu Entry
- Skip Intro Logo Videos
- Disable TAA
- Disable Sharpness
- Disable Barrel Distortion
Expand Down
3 changes: 3 additions & 0 deletions include/helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ wchar_t* GetRunningPath(wchar_t* output);
wchar_t* GetModuleName(wchar_t* output);
uintptr_t FindAndPrintPatternW(const wchar_t* Patch_Pattern, const wchar_t* Pattern_Name, size_t offset = 0);
void Make32to64Hook(void* source_target, void* second_jmp, void* target_jmp, uint32_t source_size, const wchar_t* source_name, const wchar_t* second_jmp_name, const wchar_t* target_jmp_name);
void Make32Hook(void* source_target, void* target_jmp, uint32_t source_size, const wchar_t* source_name, const wchar_t* target_jmp_name);
void Make64Hook(void* source_target, void* target_jmp, uint32_t source_size, const wchar_t* source_name, const wchar_t* target_jmp_name);
uintptr_t ReadLEA32(const wchar_t* Patch_Pattern, const wchar_t* Pattern_Name, size_t offset, size_t lea_size, size_t lea_opcode_size);

#define SID(str) ToStringId64(str)
typedef uint64_t StringId64;
Expand Down
67 changes: 67 additions & 0 deletions source/Shared/helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,75 @@ uintptr_t FindAndPrintPatternW(const wchar_t* Patch_Pattern, const wchar_t* Patt

void Make32to64Hook(void* source_target, void* second_jmp, void* target_jmp, uint32_t source_size, const wchar_t* source_name, const wchar_t* second_jmp_name, const wchar_t* target_jmp_name)
{
if (!source_target || !second_jmp || !target_jmp || source_size < 5)
{
LOG(L"Canoot create jump '%s' from '%s' to '%s'\n", source_name, second_jmp_name, target_jmp_name);
LOG(L"source_target: 0x%p\n", source_target);
LOG(L"source_size: %u bytes\n", source_size);
LOG(L"second_jmp: 0x%p\n", second_jmp);
LOG(L"target_jmp: 0x%p\n", target_jmp);
return;
}
Memory::DetourFunction32((void*)source_target, (void*)second_jmp, source_size);
LOG(L"Created jump %s (0x%016llx) to %s (0x%016llx)\n", source_name, (uintptr_t)source_target, second_jmp_name, (uintptr_t)second_jmp);
Memory::DetourFunction64((void*)second_jmp, (void*)target_jmp, 14);
LOG(L"Created jump %s (0x%016llx) to %s (0x%016llx)\n", second_jmp_name, (uintptr_t)second_jmp, target_jmp_name, (uintptr_t)target_jmp);
}

void Make32Hook(void* source_target, void* target_jmp, uint32_t source_size, const wchar_t* source_name, const wchar_t* target_jmp_name)
{
if (!source_target || !target_jmp || source_size < 5)
{
LOG(L"Canoot create jump '%s' to '%s'\n", source_name, target_jmp_name);
LOG(L"source_target: 0x%p\n", source_target);
LOG(L"source_size: %u bytes\n", source_size);
LOG(L"target_jmp: 0x%p\n", target_jmp);
return;
}
Memory::DetourFunction32((void*)source_target, (void*)target_jmp, source_size);
LOG(L"Created jump %s (0x%016llx) to %s (0x%016llx)\n", source_name, (uintptr_t)source_target, target_jmp_name, (uintptr_t)target_jmp);
}

void Make64Hook(void* source_target, void* target_jmp, uint32_t source_size, const wchar_t* source_name, const wchar_t* target_jmp_name)
{
if (!source_target || !target_jmp || source_size < 14)
{
LOG(L"Canoot create jump '%s' to '%s'\n", source_name, target_jmp_name);
LOG(L"source_target: 0x%p\n", source_target);
LOG(L"source_size: %u bytes\n", source_size);
LOG(L"target_jmp: 0x%p\n", target_jmp);
return;
}
Memory::DetourFunction64((void*)source_target, (void*)target_jmp, source_size);
LOG(L"Created jump %s (0x%016llx) to %s (0x%016llx)\n", source_name, (uintptr_t)source_target, target_jmp_name, (uintptr_t)target_jmp);
}

uintptr_t ReadLEA32(const wchar_t* Patch_Pattern, const wchar_t* Pattern_Name, size_t offset, size_t lea_size, size_t lea_opcode_size)
{
uintptr_t Address_Result = (uintptr_t)Memory::PatternScanW(baseModule, Patch_Pattern);
uintptr_t Patch_Address = 0;
int32_t lea_offset = 0;
uintptr_t New_Offset = 0;
if (Address_Result)
{
if (offset)
{
Patch_Address = offset + Address_Result;
lea_offset = *(int32_t*)(lea_size + Address_Result);
New_Offset = Patch_Address + lea_offset + lea_opcode_size;
}
else
{
Patch_Address = Address_Result;
lea_offset = *(int32_t*)(lea_size + Address_Result);
New_Offset = Patch_Address + lea_offset + lea_opcode_size;
}
LOG(L"%s: 0x%016llx -> 0x%016llx\n", Pattern_Name, Address_Result, New_Offset);
return New_Offset;
}
else
{
LogPatchFailed(Pattern_Name, Patch_Pattern);
}
return 0;
}
3 changes: 3 additions & 0 deletions source/Uncharted4TLL.NoTAA/Uncharted4TLL.NoTAA.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,15 @@
<ClCompile Include="..\Shared\helper.cpp" />
<ClCompile Include="..\Shared\memory.cpp" />
<ClCompile Include="..\Shared\stdafx.cpp" />
<ClCompile Include="code_caves.cpp" />
<ClCompile Include="dllmain.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\helper.hpp" />
<ClInclude Include="..\..\include\memory.hpp" />
<ClInclude Include="..\..\include\stdafx.h" />
<ClInclude Include="code_caves.hpp" />
<ClInclude Include="patterns.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
<ClCompile Include="..\Shared\memory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="code_caves.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\helper.hpp">
Expand All @@ -34,5 +37,11 @@
<ClInclude Include="..\..\include\memory.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="patterns.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="code_caves.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
20 changes: 20 additions & 0 deletions source/Uncharted4TLL.NoTAA/code_caves.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "code_caves.hpp"

namespace CodeCave
{
uintptr_t DMenu_Addr = 0;
uintptr_t DebugDraw_UpdateLoopAddr = 0;
uintptr_t DebugDraw_UpdateLoopReturnAddr = 0;
uintptr_t DMenu_Update = 0;

void __attribute__((naked)) DebugDraw_UpdateLoop()
{
__asm
{
mov rcx, [DMenu_Addr];
mov rcx, [rcx];
call[DMenu_Update];
jmp[DebugDraw_UpdateLoopReturnAddr];
}
}
}
12 changes: 12 additions & 0 deletions source/Uncharted4TLL.NoTAA/code_caves.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include "helper.hpp"

namespace CodeCave
{
extern uintptr_t DMenu_Addr;
extern uintptr_t DebugDraw_UpdateLoopAddr;
extern uintptr_t DebugDraw_UpdateLoopReturnAddr;
extern uintptr_t DMenu_Update;
void __attribute__((naked)) DebugDraw_UpdateLoop();
};
109 changes: 79 additions & 30 deletions source/Uncharted4TLL.NoTAA/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
#include "helper.hpp"
#include "memory.hpp"
#include "git_ver.h"
#include "code_caves.hpp"
#include "patterns.hpp"

HMODULE baseModule = GetModuleHandle(NULL);
HMODULE baseModule{};

#define wstr(s) L#s
#define wxstr(s) wstr(s)
Expand All @@ -17,13 +19,15 @@ wchar_t tll_exe[] = { L"tll.exe" };
wchar_t tll_l_exe[] = { L"tll-l.exe" };

// INI Variables
bool bDisableTAA;
bool bDisableSharpening;
bool bDisableBarrelDistortion;
bool bDisableScreenZoom;
bool bDisableChromaticAberration;
bool bDisableDoF;
bool bDisableVignette;
bool bDebugMenu{};
bool bSkipIntroLogos{};
bool bDisableTAA{};
bool bDisableSharpening{};
bool bDisableBarrelDistortion{};
bool bDisableScreenZoom{};
bool bDisableChromaticAberration{};
bool bDisableDoF{};
bool bDisableVignette{};

void ReadConfig(void)
{
Expand All @@ -44,16 +48,23 @@ void ReadConfig(void)
{
// no ini, lets generate one.
LOG(L"Failed to load config file.\n");
std::wstring ini_defaults = L"[Settings]\n"
wstr(bDisableTAA)" = true\n"
wstr(bDisableSharpening)" = true\n"
wstr(bDisableBarrelDistortion)" = true\n"
wstr(bDisableScreenZoom)" = true\n"
wstr(bDisableChromaticAberration)" = true\n"
wstr(bDisableDoF)" = true\n"
wstr(bDisableVignette)" = true\n";
std::wstring ini_defaults = L""
"[Settings]\n"
"; Debug Menu by SunBeam\n"
wstr(bDebugMenu)" = false\n"
"; Skip Startup Logo Videos\n"
wstr(bSkipIntroLogos)" = true\n"
wstr(bDisableTAA)" = true\n"
wstr(bDisableSharpening)" = true\n"
wstr(bDisableBarrelDistortion)" = true\n"
wstr(bDisableScreenZoom)" = true\n"
wstr(bDisableChromaticAberration)" = true\n"
wstr(bDisableDoF)" = true\n"
wstr(bDisableVignette)" = true\n";
std::wofstream iniFile(config_path);
iniFile << ini_defaults;
bDebugMenu = false;
bSkipIntroLogos = true;
bDisableTAA = true;
bDisableSharpening = true;
bDisableBarrelDistortion = true;
Expand All @@ -67,6 +78,8 @@ void ReadConfig(void)
else
{
ini.parse(iniFile);
inipp::get_value(ini.sections[L"Settings"], wstr(bDebugMenu), bDebugMenu);
inipp::get_value(ini.sections[L"Settings"], wstr(bSkipIntroLogos), bSkipIntroLogos);
inipp::get_value(ini.sections[L"Settings"], wstr(bDisableTAA), bDisableTAA);
inipp::get_value(ini.sections[L"Settings"], wstr(bDisableSharpening), bDisableSharpening);
inipp::get_value(ini.sections[L"Settings"], wstr(bDisableBarrelDistortion), bDisableBarrelDistortion);
Expand All @@ -77,6 +90,8 @@ void ReadConfig(void)
}

// Log config parse
LOG(L"%s: %s (%i)\n", wstr(bDebugMenu), GetBoolStr(bDebugMenu), bDebugMenu);
LOG(L"%s: %s (%i)\n", wstr(bSkipIntroLogos), GetBoolStr(bSkipIntroLogos), bSkipIntroLogos);
LOG(L"%s: %s (%i)\n", wstr(bDisableTAA), GetBoolStr(bDisableTAA), bDisableTAA);
LOG(L"%s: %s (%i)\n", wstr(bDisableSharpening), GetBoolStr(bDisableSharpening), bDisableSharpening);
LOG(L"%s: %s (%i)\n", wstr(bDisableBarrelDistortion), GetBoolStr(bDisableBarrelDistortion), bDisableBarrelDistortion);
Expand Down Expand Up @@ -207,16 +222,47 @@ void DisableVignette(wchar_t* exeName)
}
}

DWORD __stdcall Main(void*)
void EnbaleDebugMenu()
{
CodeCave::DMenu_Addr = ReadLEA32(Patterns::DMenu_Ptr, wstr(Patterns::DMenu_Ptr), 0, 3, 7);
CodeCave::DebugDraw_UpdateLoopAddr = FindAndPrintPatternW(Patterns::DebugDraw_UpdateLoop, wstr(Pattern::DebugDraw_UpdateLoop));
CodeCave::DMenu_Update = FindAndPrintPatternW(Patterns::DMenu_Update, wstr(Pattern::DMenu_Update));
if (CodeCave::DMenu_Addr && CodeCave::DebugDraw_UpdateLoop && CodeCave::DMenu_Update)
{
WritePatchPattern_Hook(Patterns::DebugDraw_UpdateLoop, 22, wstr(Patterns::DebugDraw_UpdateLoop), 0, (void*)CodeCave::DebugDraw_UpdateLoop, nullptr);
CodeCave::DebugDraw_UpdateLoopReturnAddr = CodeCave::DebugDraw_UpdateLoopAddr + 22;
}
}

void SkipIntroLogos()
{
uintptr_t skiplogos_clargAddr = FindAndPrintPatternW(Patterns::skiplogos_clarg, wstr(Patterns::skiplogos_clarg));
if (skiplogos_clargAddr)
{
const uint8_t long_jmp[] = { 0x48, 0xe9 };
Memory::PatchBytes(skiplogos_clargAddr + 9, long_jmp, sizeof(long_jmp));
}
}

void KillPrintf()
{
const uint8_t ret_0[] = { 0x31, 0xc0, 0xc3 };
WritePatchPattern(Patterns::GamePrintf, ret_0, sizeof(ret_0), wstr(Patterns::GamePrintf), 0);
}

DWORD __stdcall Main()
{
baseModule = GetModuleHandle(NULL);
bLoggingEnabled = false;
wchar_t LogPath[_MAX_PATH] = { 0 };
wcscpy_s(exePath, _countof(exePath), GetRunningPath(exePath));
_snwprintf_s(LogPath, _countof(LogPath), _TRUNCATE, L"%s\\%s", exePath, _PROJECT_LOG_PATH);
LoggingInit(_PROJECT_NAME, LogPath);
LOG(L"GetModuleHandle: 0x%p\n", baseModule);
ReadConfig();

wchar_t* exeName = GetModuleName(exePath);
KillPrintf();
if (bDisableTAA)
DisableTAA(exeName);
if (bDisableSharpening)
Expand All @@ -231,27 +277,30 @@ DWORD __stdcall Main(void*)
DisableDoF(exeName);
if (bDisableVignette)
DisableVignette(exeName);

if (bDebugMenu)
EnbaleDebugMenu();
if (bSkipIntroLogos)
SkipIntroLogos();
LOG(L"Shutting down " wstr(fp_log) " file handle.\n");
fclose(fp_log);
return true;
}

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
CreateThread(NULL, 0, Main, 0, NULL, 0);
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
case DLL_PROCESS_ATTACH:
{
Main();
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
10 changes: 10 additions & 0 deletions source/Uncharted4TLL.NoTAA/patterns.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

namespace Patterns
{
const wchar_t* DMenu_Ptr = L"48 8b 0d ?? ?? ?? ?? 44 8b c0 44 8b bf d0 00 00 00 41 f7 d0";
const wchar_t* DebugDraw_UpdateLoop = L"48 8b 05 ?? ?? ?? ?? 0f b6 88 ?? ?? ?? ?? 38 4f 72 74 ?? 88 4f 72";
const wchar_t* DMenu_Update = L"48 89 5c 24 ?? 48 89 74 24 ?? 48 89 7c 24 ?? 55 41 54 41 55 41 56 41 57 48 8d ac 24 ?? ?? ?? ?? 48 81 ec ?? ?? ?? ?? 48 8b 05 ?? ?? ?? ?? 48 33 c4 48 89 85 ?? ?? ?? ?? 80 3d ?? ?? ?? ?? ??";
const wchar_t* skiplogos_clarg = L"0f b6 05 ?? ?? ?? ?? 84 c0 0f 84 ?? ?? ?? ?? 48 8b 05 ?? ?? ?? ?? 40 38 b8 ?? ?? ?? ?? 0f 84 ?? ?? ?? ??";
const wchar_t* GamePrintf = L"48 89 4c 24 ?? 48 89 54 24 ?? 4c 89 44 24 ?? 4c 89 4c 24 ?? 53 56 57 48 83 ec ?? 48 8b f9";
}

0 comments on commit a456f12

Please sign in to comment.