diff --git a/.gitignore b/.gitignore
index 5ebe5382ed..4688d5fa52 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@
/lib
/tmp
/ipch
+/packages
/rpcs3/Debug
/rpcs3/Release
diff --git a/buildfiles/msvc/rpcs3_default.props b/buildfiles/msvc/rpcs3_default.props
index 4725434147..d8df69d503 100644
--- a/buildfiles/msvc/rpcs3_default.props
+++ b/buildfiles/msvc/rpcs3_default.props
@@ -7,6 +7,8 @@
$(SolutionDir)build\lib\$(Configuration)-$(Platform)\
$(SolutionDir)build\lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath)
$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)\
+ $(SolutionDir)packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-static.1.8.1.7\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-static.targets
+ true
diff --git a/rpcs3.sln b/rpcs3.sln
index 873982236d..be1e9a6ec8 100644
--- a/rpcs3.sln
+++ b/rpcs3.sln
@@ -107,6 +107,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openal-soft", "3rdparty\ope
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fusion", "3rdparty\fusion\fusion.vcxproj", "{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rpcs3.test", "rpcs3.test", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3_test", "rpcs3\tests\rpcs3_test.vcxproj", "{D1CBF84E-07F8-4ACB-9CD2-BD205FDEEE1E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12} = {70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -219,6 +226,10 @@ Global
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}.Debug|x64.Build.0 = Debug|x64
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}.Release|x64.ActiveCfg = Release|x64
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}.Release|x64.Build.0 = Release|x64
+ {D1CBF84E-07F8-4ACB-9CD2-BD205FDEEE1E}.Debug|x64.ActiveCfg = Debug|x64
+ {D1CBF84E-07F8-4ACB-9CD2-BD205FDEEE1E}.Debug|x64.Build.0 = Debug|x64
+ {D1CBF84E-07F8-4ACB-9CD2-BD205FDEEE1E}.Release|x64.ActiveCfg = Release|x64
+ {D1CBF84E-07F8-4ACB-9CD2-BD205FDEEE1E}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -252,6 +263,7 @@ Global
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{8846A9AA-5539-4C91-8301-F54260E1A07A} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
+ {D1CBF84E-07F8-4ACB-9CD2-BD205FDEEE1E} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {06CC7920-E085-4B81-9582-8DE8AAD42510}
diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj
index ea8f2e7342..025c3d0a15 100644
--- a/rpcs3/rpcs3.vcxproj
+++ b/rpcs3/rpcs3.vcxproj
@@ -120,6 +120,15 @@
+
+ @echo off
+> "$(IntermediateOutputPath)obj_files.rsp" (
+ for /F "delims=" %%i in ('dir "$(IntermediateOutputPath)*.obj" /B ^| findstr /V /I "main.obj"') do (
+ echo "$(IntermediateOutputPath)%%i"
+ )
+)
+"$(VCToolsInstallDir)bin\Hostx64\x64\lib.exe" /out:"$(SolutionDir)build\lib\$(Configuration)-$(Platform)\rpcs3.lib" @$(IntermediateOutputPath)obj_files.rsp
+
@@ -171,6 +180,15 @@
+
+ @echo off
+> "$(IntermediateOutputPath)obj_files.rsp" (
+ for /F "delims=" %%i in ('dir "$(IntermediateOutputPath)*.obj" /B ^| findstr /V /I "main.obj"') do (
+ echo "$(IntermediateOutputPath)%%i"
+ )
+)
+"$(VCToolsInstallDir)bin\Hostx64\x64\lib.exe" /out:"$(SolutionDir)build\lib\$(Configuration)-$(Platform)\rpcs3d.lib" @$(IntermediateOutputPath)obj_files.rsp
+
diff --git a/rpcs3/tests/packages.config b/rpcs3/tests/packages.config
new file mode 100644
index 0000000000..a71561e644
--- /dev/null
+++ b/rpcs3/tests/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/rpcs3/tests/rpcs3_test.vcxproj b/rpcs3/tests/rpcs3_test.vcxproj
new file mode 100644
index 0000000000..00b62f6636
--- /dev/null
+++ b/rpcs3/tests/rpcs3_test.vcxproj
@@ -0,0 +1,100 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {d1cbf84e-07f8-4acb-9cd2-bd205fdeee1e}
+ Application
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ x64
+ $(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)\
+ .\;$(SolutionDir);$(SolutionDir)rpcs3;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);
+ $(SolutionDir)build\lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath)
+
+
+
+ X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ Level3
+ ProgramDatabase
+ $(IntDir)
+ $(IntDir)vc$(PlatformToolsetVersion).pdb
+
+
+ rpcs3.lib;opencv_world4100.lib;DbgHelp.lib;Ole32.lib;gdi32.lib;hidapi.lib;libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;imm32.lib;ksuser.lib;version.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;MachineIndependent.lib;GenericCodeGen.lib;Advapi32.lib;user32.lib;zlib.lib;zstd.lib;libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;shell32.lib;Qt6Core.lib;Qt6Gui.lib;Qt6Widgets.lib;Qt6Concurrent.lib;Qt6Multimedia.lib;Qt6MultimediaWidgets.lib;Qt6Svg.lib;Qt6SvgWidgets.lib;7zip.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;SDL.lib;fusion.lib;%(AdditionalDependencies)
+ $(SolutionDir)3rdparty\opencv\opencv\opencv410\build\x64\lib;$(SolutionDir)build\lib\$(Configuration)-$(Platform)\glslang;$(SolutionDir)build\lib_ext\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;$(VULKAN_SDK)\Lib;%(AdditionalLibraryDirectories)
+ Console
+ false
+ 0x10000
+
+
+
+ $(QTDIR)\bin\windeployqt --no-compiler-runtime --no-opengl-sw --no-patchqt --no-translations --no-quick --no-system-d3d-compiler --no-system-dxc-compiler --no-ffmpeg --no-quick-import --plugindir "$(TargetDir)qt6\plugins" --release "$(TargetPath)"
+ xcopy /y /d "$(SolutionDir)3rdparty\opencv\opencv\opencv410\build\x64\bin\opencv_world4100.dll" "$(OutDir)"
+
+
+
+
+
+ Disabled
+ X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ Level3
+ $(IntDir)
+ $(IntDir)vc$(PlatformToolsetVersion).pdb
+
+
+ rpcs3d.lib;opencv_world4100.lib;DbgHelp.lib;Ole32.lib;gdi32.lib;hidapi.lib;libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;imm32.lib;ksuser.lib;version.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;MachineIndependentd.lib;GenericCodeGend.lib;Advapi32.lib;user32.lib;zlib.lib;zstd.lib;libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;shell32.lib;Qt6Cored.lib;Qt6Guid.lib;Qt6Widgetsd.lib;Qt6Concurrentd.lib;Qt6Multimediad.lib;Qt6MultimediaWidgetsd.lib;Qt6Svgd.lib;Qt6SvgWidgetsd.lib;7zip.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;SDL.lib;fusion.lib;%(AdditionalDependencies)
+ $(SolutionDir)3rdparty\opencv\opencv\opencv410\build\x64\lib;$(SolutionDir)build\lib\$(Configuration)-$(Platform)\glslang;$(SolutionDir)build\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;$(VULKAN_SDK)\Lib;%(AdditionalLibraryDirectories)
+ Console
+ false
+ 0x10000
+
+
+
+ $(QTDIR)\bin\windeployqt --no-compiler-runtime --no-opengl-sw --no-patchqt --no-translations --no-quick --no-system-d3d-compiler --no-system-dxc-compiler --no-ffmpeg --no-quick-import --plugindir "$(TargetDir)qt6\plugins" --release "$(TargetPath)"
+ xcopy /y /d "$(SolutionDir)3rdparty\opencv\opencv\opencv410\build\x64\bin\opencv_world4100.dll" "$(OutDir)"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
\ No newline at end of file
diff --git a/rpcs3/tests/test.cpp b/rpcs3/tests/test.cpp
new file mode 100644
index 0000000000..818b1066fc
--- /dev/null
+++ b/rpcs3/tests/test.cpp
@@ -0,0 +1,8 @@
+#include
+
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/rpcs3/tests/test_fmt.cpp b/rpcs3/tests/test_fmt.cpp
new file mode 100644
index 0000000000..d494229da3
--- /dev/null
+++ b/rpcs3/tests/test_fmt.cpp
@@ -0,0 +1,21 @@
+#include
+#include "Utilities/StrUtil.h"
+
+namespace fmt
+{
+ TEST(StrUtil, to_upper_to_lower)
+ {
+ const std::string lowercase = "abcdefghijklmnopqrstuvwxyzäüöß0123456789 .,-<#+";
+ const std::string uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZäüöß0123456789 .,-<#+";
+ const std::string to_lower_res = fmt::to_lower(uppercase);
+ const std::string to_upper_res = fmt::to_upper(lowercase);
+
+ EXPECT_EQ(std::string(), fmt::to_lower(""));
+ EXPECT_EQ(lowercase, fmt::to_lower(lowercase));
+ EXPECT_EQ(lowercase, to_lower_res);
+
+ EXPECT_EQ(std::string(), fmt::to_upper(""));
+ EXPECT_EQ(uppercase, fmt::to_upper(uppercase));
+ EXPECT_EQ(uppercase, to_upper_res);
+ }
+}