Updated the kNoBorder fix to cover all non-VR versions
This commit is contained in:
parent
9cc519a8aa
commit
d710d60519
@ -255,8 +255,7 @@ SKSEPluginLoad(const LoadInterface* skse) {
|
||||
logger::info("Initializing Stay At The System Page...");
|
||||
JournalMenuEx::InstallHooks();
|
||||
}
|
||||
// Menus are only stretched to fill the viewport since 1.6.1130
|
||||
if (g_settings.at("MenuAspectRatioFix") && REL::Module::get().version() >= REL::Version(1, 6, 1130, 0)) {
|
||||
if (g_settings.at("MenuAspectRatioFix")) {
|
||||
MenuAspectRatioFix::Install();
|
||||
}
|
||||
LoadScreenFrameFix::Install(g_settings.at("LoadScreenFrameFix"));
|
||||
|
||||
@ -1,17 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
// Restores the Scaleform scale modes menus were loaded with before Skyrim 1.6.1130, and stops
|
||||
// kNoBorder from cropping them on displays wider than 16:9.
|
||||
// Two independent corrections to the Scaleform scale mode menus are loaded with, both applied
|
||||
// from the same BSScaleformManager::LoadMovie hook:
|
||||
//
|
||||
// 1.6.1130 switched nearly every menu to kExactFit, which stretches the movie across the whole
|
||||
// viewport instead of preserving its aspect ratio. Enderal's menus - including the SkyUI-derived
|
||||
// widescreen versions shipped with them - are authored for the old modes, so on anything that is
|
||||
// not 16:9 they come out distorted.
|
||||
// 1. Restore the modes used before 1.6.1130. That build switched nearly every menu to
|
||||
// kExactFit, which stretches the movie across the whole viewport instead of preserving its
|
||||
// aspect ratio. Enderal's menus - including the SkyUI-derived widescreen versions shipped
|
||||
// with them - are authored for the old modes, so on anything that is not 16:9 they come out
|
||||
// distorted. Only 1.6.1130 and later need this; see g_restoreScaleModes.
|
||||
// 2. Stop kNoBorder from cropping menus on displays wider than 16:9. That one predates
|
||||
// 1.6.1130 and is needed on every runtime, so it is not version gated; see ClampToViewport.
|
||||
//
|
||||
// The table below is what 1.6.640 passes to BSScaleformManager::LoadMovie, plus BookMenu and
|
||||
// GiftMenu, which 1.6.1130 left on kNoBorder and which need the same clamp. Menus that want no
|
||||
// help (Book, Console, CreditsMenu, CursorMenu, FaderMenu, StartMenu) are absent and keep
|
||||
// whatever the caller asked for.
|
||||
// The table below is what 1.6.640 passes to LoadMovie, plus BookMenu and GiftMenu, which 1.6.1130
|
||||
// left on kNoBorder and which need the clamp. Menus that want no help (Book, Console, CreditsMenu,
|
||||
// CursorMenu, FaderMenu, StartMenu) are absent and keep whatever the caller asked for. It doubles
|
||||
// as the list of menus this patch is allowed to touch at all, so on older runtimes - where the
|
||||
// engine already passes these very modes - a third-party menu loaded with kNoBorder is left alone.
|
||||
//
|
||||
// Based on Widescreen Scale Removed by SkyHorizon (GPL-3.0)
|
||||
// https://www.nexusmods.com/skyrimspecialedition/mods/136793
|
||||
@ -19,6 +23,10 @@ namespace MenuAspectRatioFix
|
||||
{
|
||||
using ScaleModeType = RE::GFxMovieView::ScaleModeType;
|
||||
|
||||
// True on the runtimes that stretch menus to fill the viewport, i.e. 1.6.1130 and later. Below
|
||||
// that the engine already asks for the modes in the table, so only the clamp has work to do.
|
||||
inline bool g_restoreScaleModes = false;
|
||||
|
||||
std::optional<ScaleModeType> GetScaleMode(const char* a_fileName)
|
||||
{
|
||||
static const std::map<std::string_view, ScaleModeType> modes{
|
||||
@ -88,7 +96,7 @@ namespace MenuAspectRatioFix
|
||||
{
|
||||
if (a_fileName && a_fileName[0]) {
|
||||
if (const auto mode = GetScaleMode(a_fileName); mode) {
|
||||
a_mode = ClampToViewport(*mode);
|
||||
a_mode = ClampToViewport(g_restoreScaleModes ? *mode : a_mode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,21 +108,32 @@ namespace MenuAspectRatioFix
|
||||
|
||||
void Install()
|
||||
{
|
||||
// Checked: 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179
|
||||
g_restoreScaleModes = REL::Module::get().version() >= REL::Version(1, 6, 1130, 0);
|
||||
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179
|
||||
const auto target = REL::RelocationID(80302, 82325).address();
|
||||
|
||||
// mov rax,rsp / mov qword ptr [rax+10h],rdx - relocated into the trampoline by the hook,
|
||||
// so bail out rather than corrupt the function if a future runtime changes the prologue
|
||||
constexpr std::uint8_t prologue[]{ 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x50, 0x10 };
|
||||
// mov rax,rsp followed by one argument spill - 7 bytes of position-independent code, which
|
||||
// the hook relocates into the trampoline. The spilled argument differs between the runtime
|
||||
// families, so accept either and bail out rather than corrupt the function if a future
|
||||
// build changes the prologue again.
|
||||
constexpr std::uint8_t prologueAE[]{ 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x50, 0x10 }; // mov [rax+10h],rdx
|
||||
constexpr std::uint8_t prologueSE[]{ 0x48, 0x8B, 0xC4, 0x4C, 0x89, 0x40, 0x18 }; // mov [rax+18h],r8
|
||||
|
||||
if (!target || std::memcmp(reinterpret_cast<const void*>(target), prologue, sizeof(prologue)) != 0) {
|
||||
static_assert(sizeof(prologueAE) == sizeof(prologueSE));
|
||||
|
||||
const auto prologue = reinterpret_cast<const void*>(target);
|
||||
|
||||
if (!target ||
|
||||
(std::memcmp(prologue, prologueAE, sizeof(prologueAE)) != 0 &&
|
||||
std::memcmp(prologue, prologueSE, sizeof(prologueSE)) != 0)) {
|
||||
logger::error("Unexpected BSScaleformManager::LoadMovie prologue, menu aspect ratio fix is disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
SKSE::AllocTrampoline(64);
|
||||
SKSE::stl::hook_function_prologue<LoadMovie, sizeof(prologue)>(target);
|
||||
SKSE::stl::hook_function_prologue<LoadMovie, sizeof(prologueAE)>(target);
|
||||
|
||||
logger::info("Applied menu aspect ratio fix");
|
||||
logger::info("Applied menu aspect ratio fix{}", g_restoreScaleModes ? "" : " (viewport clamp only)");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user