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...");
|
logger::info("Initializing Stay At The System Page...");
|
||||||
JournalMenuEx::InstallHooks();
|
JournalMenuEx::InstallHooks();
|
||||||
}
|
}
|
||||||
// Menus are only stretched to fill the viewport since 1.6.1130
|
if (g_settings.at("MenuAspectRatioFix")) {
|
||||||
if (g_settings.at("MenuAspectRatioFix") && REL::Module::get().version() >= REL::Version(1, 6, 1130, 0)) {
|
|
||||||
MenuAspectRatioFix::Install();
|
MenuAspectRatioFix::Install();
|
||||||
}
|
}
|
||||||
LoadScreenFrameFix::Install(g_settings.at("LoadScreenFrameFix"));
|
LoadScreenFrameFix::Install(g_settings.at("LoadScreenFrameFix"));
|
||||||
|
|||||||
@ -1,17 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Restores the Scaleform scale modes menus were loaded with before Skyrim 1.6.1130, and stops
|
// Two independent corrections to the Scaleform scale mode menus are loaded with, both applied
|
||||||
// kNoBorder from cropping them on displays wider than 16:9.
|
// from the same BSScaleformManager::LoadMovie hook:
|
||||||
//
|
//
|
||||||
// 1.6.1130 switched nearly every menu to kExactFit, which stretches the movie across the whole
|
// 1. Restore the modes used before 1.6.1130. That build switched nearly every menu to
|
||||||
// viewport instead of preserving its aspect ratio. Enderal's menus - including the SkyUI-derived
|
// kExactFit, which stretches the movie across the whole viewport instead of preserving its
|
||||||
// widescreen versions shipped with them - are authored for the old modes, so on anything that is
|
// aspect ratio. Enderal's menus - including the SkyUI-derived widescreen versions shipped
|
||||||
// not 16:9 they come out distorted.
|
// 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
|
// The table below is what 1.6.640 passes to LoadMovie, plus BookMenu and GiftMenu, which 1.6.1130
|
||||||
// GiftMenu, which 1.6.1130 left on kNoBorder and which need the same clamp. Menus that want no
|
// left on kNoBorder and which need the clamp. Menus that want no help (Book, Console, CreditsMenu,
|
||||||
// help (Book, Console, CreditsMenu, CursorMenu, FaderMenu, StartMenu) are absent and keep
|
// CursorMenu, FaderMenu, StartMenu) are absent and keep whatever the caller asked for. It doubles
|
||||||
// whatever the caller asked for.
|
// 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)
|
// Based on Widescreen Scale Removed by SkyHorizon (GPL-3.0)
|
||||||
// https://www.nexusmods.com/skyrimspecialedition/mods/136793
|
// https://www.nexusmods.com/skyrimspecialedition/mods/136793
|
||||||
@ -19,6 +23,10 @@ namespace MenuAspectRatioFix
|
|||||||
{
|
{
|
||||||
using ScaleModeType = RE::GFxMovieView::ScaleModeType;
|
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)
|
std::optional<ScaleModeType> GetScaleMode(const char* a_fileName)
|
||||||
{
|
{
|
||||||
static const std::map<std::string_view, ScaleModeType> modes{
|
static const std::map<std::string_view, ScaleModeType> modes{
|
||||||
@ -88,7 +96,7 @@ namespace MenuAspectRatioFix
|
|||||||
{
|
{
|
||||||
if (a_fileName && a_fileName[0]) {
|
if (a_fileName && a_fileName[0]) {
|
||||||
if (const auto mode = GetScaleMode(a_fileName); mode) {
|
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()
|
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();
|
const auto target = REL::RelocationID(80302, 82325).address();
|
||||||
|
|
||||||
// mov rax,rsp / mov qword ptr [rax+10h],rdx - relocated into the trampoline by the hook,
|
// mov rax,rsp followed by one argument spill - 7 bytes of position-independent code, which
|
||||||
// so bail out rather than corrupt the function if a future runtime changes the prologue
|
// the hook relocates into the trampoline. The spilled argument differs between the runtime
|
||||||
constexpr std::uint8_t prologue[]{ 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x50, 0x10 };
|
// 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");
|
logger::error("Unexpected BSScaleformManager::LoadMovie prologue, menu aspect ratio fix is disabled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SKSE::AllocTrampoline(64);
|
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