diff --git a/Common/AutoUpdate.cpp b/Common/AutoUpdate.cpp
index 26149c77..dcbffd04 100644
--- a/Common/AutoUpdate.cpp
+++ b/Common/AutoUpdate.cpp
@@ -295,7 +295,9 @@ bool NewProjectReleaseAvailable(std::string &path_str)
 		}
 
 		if (IsProjectUpdateAvailable)
+		{
 			return true;
+		}
 	}
 
 	return false;
diff --git a/Common/FileSystemHooks.cpp b/Common/FileSystemHooks.cpp
index 46a3bf5a..91ecefd9 100644
--- a/Common/FileSystemHooks.cpp
+++ b/Common/FileSystemHooks.cpp
@@ -137,10 +137,10 @@ inline bool isInString(LPCWSTR strCheck, LPCSTR, LPCWSTR strW, size_t size)
 template<typename T>
 inline bool isDataPath(T sh2)
 {
-	if ((sh2[0] == 'd' || sh2[0] == 'D') &&
-		(sh2[1] == 'a' || sh2[1] == 'A') &&
-		(sh2[2] == 't' || sh2[2] == 'T') &&
-		(sh2[3] == 'a' || sh2[3] == 'A'))
+	if (sh2[0] != '\0' && (sh2[0] == 'd' || sh2[0] == 'D') &&
+		sh2[1] != '\0' && (sh2[1] == 'a' || sh2[1] == 'A') &&
+		sh2[2] != '\0' && (sh2[2] == 't' || sh2[2] == 'T') &&
+		sh2[3] != '\0' && (sh2[3] == 'a' || sh2[3] == 'A'))
 	{
 		return true;
 	}
@@ -150,34 +150,38 @@ inline bool isDataPath(T sh2)
 template<typename T>
 inline bool isEndVideoPath(T sh2)
 {
-	if ((sh2[0] == 'm' || sh2[0] == 'M') &&
-		(sh2[1] == 'o' || sh2[1] == 'O') &&
-		(sh2[2] == 'v' || sh2[2] == 'V') &&
-		(sh2[3] == 'i' || sh2[3] == 'I') &&
-		(sh2[4] == 'e' || sh2[4] == 'E') &&
-		(sh2[6] == 'e' || sh2[6] == 'E') &&
-		(sh2[7] == 'n' || sh2[7] == 'N') &&
-		(sh2[8] == 'd' || sh2[8] == 'D') &&
-		(sh2[9] == 'i' || sh2[9] == 'I') &&
-		(sh2[10] == 'n' || sh2[10] == 'N') &&
-		(sh2[11] == 'g' || sh2[11] == 'G') &&
-		(sh2[13] == 'b' || sh2[13] == 'B') &&
-		(sh2[14] == 'i' || sh2[14] == 'I') &&
-		(sh2[15] == 'k' || sh2[15] == 'K'))
+	if (sh2[0] != '\0' && (sh2[0] == 'm' || sh2[0] == 'M') &&
+		sh2[1] != '\0' && (sh2[1] == 'o' || sh2[1] == 'O') &&
+		sh2[2] != '\0' && (sh2[2] == 'v' || sh2[2] == 'V') &&
+		sh2[3] != '\0' && (sh2[3] == 'i' || sh2[3] == 'I') &&
+		sh2[4] != '\0' && (sh2[4] == 'e' || sh2[4] == 'E') &&
+		sh2[5] != '\0' &&
+		sh2[6] != '\0' && (sh2[6] == 'e' || sh2[6] == 'E') &&
+		sh2[7] != '\0' && (sh2[7] == 'n' || sh2[7] == 'N') &&
+		sh2[8] != '\0' && (sh2[8] == 'd' || sh2[8] == 'D') &&
+		sh2[9] != '\0' && (sh2[9] == 'i' || sh2[9] == 'I') &&
+		sh2[10] != '\0' && (sh2[10] == 'n' || sh2[10] == 'N') &&
+		sh2[11] != '\0' && (sh2[11] == 'g' || sh2[11] == 'G') &&
+		sh2[12] != '\0' &&
+		sh2[13] != '\0' && (sh2[13] == 'b' || sh2[13] == 'B') &&
+		sh2[14] != '\0' && (sh2[14] == 'i' || sh2[14] == 'I') &&
+		sh2[15] != '\0' && (sh2[15] == 'k' || sh2[15] == 'K'))
 	{
 		return true;
 	}
-	if ((sh2[0] == 'm' || sh2[0] == 'M') &&
-		(sh2[1] == 'o' || sh2[1] == 'O') &&
-		(sh2[2] == 'v' || sh2[2] == 'V') &&
-		(sh2[3] == 'i' || sh2[3] == 'I') &&
-		(sh2[4] == 'e' || sh2[4] == 'E') &&
-		(sh2[6] == 'e' || sh2[6] == 'E') &&
-		(sh2[7] == 'n' || sh2[7] == 'N') &&
-		(sh2[8] == 'd' || sh2[8] == 'D') &&
-		(sh2[10] == 'b' || sh2[10] == 'B') &&
-		(sh2[11] == 'i' || sh2[11] == 'I') &&
-		(sh2[12] == 'k' || sh2[12] == 'K'))
+	if (sh2[0] != '\0' && (sh2[0] == 'm' || sh2[0] == 'M') &&
+		sh2[1] != '\0' && (sh2[1] == 'o' || sh2[1] == 'O') &&
+		sh2[2] != '\0' && (sh2[2] == 'v' || sh2[2] == 'V') &&
+		sh2[3] != '\0' && (sh2[3] == 'i' || sh2[3] == 'I') &&
+		sh2[4] != '\0' && (sh2[4] == 'e' || sh2[4] == 'E') &&
+		sh2[5] != '\0' &&
+		sh2[6] != '\0' && (sh2[6] == 'e' || sh2[6] == 'E') &&
+		sh2[7] != '\0' && (sh2[7] == 'n' || sh2[7] == 'N') &&
+		sh2[8] != '\0' && (sh2[8] == 'd' || sh2[8] == 'D') &&
+		sh2[9] != '\0' &&
+		sh2[10] != '\0' && (sh2[10] == 'b' || sh2[10] == 'B') &&
+		sh2[11] != '\0' && (sh2[11] == 'i' || sh2[11] == 'I') &&
+		sh2[12] != '\0' && (sh2[12] == 'k' || sh2[12] == 'K'))
 	{
 		return true;
 	}
@@ -187,30 +191,32 @@ inline bool isEndVideoPath(T sh2)
 template<typename T>
 inline DWORD getPicPath(T sh2)
 {
-	if ((sh2[0] == 'p' || sh2[0] == 'P') &&
-		(sh2[1] == 'i' || sh2[1] == 'I') &&
-		(sh2[2] == 'c' || sh2[2] == 'C'))
+	if (sh2[0] != '\0' && (sh2[0] == 'p' || sh2[0] == 'P') &&
+		sh2[1] != '\0' && (sh2[1] == 'i' || sh2[1] == 'I') &&
+		sh2[2] != '\0' && (sh2[2] == 'c' || sh2[2] == 'C'))
 	{
 		return 3;
 	}
-	if ((sh2[0] == 'm' || sh2[0] == 'M') &&
-		(sh2[1] == 'e' || sh2[1] == 'E') &&
-		(sh2[2] == 'n' || sh2[2] == 'N') &&
-		(sh2[3] == 'u' || sh2[3] == 'U') &&
-		(sh2[5] == 'm' || sh2[5] == 'M') &&
-		(sh2[6] == 'c' || sh2[6] == 'C'))
+	if (sh2[0] != '\0' && (sh2[0] == 'm' || sh2[0] == 'M') &&
+		sh2[1] != '\0' && (sh2[1] == 'e' || sh2[1] == 'E') &&
+		sh2[2] != '\0' && (sh2[2] == 'n' || sh2[2] == 'N') &&
+		sh2[3] != '\0' && (sh2[3] == 'u' || sh2[3] == 'U') &&
+		sh2[4] != '\0' &&
+		sh2[5] != '\0' && (sh2[5] == 'm' || sh2[5] == 'M') &&
+		sh2[6] != '\0' && (sh2[6] == 'c' || sh2[6] == 'C'))
 	{
 		return 4;
 	}
-	if ((sh2[0] == 'e' || sh2[0] == 'E') &&
-		(sh2[1] == 't' || sh2[1] == 'T') &&
-		(sh2[2] == 'c' || sh2[2] == 'C') &&
-		(sh2[4] == 'e' || sh2[4] == 'E') &&
-		(sh2[5] == 'f' || sh2[5] == 'F') &&
-		(sh2[6] == 'f' || sh2[6] == 'F') &&
-		(sh2[7] == 'e' || sh2[7] == 'E') &&
-		(sh2[8] == 'c' || sh2[8] == 'C') &&
-		(sh2[9] == 't' || sh2[9] == 'T'))
+	if (sh2[0] != '\0' && (sh2[0] == 'e' || sh2[0] == 'E') &&
+		sh2[1] != '\0' && (sh2[1] == 't' || sh2[1] == 'T') &&
+		sh2[2] != '\0' && (sh2[2] == 'c' || sh2[2] == 'C') &&
+		sh2[3] != '\0' &&
+		sh2[4] != '\0' && (sh2[4] == 'e' || sh2[4] == 'E') &&
+		sh2[5] != '\0' && (sh2[5] == 'f' || sh2[5] == 'F') &&
+		sh2[6] != '\0' && (sh2[6] == 'f' || sh2[6] == 'F') &&
+		sh2[7] != '\0' && (sh2[7] == 'e' || sh2[7] == 'E') &&
+		sh2[8] != '\0' && (sh2[8] == 'c' || sh2[8] == 'C') &&
+		sh2[9] != '\0' && (sh2[9] == 't' || sh2[9] == 'T'))
 	{
 		return 3;
 	}
@@ -225,14 +231,22 @@ inline T UpdateModPath(T sh2, D str)
 		return sh2;
 	}
 
+	DWORD StrSize = strlen(sh2);
 	DWORD padding = 0;
+	bool isEnding = false;
 
 	// Check if data path is found and store location
 	if (isDataPath(sh2))
 	{
 		// Data path found at location '0', do nothing
 	}
-	else if (isDataPath(sh2 + modLoc))
+	else if (StrSize + strlen(ModPath(sh2)) + 4 > MAX_PATH)
+	{
+		// Game path is too long
+		LOG_ONCE(__FUNCTION__ " Error: Game path is too long: '" << sh2 << "'");
+		return sh2;
+	}
+	else if (StrSize > modLoc && isDataPath(sh2 + modLoc))
 	{
 		// Data path found at mod location, update padding and initialize
 		padding = modLoc;
@@ -254,8 +268,11 @@ inline T UpdateModPath(T sh2, D str)
 		strcpy_s(str + padding + PathLen, MAX_PATH - padding - PathLen, sh2 + padding + 4);
 
 		// Handle end.bik/ending.bik (favor end.bik)
-		if (isEndVideoPath(sh2 + padding + 5))
+		if ((StrSize > padding + PathLen + 1) && isEndVideoPath(sh2 + padding + PathLen + 1))
 		{
+			Logging::Log() << __FUNCTION__ " " << sh2;
+			isEnding = true;
+
 			// Check mod path
 			strcpy_s(str + padding + PathLen, MAX_PATH - padding - PathLen, GetEnding1(sh2));
 			if (PathFileExists(str))
@@ -267,20 +284,6 @@ inline T UpdateModPath(T sh2, D str)
 			{
 				return str;
 			}
-
-			// Check data path
-			strcpy_s(str, MAX_PATH, sh2);
-			strcpy_s(str + padding + 4, MAX_PATH - padding - 4, GetEnding1(sh2));
-			if (PathFileExists(str))
-			{
-				return str;
-			}
-			strcpy_s(str + padding + 4, MAX_PATH - padding - 4, GetEnding2(sh2));
-			if (PathFileExists(str))
-			{
-				return str;
-			}
-			return sh2;
 		}
 
 		// Handle PS2 low texture mod
@@ -302,6 +305,23 @@ inline T UpdateModPath(T sh2, D str)
 		}
 	}
 
+	// Handle end.bik/ending.bik (favor end.bik)
+	if (isEnding)
+	{
+		// Check data path
+		strcpy_s(str, MAX_PATH, sh2);
+		strcpy_s(str + padding + 4, MAX_PATH - padding - 4, GetEnding1(sh2));
+		if (PathFileExists(str))
+		{
+			return str;
+		}
+		strcpy_s(str + padding + 4, MAX_PATH - padding - 4, GetEnding2(sh2));
+		if (PathFileExists(str))
+		{
+			return str;
+		}
+	}
+
 	return sh2;
 }
 
