Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix stretched FMVs for Resident Evil Revelations 2. #1695

Merged
merged 3 commits into from
Jan 14, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 113 additions & 13 deletions source/ResidentEvilRevelations2.FusionFix/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ enum GUI
VirtualScreen = 0x141AC10
};

static IDirect3DVertexShader9* g_screenVertexShader = nullptr;
static IDirect3DPixelShader9* g_wmvYuvDecodePixelShader = nullptr;
static IDirect3DVertexShader9* g_myScreenVertexShader = nullptr;

bool IsSplitScreenActive()
{
auto ptr = *(uint32_t*)0x157AE00;
Expand Down Expand Up @@ -256,7 +260,8 @@ enum
{
RESCALE = 0xAAAAEEEE,
STRETCH = 0xBBBBFFFF,
OFFSET = 0xCCCCDDDD
OFFSET = 0xCCCCDDDD,
SUBTITLES = 0xDDDDDDDD,
};

void __fastcall sub_E18040(int _this, int edx, int a2)
Expand Down Expand Up @@ -361,6 +366,7 @@ void __fastcall sub_E18040(int _this, int edx, int a2)

switch (edx)
{
case SUBTITLES:
case RESCALE:
{
if (IsSplitScreenActive())
Expand All @@ -369,7 +375,7 @@ void __fastcall sub_E18040(int _this, int edx, int a2)
{
v14 = 2.0 / (float)(v28 - v19);
v15 = -2.0 / (float)(v21 - v29);
v13[0] = v14 * v4;
v13[0] = v14 * v4 * ((edx == SUBTITLES) ? (1.0f / GetDiff()) : 1.0f);
v13[1] = v15 * v5;
v13[2] = (float)(v14 * v6) - (1.0f / GetDiff());
v13[3] = (float)(v15 * v7) + 1.0;
Expand All @@ -378,7 +384,7 @@ void __fastcall sub_E18040(int _this, int edx, int a2)
{
v14 = 2.0 / (float)(v28 - v19);
v15 = -2.0 / (float)(v21 - v29);
v13[0] = v14 * v4;
v13[0] = v14 * v4 * ((edx == SUBTITLES) ? (1.0f / GetDiff()) : 1.0f);
v13[1] = v15 * v5;
v13[2] = (float)(v14 * v6) - (1.0f / (GetAspectRatio() / defaultAspectRatio));
v13[3] = (float)(v15 * v7) + 1.0;
Expand All @@ -388,7 +394,7 @@ void __fastcall sub_E18040(int _this, int edx, int a2)
{
v14 = 2.0 / (float)(v28 - v19);
v15 = -2.0 / (float)(v21 - v29);
v13[0] = v14 * v4;
v13[0] = v14 * v4 * ((edx == SUBTITLES) ? (1.0f / GetDiff()) : 1.0f);
v13[1] = v15 * v5;
v13[2] = (float)(v14 * v6) - (1.0f / GetDiff());
v13[3] = (float)(v15 * v7) + 1.0;
Expand Down Expand Up @@ -493,6 +499,11 @@ void __fastcall sub_E18040_nop(int _this, int edx, int a2)

void __fastcall sub_E18040_rescale(int _this, int edx, int a2)
{
auto uBioGUISubtitles = (const char*)(*(uintptr_t*)_this + 0x1B8);

if (!IsBadReadPtr(uBioGUISubtitles, sizeof(char*)) && std::string_view(uBioGUISubtitles) == "uBioGUISubtitles")
return sub_E18040(_this, SUBTITLES, a2);

return sub_E18040(_this, RESCALE, a2);
}

Expand Down Expand Up @@ -521,6 +532,7 @@ IDirect3DVertexShader9* __stdcall CreateVertexShaderHook(const DWORD** a1)
return nullptr;

auto pDevice = (IDirect3DDevice9*)*((uint32_t*)*(uint32_t*)0x15E0388 + 0x26);

IDirect3DVertexShader9* pShader = nullptr;
pDevice->CreateVertexShader(a1[2], &pShader);

Expand All @@ -534,7 +546,6 @@ IDirect3DVertexShader9* __stdcall CreateVertexShaderHook(const DWORD** a1)

pShader->GetFunction(pbFunc.data(), &len);

uint32_t crc32(uint32_t crc, const void* buf, size_t size);
auto crc = crc32(0, pbFunc.data(), len);

// various overlays (low health, waiting for partner, pause text, maybe more)
Expand Down Expand Up @@ -596,17 +607,84 @@ IDirect3DVertexShader9* __stdcall CreateVertexShaderHook(const DWORD** a1)
{
pShaderData = (DWORD*)pCode->GetBufferPointer();
IDirect3DVertexShader9* shader = nullptr;
result = pDevice->CreateVertexShader(pShaderData, &shader);
if (FAILED(result)) {
return pShader;
}
else
if (pDevice->CreateVertexShader(pShaderData, &shader) == D3D_OK)
{
pShader->Release();
return shader;
}
}
}
else if (crc == 0x1287841D)
{
g_screenVertexShader = pShader;

// inject additional, alternative screenspace shader for FMV fixups
constexpr auto src = R"(
struct VS_INPUT {
float4 position : POSITION;
};

struct VS_OUTPUT {
float4 position : POSITION;
float4 uv : TEXCOORD;
};

float2 fScreenHalfPixelOffset : register(c1);
float fHorizontalAspectScale : register(c20);

VS_OUTPUT main(VS_INPUT input)
{
VS_OUTPUT output;

output.position = float4(
-fScreenHalfPixelOffset.x + input.position.x * fHorizontalAspectScale,
fScreenHalfPixelOffset.y + input.position.y,
0.0,
1.0);
output.uv = float4(
1.0 * input.position.z,
1.0 * input.position.w,
0.0, 0.0
);

return output;
})";

LPD3DXBUFFER code;
if (SUCCEEDED(D3DXCompileShader(src, strlen(src), nullptr, nullptr, "main", "vs_3_0", NULL, &code, nullptr, nullptr)))
{
pDevice->CreateVertexShader(reinterpret_cast<const DWORD*>(code->GetBufferPointer()), &g_myScreenVertexShader);
}
}
}

return pShader;
}

IDirect3DPixelShader9* __stdcall CreatePixelShaderHook(const DWORD** a1)
{
if (!a1)
return nullptr;

auto pDevice = (IDirect3DDevice9*)*((uint32_t*)*(uint32_t*)0x15E0388 + 0x26);

IDirect3DPixelShader9* pShader = nullptr;
pDevice->CreatePixelShader(a1[2], &pShader);

if (pShader != nullptr)
{
UINT len;
pShader->GetFunction(nullptr, &len);
std::vector<uint8_t> pbFunc(len, 0);

pShader->GetFunction(pbFunc.data(), &len);

auto crc = crc32(0, pbFunc.data(), len);

if (crc == 0x9D190FC7)
{
g_wmvYuvDecodePixelShader = pShader;
}
}

return pShader;
Expand Down Expand Up @@ -755,7 +833,28 @@ void Init()
});

// movies fix for ultra wide
// ?
{
static auto DrawPrimitiveHook = safetyhook::create_mid(0xCC8788, [](SafetyHookContext& regs)
{
auto g_device = (IDirect3DDevice9*)regs.edi;

// switch to a x-scaling vertex shader if drawing FMVs
IDirect3DPixelShader9* frag;
g_device->GetPixelShader(&frag);
if (frag != g_wmvYuvDecodePixelShader)
return;

IDirect3DVertexShader9* vert;
g_device->GetVertexShader(&vert);
if (vert != g_screenVertexShader)
return;

g_device->SetVertexShader(g_myScreenVertexShader);
const float horzScaleFactor = (defaultAspectRatio / GetAspectRatio());
const std::array<float, 4> shaderConsts = { horzScaleFactor, 0.0f, 0.0f, 0.0f };
g_device->SetVertexShaderConstantF(20, shaderConsts.data(), 1);
});
}

// split screen windows dimensions
injector::MakeCALL(0x4AE6E8, SplitScreenSetupTop, true);
Expand Down Expand Up @@ -805,7 +904,8 @@ void Init()

//disable shader overlays (don't scale to fullscreen)
{
injector::MakeCALL(0xFFB9E2, CreateVertexShaderHook, true);
injector::MakeCALL(0xFFB9E2, CreateVertexShaderHook, true);
injector::MakeCALL(0xFFBA31, CreatePixelShaderHook, true);

//struct SetVertexShaderHook
//{
Expand Down Expand Up @@ -974,7 +1074,7 @@ CEXP void InitializeASI()
{
std::call_once(CallbackHandler::flag, []()
{
CallbackHandler::RegisterCallback(Init, hook::pattern("F3 0F 5C 15 ? ? ? ? F3 0F 59 E5"));
CallbackHandler::RegisterCallbackAtGetSystemTimeAsFileTime(Init, hook::pattern("F3 0F 5C 15 ? ? ? ? F3 0F 59 E5"));
});
}

Expand Down