aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp')
-rw-r--r--Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp551
1 files changed, 551 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp b/Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp
new file mode 100644
index 00000000..b86d768a
--- /dev/null
+++ b/Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp
@@ -0,0 +1,551 @@
+/*
+ * mptOS.cpp
+ * ---------
+ * Purpose: Operating system version information.
+ * Notes : (currently none)
+ * Authors: OpenMPT Devs
+ * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
+ */
+
+
+#include "stdafx.h"
+#include "mptOS.h"
+
+#include "mpt/binary/hex.hpp"
+
+#if MPT_OS_WINDOWS
+#include <windows.h>
+#endif
+
+
+OPENMPT_NAMESPACE_BEGIN
+
+
+namespace mpt
+{
+namespace OS
+{
+namespace Windows
+{
+
+
+#if MPT_OS_WINDOWS
+
+namespace {
+struct WindowsVersionCache
+{
+ mpt::osinfo::windows::Version version;
+ WindowsVersionCache() noexcept
+ : version(mpt::osinfo::windows::Version::Current())
+ {
+ }
+};
+}
+
+static mpt::osinfo::windows::Version GatherWindowsVersionFromCache() noexcept
+{
+ static WindowsVersionCache gs_WindowsVersionCache;
+ return gs_WindowsVersionCache.version;
+}
+
+#endif // MPT_OS_WINDOWS
+
+
+mpt::osinfo::windows::Version Version::Current() noexcept
+{
+ #if MPT_OS_WINDOWS
+ #ifdef MODPLUG_TRACKER
+ return GatherWindowsVersionFromCache();
+ #else // !MODPLUG_TRACKER
+ return mpt::osinfo::windows::Version::Current();
+ #endif // MODPLUG_TRACKER
+ #else // !MPT_OS_WINDOWS
+ return mpt::osinfo::windows::Version::NoWindows();
+ #endif // MPT_OS_WINDOWS
+}
+
+
+static constexpr struct { mpt::osinfo::windows::Version version; const mpt::uchar * name; bool showDetails; } versionMap[] =
+{
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinNewer, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 22000, 0 }, UL_("Windows 11 (or newer)"), false },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 22000, 0 }, UL_("Windows 11"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 19044, 0 }, UL_("Windows 10 21H2"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 19043, 0 }, UL_("Windows 10 21H1"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 19042, 0 }, UL_("Windows 10 20H2"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 19041, 0 }, UL_("Windows 10 2004"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 18363, 0 }, UL_("Windows 10 1909"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 18362, 0 }, UL_("Windows 10 1903"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 17763, 0 }, UL_("Windows 10 1809"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 17134, 0 }, UL_("Windows 10 1803"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 16299, 0 }, UL_("Windows 10 1709"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 15063, 0 }, UL_("Windows 10 1703"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 14393, 0 }, UL_("Windows 10 1607"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 10586, 0 }, UL_("Windows 10 1511"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 10240, 0 }, UL_("Windows 10 1507"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win81, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 8.1"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win8, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 8"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win7, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 7"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinVista, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows Vista"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinXP64, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows XP x64 / Windows Server 2003"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinXP, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows XP"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win2000, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 2000"), true },
+ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinNT4, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows NT4"), true }
+};
+
+
+mpt::ustring Version::GetName(mpt::osinfo::windows::Version version)
+{
+ mpt::ustring name = U_("Generic Windows NT");
+ bool showDetails = false;
+ for(const auto &v : versionMap)
+ {
+ if(version.IsAtLeast(v.version))
+ {
+ name = v.name;
+ showDetails = v.showDetails;
+ break;
+ }
+ }
+ name += U_(" (");
+ name += MPT_UFORMAT("Version {}.{}")(version.GetSystem().Major, version.GetSystem().Minor);
+ if(showDetails)
+ {
+ if(version.GetServicePack().HasServicePack())
+ {
+ if(version.GetServicePack().Minor)
+ {
+ name += MPT_UFORMAT(" Service Pack {}.{}")(version.GetServicePack().Major, version.GetServicePack().Minor);
+ } else
+ {
+ name += MPT_UFORMAT(" Service Pack {}")(version.GetServicePack().Major);
+ }
+ }
+ if(version.GetBuild() != 0)
+ {
+ name += MPT_UFORMAT(" (Build {})")(version.GetBuild());
+ }
+ }
+ name += U_(")");
+ mpt::ustring result = name;
+ #if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
+ if(mpt::OS::Windows::IsWine())
+ {
+ mpt::OS::Wine::VersionContext v;
+ if(v.Version().IsValid())
+ {
+ result = MPT_UFORMAT("Wine {} ({})")(
+ v.Version().AsString()
+ , name
+ );
+ } else
+ {
+ result = MPT_UFORMAT("Wine (unknown version: '{}') ({})")(
+ mpt::ToUnicode(mpt::Charset::UTF8, v.RawVersion())
+ , name
+ );
+ }
+ }
+ #endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
+ return result;
+}
+
+
+mpt::osinfo::windows::Version Version::GetMinimumKernelLevel() noexcept
+{
+ uint64 minimumKernelVersion = 0;
+ #if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
+ #if defined(MPT_BUILD_RETRO)
+ minimumKernelVersion = std::max(minimumKernelVersion, static_cast<uint64>(mpt::osinfo::windows::Version::WinXP));
+ #else
+ minimumKernelVersion = std::max(minimumKernelVersion, static_cast<uint64>(mpt::osinfo::windows::Version::WinVista));
+ #endif
+ #endif
+ return mpt::osinfo::windows::Version(mpt::osinfo::windows::Version::System(minimumKernelVersion), mpt::osinfo::windows::Version::ServicePack(0, 0), 0, 0);
+}
+
+
+mpt::osinfo::windows::Version Version::GetMinimumAPILevel() noexcept
+{
+ #if MPT_OS_WINDOWS
+ return mpt::osinfo::windows::Version::FromSDK();
+ #else // !MPT_OS_WINDOWS
+ return mpt::osinfo::windows::Version::NoWindows();
+ #endif // MPT_OS_WINDOWS
+}
+
+
+#if MPT_OS_WINDOWS
+
+
+#ifndef PROCESSOR_ARCHITECTURE_NEUTRAL
+#define PROCESSOR_ARCHITECTURE_NEUTRAL 11
+#endif
+#ifndef PROCESSOR_ARCHITECTURE_ARM64
+#define PROCESSOR_ARCHITECTURE_ARM64 12
+#endif
+#ifndef PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64
+#define PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64 13
+#endif
+#ifndef PROCESSOR_ARCHITECTURE_IA32_ON_ARM64
+#define PROCESSOR_ARCHITECTURE_IA32_ON_ARM64 14
+#endif
+
+
+struct OSArchitecture
+{
+ uint16 ProcessorArchitectur;
+ Architecture Host;
+ Architecture Process;
+};
+static constexpr OSArchitecture architectures [] = {
+ { PROCESSOR_ARCHITECTURE_INTEL , Architecture::x86 , Architecture::x86 },
+ { PROCESSOR_ARCHITECTURE_AMD64 , Architecture::amd64 , Architecture::amd64 },
+ { PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 , Architecture::amd64 , Architecture::x86 },
+ { PROCESSOR_ARCHITECTURE_ARM , Architecture::arm , Architecture::arm },
+ { PROCESSOR_ARCHITECTURE_ARM64 , Architecture::arm64 , Architecture::arm64 },
+ { PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64, Architecture::arm64 , Architecture::arm },
+ { PROCESSOR_ARCHITECTURE_IA32_ON_ARM64 , Architecture::arm64 , Architecture::x86 },
+ { PROCESSOR_ARCHITECTURE_MIPS , Architecture::mips , Architecture::mips },
+ { PROCESSOR_ARCHITECTURE_PPC , Architecture::ppc , Architecture::ppc },
+ { PROCESSOR_ARCHITECTURE_SHX , Architecture::shx , Architecture::shx },
+ { PROCESSOR_ARCHITECTURE_ALPHA , Architecture::alpha , Architecture::alpha },
+ { PROCESSOR_ARCHITECTURE_ALPHA64 , Architecture::alpha64, Architecture::alpha64 },
+ { PROCESSOR_ARCHITECTURE_IA64 , Architecture::ia64 , Architecture::ia64 },
+ { PROCESSOR_ARCHITECTURE_MSIL , Architecture::unknown, Architecture::unknown },
+ { PROCESSOR_ARCHITECTURE_NEUTRAL , Architecture::unknown, Architecture::unknown },
+ { PROCESSOR_ARCHITECTURE_UNKNOWN , Architecture::unknown, Architecture::unknown }
+};
+
+
+struct HostArchitecture
+{
+ Architecture Host;
+ Architecture Process;
+ EmulationLevel Emulation;
+};
+static constexpr HostArchitecture hostArchitectureCanRun [] = {
+ { Architecture::x86 , Architecture::x86 , EmulationLevel::Native },
+ { Architecture::amd64 , Architecture::amd64 , EmulationLevel::Native },
+ { Architecture::amd64 , Architecture::x86 , EmulationLevel::Virtual },
+ { Architecture::arm , Architecture::arm , EmulationLevel::Native },
+ { Architecture::arm64 , Architecture::arm64 , EmulationLevel::Native },
+ { Architecture::arm64 , Architecture::arm , EmulationLevel::Virtual },
+ { Architecture::arm64 , Architecture::x86 , EmulationLevel::Software },
+ { Architecture::arm64 , Architecture::amd64 , EmulationLevel::Software },
+ { Architecture::mips , Architecture::mips , EmulationLevel::Native },
+ { Architecture::ppc , Architecture::ppc , EmulationLevel::Native },
+ { Architecture::shx , Architecture::shx , EmulationLevel::Native },
+ { Architecture::alpha , Architecture::alpha , EmulationLevel::Native },
+ { Architecture::alpha64, Architecture::alpha64, EmulationLevel::Native },
+ { Architecture::alpha64, Architecture::alpha , EmulationLevel::Virtual },
+ { Architecture::ia64 , Architecture::ia64 , EmulationLevel::Native },
+ { Architecture::ia64 , Architecture::x86 , EmulationLevel::Hardware }
+};
+
+
+struct ArchitectureInfo
+{
+ Architecture Arch;
+ int Bitness;
+ const mpt::uchar * Name;
+};
+static constexpr ArchitectureInfo architectureInfo [] = {
+ { Architecture::x86 , 32, UL_("x86") },
+ { Architecture::amd64 , 64, UL_("amd64") },
+ { Architecture::arm , 32, UL_("arm") },
+ { Architecture::arm64 , 64, UL_("arm64") },
+ { Architecture::mips , 32, UL_("mips") },
+ { Architecture::ppc , 32, UL_("ppc") },
+ { Architecture::shx , 32, UL_("shx") },
+ { Architecture::alpha , 32, UL_("alpha") },
+ { Architecture::alpha64, 64, UL_("alpha64") },
+ { Architecture::ia64 , 64, UL_("ia64") }
+};
+
+
+int Bitness(Architecture arch) noexcept
+{
+ for(const auto &info : architectureInfo)
+ {
+ if(arch == info.Arch)
+ {
+ return info.Bitness;
+ }
+ }
+ return 0;
+}
+
+
+mpt::ustring Name(Architecture arch)
+{
+ for(const auto &info : architectureInfo)
+ {
+ if(arch == info.Arch)
+ {
+ return info.Name;
+ }
+ }
+ return mpt::ustring();
+}
+
+
+Architecture GetHostArchitecture() noexcept
+{
+ SYSTEM_INFO systemInfo = {};
+ GetNativeSystemInfo(&systemInfo);
+ for(const auto &arch : architectures)
+ {
+ if(systemInfo.wProcessorArchitecture == arch.ProcessorArchitectur)
+ {
+ return arch.Host;
+ }
+ }
+ return Architecture::unknown;
+}
+
+
+Architecture GetProcessArchitecture() noexcept
+{
+ SYSTEM_INFO systemInfo = {};
+ GetSystemInfo(&systemInfo);
+ for(const auto &arch : architectures)
+ {
+ if(systemInfo.wProcessorArchitecture == arch.ProcessorArchitectur)
+ {
+ return arch.Process;
+ }
+ }
+ return Architecture::unknown;
+}
+
+
+EmulationLevel HostCanRun(Architecture host, Architecture process) noexcept
+{
+ for(const auto & can : hostArchitectureCanRun)
+ {
+ if(can.Host == host && can.Process == process)
+ {
+ return can.Emulation;
+ }
+ }
+ return EmulationLevel::NA;
+}
+
+
+std::vector<Architecture> GetSupportedProcessArchitectures(Architecture host)
+{
+ std::vector<Architecture> result;
+ for(const auto & entry : hostArchitectureCanRun)
+ {
+ if(entry.Host == host)
+ {
+ result.push_back(entry.Process);
+ }
+ }
+ return result;
+}
+
+
+uint64 GetSystemMemorySize()
+{
+ MEMORYSTATUSEX memoryStatus = {};
+ memoryStatus.dwLength = sizeof(MEMORYSTATUSEX);
+ if(GlobalMemoryStatusEx(&memoryStatus) == 0)
+ {
+ return 0;
+ }
+ return memoryStatus.ullTotalPhys;
+}
+
+
+#endif // MPT_OS_WINDOWS
+
+
+#if defined(MODPLUG_TRACKER)
+
+
+#if MPT_OS_WINDOWS
+
+static bool GatherSystemIsWine()
+{
+ bool SystemIsWine = false;
+ std::optional<mpt::library> NTDLL = mpt::library::load({ mpt::library::path_search::system, mpt::library::path_prefix::none, MPT_PATH("ntdll.dll"), mpt::library::path_suffix::none });
+ if(NTDLL)
+ {
+ SystemIsWine = (NTDLL->get_address("wine_get_version") != nullptr);
+ }
+ return SystemIsWine;
+}
+
+namespace {
+struct SystemIsWineCache
+{
+ bool SystemIsWine;
+ SystemIsWineCache()
+ : SystemIsWine(GatherSystemIsWine())
+ {
+ return;
+ }
+ SystemIsWineCache(bool isWine)
+ : SystemIsWine(isWine)
+ {
+ return;
+ }
+};
+}
+
+#endif // MPT_OS_WINDOWS
+
+static bool SystemIsWine(bool allowDetection = true)
+{
+ #if MPT_OS_WINDOWS
+ static SystemIsWineCache gs_SystemIsWineCache = allowDetection ? SystemIsWineCache() : SystemIsWineCache(false);
+ if(!allowDetection)
+ { // catch too late calls of PreventWineDetection
+ MPT_ASSERT(!gs_SystemIsWineCache.SystemIsWine);
+ }
+ return gs_SystemIsWineCache.SystemIsWine;
+ #else
+ MPT_UNREFERENCED_PARAMETER(allowDetection);
+ return false;
+ #endif
+}
+
+void PreventWineDetection()
+{
+ SystemIsWine(false);
+}
+
+bool IsOriginal()
+{
+ return mpt::OS::Windows::Version::Current().IsWindows() && !SystemIsWine();
+}
+
+bool IsWine()
+{
+ return mpt::OS::Windows::Version::Current().IsWindows() && SystemIsWine();
+}
+
+
+#endif // MODPLUG_TRACKER
+
+
+} // namespace Windows
+} // namespace OS
+} // namespace mpt
+
+
+
+namespace mpt
+{
+namespace OS
+{
+namespace Wine
+{
+
+
+Version::Version()
+{
+ return;
+}
+
+
+Version::Version(const mpt::ustring &rawVersion)
+ : mpt::osinfo::windows::wine::version()
+{
+ if(rawVersion.empty())
+ {
+ return;
+ }
+ std::vector<uint8> version = mpt::String::Split<uint8>(rawVersion, U_("."));
+ if(version.size() < 2)
+ {
+ return;
+ }
+ mpt::ustring parsedVersion = mpt::String::Combine(version, U_("."));
+ std::size_t len = std::min(parsedVersion.length(), rawVersion.length());
+ if(len == 0)
+ {
+ return;
+ }
+ if(parsedVersion.substr(0, len) != rawVersion.substr(0, len))
+ {
+ return;
+ }
+ valid = true;
+ vmajor = version[0];
+ vminor = version[1];
+ vupdate = (version.size() >= 3) ? version[2] : 0;
+}
+
+
+Version::Version(uint8 vmajor, uint8 vminor, uint8 vupdate)
+ : mpt::osinfo::windows::wine::version(vmajor, vminor, vupdate)
+{
+ return;
+}
+
+
+mpt::ustring Version::AsString() const
+{
+ return mpt::ufmt::dec(GetMajor()) + U_(".") + mpt::ufmt::dec(GetMinor()) + U_(".") + mpt::ufmt::dec(GetUpdate());
+}
+
+
+
+mpt::OS::Wine::Version GetMinimumWineVersion()
+{
+ mpt::OS::Wine::Version minimumWineVersion = mpt::OS::Wine::Version(0,0,0);
+ #if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
+ minimumWineVersion = mpt::OS::Wine::Version(1,8,0);
+ #endif
+ return minimumWineVersion;
+}
+
+
+VersionContext::VersionContext()
+ : m_IsWine(false)
+ , m_HostClass(mpt::osinfo::osclass::Unknown)
+{
+ #if MPT_OS_WINDOWS
+ m_IsWine = mpt::OS::Windows::IsWine();
+ if(!m_IsWine)
+ {
+ return;
+ }
+ std::optional<mpt::library> NTDLL = mpt::library::load({mpt::library::path_search::system, mpt::library::path_prefix::none, MPT_PATH("ntdll.dll"), mpt::library::path_suffix::none});
+ if(NTDLL)
+ {
+ const char * (__cdecl * wine_get_version)(void) = nullptr;
+ const char * (__cdecl * wine_get_build_id)(void) = nullptr;
+ void (__cdecl * wine_get_host_version)(const char * *, const char * *) = nullptr;
+ NTDLL->bind(wine_get_version, "wine_get_version");
+ NTDLL->bind(wine_get_build_id, "wine_get_build_id");
+ NTDLL->bind(wine_get_host_version, "wine_get_host_version");
+ const char * wine_version = nullptr;
+ const char * wine_build_id = nullptr;
+ const char * wine_host_sysname = nullptr;
+ const char * wine_host_release = nullptr;
+ wine_version = wine_get_version ? wine_get_version() : "";
+ wine_build_id = wine_get_build_id ? wine_get_build_id() : "";
+ if(wine_get_host_version)
+ {
+ wine_get_host_version(&wine_host_sysname, &wine_host_release);
+ }
+ m_RawVersion = wine_version ? wine_version : "";
+ m_RawBuildID = wine_build_id ? wine_build_id : "";
+ m_RawHostSysName = wine_host_sysname ? wine_host_sysname : "";
+ m_RawHostRelease = wine_host_release ? wine_host_release : "";
+ }
+ m_Version = mpt::OS::Wine::Version(mpt::ToUnicode(mpt::Charset::UTF8, m_RawVersion));
+ m_HostClass = mpt::osinfo::get_class_from_sysname(m_RawHostSysName);
+ #endif // MPT_OS_WINDOWS
+}
+
+
+} // namespace Wine
+} // namespace OS
+} // namespace mpt
+
+
+OPENMPT_NAMESPACE_END