@@ -669,9 +689,9 @@ void InstallFileSystemHooks()
 	modLoc = wcslen(tmpPath) + 1;
 	size_t modLen = strlen(ModPathA);
 	picLen = strlen(ModPicPathA);
-	if (modLoc + modLen > MAX_PATH)
+	if (modLoc + modLen + 42 > MAX_PATH)	// Check max length of a file in the game
 	{
-		Logging::Log() << __FUNCTION__ " Error: custom mod path length is too long! " << modLoc + modLen;
+		Logging::Log() << __FUNCTION__ " Error: Game path is too long: " << modLoc + modLen;
 		DisableFileSystemHooking();
 		return;
 	}
diff --git a/Common/Settings.h b/Common/Settings.h
index e6d785bd..3d5395d4 100644
--- a/Common/Settings.h
+++ b/Common/Settings.h
@@ -261,6 +261,7 @@ typedef void(__stdcall* NV)(char* name, char* value, void* lpParam);
 extern HMODULE m_hModule;
 extern bool CustomExeStrSet;
 extern bool EnableCustomShaders;
+extern bool ShadersReady;
 extern bool IsUpdating;
 extern bool m_StopThreadFlag;
 extern bool AutoScaleImages;
diff --git a/Launcher/Launcher.vcxproj b/Launcher/Launcher.vcxproj
index 339141fb..e1ca26ba 100644
--- a/Launcher/Launcher.vcxproj
+++ b/Launcher/Launcher.vcxproj
@@ -27,7 +27,6 @@
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
     <PlatformToolset>v141_xp</PlatformToolset>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
