X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=sidebyside;f=src%2Fporting.cpp;h=caf9e9be340aa58db45e806e6c7cdf7da1f3ece7;hb=54dccc480eb03adcf219a7add58f547284f40f76;hp=02ce6174b881eeb0e64955649a1d8b43b6b51e48;hpb=1dfd977ec43370da6931b11a8d0469792c8ebc36;p=dragonfireclient.git diff --git a/src/porting.cpp b/src/porting.cpp index 02ce6174b..caf9e9be3 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -25,29 +25,40 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) #include #include + extern char **environ; #elif defined(_WIN32) #include #include #include + #include + #include + #include #endif #if !defined(_WIN32) #include #include + #if !defined(__ANDROID__) + #include + #endif #endif #if defined(__hpux) #define _PSTAT64 #include #endif -#if !defined(_WIN32) && !defined(__APPLE__) && \ - !defined(__ANDROID__) && !defined(SERVER) - #define XORG_USED +#if defined(__ANDROID__) + #include "porting_android.h" +#endif +#if defined(__APPLE__) + // For _NSGetEnviron() + // Related: https://gitlab.haskell.org/ghc/ghc/issues/2458 + #include #endif -#ifdef XORG_USED - #include - #include + +#if defined(__HAIKU__) + #include #endif #include "config.h" @@ -55,8 +66,18 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "log.h" #include "util/string.h" -#include "settings.h" #include +#include +#include + +#if !defined(SERVER) && defined(_WIN32) +// On Windows export some driver-specific variables to encourage Minetest to be +// executed on the discrete GPU in case of systems with two. Portability is fun. +extern "C" { + __declspec(dllexport) DWORD NvOptimusEnablement = 1; + __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 1; +} +#endif namespace porting { @@ -67,7 +88,7 @@ namespace porting bool g_killed = false; -bool * signal_handler_killstatus(void) +bool *signal_handler_killstatus() { return &g_killed; } @@ -175,26 +196,32 @@ bool detectMSVCBuildDir(const std::string &path) "bin\\Build", NULL }; - return (removeStringEnd(path, ends) != ""); + return (!removeStringEnd(path, ends).empty()); } std::string get_sysinfo() { #ifdef _WIN32 - OSVERSIONINFO osvi; + std::ostringstream oss; - std::string tmp; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - tmp = osvi.szCSDVersion; - std::replace(tmp.begin(), tmp.end(), ' ', '_'); - - oss << "Windows/" << osvi.dwMajorVersion << "." - << osvi.dwMinorVersion; - if (osvi.szCSDVersion[0]) - oss << "-" << tmp; - oss << " "; + LPSTR filePath = new char[MAX_PATH]; + UINT blockSize; + VS_FIXEDFILEINFO *fixedFileInfo; + + GetSystemDirectoryA(filePath, MAX_PATH); + PathAppendA(filePath, "kernel32.dll"); + + DWORD dwVersionSize = GetFileVersionInfoSizeA(filePath, NULL); + LPBYTE lpVersionInfo = new BYTE[dwVersionSize]; + + GetFileVersionInfoA(filePath, 0, dwVersionSize, lpVersionInfo); + VerQueryValueA(lpVersionInfo, "\\", (LPVOID *)&fixedFileInfo, &blockSize); + + oss << "Windows/" + << HIWORD(fixedFileInfo->dwProductVersionMS) << '.' // Major + << LOWORD(fixedFileInfo->dwProductVersionMS) << '.' // Minor + << HIWORD(fixedFileInfo->dwProductVersionLS) << ' '; // Build + #ifdef _WIN64 oss << "x86_64"; #else @@ -205,6 +232,9 @@ std::string get_sysinfo() oss << "x86"; #endif + delete[] lpVersionInfo; + delete[] filePath; + return oss.str(); #else struct utsname osinfo; @@ -305,6 +335,12 @@ bool getCurrentExecPath(char *buf, size_t len) return true; } +#elif defined(__HAIKU__) + +bool getCurrentExecPath(char *buf, size_t len) +{ + return find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, buf, len) == B_OK; +} //// Solaris #elif defined(__sun) || defined(sun) @@ -349,6 +385,21 @@ bool getCurrentExecPath(char *buf, size_t len) #endif +//// Non-Windows +#if !defined(_WIN32) + +const char *getHomeOrFail() +{ + const char *home = getenv("HOME"); + // In rare cases the HOME environment variable may be unset + FATAL_ERROR_IF(!home, + "Required environment variable HOME is not set"); + return home; +} + +#endif + + //// Windows #if defined(_WIN32) @@ -361,20 +412,27 @@ bool setSystemPaths() "Failed to get current executable path"); pathRemoveFile(buf, '\\'); + std::string exepath(buf); + // Use ".\bin\.." - path_share = std::string(buf) + "\\.."; + path_share = exepath + "\\.."; + if (detectMSVCBuildDir(exepath)) { + // The msvc build dir schould normaly not be present if properly installed, + // but its usefull for debugging. + path_share += DIR_DELIM ".."; + } - // Use "C:\Documents and Settings\user\Application Data\" + // Use "C:\Users\\AppData\Roaming\" DWORD len = GetEnvironmentVariable("APPDATA", buf, sizeof(buf)); FATAL_ERROR_IF(len == 0 || len > sizeof(buf), "Failed to get APPDATA"); - path_user = std::string(buf) + DIR_DELIM + PROJECT_NAME; + path_user = std::string(buf) + DIR_DELIM + PROJECT_NAME_C; return true; } //// Linux -#elif defined(__linux__) +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) bool setSystemPaths() { @@ -396,7 +454,7 @@ bool setSystemPaths() // It is identified by containing the subdirectory "builtin". std::list trylist; std::string static_sharedir = STATIC_SHAREDIR; - if (static_sharedir != "" && static_sharedir != ".") + if (!static_sharedir.empty() && static_sharedir != ".") trylist.push_back(static_sharedir); trylist.push_back(bindir + DIR_DELIM ".." DIR_DELIM "share" @@ -408,7 +466,7 @@ bool setSystemPaths() #endif for (std::list::const_iterator - i = trylist.begin(); i != trylist.end(); i++) { + i = trylist.begin(); i != trylist.end(); ++i) { const std::string &trypath = *i; if (!fs::PathExists(trypath) || !fs::PathExists(trypath + DIR_DELIM + "builtin")) { @@ -428,7 +486,7 @@ bool setSystemPaths() } #ifndef __ANDROID__ - path_user = std::string(getenv("HOME")) + DIR_DELIM "." + path_user = std::string(getHomeOrFail()) + DIR_DELIM "." + PROJECT_NAME; #endif @@ -452,7 +510,7 @@ bool setSystemPaths() } CFRelease(resources_url); - path_user = std::string(getenv("HOME")) + path_user = std::string(getHomeOrFail()) + "/Library/Application Support/" + PROJECT_NAME; return true; @@ -464,7 +522,7 @@ bool setSystemPaths() bool setSystemPaths() { path_share = STATIC_SHAREDIR; - path_user = std::string(getenv("HOME")) + DIR_DELIM "." + path_user = std::string(getHomeOrFail()) + DIR_DELIM "." + lowercase(PROJECT_NAME); return true; } @@ -542,6 +600,10 @@ void initializePaths() if (!setSystemPaths()) errorstream << "Failed to get one or more system-wide path" << std::endl; + +# ifdef _WIN32 + path_cache = path_user + DIR_DELIM + "cache"; +# else // Initialize path_cache // First try $XDG_CACHE_HOME/PROJECT_NAME const char *cache_dir = getenv("XDG_CACHE_HOME"); @@ -558,27 +620,28 @@ void initializePaths() } // Migrate cache folder to new location if possible migrateCachePath(); -#endif +# endif // _WIN32 +#endif // RUN_IN_PLACE infostream << "Detected share path: " << path_share << std::endl; infostream << "Detected user path: " << path_user << std::endl; infostream << "Detected cache path: " << path_cache << std::endl; -#ifdef USE_GETTEXT +#if USE_GETTEXT bool found_localedir = false; # ifdef STATIC_LOCALEDIR - if (STATIC_LOCALEDIR[0] && fs::PathExists(STATIC_LOCALEDIR)) { + /* STATIC_LOCALEDIR may be a generalized path such as /usr/share/locale that + * doesn't necessarily contain our locale files, so check data path first. */ + path_locale = getDataPath("locale"); + if (fs::PathExists(path_locale)) { + found_localedir = true; + infostream << "Using in-place locale directory " << path_locale + << " even though a static one was provided." << std::endl; + } else if (STATIC_LOCALEDIR[0] && fs::PathExists(STATIC_LOCALEDIR)) { found_localedir = true; path_locale = STATIC_LOCALEDIR; - infostream << "Using locale directory " << STATIC_LOCALEDIR << std::endl; - } else { - path_locale = getDataPath("locale"); - if (fs::PathExists(path_locale)) { - found_localedir = true; - infostream << "Using in-place locale directory " << path_locale - << " even though a static one was provided " - << "(RUN_IN_PLACE or CUSTOM_LOCALEDIR)." << std::endl; - } + infostream << "Using static locale directory " << STATIC_LOCALEDIR + << std::endl; } # else path_locale = getDataPath("locale"); @@ -592,165 +655,6 @@ void initializePaths() #endif // USE_GETTEXT } - - -void setXorgClassHint(const video::SExposedVideoData &video_data, - const std::string &name) -{ -#ifdef XORG_USED - if (video_data.OpenGLLinux.X11Display == NULL) - return; - - XClassHint *classhint = XAllocClassHint(); - classhint->res_name = (char *)name.c_str(); - classhint->res_class = (char *)name.c_str(); - - XSetClassHint((Display *)video_data.OpenGLLinux.X11Display, - video_data.OpenGLLinux.X11Window, classhint); - XFree(classhint); -#endif -} - - -//// -//// Video/Display Information (Client-only) -//// - -#ifndef SERVER - -static irr::IrrlichtDevice *device; - -void initIrrlicht(irr::IrrlichtDevice *device_) -{ - device = device_; -} - -v2u32 getWindowSize() -{ - return device->getVideoDriver()->getScreenSize(); -} - - -std::vector > getSupportedVideoModes() -{ - IrrlichtDevice *nulldevice = createDevice(video::EDT_NULL); - sanity_check(nulldevice != NULL); - - std::vector > mlist; - video::IVideoModeList *modelist = nulldevice->getVideoModeList(); - - u32 num_modes = modelist->getVideoModeCount(); - for (u32 i = 0; i != num_modes; i++) { - core::dimension2d mode_res = modelist->getVideoModeResolution(i); - s32 mode_depth = modelist->getVideoModeDepth(i); - mlist.push_back(core::vector3d(mode_res.Width, mode_res.Height, mode_depth)); - } - - nulldevice->drop(); - - return mlist; -} - -std::vector getSupportedVideoDrivers() -{ - std::vector drivers; - - for (int i = 0; i != irr::video::EDT_COUNT; i++) { - if (irr::IrrlichtDevice::isDriverSupported((irr::video::E_DRIVER_TYPE)i)) - drivers.push_back((irr::video::E_DRIVER_TYPE)i); - } - - return drivers; -} - -const char *getVideoDriverName(irr::video::E_DRIVER_TYPE type) -{ - static const char *driver_ids[] = { - "null", - "software", - "burningsvideo", - "direct3d8", - "direct3d9", - "opengl", - "ogles1", - "ogles2", - }; - - return driver_ids[type]; -} - - -const char *getVideoDriverFriendlyName(irr::video::E_DRIVER_TYPE type) -{ - static const char *driver_names[] = { - "NULL Driver", - "Software Renderer", - "Burning's Video", - "Direct3D 8", - "Direct3D 9", - "OpenGL", - "OpenGL ES1", - "OpenGL ES2", - }; - - return driver_names[type]; -} - -# ifndef __ANDROID__ -# ifdef XORG_USED - -static float calcDisplayDensity() -{ - const char *current_display = getenv("DISPLAY"); - - if (current_display != NULL) { - Display *x11display = XOpenDisplay(current_display); - - if (x11display != NULL) { - /* try x direct */ - float dpi_height = floor(DisplayHeight(x11display, 0) / - (DisplayHeightMM(x11display, 0) * 0.039370) + 0.5); - float dpi_width = floor(DisplayWidth(x11display, 0) / - (DisplayWidthMM(x11display, 0) * 0.039370) + 0.5); - - XCloseDisplay(x11display); - - return std::max(dpi_height,dpi_width) / 96.0; - } - } - - /* return manually specified dpi */ - return g_settings->getFloat("screen_dpi")/96.0; -} - - -float getDisplayDensity() -{ - static float cached_display_density = calcDisplayDensity(); - return cached_display_density; -} - - -# else // XORG_USED -float getDisplayDensity() -{ - return g_settings->getFloat("screen_dpi")/96.0; -} -# endif // XORG_USED - -v2u32 getDisplaySize() -{ - IrrlichtDevice *nulldevice = createDevice(video::EDT_NULL); - - core::dimension2d deskres = nulldevice->getVideoModeList()->getDesktopResolution(); - nulldevice -> drop(); - - return deskres; -} -# endif // __ANDROID__ -#endif // SERVER - - //// //// OS-specific Secure Random //// @@ -790,4 +694,98 @@ bool secure_rand_fill_buf(void *buf, size_t len) #endif +void attachOrCreateConsole() +{ +#ifdef _WIN32 + static bool consoleAllocated = false; + const bool redirected = (_fileno(stdout) == -2 || _fileno(stdout) == -1); // If output is redirected to e.g a file + if (!consoleAllocated && redirected && (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole())) { + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + consoleAllocated = true; + } +#endif +} + +int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...) +{ + // https://msdn.microsoft.com/en-us/library/bt7tawza.aspx + // Many of the MSVC / Windows printf-style functions do not support positional + // arguments (eg. "%1$s"). We just forward the call to vsnprintf for sane + // platforms, but defer to _vsprintf_p on MSVC / Windows. + // https://github.com/FFmpeg/FFmpeg/blob/5ae9fa13f5ac640bec113120d540f70971aa635d/compat/msvcrt/snprintf.c#L46 + // _vsprintf_p has to be shimmed with _vscprintf_p on -1 (for an example see + // above FFmpeg link). + va_list args; + va_start(args, fmt); +#ifndef _MSC_VER + int c = vsnprintf(buf, buf_size, fmt, args); +#else // _MSC_VER + int c = _vsprintf_p(buf, buf_size, fmt, args); + if (c == -1) + c = _vscprintf_p(fmt, args); +#endif // _MSC_VER + va_end(args); + return c; +} + +static bool open_uri(const std::string &uri) +{ + if (uri.find_first_of("\r\n") != std::string::npos) { + errorstream << "Unable to open URI as it is invalid, contains new line: " << uri << std::endl; + return false; + } + +#if defined(_WIN32) + return (intptr_t)ShellExecuteA(NULL, NULL, uri.c_str(), NULL, NULL, SW_SHOWNORMAL) > 32; +#elif defined(__ANDROID__) + openURIAndroid(uri); + return true; +#elif defined(__APPLE__) + const char *argv[] = {"open", uri.c_str(), NULL}; + return posix_spawnp(NULL, "open", NULL, NULL, (char**)argv, + (*_NSGetEnviron())) == 0; +#else + const char *argv[] = {"xdg-open", uri.c_str(), NULL}; + return posix_spawnp(NULL, "xdg-open", NULL, NULL, (char**)argv, environ) == 0; +#endif +} + +bool open_url(const std::string &url) +{ + if (url.substr(0, 7) != "http://" && url.substr(0, 8) != "https://") { + errorstream << "Unable to open browser as URL is missing schema: " << url << std::endl; + return false; + } + + return open_uri(url); +} + +bool open_directory(const std::string &path) +{ + if (!fs::IsDir(path)) { + errorstream << "Unable to open directory as it does not exist: " << path << std::endl; + return false; + } + + return open_uri(path); +} + +// Load performance counter frequency only once at startup +#ifdef _WIN32 + +inline double get_perf_freq() +{ + // Also use this opportunity to enable high-res timers + timeBeginPeriod(1); + + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + return freq.QuadPart; +} + +double perf_freq = get_perf_freq(); + +#endif + } //namespace porting