#define NOMINMAX #define IMGUI_DISABLE_INCLUDE_IMCONFIG_H #define IMGUI_HAS_DOCK 1 #include "CommonHeaders.h" #include "HotkeysManager.h" #include "OSDManager.h" #include #include // std::min // Screen informations static uint32_t g_width = 0; static uint32_t g_height = 0; // Core game dll functions declarations typedef void (*SetFixesFn)(GameFixes, bool); typedef void (*SetBoolFn)(bool, bool); typedef void (*SetIntFn)(int); typedef void (*SetFloatFn)(float); static HMODULE fixLib = nullptr; static LONG g_coreInitialized = 0; static LONG g_hotkeysInitialized = 0; static LONG g_uniformReseted = 0; static SetBoolFn SetFixEnabled = nullptr; static SetFixesFn SetFixes = nullptr; static SetIntFn SetFOV = nullptr; static SetFloatFn SetCameraDistance = nullptr; static SetFloatFn SetFogDensity = nullptr; static SetFloatFn SetFogMaxOpacity = nullptr; static SetFloatFn SetWorldTimeDilation = nullptr; static SetFloatFn SetAITimeDilation = nullptr; static GetGameInfosStruct GetGameInfos = nullptr; void SetFixesEnabled(GameFixes fix, bool value) { if (SetFixes) SetFixes(fix, value); } // Plugin variables for checkboxes and sliders static bool skip_Intro_enabled = true; static bool fov_fix_enabled = false; static bool DOF_fix_enabled = false; static bool CA_fix_enabled = false; static bool Vignetting_fix_enabled = false; static bool camera_fix_enabled = false; static bool cutscenes_fix_enabled = false; static bool cutscenes_FPS_fix_enabled = false; static bool volumetric_fog_fix_enabled = false; static bool Fog_fix_enabled = false; static bool fix_enabled = false; static bool Time_Dilation_fix_enabled = false; static bool StealthMode_fix_enabled; static int worldFOVvalue = 0; static float cameraDistanceValue = 1.f; static float fogDensityValue = 0.1f; static float fogMaxOpacityValue = 1.f; static float worldTimeDilationValue = 1.f; static float AITimeDilationValue = 1.f; static bool console = true; static float OSD_duration = 3.f; // Overlays popups static bool popup_Informations = false; static bool show_log_overlay = false; static std::string log_content; // Plugin settings const std::string SETTINGS_FILE = "./pluginsettings.ini"; const char* FIX_VERSION = "1.0.4"; const char* FIX_INFORMATIONS = "This fix allows to:\n - Control FOV in game.\n - Control camera distance.\n - Unlock cutscenes FPS and enable ultrawide.\n - Enable cheats.\n - Disable depth of field.\n - Disable chromatic aberrations.\n - Disable vignetting.\n - Control fog.\n - Re enable console."; const char* DONATION_URL = "https://buymeacoffee.com/k4sh44"; // Prepare arrays of checkboxes for ImGui static FixToggle individualFixes[] = { { "FOV", &fov_fix_enabled, GameFixes::FOV }, { "Cutscenes", &cutscenes_fix_enabled, GameFixes::Cutscenes, "Remove black bars"}, { "Vignetting", &Vignetting_fix_enabled, GameFixes::Vignetting }, { "Fog", &Fog_fix_enabled, GameFixes::Fog }, { "Camera", &camera_fix_enabled, GameFixes::Camera }, { "Cutscenes FPS", &cutscenes_FPS_fix_enabled, GameFixes::Framerate, "Unlock cutscenes up to 240 FPS"}, { "Depth of field", &DOF_fix_enabled, GameFixes::DOF }, { "Chromatic aberrations", &CA_fix_enabled, GameFixes::ChromaticAberrations }, { "Volumetric fog", &volumetric_fog_fix_enabled, GameFixes::VolumetricFog } }; static FixToggle cheatFixes[] = { { "Time dilation", &Time_Dilation_fix_enabled, GameFixes::TimeDilation, "ALT + 1 (top keyboard row) to toggle" }, { "Stealth mode", &StealthMode_fix_enabled, GameFixes::Stealth, "ALT + 2 (top keyboard row) to toggle." }, }; // Prepare array of sliders for ImGui static SliderFix sliders[6]; // Load and unload game core dll functions /!\ necessary static void LoadFixDLL() { if (InterlockedCompareExchange(&g_coreInitialized, 1, 0) != 0) return; if (GetModuleHandleA("SilentHillfCore.dll") == nullptr) { fixLib = LoadLibraryA("SilentHillfCore.dll"); if (!fixLib) { MessageBoxA(nullptr, "Impossible to load game core dll", "Erreur", MB_OK); return; } SetFixEnabled = (SetBoolFn)GetProcAddress(fixLib, "SetFixEnabled"); SetFixes = (SetFixesFn)GetProcAddress(fixLib, "SetFixesEnabled"); SetFOV = (SetIntFn)GetProcAddress(fixLib, "SetFOV"); SetCameraDistance = (SetFloatFn)GetProcAddress(fixLib, "SetCameraDistance"); SetFogDensity = (SetFloatFn)GetProcAddress(fixLib,"SetFogDensity"); SetFogMaxOpacity = (SetFloatFn)GetProcAddress(fixLib, "SetFogMaxOpacity"); SetWorldTimeDilation = (SetFloatFn)GetProcAddress(fixLib, "SetWorldTimeDilation"); SetAITimeDilation = (SetFloatFn)GetProcAddress(fixLib, "SetAITimeDilation"); GetGameInfos = (GetGameInfosStruct)GetProcAddress(fixLib, "GetGameInfos"); // Apply initial values loaded from settings if (SetFOV) SetFOV(worldFOVvalue); if (SetCameraDistance) SetCameraDistance(cameraDistanceValue); if (SetFogDensity) SetFogDensity(fogDensityValue); if (SetFogMaxOpacity) SetFogMaxOpacity(fogMaxOpacityValue); if (SetWorldTimeDilation) SetWorldTimeDilation(worldTimeDilationValue); if (SetAITimeDilation) SetAITimeDilation(AITimeDilationValue); if (SetFixEnabled) SetFixEnabled(fix_enabled, true); if (SetFixes) { SetFixes(GameFixes::SkipIntro, skip_Intro_enabled); SetFixes(GameFixes::FOV, fov_fix_enabled); SetFixes(GameFixes::Camera, camera_fix_enabled); SetFixes(GameFixes::Cutscenes, cutscenes_fix_enabled); SetFixes(GameFixes::Framerate, cutscenes_FPS_fix_enabled); SetFixes(GameFixes::DOF, DOF_fix_enabled); SetFixes(GameFixes::ChromaticAberrations, CA_fix_enabled); SetFixes(GameFixes::Vignetting, Vignetting_fix_enabled); SetFixes(GameFixes::VolumetricFog, volumetric_fog_fix_enabled); SetFixes(GameFixes::Fog, Fog_fix_enabled); SetFixes(GameFixes::TimeDilation, Time_Dilation_fix_enabled); SetFixes(GameFixes::Stealth, StealthMode_fix_enabled); SetFixes(GameFixes::DevConsole, console); } // Declare sliders only when function pointers are initilized (SetFOV ...) sliders[0] = { "In game additional FOV", "##FOVValue", SliderType::Int, &worldFOVvalue, -20, 50, SetFOV }; sliders[1] = { "Camera distance (*)", "##CameraOffset", SliderType::Float, &cameraDistanceValue, 0, 3, SetCameraDistance, "%.2f", "Value is a multiplier."}; sliders[2] = { "Fog density (*)", "##FogDensityValue", SliderType::Float, &fogDensityValue, 0, 5, SetFogDensity, "%.2f", "This will override engine dynamic value." }; sliders[3] = { "Fog opacity (*)", "##CameraSmoothnessValue", SliderType::Float, &fogMaxOpacityValue, 0, 1, SetFogMaxOpacity, "%.2f", "This will override engine dynamic value." }; sliders[4] = { "World time dilation", "##WorldTimeDilationValue", SliderType::Float, &worldTimeDilationValue, 0.f, 2.f, SetWorldTimeDilation, nullptr, "Will affect everything in the world.\nDefault value is 1." }; sliders[5] = { "AI time dilation", "##AITimeDilationValue", SliderType::Float, &AITimeDilationValue, 0.f, 2.f, SetAITimeDilation, nullptr, "Will affect only enemies in the world.\nDefault value is 1." }; } } // Settings functions static void SaveSettings() { ini::IniFile pluginIniFile; pluginIniFile["1#General fix"].setComment(std::vector{ "The following sections are saved by plugin", "You should not need to modify them", " ", "Controls if fix mod (globally) is enabled", "Set Console to false if you don't want dev console to be enabled", "Set Skip Intro to false if you don't wan't to skip them."}); pluginIniFile["1#General fix"]["Console"] = console; pluginIniFile["1#General fix"]["Enabled"] = fix_enabled; pluginIniFile["1#General fix"]["Skip Intro"] = skip_Intro_enabled; pluginIniFile["2#Individual fix"].setComment("Controls each fix individually"); pluginIniFile["2#Individual fix"]["FOV"] = fov_fix_enabled; pluginIniFile["2#Individual fix"]["Camera"] = camera_fix_enabled; pluginIniFile["2#Individual fix"]["Cutscenes"] = cutscenes_fix_enabled; pluginIniFile["2#Individual fix"]["CutscenesFPS"] = cutscenes_FPS_fix_enabled; pluginIniFile["2#Individual fix"]["DOF"] = DOF_fix_enabled; pluginIniFile["2#Individual fix"]["Chromatic aberrations"] = CA_fix_enabled; pluginIniFile["2#Individual fix"]["Vignetting"] = Vignetting_fix_enabled; pluginIniFile["2#Individual fix"]["Volumetric fog"] = volumetric_fog_fix_enabled; pluginIniFile["2#Individual fix"]["Fog"] = Fog_fix_enabled; pluginIniFile["2#Individual fix"]["Time dilation"] = Time_Dilation_fix_enabled; pluginIniFile["2#Individual fix"]["Stealth Mode"] = StealthMode_fix_enabled; pluginIniFile["3#Fixes tuning"].setComment("Individual fix fine tune"); pluginIniFile["3#Fixes tuning"]["World FOV"] = worldFOVvalue; pluginIniFile["3#Fixes tuning"]["Camera distance"] = cameraDistanceValue; pluginIniFile["3#Fixes tuning"]["Fog density"] = fogDensityValue; pluginIniFile["3#Fixes tuning"]["Fog opacity"] = fogMaxOpacityValue; pluginIniFile["3#Fixes tuning"]["World time dilation scale"] = worldTimeDilationValue; pluginIniFile["3#Fixes tuning"]["AI time dilation scale"] = AITimeDilationValue; pluginIniFile.save(SETTINGS_FILE); } static void LoadSettings() { ini::IniFile pluginIniFile; try { pluginIniFile.load(SETTINGS_FILE); console = pluginIniFile["1#General fix"]["Console"].as(); fix_enabled = pluginIniFile["1#General fix"]["Enabled"].as(); skip_Intro_enabled = pluginIniFile["1#General fix"]["Skip Intro"].as(); fov_fix_enabled = pluginIniFile["2#Individual fix"]["FOV"].as(); camera_fix_enabled = pluginIniFile["2#Individual fix"]["Camera"].as(); cutscenes_fix_enabled = pluginIniFile["2#Individual fix"]["Cutscenes"].as(); cutscenes_FPS_fix_enabled = pluginIniFile["2#Individual fix"]["CutscenesFPS"].as(); DOF_fix_enabled = pluginIniFile["2#Individual fix"]["DOF"].as(); CA_fix_enabled = pluginIniFile["2#Individual fix"]["Chromatic aberrations"].as(); Vignetting_fix_enabled = pluginIniFile["2#Individual fix"]["Vignetting"].as(); volumetric_fog_fix_enabled = pluginIniFile["2#Individual fix"]["Volumetric fog"].as(); Fog_fix_enabled = pluginIniFile["2#Individual fix"]["Fog"].as(); Time_Dilation_fix_enabled = pluginIniFile["2#Individual fix"]["Time dilation"].as(); StealthMode_fix_enabled = pluginIniFile["2#Individual fix"]["Stealth Mode"].as(); worldFOVvalue = pluginIniFile["3#Fixes tuning"]["World FOV"].as(); cameraDistanceValue = pluginIniFile["3#Fixes tuning"]["Camera distance"].as(); fogDensityValue = pluginIniFile["3#Fixes tuning"]["Fog density"].as(); fogMaxOpacityValue = pluginIniFile["3#Fixes tuning"]["Fog opacity"].as(); worldTimeDilationValue = pluginIniFile["3#Fixes tuning"]["World time dilation scale"].as(); AITimeDilationValue = pluginIniFile["3#Fixes tuning"]["AI time dilation scale"].as(); } catch (const std::exception& e) {} } // Read plugin log file static std::string read_log_file(const std::string& filename) { std::ifstream file(filename); std::string log; if (!file.is_open()) { log = "Impossible to open file : " + filename; return log; } std::ostringstream ss; ss << file.rdbuf(); log = ss.str(); return log; } // Reshade event callback functions static void on_init_swapchain(reshade::api::swapchain* swapchain, bool resize) { reshade::api::resource backbuffer = swapchain->get_current_back_buffer(); if (backbuffer != 0) { reshade::api::device* device = swapchain->get_device(); reshade::api::resource_desc desc = device->get_resource_desc(backbuffer); g_width = desc.texture.width; g_height = desc.texture.height; } } // Initialize ImGui widgets for Reshade static void on_overlay_draw(reshade::api::effect_runtime* runtime) { using namespace ImGui; float aspectRatio = (float)g_width / g_height; // Scaling factor based on screen resolution float scale = std::min((float)g_height / 1200,1.f); ImGuiStyle& style = GetStyle(); style.ItemSpacing = ImVec2(8 * scale, 8 * scale); // Spacing between widgets style.FramePadding = ImVec2(3 * scale, 3 * scale); // Widgets padding style.WindowPadding = ImVec2(10 * scale, 10 * scale); // Overlay padding style.CellPadding = ImVec2(10 * scale, 10 * scale); // Table cells padding SetNextWindowSize(ImVec2(350 * scale, 150 * scale), ImGuiCond_Once); PushStyleColor(ImGuiCol_Button, ImVec4(0.84f, 0.12f, 0.51f, 1.0f)); // red PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.84f, 0.12f, 0.51f, 1.0f)); // red PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.84f, 0.2f, 0.51f, 1.0f)); // red PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 1.f, 1.f, 1.f)); // white if (Button("Like my work ? Consider donation")) ShellExecuteA(NULL, "open", DONATION_URL, NULL, NULL, SW_SHOWNORMAL); // Donation PopStyleColor(4); // Restore color SameLine(); if (Button("Fix informations")) popup_Informations = true; // Fix information SameLine(); if (Button("View logs")) { log_content = read_log_file("SilentHillf.log"); show_log_overlay = true; // Fix information } if (popup_Informations) { Begin("Informations", &popup_Informations, ImGuiWindowFlags_AlwaysAutoResize); Text("Version : %s", FIX_VERSION); Text(FIX_INFORMATIONS); End(); } if (show_log_overlay) { Begin("Game log", &show_log_overlay, ImGuiWindowFlags_AlwaysAutoResize); TextUnformatted(log_content.c_str()); End(); } if (BeginTabBar("MainTabs")) { if (BeginTabItem("Fixes")) { if (BeginTable("FixesTable", 2, ImGuiTableFlags_SizingStretchSame)) { TableSetupColumn("LeftFix", ImGuiTableColumnFlags_WidthStretch, 0.3f); TableSetupColumn("RightFix", ImGuiTableColumnFlags_WidthStretch, 0.7f); TableNextRow(); // Drawing a left column with slider and general fix TableSetColumnIndex(0); if (CollapsingHeader("Enable fixes", ImGuiTreeNodeFlags_DefaultOpen)) if (Checkbox("Fix enabled", &fix_enabled)) { if (SetFixEnabled) SetFixEnabled(fix_enabled, false); SaveSettings(); } // Individual fixes TableSetColumnIndex(1); if (CollapsingHeader("Individual fixes", ImGuiTreeNodeFlags_DefaultOpen)) { if (BeginTable("IndividualFixesTable", 2, ImGuiTableFlags_SizingStretchSame)) { TableSetupColumn("IndFix1", ImGuiTableColumnFlags_WidthStretch, 0.35f); TableSetupColumn("IndFix2", ImGuiTableColumnFlags_WidthStretch, 0.65f); TableNextRow(); TableSetColumnIndex(0); for (int i = 0; i < 4; ++i) DrawFixCheckbox(individualFixes[i]); TableSetColumnIndex(1); for (int i = 4; i < IM_ARRAYSIZE(individualFixes); ++i) DrawFixCheckbox(individualFixes[i]); EndTable(); } } EndTable(); } SetCursorPosY(GetCursorPosY() - 2 * style.ItemSpacing.y); if (BeginTable("FixesSliders", 2, ImGuiTableFlags_SizingStretchSame)) { TableNextRow(); // Sliders TableSetColumnIndex(0); for (int i = 0; i < 2; ++i) DrawSlider(sliders[i], 200); TableSetColumnIndex(1); for (int i = 2; i < 4; ++i) DrawSlider(sliders[i], 200); EndTable(); } EndTabItem(); } if (BeginTabItem("Cheats")){ for (const auto& cheat : cheatFixes) DrawFixCheckbox(cheat); if (BeginTable("SlidersTable", 2, ImGuiTableFlags_SizingStretchSame)) { TableSetupColumn("LeftSliders", ImGuiTableColumnFlags_WidthStretch, 0.5f); TableSetupColumn("RightSliders", ImGuiTableColumnFlags_WidthStretch, 0.5f); TableNextRow(); TableSetColumnIndex(0); DrawSlider(sliders[4], 180); TableSetColumnIndex(1); DrawSlider(sliders[5], 180); EndTable(); } EndTabItem(); } EndTabBar(); // Fix status if (CollapsingHeader("Fix informations", ImGuiTreeNodeFlags_DefaultOpen)) { Text("Screen width: %d, height: %d, aspect ratio: %.2f", g_width, g_height, aspectRatio); if (GetGameInfos) { GameInfos infos{}; GetGameInfos(&infos); if (infos.consoleEnabled) Text("Console enabled and bound to key F2"); TextColored(ImColor(48, 179, 25), "FOV In: %.2f, Out: %.2f", infos.FOVIn, infos.FOVOut); TextColored(ImColor(48, 179, 25), "Camera distance In: %.2f, Out: %.2f", infos.cameraIn, infos.cameraOut); TextColored(ImColor(48, 179, 25), "Default fog density: %.3f, opacity: %3.f", infos.defaultFogDensity, infos.fogMaxOpacity); } } } } static void on_reshade_present(reshade::api::effect_runtime* runtime) { static auto last = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now(); float dt = std::chrono::duration(now - last).count(); last = now; ProcessHotkeys(runtime); UpdateOSD(runtime, dt); } // Retrieve all shader uniform variables static void on_reshade_begin_effects(reshade::api::effect_runtime* runtime, reshade::api::command_list* cmd_list, reshade::api::resource_view rtv, reshade::api::resource_view rtv_srgb) { if (!runtime) return; FindAllUniformVariables(runtime, OSD_SHADER_NAME); // Find all uniforms and set their handle if (InterlockedCompareExchange(&g_uniformReseted, 1, 0) != 0) return; // reset OSD uniforms once ResetAllUniformVariables(runtime, OSD_SHADER_NAME); runtime->save_current_preset(); // Save shader preset } static void InitializeHotkeys() { // Initialize hotkeys for cheats if (InterlockedCompareExchange(&g_hotkeysInitialized, 1, 0) != 0) return; // Initialize hotkeys once RegisterHotkey('1', Modifier::Alt, [] { ToggleOSD(Time_Dilation_fix_enabled, GameFixes::TimeDilation, u_td_show, u_td_enabled, OSD_duration, { {u_td_world, worldTimeDilationValue}, {u_td_AI, AITimeDilationValue} }); }); RegisterHotkey('2', Modifier::Alt, [] { ToggleOSD(StealthMode_fix_enabled, GameFixes::Stealth, u_Stealth_show, u_Stealth_enabled, OSD_duration); }); } // Main dll intrance BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: if (!reshade::register_addon(hinstDLL)) return FALSE; LoadSettings(); reshade::register_overlay("Silent Hill f", &on_overlay_draw); reshade::register_event(on_init_swapchain); reshade::register_event( [](reshade::api::effect_runtime* runtime) { LoadFixDLL(); InitializeHotkeys(); }); reshade::register_event(&on_reshade_present); reshade::register_event(&on_reshade_begin_effects); break; case DLL_PROCESS_DETACH: reshade::unregister_event(&on_reshade_present); reshade::unregister_event(&on_reshade_begin_effects); reshade::unregister_event(on_init_swapchain); reshade::unregister_addon(hinstDLL); break; } return TRUE; }