diff --git a/Patches/FullscreenImages.cpp b/Patches/FullscreenImages.cpp
index 2c02f3f4..71fc9d60 100644
--- a/Patches/FullscreenImages.cpp
+++ b/Patches/FullscreenImages.cpp
@@ -101,8 +101,9 @@ bool GetTextureRes(char *TexName, DWORD &TextureX, DWORD &TextureY);
 
 struct ImageCache
 {
-	void *Name;
+	void *Addr;
 	BOOL Flag;
+	std::string Name;
 };
 
 std::vector<ImageCache> ScaleList, MapList;
@@ -112,17 +113,20 @@ BOOL CheckTexture()
 	static BOOL flag = FALSE;
 	static void *last = nullptr;
 
-	if (!TexNameAddr || !*TexNameAddr  || last == *TexNameAddr ||
-		std::any_of(ScaleList.begin(), ScaleList.end(), [](const ImageCache & TexCache) { if (TexCache.Name == *TexNameAddr) { flag = TexCache.Flag; return true; } return false; })
-		|| strcmp(*TexNameAddr, "data/etc/effect/lens_flare.tbn2") == 0)
+	if (!TexNameAddr || !*TexNameAddr || strcmp(*TexNameAddr, "data/etc/effect/lens_flare.tbn2") == 0)
+	{
+		return FALSE;
+	}
+
+	if (last == *TexNameAddr ||
+		std::any_of(ScaleList.begin(), ScaleList.end(), [](const ImageCache& TexCache) { if (TexCache.Addr == *TexNameAddr && strcmp(*TexNameAddr, TexCache.Name.c_str()) == 0) { flag = TexCache.Flag; return true; } return false; }))
 	{
-		last = (TexNameAddr) ? *TexNameAddr : nullptr;
 		return flag;
 	}
 
 	flag = (std::any_of(std::begin(DefaultTextureList), std::end(DefaultTextureList), [](const TexSize & TexItem) { return TexItem.IsScaled && strcmp(TexItem.Name, *TexNameAddr) == 0; }));
 	
