Skip to content

Instantly share code, notes, and snippets.

@emoose
Last active February 19, 2022 23:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emoose/460a9d509b767af39ce6acc611f9233e to your computer and use it in GitHub Desktop.
Save emoose/460a9d509b767af39ce6acc611f9233e to your computer and use it in GitHub Desktop.
Bloodstained RotN dialogue/menu resolution fix
// This code requires some files from my Arise-SDK project:
// https://github.com/emoose/Arise-SDK/tree/b73c7ea9fceea2c494cbb8ebc74c6b3d1d35cbf6
#include "pch.h"
#include <cstdio>
#define SDK_VERSION "0.1.25"
HMODULE DllHModule;
HMODULE GameHModule;
uintptr_t mBaseAddress;
bool InitGame()
{
printf("\nBloodstainedFix " SDK_VERSION " - https://github.com/emoose\n");
GameHModule = GetModuleHandleA(NULL);
if (!GameHModule)
{
MessageBoxA(0, "Failed to get module handle for game, unloading ResolutionFix...", "ResolutionFix", 0);
return false;
}
mBaseAddress = reinterpret_cast<uintptr_t>(GameHModule);
return true;
}
bool inited = false;
uint32_t Addr_UTextureRenderTarget2D__PostLoad = 0x1E7A100; // steam addr, as of 30th sept 2021
typedef void*(*UTextureRenderTarget2D__PostLoad_Fn)(uint8_t* thisptr);
UTextureRenderTarget2D__PostLoad_Fn UTextureRenderTarget2D__PostLoad_Orig;
void* UTextureRenderTarget2D__PostLoad_Hook(uint8_t* thisptr)
{
void* ret = UTextureRenderTarget2D__PostLoad_Orig(thisptr);
uint32_t* SizeX = (uint32_t*)(thisptr + 0xD0);
uint32_t* SizeY = (uint32_t*)(thisptr + 0xD4);
// TODO: two different PostLoad calls use 1920x1080, which one actually needs the fix?
if (*SizeX == 1920 && *SizeY == 1080)
{
*SizeX = 3840;
*SizeY = 2160;
}
return ret;
}
void InitPlugin()
{
inited = false;
MH_Initialize();
MODULEINFO modInfo;
if (GetModuleInformation(GetCurrentProcess(), GameHModule, &modInfo, sizeof(MODULEINFO)))
{
auto* funcSignature = "\x3B\xC2\x44\x8B\x81\xD4\x00\x00\x00";
auto* funcMask = "xxxxxxxxx";
uint8_t* UTextureRenderTarget2D__PostLoad = FindSignature((void*)mBaseAddress, modInfo.SizeOfImage, funcSignature, funcMask);
if (UTextureRenderTarget2D__PostLoad)
{
UTextureRenderTarget2D__PostLoad -= 0xC;
Addr_UTextureRenderTarget2D__PostLoad = (uint32_t)(UTextureRenderTarget2D__PostLoad - mBaseAddress);
}
}
auto* funcExpectedBytes = "\x8B\x81\xD0\x00\x00\x00"; // mov eax, [rcx+0D0h]
if (memcmp(funcExpectedBytes, (void*)(mBaseAddress + Addr_UTextureRenderTarget2D__PostLoad), 6))
{
MessageBoxA(0, "Failed to locate UTextureRenderTarget2D::PostLoad inside 'BloodstainedRotN-Win64-Shipping.exe', unloading ResolutionFix...", "ResolutionFix", 0);
return;
}
// Hook UTextureRenderTarget2D::PostLoad so we can adjust RT width/height after it's been loaded in
MH_GameHook(UTextureRenderTarget2D__PostLoad);
MH_EnableHook(MH_ALL_HOOKS);
inited = true;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DllHModule = hModule;
bool Proxy_Attach(); // proxy.cpp
Proxy_Attach();
if (InitGame())
Proxy_InitSteamStub();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
void Proxy_Detach();
Proxy_Detach();
break;
}
return TRUE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment