Updated CommonLibSSE, added GOG VRAM Leak Fix by DwemerEngineer

This commit is contained in:
Eddoursul 2026-01-19 04:42:24 +01:00
parent 3fe7fb62ac
commit 7692789c38
9 changed files with 82 additions and 23 deletions

View File

@ -11,6 +11,11 @@ Beware, spoilers ahead!
- Removed the Blueprint keyword from the Dreamflower Elixir Recipe to avoid sorting it into the blueprint storage (reported by Fubz).
- Fixed an exploit allowing to collect more gold from containers (reported by LevinLozenges).
Engine patches:
- Automatically detects and warns about form type collisions when using Skyrim mods.
- `Enderal - Forgotten Stories.esm` is always force-loaded.
- Included GOG Memory (VRAM) Leak Fix by DwemerEngineer.
Lirk:
- Fixed several issues with weapon impact sounds.
- Fixed normals in agnodwall.nif.

View File

@ -8,3 +8,4 @@ ForceBorderless = true
AttachLightHitEffectCrashFix = true
AutoScaleHeroMenu = true
WarnFormTypeCollisions = true
GogVramLeakFix = true

View File

@ -80,7 +80,7 @@ add_library("Microsoft::DirectXTK" ALIAS "DirectXTK")
# simpleini
FetchContent_Declare(
simpleini
URL "https://github.com/brofield/simpleini/archive/refs/tags/v4.22.tar.gz"
URL "https://github.com/brofield/simpleini/archive/refs/tags/v4.25.tar.gz"
DOWNLOAD_EXTRACT_TIMESTAMP 1
)
FetchContent_MakeAvailable(simpleini)
@ -89,7 +89,7 @@ INCLUDE_DIRECTORIES(${simpleini_SOURCE_DIR})
# rapidcsv
FetchContent_Declare(
rapidcsv
URL "https://github.com/d99kris/rapidcsv/archive/refs/tags/v8.87.tar.gz"
URL "https://github.com/d99kris/rapidcsv/archive/refs/tags/v8.90.tar.gz"
DOWNLOAD_EXTRACT_TIMESTAMP 1
OVERRIDE_FIND_PACKAGE
)
@ -97,11 +97,11 @@ FetchContent_MakeAvailable(rapidcsv)
set(RAPIDCSV_INCLUDE_DIRS ${rapidcsv_SOURCE_DIR}/src)
# spdlog
set(SPDLOG_INSTALL ON CACHE INTERNAL "Install SPDLOG for CommonLibSSE")
set(SPDLOG_USE_STD_FORMAT ON CACHE INTERNAL "Use std::format in SPDLOG, not fmt")
set(SPDLOG_INSTALL ON CACHE BOOL " " FORCE)
set(SPDLOG_USE_STD_FORMAT ON CACHE BOOL " " FORCE)
FetchContent_Declare(
spdlog
URL "https://github.com/gabime/spdlog/archive/refs/tags/v1.15.3.tar.gz"
URL "https://github.com/gabime/spdlog/archive/refs/tags/v1.17.0.tar.gz"
DOWNLOAD_EXTRACT_TIMESTAMP 1
OVERRIDE_FIND_PACKAGE
)
@ -110,7 +110,7 @@ FetchContent_MakeAvailable(spdlog)
# xbyak
FetchContent_Declare(
xbyak
URL "https://github.com/herumi/xbyak/archive/v7.28.tar.gz"
URL "https://github.com/herumi/xbyak/archive/v7.30.tar.gz"
DOWNLOAD_EXTRACT_TIMESTAMP 1
)
FetchContent_MakeAvailable(xbyak)
@ -121,11 +121,11 @@ set(ENABLE_SKYRIM_SE ON CACHE BOOL " " FORCE)
set(ENABLE_SKYRIM_AE ON CACHE BOOL " " FORCE)
set(ENABLE_SKYRIM_VR ON CACHE BOOL " " FORCE)
set(BUILD_TESTS OFF CACHE BOOL " " FORCE)
message(STATUS "Fetching CommonLibSSE-NG (5e5417e3585c9434295e919bdda27737244e9c5a)...")
message(STATUS "Fetching CommonLibSSE-NG...")
FetchContent_Declare(
CommonLibSSE
GIT_REPOSITORY https://github.com/eddoursul/CommonLibVR.git
GIT_TAG 5e5417e3585c9434295e919bdda27737244e9c5a
GIT_REPOSITORY https://github.com/alandtse/CommonLibVR
GIT_TAG aacbd76c01bff9381e253ffdfcb4f9d5f263f1df
)
FetchContent_MakeAvailable(CommonLibSSE)

BIN
source/Enderal DLL/LICENSE (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -15,6 +15,7 @@
#include "Patches/AttachLightHitEffectCrash.h"
#include "Patches/PluginsTxtPatch.h"
#include "Patches/FormTypeCollisionDetector.h"
#include "Patches/GogVramLeakFix.h"
using namespace SKSE;
@ -28,7 +29,8 @@ static std::map<std::string, bool> g_settings{
{ "VideoInterruptPatch", true },
{ "ForceBorderless", true },
{ "AttachLightHitEffectCrashFix", true },
{ "AutoScaleHeroMenu", true }
{ "AutoScaleHeroMenu", true },
{ "GogVramLeakFix", true }
};
namespace {
@ -69,6 +71,11 @@ namespace {
if (message->type == MessagingInterface::kPostLoad) {
if (!REL::Module::IsVR()) {
if (g_settings.at("GogVramLeakFix") && REL::Module::get().version() == REL::Version(1, 6, 1179, 0) && !GetLoadInterface()->GetPluginInfo("GOG-Leak-Fix")) {
logger::info("Installing GOG VRAM leak fix...");
GogVramLeakFix::Install();
}
if (g_settings.at("AttachLightHitEffectCrashFix")) {
logger::info("Installing light attach crash fix...");
AttachLightHitEffectCrash::Install();
@ -188,12 +195,15 @@ SKSEPluginLoad(const LoadInterface* skse) {
auto* plugin = PluginDeclaration::GetSingleton();
auto version = plugin->GetVersion();
logger::info("{} {} ({}) is loading...", plugin->GetName(), version, SemVerToInt({ version.major(), version.minor(), version.patch(), version.build() }));
auto versionStr = version.build() > 0
? std::format("{}.{}.{}.{}", version.major(), version.minor(), version.patch(), version.build())
: std::format("{}.{}.{}", version.major(), version.minor(), version.patch());
logger::info("{} {} ({}) is loading...", plugin->GetName(), versionStr, SemVerToInt(version.major(), version.minor(), version.patch(), version.build()));
Init(skse);
Init(skse, false);
InitializeMessaging();
if (g_settings.at("WarnFormTypeCollisions")) {
if (g_settings.at("WarnFormTypeCollisions") && !!REL::Module::IsVR()) {
FormTypeCollisionDetector::Install();
}

View File

@ -1,5 +1,7 @@
#pragma once
#define SPDLOG_COMPILED_LIB
#include <RE/Skyrim.h>
#include <SKSE/SKSE.h>
#include <REL/Relocation.h>
@ -28,4 +30,11 @@ namespace SKSE::stl
{
asm_replace(a_from, a_size, reinterpret_cast<std::uintptr_t>(T::func));
}
template <class T, std::size_t N = 5>
void write_thunk_jump(std::uintptr_t a_src)
{
auto& trampoline = SKSE::GetTrampoline();
T::func = trampoline.write_branch<N>(a_src, T::thunk);
}
}

View File

@ -59,7 +59,7 @@ namespace Papyrus::PapyrusFunctions
{
const auto pluginVersion = SKSE::PluginDeclaration::GetSingleton()->GetVersion();
return SemVerToInt({ pluginVersion.major(), pluginVersion.minor(), pluginVersion.patch(), pluginVersion.build() });
return SemVerToInt(pluginVersion.major(), pluginVersion.minor(), pluginVersion.patch(), pluginVersion.build());
}
inline RE::TESObjectREFR* GetCurrentContainer(RE::StaticFunctionTag*)

View File

@ -0,0 +1,36 @@
#pragma once
// Fix GOG VRAM leak by properly releasing Direct3D texture resources
// Based on https://github.com/SaneEngineer/GOG-Leak-Fix
namespace GogVramLeakFix
{
struct ReplaceRelease
{
static void thunk(RE::BSGraphics::Renderer* a_renderer, RE::BSGraphics::Texture* a_texture)
{
if (_InterlockedExchangeAdd(&a_texture->unk20, 0xFFFFFFFF) == 1) {
if (a_texture->resourceView) {
a_texture->resourceView->Release();
}
if (a_texture->texture) {
a_texture->texture->Release();
}
if (a_texture->unk08) {
reinterpret_cast<ID3D11UnorderedAccessView*>(a_texture->unk08)->Release();
}
REL::Relocation<void(void*, int)> NiMemFree{ REL::RelocationID(102158, 109588) };
NiMemFree(a_texture, 0x28);
}
}
static inline REL::Relocation<decltype(thunk)> func;
};
void Install()
{
SKSE::AllocTrampoline(14);
SKSE::stl::write_thunk_jump<ReplaceRelease>(REL::RelocationID(75527, 77322).address());
logger::info("Initialized GOG VRAM Leak Fix");
}
}

View File

@ -23,14 +23,9 @@ inline uint8_t NewGameCount(bool increment = false)
return g_NewGameStarted;
}
inline std::uint32_t SemVerToInt(std::vector<int> numbers)
inline std::uint32_t SemVerToInt(std::uint16_t major, std::uint16_t minor, std::uint16_t patch, std::uint16_t build)
{
if (numbers.size() < 4) {
logger::error("Invalid SemVerToInt argument");
return 0;
}
return (numbers[0] << 24) | (numbers[1] << 16) | (numbers[2] << 8) | numbers[3];
return (static_cast<std::uint32_t>(major) << 24) | (static_cast<std::uint32_t>(minor) << 16) | (static_cast<std::uint32_t>(patch) << 8) | static_cast<std::uint32_t>(build);
}
inline void CheckIncompatibleMods()
@ -311,10 +306,10 @@ inline RE::BSFixedString GetPlayerHash()
{
char buf[] = "DEADBEEF";
auto saveData = RE::BSWin32SaveDataSystemUtility::GetSingleton();
if (saveData->profileHash == static_cast<std::uint32_t>(-1)) {
if (saveData->currentCharacterID == static_cast<std::uint32_t>(-1)) {
std::snprintf(buf, sizeof(buf), "%08o", 0);
} else {
std::snprintf(buf, sizeof(buf), "%08X", saveData->profileHash);
std::snprintf(buf, sizeof(buf), "%08X", saveData->currentCharacterID);
}
return buf;
}