-	ScaleList.push_back({ *TexNameAddr , flag });
+	ScaleList.push_back({ *TexNameAddr, flag, std::string(*TexNameAddr) });
 	last = *TexNameAddr;
 
 	return flag;
@@ -133,17 +137,20 @@ BOOL CheckMapTexture()
 	static BOOL flag = FALSE;
 	static void *last = nullptr;
 
-	if (!TexNameAddr || !*TexNameAddr || last == *TexNameAddr ||
-		std::any_of(MapList.begin(), MapList.end(), [](const ImageCache & TexCache) { if (TexCache.Name == *TexNameAddr) { flag = TexCache.Flag; return true; } return false; })
-		|| strcmp(*TexNameAddr, "data/etc/effect/lens_flare.tbn2") == 0)
+	if (!TexNameAddr || !*TexNameAddr || strcmp(*TexNameAddr, "data/etc/effect/lens_flare.tbn2") == 0)
+	{
+		return FALSE;
+	}
+
+	if (last == *TexNameAddr ||
+		std::any_of(MapList.begin(), MapList.end(), [](const ImageCache& TexCache) { if (TexCache.Addr == *TexNameAddr && strcmp(*TexNameAddr, TexCache.Name.c_str()) == 0) { flag = TexCache.Flag; return true; } return false; }))
 	{
-		last = (TexNameAddr) ? *TexNameAddr : nullptr;
 		return flag;
 	}
 
 	flag = (std::any_of(std::begin(DefaultTextureList), std::end(DefaultTextureList), [](const TexSize & TexItem) { return TexItem.IsMap && strcmp(TexItem.Name, *TexNameAddr) == 0; }));
 	
-	MapList.push_back({ *TexNameAddr , flag });
+	MapList.push_back({ *TexNameAddr, flag, std::string(*TexNameAddr) });
 	last = *TexNameAddr;
 
 	return flag;
@@ -194,9 +201,12 @@ void OnFileLoadTex(LPCSTR lpFileName)
 // Runs each time a texture is loaded
 void CheckLoadedTexture()
 {
-	CheckingTexture = true;
-	GetTextureOnLoad();
-	CheckingTexture = false;
+	if (!CheckingTexture)
+	{
+		CheckingTexture = true;
+		GetTextureOnLoad();
+		CheckingTexture = false;
+	}
 }
 
 // ASM function to check texture on load
diff --git a/Patches/FullscreenVideos.cpp b/Patches/FullscreenVideos.cpp
index 07365b10..85179652 100644
--- a/Patches/FullscreenVideos.cpp
+++ b/Patches/FullscreenVideos.cpp
@@ -81,9 +81,12 @@ void OnFileLoadVid(LPCSTR lpFileName)
 // Check if loading a Game Result save
 void UpdateLoadedVideo()
 {
-	CheckingVideo = true;
-	GetVideoOnLoad();
-	CheckingVideo = false;
+	if (!CheckingVideo)
+	{
+		CheckingVideo = true;
+		GetVideoOnLoad();
+		CheckingVideo = false;
+	}
 }
 
 // ASM function to Fix Game Result Saves
diff --git a/Patches/Resolution.cpp b/Patches/Resolution.cpp
index 6b83d3f5..7fb129a8 100644
--- a/Patches/Resolution.cpp
+++ b/Patches/Resolution.cpp
@@ -340,74 +340,83 @@ void GetCustomResolutions()
 {
 	GetDesktopRes(MaxWidth, MaxHeight);
 
-	// Exclusive fullscreen mode
-	if (ScreenMode == EXCLUSIVE_FULLSCREEN)
-	{
-		IDirect3D8 *pDirect3D = Direct3DCreate8Wrapper(D3D_SDK_VERSION);
-
-		if (!pDirect3D)
+	do {
+		// Exclusive fullscreen mode
+		if (ScreenMode == EXCLUSIVE_FULLSCREEN)
 		{
-			Logging::Log() << __FUNCTION__ << " Error: failed to create Direct3D8!";
-			return;
-		}
+			IDirect3D8* pDirect3D = Direct3DCreate8Wrapper(D3D_SDK_VERSION);
 
-		// Add custom resolution to list
-		if (ResY && ResX)
-		{
-			AddResolutionToList(ResX, ResY, true);
-		}
+			if (!pDirect3D)
+			{
+				Logging::Log() << __FUNCTION__ << " Error: failed to create Direct3D8!";
+				break;
+			}
 
-		// Setup display mode
-		D3DDISPLAYMODE d3ddispmode;
+			// Add custom resolution to list
+			if (ResY && ResX)
+			{
+				AddResolutionToList(ResX, ResY, true);
+			}
 
-		// Enumerate modes for format XRGB
-		UINT modeCount = pDirect3D->GetAdapterModeCount(D3DADAPTER_DEFAULT);
+			// Setup display mode
+			D3DDISPLAYMODE d3ddispmode;
 
-		// Loop through each mode
-		for (UINT i = 0; i < modeCount; i++)
-		{
-			// Get next resolution
-			if (FAILED(pDirect3D->EnumAdapterModes(D3DADAPTER_DEFAULT, i, &d3ddispmode)))
+			// Enumerate modes for format XRGB
+			UINT modeCount = pDirect3D->GetAdapterModeCount(D3DADAPTER_DEFAULT);
+
+			// Loop through each mode
+			for (UINT i = 0; i < modeCount; i++)
 			{
-				break;
+				// Get next resolution
+				if (FAILED(pDirect3D->EnumAdapterModes(D3DADAPTER_DEFAULT, i, &d3ddispmode)))
+				{
+					break;
+				}
+
+				// Add resolution to list
+				AddResolutionToList(d3ddispmode.Width, d3ddispmode.Height);
 			}
 
-			// Add resolution to list
-			AddResolutionToList(d3ddispmode.Width, d3ddispmode.Height);
+			// Release Direct3D8
+			pDirect3D->Release();
 		}
-
-		// Release Direct3D8
-		pDirect3D->Release();
-	}
-	// Windowed and windowed fullscreen modes
-	else
-	{
-		// Add custom resolution to list
-		if (ResY && ResX)
+		// Windowed and windowed fullscreen modes
+		else
 		{
-			AddResolutionToList(ResX, ResY, true);
-		}
+			// Add custom resolution to list
+			if (ResY && ResX)
+			{
+				AddResolutionToList(ResX, ResY, true);
+			}
 
-		// Get monitor info
-		MONITORINFOEX infoex = {};
-		infoex.cbSize = sizeof(MONITORINFOEX);
-		BOOL bRet = GetMonitorInfo(GetMonitorHandle(), &infoex);
+			// Get monitor info
+			MONITORINFOEX infoex = {};
+			infoex.cbSize = sizeof(MONITORINFOEX);
+			BOOL bRet = GetMonitorInfo(GetMonitorHandle(), &infoex);
 
-		// Get resolution list for specified monitor
-		DEVMODE dm = {};
-		dm.dmSize = sizeof(dm);
-		for (int x = 0; EnumDisplaySettings(bRet ? infoex.szDevice : nullptr, x, &dm) != 0; x++)
-		{
-			// Add resolution to list
-			AddResolutionToList(dm.dmPelsWidth, dm.dmPelsHeight);
+			// Get resolution list for specified monitor
+			DEVMODE dm = {};
+			dm.dmSize = sizeof(dm);
+			for (int x = 0; EnumDisplaySettings(bRet ? infoex.szDevice : nullptr, x, &dm) != 0; x++)
+			{
+				// Add resolution to list
+				AddResolutionToList(dm.dmPelsWidth, dm.dmPelsHeight);
+			}
 		}
-	}
+	} while (FALSE);
 
 	// Check if any resolutions were found
 	if (ResolutionVector.empty())
 	{
-		Logging::Log() << __FUNCTION__ << " Error: failed to get resolution list!";
-		return;
+		Logging::Log() << __FUNCTION__ << " Error: failed to get resolution list!  Adding default resolutions.";
+
+		// Add default resolution list
+		AddResolutionToList(640, 480);
+		AddResolutionToList(800, 600);
+		AddResolutionToList(1024, 768);
+		AddResolutionToList(1280, 1024);
+		AddResolutionToList(1600, 1200);
+		AddResolutionToList(MaxWidth, MaxHeight);
 	}
 }
 
