diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj
index 73f6c8815b..85a9a47eb7 100644
--- a/Source/Core/Common/Common.vcxproj
+++ b/Source/Core/Common/Common.vcxproj
@@ -162,13 +162,13 @@
+
-
diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters
index f9f84f8426..af926981f3 100644
--- a/Source/Core/Common/Common.vcxproj.filters
+++ b/Source/Core/Common/Common.vcxproj.filters
@@ -230,7 +230,6 @@
Logging
-
@@ -249,6 +248,7 @@
GL\GLInterface
+
diff --git a/Source/Core/Common/XSaveWorkaround.cpp b/Source/Core/Common/XSaveWorkaround.cpp
deleted file mode 100644
index a91af47a39..0000000000
--- a/Source/Core/Common/XSaveWorkaround.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2014 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#if defined(_WIN32)
-
-#include
-#include
-
-typedef decltype(&GetEnabledXStateFeatures) GetEnabledXStateFeatures_t;
-
-int __cdecl EnableXSaveWorkaround()
-{
- // Some Windows environments may have hardware support for AVX/FMA,
- // but the OS does not support it. The CRT math library does not support
- // this scenario, so we have to manually tell it not to use FMA3
- // instructions.
-
- // The API name is somewhat misleading - we're testing for OS support
- // here.
- if (!IsProcessorFeaturePresent(PF_XSAVE_ENABLED))
- {
- _set_FMA3_enable(0);
- return 0;
- }
-
- // Even if XSAVE feature is enabled, we have to see if
- // GetEnabledXStateFeatures function is present, and see what it says about
- // AVX state.
- auto kernel32Handle = GetModuleHandle(TEXT("kernel32.dll"));
- if (kernel32Handle == nullptr)
- {
- std::abort();
- }
-
- auto pGetEnabledXStateFeatures = (GetEnabledXStateFeatures_t)GetProcAddress(
- kernel32Handle, "GetEnabledXStateFeatures");
- if (pGetEnabledXStateFeatures == nullptr ||
- (pGetEnabledXStateFeatures() & XSTATE_MASK_AVX) == 0)
- {
- _set_FMA3_enable(0);
- }
-
- return 0;
-}
-
-// Create a segment which is recognized by the linker to be part of the CRT
-// initialization. XI* = C startup, XC* = C++ startup. "A" placement is reserved
-// for system use. Thus, the earliest we can get is XIB (C startup is before
-// C++).
-#pragma section(".CRT$XIB", read)
-
-// Place a symbol in the special segment, make it have C linkage so that
-// referencing it doesn't require ugly decorated names.
-// Use /include:XSaveWorkaround linker flag to enable this.
-extern "C" {
- __declspec(allocate(".CRT$XIB"))
- decltype(&EnableXSaveWorkaround) XSaveWorkaround = EnableXSaveWorkaround;
-};
-
-#endif
diff --git a/Source/Core/Common/ucrtFreadWorkaround.cpp b/Source/Core/Common/ucrtFreadWorkaround.cpp
new file mode 100644
index 0000000000..10f91d1d1c
--- /dev/null
+++ b/Source/Core/Common/ucrtFreadWorkaround.cpp
@@ -0,0 +1,85 @@
+// Copyright 2014 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#if defined(_WIN32)
+
+#include "CommonTypes.h"
+#include
+
+struct PatchInfo {
+ const wchar_t *module_name;
+ u32 checksum;
+ u32 rva;
+ u32 length;
+} static const s_patches[] = {
+ { L"ucrtbase.dll", 0xF61ED, 0x6AE7B, 5 },
+ { L"ucrtbased.dll", 0x1C1915 , 0x91905, 5 },
+};
+
+bool ApplyPatch(const PatchInfo &patch) {
+ auto module = GetModuleHandleW(patch.module_name);
+ if (module == nullptr)
+ {
+ return false;
+ }
+
+ auto ucrtbase_pe = (PIMAGE_NT_HEADERS)((uintptr_t)module + ((PIMAGE_DOS_HEADER)module)->e_lfanew);
+ if (ucrtbase_pe->OptionalHeader.CheckSum != patch.checksum) {
+ return false;
+ }
+
+ void *patch_addr = (void *)((uintptr_t)module + patch.rva);
+ size_t patch_size = patch.length;
+
+ DWORD old_protect;
+ if (!VirtualProtect(patch_addr, patch_size, PAGE_EXECUTE_READWRITE, &old_protect))
+ {
+ return false;
+ }
+
+ memset(patch_addr, 0x90, patch_size);
+
+ VirtualProtect(patch_addr, patch_size, old_protect, &old_protect);
+
+ FlushInstructionCache(GetCurrentProcess(), patch_addr, patch_size);
+
+ return true;
+}
+
+int __cdecl EnableucrtFreadWorkaround()
+{
+ // This patches ucrtbase such that fseek will always
+ // synchronize the file object's internal buffer.
+
+ bool applied_at_least_one = false;
+ for (const auto &patch : s_patches) {
+ if (ApplyPatch(patch)) {
+ applied_at_least_one = true;
+ }
+ }
+
+ /* For forward compat, do not fail if patches don't apply (e.g. version mismatch)
+ if (!applied_at_least_one) {
+ std::abort();
+ }
+ //*/
+
+ return 0;
+}
+
+// Create a segment which is recognized by the linker to be part of the CRT
+// initialization. XI* = C startup, XC* = C++ startup. "A" placement is reserved
+// for system use. Thus, the earliest we can get is XIB (C startup is before
+// C++).
+#pragma section(".CRT$XIB", read)
+
+// Place a symbol in the special segment, make it have C linkage so that
+// referencing it doesn't require ugly decorated names.
+// Use /include:EnableucrtFreadWorkaround linker flag to enable this.
+extern "C" {
+ __declspec(allocate(".CRT$XIB"))
+ decltype(&EnableucrtFreadWorkaround) ucrtFreadWorkaround = EnableucrtFreadWorkaround;
+};
+
+#endif
diff --git a/Source/VSProps/Base.props b/Source/VSProps/Base.props
index 86ad26a5ad..a31b726623 100644
--- a/Source/VSProps/Base.props
+++ b/Source/VSProps/Base.props
@@ -122,8 +122,8 @@
-
- XSaveWorkaround
+
+ ucrtFreadWorkaroundtrue