diff --git a/ReShade/ReShadeFX/ReShadeFX.vcxproj b/ReShade/ReShadeFX/ReShadeFX.vcxproj
index 2038ce61..bfd0d0e3 100644
--- a/ReShade/ReShadeFX/ReShadeFX.vcxproj
+++ b/ReShade/ReShadeFX/ReShadeFX.vcxproj
@@ -43,9 +43,6 @@
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v141_xp</PlatformToolset>
   </PropertyGroup>
-  <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-  </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="PropertySheets">
diff --git a/ReShade/stb/stb.vcxproj b/ReShade/stb/stb.vcxproj
index e1a891db..c4888e03 100644
--- a/ReShade/stb/stb.vcxproj
+++ b/ReShade/stb/stb.vcxproj
@@ -29,9 +29,6 @@
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v141_xp</PlatformToolset>
   </PropertyGroup>
-  <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-  </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="PropertySheets">
diff --git a/Resources/BuildNo.rc b/Resources/BuildNo.rc
index d6afc550..b1531e6f 100644
--- a/Resources/BuildNo.rc
+++ b/Resources/BuildNo.rc
@@ -1 +1 @@
-#define BUILD_NUMBER 2025 
+#define BUILD_NUMBER 2027 
diff --git a/Wrappers/d3d8/IDirect3DDevice8.cpp b/Wrappers/d3d8/IDirect3DDevice8.cpp
index f7a2a672..3757c0b6 100644
--- a/Wrappers/d3d8/IDirect3DDevice8.cpp
+++ b/Wrappers/d3d8/IDirect3DDevice8.cpp
@@ -266,7 +266,7 @@ BOOL m_IDirect3DDevice8::ShowCursor(BOOL bShow)
 	return ProxyInterface->ShowCursor(bShow);
 }
 
-HRESULT m_IDirect3DDevice8::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS *pPresentationParameters, IDirect3DSwapChain8 **ppSwapChain)
+HRESULT m_IDirect3DDevice8::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS *pPresentationParameters, IDirect3DSwapChain8** ppSwapChain)
 {
 	Logging::LogDebug() << __FUNCTION__;
 
@@ -299,6 +299,13 @@ HRESULT m_IDirect3DDevice8::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS *pPr
 		*ppSwapChain = new m_IDirect3DSwapChain8(*ppSwapChain, this);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to create swap chain! " <<
+			(pPresentationParameters ? pPresentationParameters->BackBufferWidth : 0) << "x" <<
+			(pPresentationParameters ? pPresentationParameters->BackBufferHeight : 0);
+	}
+
 	return hr;
 }
 
@@ -313,6 +320,11 @@ HRESULT m_IDirect3DDevice8::CreateCubeTexture(THIS_ UINT EdgeLength, UINT Levels
 		*ppCubeTexture = new m_IDirect3DCubeTexture8(*ppCubeTexture, this);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to create cubed texture! " << EdgeLength;
+	}
+
 	return hr;
 }
 
@@ -329,6 +341,11 @@ HRESULT m_IDirect3DDevice8::CreateDepthStencilSurface(THIS_ UINT Width, UINT Hei
 		*ppSurface = new m_IDirect3DSurface8(*ppSurface, this);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to create depth stencil surface! " << Width << "x" << Height;
+	}
+
 	return hr;
 }
 
@@ -343,6 +360,11 @@ HRESULT m_IDirect3DDevice8::CreateIndexBuffer(THIS_ UINT Length, DWORD Usage, D3
 		*ppIndexBuffer = new m_IDirect3DIndexBuffer8(*ppIndexBuffer, this);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to create index buffer! " << Length;
+	}
+
 	return hr;
 }
 
@@ -363,6 +385,11 @@ HRESULT m_IDirect3DDevice8::CreateRenderTarget(THIS_ UINT Width, UINT Height, D3
 		*ppSurface = new m_IDirect3DSurface8(*ppSurface, this);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to create render target! " << Width << "x" << Height;
+	}
+
 	return hr;
 }
 
@@ -414,6 +441,11 @@ HRESULT m_IDirect3DDevice8::CreateTexture(THIS_ UINT Width, UINT Height, UINT Le
 		}
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to create texture! " << Width << "x" << Height;
+	}
+
 	return hr;
 }
 
@@ -428,6 +460,11 @@ HRESULT m_IDirect3DDevice8::CreateVertexBuffer(THIS_ UINT Length, DWORD Usage, D
 		*ppVertexBuffer = new m_IDirect3DVertexBuffer8(*ppVertexBuffer, this);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to create vertex buffer! " << Length;
+	}
+
 	return hr;
 }
 
@@ -442,6 +479,11 @@ HRESULT m_IDirect3DDevice8::CreateVolumeTexture(THIS_ UINT Width, UINT Height, U
 		*ppVolumeTexture = new m_IDirect3DVolumeTexture8(*ppVolumeTexture, this);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to create volume texture! " << Width << "x" << Height;
+	}
+
 	return hr;
 }
 
@@ -519,6 +561,11 @@ HRESULT m_IDirect3DDevice8::GetRenderTarget(THIS_ IDirect3DSurface8** ppRenderTa
 		*ppRenderTarget = ProxyAddressLookupTableD3d8->FindAddress<m_IDirect3DSurface8>(*ppRenderTarget);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to get render target!";
+	}
+
 	return hr;
 }
 
@@ -675,6 +722,9 @@ void m_IDirect3DDevice8::SetGammaRamp(THIS_ DWORD Flags, CONST D3DGAMMARAMP* pRa
 {
 	Logging::LogDebug() << __FUNCTION__;
 
+	// Don't enable shaders until the game calls SetGamma to make sure all the shader settings are initialized
+	ShadersReady = EnableCustomShaders;
+
 	if (ScreenMode != WINDOWED || (RestoreBrightnessSelector && d3d8to9))
 	{
 		ProxyInterface->SetGammaRamp(Flags, pRamp);
@@ -713,6 +763,11 @@ HRESULT m_IDirect3DDevice8::GetIndices(THIS_ IDirect3DIndexBuffer8** ppIndexData
 		*ppIndexData = ProxyAddressLookupTableD3d8->FindAddress<m_IDirect3DIndexBuffer8>(*ppIndexData);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to get index buffer!";
+	}
+
 	return hr;
 }
 
@@ -749,12 +804,13 @@ HRESULT m_IDirect3DDevice8::GetDeviceCaps(D3DCAPS8 *pCaps)
 	return ProxyInterface->GetDeviceCaps(pCaps);
 }
 
-HRESULT m_IDirect3DDevice8::GetDirect3D(IDirect3D8 **ppD3D9)
+HRESULT m_IDirect3DDevice8::GetDirect3D(IDirect3D8** ppD3D9)
 {
 	Logging::LogDebug() << __FUNCTION__;
 
 	if (!ppD3D9)
 	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to get Direct3D!";
 		return D3DERR_INVALIDCALL;
 	}
 
@@ -1882,6 +1938,11 @@ HRESULT m_IDirect3DDevice8::GetStreamSource(THIS_ UINT StreamNumber, IDirect3DVe
 		*ppStreamData = ProxyAddressLookupTableD3d8->FindAddress<m_IDirect3DVertexBuffer8>(*ppStreamData);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to get stream source!";
+	}
+
 	return hr;
 }
 
@@ -1908,10 +1969,15 @@ HRESULT m_IDirect3DDevice8::GetBackBuffer(THIS_ UINT iBackBuffer, D3DBACKBUFFER_
 		*ppBackBuffer = ProxyAddressLookupTableD3d8->FindAddress<m_IDirect3DSurface8>(*ppBackBuffer);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to get backbuffer!";
+	}
+
 	return hr;
 }
 
-HRESULT m_IDirect3DDevice8::GetDepthStencilSurface(IDirect3DSurface8 **ppZStencilSurface)
+HRESULT m_IDirect3DDevice8::GetDepthStencilSurface(IDirect3DSurface8** ppZStencilSurface)
 {
 	Logging::LogDebug() << __FUNCTION__;
 
@@ -1922,10 +1988,15 @@ HRESULT m_IDirect3DDevice8::GetDepthStencilSurface(IDirect3DSurface8 **ppZStenci
 		*ppZStencilSurface = ProxyAddressLookupTableD3d8->FindAddress<m_IDirect3DSurface8>(*ppZStencilSurface);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to get stencil surface!";
+	}
+
 	return hr;
 }
 
-HRESULT m_IDirect3DDevice8::GetTexture(DWORD Stage, IDirect3DBaseTexture8 **ppTexture)
+HRESULT m_IDirect3DDevice8::GetTexture(DWORD Stage, IDirect3DBaseTexture8** ppTexture)
 {
 	Logging::LogDebug() << __FUNCTION__;
 
@@ -1945,10 +2016,16 @@ HRESULT m_IDirect3DDevice8::GetTexture(DWORD Stage, IDirect3DBaseTexture8 **ppTe
 			*ppTexture = ProxyAddressLookupTableD3d8->FindAddress<m_IDirect3DCubeTexture8>(*ppTexture);
 			break;
 		default:
+			Logging::Log() << __FUNCTION__ << " Error: Failed to get texture type!";
 			return D3DERR_INVALIDCALL;
 		}
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to get texture!";
+	}
+
 	return hr;
 }
 
@@ -2416,6 +2493,11 @@ HRESULT m_IDirect3DDevice8::CreateImageSurface(THIS_ UINT Width, UINT Height, D3
 		*ppSurface = new m_IDirect3DSurface8(*ppSurface, this);
 	}
 
+	if (FAILED(hr))
+	{
+		Logging::Log() << __FUNCTION__ << " Error: Failed to create image surface! " << Width << "x" << Height;
+	}
+
 	return hr;
 }
 
@@ -2763,7 +2845,7 @@ HRESULT m_IDirect3DDevice8::DrawSoftShadows()
 
 	// Variables for soft shadows
 	const DWORD SHADOW_OPACITY = (ShadowMode == SHADOW_FADING_NONE) ? GetShadowOpacity() : (GetShadowOpacity() * ShadowFadingIntensity) / 100;
-	const float SHADOW_DIVISOR = 2.0f * ((float)BufferHeight / 720.0f);
+	const float SHADOW_DIVISOR = round(((float)BufferHeight / 720.0f) + 0.5f);	// Round number to prevent shadow from being misplaced
 	const int BLUR_PASSES = 4;
 
 	IDirect3DSurface8 *pBackBuffer = nullptr, *pStencilBuffer = nullptr;
@@ -3043,7 +3125,7 @@ void m_IDirect3DDevice8::RestoreState(D3DSTATE *state)
 }
 
 template <typename T>
-void m_IDirect3DDevice8::ReleaseInterface(T **ppInterface, UINT ReleaseRefNum)
+void m_IDirect3DDevice8::ReleaseInterface(T** ppInterface, UINT ReleaseRefNum)
 {
 	if (ppInterface && *ppInterface && ReleaseRefNum)
 	{
diff --git a/Wrappers/d3d9/IDirect3DDevice9.cpp b/Wrappers/d3d9/IDirect3DDevice9.cpp
index b354a6c3..05e7bb5b 100644
--- a/Wrappers/d3d9/IDirect3DDevice9.cpp
+++ b/Wrappers/d3d9/IDirect3DDevice9.cpp
@@ -21,6 +21,7 @@
 
 extern bool DisableShaderOnPresent;
 
+bool ShadersReady = false;
 DWORD GammaLevel = 3;
 
 HRESULT m_IDirect3DDevice9::QueryInterface(REFIID riid, void** ppvObj)
@@ -251,7 +252,7 @@ HRESULT m_IDirect3DDevice9::Reset(D3DPRESENT_PARAMETERS *pPresentationParameters
 HRESULT m_IDirect3DDevice9::Present(const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion)
 {
 	// Only call into runtime if the entire surface is presented, to avoid partial updates messing up effects and the GUI
-	if (EnableCustomShaders && !DisableShaderOnPresent && m_IDirect3DSwapChain9::is_presenting_entire_surface(pSourceRect, hDestWindowOverride))
+	if (ShadersReady && !DisableShaderOnPresent && m_IDirect3DSwapChain9::is_presenting_entire_surface(pSourceRect, hDestWindowOverride))
 	{
 		_implicit_swapchain->_runtime->on_present();
 	}
@@ -310,9 +311,7 @@ void m_IDirect3DDevice9::SetGammaRamp(UINT iSwapChain, DWORD Flags, const D3DGAM
 
 		const auto runtime = _implicit_swapchain->_runtime;
 
-		runtime->reset_gamma(GammaSet);
-
-		GammaSet = true;
+		runtime->reset_gamma(true);
 
 		return;
 	}
diff --git a/Wrappers/d3d9/IDirect3DDevice9.h b/Wrappers/d3d9/IDirect3DDevice9.h
index da2a1aa0..d0032f05 100644
--- a/Wrappers/d3d9/IDirect3DDevice9.h
+++ b/Wrappers/d3d9/IDirect3DDevice9.h
@@ -29,7 +29,6 @@ class m_IDirect3DDevice9 : public IDirect3DDevice9
 private:
 	LPDIRECT3DDEVICE9 ProxyInterface;
 	bool UseSoftwareRendering;
-	bool GammaSet = false;
 	D3DGAMMARAMP Ramp = {};
 
 public:
diff --git a/sh2-enhce.vcxproj b/sh2-enhce.vcxproj
index f45e2397..9296e6c0 100644
--- a/sh2-enhce.vcxproj
+++ b/sh2-enhce.vcxproj
@@ -218,9 +218,6 @@
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v141_xp</PlatformToolset>
   </PropertyGroup>
-  <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-  </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="PropertySheets">
@@ -277,9 +274,6 @@
       <ObjectFileName>$(SolutionDir)bin\Intermediate\$(ProjectName)\$(Configuration)\Object\%(RelativeDir)</ObjectFileName>
       <LanguageStandard>stdcpp17</LanguageStandard>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
-      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
     </ClCompile>
     <Link>
       <ModuleDefinitionFile>Wrappers\wrapper.def</ModuleDefinitionFile>