From a95bcc10f6eb64479c381f55939670017e42081f Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Tue, 19 Sep 2023 04:59:40 +0100 Subject: [PATCH] Windows 9x MinGW build (#6619) --- .github/workflows/Windows9x_MinGW.yml | 66 ++++++++++++++++++++++++ 3rdParty/libfmt/CMakeLists.txt | 20 +++---- 3rdParty/libmpq/CMakeLists.txt | 8 ++- CMake/Platforms.cmake | 4 +- CMake/platforms/mingw9x.toolchain.cmake | 25 +++++++++ CMake/platforms/mingw9x/include/windef.h | 22 ++++++++ CMake/platforms/windows9x.cmake | 38 ++++++++++++++ CMakeLists.txt | 2 +- Packaging/windows/mingw-prep.sh | 4 ++ Packaging/windows/mingw9x-prep.sh | 48 +++++++++++++++++ Source/utils/file_util.cpp | 43 +++++++++++++-- Source/utils/sdl2_to_1_2_backports.cpp | 49 +++++++++++++----- Source/utils/stdcompat/filesystem.hpp | 3 +- 13 files changed, 298 insertions(+), 34 deletions(-) create mode 100644 .github/workflows/Windows9x_MinGW.yml create mode 100644 CMake/platforms/mingw9x.toolchain.cmake create mode 100644 CMake/platforms/mingw9x/include/windef.h create mode 100644 CMake/platforms/windows9x.cmake create mode 100755 Packaging/windows/mingw9x-prep.sh diff --git a/.github/workflows/Windows9x_MinGW.yml b/.github/workflows/Windows9x_MinGW.yml new file mode 100644 index 000000000..d715f50bc --- /dev/null +++ b/.github/workflows/Windows9x_MinGW.yml @@ -0,0 +1,66 @@ +name: Windows 9x MinGW + +on: + push: + branches: + - master + paths-ignore: + - '*.md' + - 'docs/**' + pull_request: + types: [ opened, synchronize ] + paths-ignore: + - '*.md' + - 'docs/**' + release: + types: [published] + paths-ignore: + - '*.md' + - 'docs/**' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Create Build Environment + run: > + sudo apt-get update && + sudo apt-get install -y cmake gcc-mingw-w64-i686 g++-mingw-w64-i686 mingw-w64-tools libz-mingw-w64-dev gettext dpkg-dev wget git sudo smpq && + sudo rm /usr/i686-w64-mingw32/lib/libz.dll.a && + sudo Packaging/windows/mingw9x-prep.sh + + - name: Configure CMake + shell: bash + working-directory: ${{github.workspace}} + run: cmake -S. -Bbuild-windows9x -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DCPACK=ON -DCMAKE_TOOLCHAIN_FILE=../CMake/platforms/mingw9x.toolchain.cmake -DTARGET_PLATORM=windows9x + + - name: Build + working-directory: ${{github.workspace}} + shell: bash + run: | + cmake --build build-windows9x -j $(nproc) --target package + mv build-windows9x/devilutionx.zip devilutionx-win9x.zip + + - name: Upload-Package + if: ${{ !env.ACT }} + uses: actions/upload-artifact@v3 + with: + path: devilutionx-win9x.zip + + - name: Update Release + if: ${{ github.event_name == 'release' && !env.ACT }} + uses: svenstaro/upload-release-action@v2 + with: + file: devilutionx-win9x.zip + overwrite: true + diff --git a/3rdParty/libfmt/CMakeLists.txt b/3rdParty/libfmt/CMakeLists.txt index 23ad7fa8d..71fa3fdce 100644 --- a/3rdParty/libfmt/CMakeLists.txt +++ b/3rdParty/libfmt/CMakeLists.txt @@ -15,16 +15,12 @@ else() set(BUILD_SHARED_LIBS ON) endif() include(FetchContent) -if(NXDK) - # branch: nxdk-v10.0.0 - FetchContent_Declare(libfmt - URL https://github.com/diasurgical/fmt/archive/e421e854efcb21ee641349bab604d91b34af26b8.tar.gz - URL_HASH MD5=ebaac86fca56d4ef4a162ef125433f6f - ) -else() - FetchContent_Declare(libfmt - URL https://github.com/fmtlib/fmt/archive/refs/tags/10.1.1.tar.gz - URL_HASH MD5=0d41a16f1b3878d44e6fd7ff1f6cc45a - ) -endif() +FetchContent_Declare(libfmt + URL https://github.com/fmtlib/fmt/archive/a8a73da7e44e26d7c18d752976522eff7a21e0bf.tar.gz + URL_HASH MD5=4ddd617a0921e919f1c2e6ab7c36c349 +) FetchContent_MakeAvailableExcludeFromAll(libfmt) + +if(DEVILUTIONX_WINDOWS_NO_WCHAR) + target_compile_definitions(fmt PUBLIC FMT_WINDOWS_NO_WCHAR) +endif() diff --git a/3rdParty/libmpq/CMakeLists.txt b/3rdParty/libmpq/CMakeLists.txt index 0717f753f..a5269ea3a 100644 --- a/3rdParty/libmpq/CMakeLists.txt +++ b/3rdParty/libmpq/CMakeLists.txt @@ -10,8 +10,8 @@ include(functions/FetchContent_MakeAvailableExcludeFromAll) include(FetchContent) FetchContent_Declare(libmpq - URL https://github.com/diasurgical/libmpq/archive/2cf61ebd1ce78082e20dc1e23bd9d66aec7fc0d5.tar.gz - URL_HASH MD5=073d634575465e57d679a7498a666fe3 + URL https://github.com/diasurgical/libmpq/archive/fc2ec5c0a83106f971602dec06dcdbc50a8bd5d4.tar.gz + URL_HASH MD5=1b3964264015792387f71f3f2325661d ) FetchContent_MakeAvailableExcludeFromAll(libmpq) @@ -32,3 +32,7 @@ target_link_libraries(libmpq PRIVATE ZLIB::ZLIB BZip2::BZip2) if(LIBMPQ_FILE_BUFFER_SIZE) target_compile_definitions(libmpq PRIVATE "LIBMPQ_FILE_BUFFER_SIZE=${LIBMPQ_FILE_BUFFER_SIZE}") endif() + +if(DEVILUTIONX_WINDOWS_NO_WCHAR) + target_compile_definitions(libmpq PRIVATE LIBMPQ_WINDOWS_NO_WCHAR) +endif() diff --git a/CMake/Platforms.cmake b/CMake/Platforms.cmake index 56e138f1b..b60f98950 100644 --- a/CMake/Platforms.cmake +++ b/CMake/Platforms.cmake @@ -18,7 +18,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD|OpenBSD|DragonFly|NetBSD") endif() set(TARGET_PLATFORM host CACHE STRING "Target platform") -set_property(CACHE TARGET_PLATFORM PROPERTY STRINGS host retrofw rg99 rg350 gkd350h cpigamesh miyoo_mini) +set_property(CACHE TARGET_PLATFORM PROPERTY STRINGS host retrofw rg99 rg350 gkd350h cpigamesh miyoo_mini windows9x) if(TARGET_PLATFORM STREQUAL "retrofw") include(platforms/retrofw) elseif(TARGET_PLATFORM STREQUAL "rg99") @@ -33,6 +33,8 @@ elseif(TARGET_PLATFORM STREQUAL "lepus") include(platforms/lepus) elseif(TARGET_PLATFORM STREQUAL "miyoo_mini") include(platforms/miyoo_mini) +elseif(TARGET_PLATORM STREQUAL "windows9x") + include(platforms/windows9x) endif() if(NINTENDO_SWITCH) diff --git a/CMake/platforms/mingw9x.toolchain.cmake b/CMake/platforms/mingw9x.toolchain.cmake new file mode 100644 index 000000000..66e907ea9 --- /dev/null +++ b/CMake/platforms/mingw9x.toolchain.cmake @@ -0,0 +1,25 @@ +SET(MINGW_CROSS TRUE) + +SET(CROSS_PREFIX "/usr" CACHE STRING "crosstool-NG prefix") + +SET(CMAKE_SYSTEM_NAME Windows) + +# workaround +list(APPEND CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "${CROSS_PREFIX}/i686-w64-mingw32/include") + +list(PREPEND CMAKE_C_STANDARD_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/mingw9x/include") +list(PREPEND CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/mingw9x/include") + +SET(CMAKE_C_COMPILER "i686-w64-mingw32-gcc") +SET(CMAKE_CXX_COMPILER "i686-w64-mingw32-g++") +set(CMAKE_RC_COMPILER "i686-w64-mingw32-windres") +set(PKG_CONFIG_EXECUTABLE "${CROSS_PREFIX}/bin/i686-w64-mingw32-pkg-config" CACHE STRING "Path to pkg-config") + +SET(CMAKE_FIND_ROOT_PATH "${CROSS_PREFIX}/i686-w64-mingw32" "${CROSS_PREFIX}/i686-w64-mingw32/i686-w64-mingw32") + +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +set(WIN32_INSTALL_DLLS "${CROSS_PREFIX}/i686-w64-mingw32/bin/SDL.dll") diff --git a/CMake/platforms/mingw9x/include/windef.h b/CMake/platforms/mingw9x/include/windef.h new file mode 100644 index 000000000..1c0aebec0 --- /dev/null +++ b/CMake/platforms/mingw9x/include/windef.h @@ -0,0 +1,22 @@ +#ifndef _WINDEF_OVERRIDE_ +#define _WINDEF_OVERRIDE_ + +#include_next + +// MinGW does not define these when _WIN32_WINNT < 0x0400 +// but it declares functions that use it unconditionally. +typedef enum _FINDEX_INFO_LEVELS { + FindExInfoStandard, + FindExInfoBasic, + FindExInfoMaxInfoLevel +} FINDEX_INFO_LEVELS; +typedef enum _FINDEX_SEARCH_OPS { + FindExSearchNameMatch, + FindExSearchLimitToDirectories, + FindExSearchLimitToDevices, + FindExSearchMaxSearchOp +} FINDEX_SEARCH_OPS; + +typedef void* SOLE_AUTHENTICATION_SERVICE; + +#endif /* _WINDEF_ */ diff --git a/CMake/platforms/windows9x.cmake b/CMake/platforms/windows9x.cmake new file mode 100644 index 000000000..d070cbe06 --- /dev/null +++ b/CMake/platforms/windows9x.cmake @@ -0,0 +1,38 @@ +set(ASAN OFF) +set(UBSAN OFF) +set(DIST ON) + +set(NONET ON) +set(DISABLE_ZERO_TIER ON) +set(USE_SDL1 ON) +set(DEVILUTIONX_SYSTEM_BZIP2 OFF) +set(DEVILUTIONX_SYSTEM_LIBFMT OFF) +set(DEVILUTIONX_STATIC_LIBSODIUM OFF) + +# Compatibility with Windows 9x 8-bit mode and improved performance +set(SDL1_VIDEO_MODE_BPP 8) +set(SDL1_FORCE_DIRECT_RENDER ON) + +set(DEVILUTIONX_WINDOWS_NO_WCHAR ON) + +# `WINVER=0x0500` without `_WIN32_WINNT` is Windows 98. +# MinGW force-defines `_WIN32_WINNT=0xa00` if it isn't defined, so define it as 0. +add_definitions(-DWINVER=0x0500 -D_WIN32_WINDOWS=0x0500 -D_WIN32_WINNT=0) + +list(APPEND DEVILUTIONX_PLATFORM_LINK_LIBRARIES + shlwapi + wsock32 + ws2_32 + wininet +) + +if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + list(APPEND DEVILUTIONX_PLATFORM_COMPILE_OPTIONS "/W3" "/Zc:__cplusplus" "/utf-8") + list(APPEND DEVILUTIONX_PLATFORM_COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS) +else() + list(APPEND DEVILUTIONX_PLATFORM_COMPILE_OPTIONS $<$:-gstabs>) +endif() + +if(MINGW_CROSS) + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/mingw") +endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 21211674d..7b0762a99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -533,7 +533,7 @@ if(CPACK AND (APPLE OR BUILD_ASSETS_MPQ OR SRC_DIST)) DESTINATION "." ) - foreach(_SDL2_WIN32_DLL_PATH ${SDL2_WIN32_ALL_DLLS}) + foreach(_SDL2_WIN32_DLL_PATH ${SDL2_WIN32_ALL_DLLS} ${WIN32_INSTALL_DLLS}) install(FILES "${_SDL2_WIN32_DLL_PATH}" DESTINATION "." ) diff --git a/Packaging/windows/mingw-prep.sh b/Packaging/windows/mingw-prep.sh index d7dd0795a..3dc88ea28 100755 --- a/Packaging/windows/mingw-prep.sh +++ b/Packaging/windows/mingw-prep.sh @@ -31,6 +31,10 @@ else SUDO="" fi +rm -rf "tmp-mingw-${MINGW_ARCH}-prep" +mkdir -p "tmp-mingw-${MINGW_ARCH}-prep" +cd "tmp-mingw-${MINGW_ARCH}-prep" + wget -q https://www.libsdl.org/release/SDL2-devel-${SDLDEV_VERS}-mingw.tar.gz -OSDL2-devel-${SDLDEV_VERS}-mingw.tar.gz tar -xzf SDL2-devel-${SDLDEV_VERS}-mingw.tar.gz $SUDO cp -r SDL2*/${MINGW_ARCH}/* ${MINGW_PREFIX} diff --git a/Packaging/windows/mingw9x-prep.sh b/Packaging/windows/mingw9x-prep.sh new file mode 100755 index 000000000..020983cef --- /dev/null +++ b/Packaging/windows/mingw9x-prep.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +SDLDEV_VERS=1.2.15 +SODIUM_VERS=1.0.18 + +# exit when any command fails +set -euo pipefail + +MINGW_ARCH=i686-w64-mingw32 +SODIUM_ARCH=win32 + +# set MINGW_PREFIX +MINGW_PREFIX=/usr/${MINGW_ARCH} +if [ ! -d "${MINGW_PREFIX}" ]; then + echo "MinGW prefix not found (${MINGW_PREFIX})" + exit 1 +else + echo "Installing to ${MINGW_PREFIX}" +fi + +# only use sudo when necessary +if [ `id -u` -ne 0 ]; then + SUDO=sudo +else + SUDO="" +fi + +rm -rf tmp-mingw9x-prep +mkdir -p tmp-mingw9x-prep +cd tmp-mingw9x-prep + +curl --no-progress-meter -OL https://www.libsdl.org/release/SDL-devel-${SDLDEV_VERS}-mingw32.tar.gz +tar -xzf SDL-devel-${SDLDEV_VERS}-mingw32.tar.gz +$SUDO cp -r SDL-*/include/* ${MINGW_PREFIX}/include +$SUDO cp -r SDL-*/lib/* ${MINGW_PREFIX}/lib +$SUDO cp -r SDL-*/bin/* ${MINGW_PREFIX}/bin + +wget -q https://github.com/jedisct1/libsodium/releases/download/${SODIUM_VERS}-RELEASE/libsodium-${SODIUM_VERS}-mingw.tar.gz -Olibsodium-${SODIUM_VERS}-mingw.tar.gz +tar -xzf libsodium-${SODIUM_VERS}-mingw.tar.gz --no-same-owner +$SUDO cp -r libsodium-${SODIUM_ARCH}/* ${MINGW_PREFIX} + +# Fixup pkgconfig prefix: +find "${MINGW_PREFIX}/lib/pkgconfig/" -name '*.pc' -exec \ + $SUDO sed -i "s|^prefix=.*|prefix=${MINGW_PREFIX}|" '{}' \; + +# Fixup CMake prefix: +find "${MINGW_PREFIX}" -name '*.cmake' -exec \ + $SUDO sed -i "s|/opt/local/${MINGW_ARCH}|${MINGW_PREFIX}|" '{}' \; diff --git a/Source/utils/file_util.cpp b/Source/utils/file_util.cpp index 4f67a1324..ff9e8ba69 100644 --- a/Source/utils/file_util.cpp +++ b/Source/utils/file_util.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -181,6 +182,24 @@ bool FileExistsAndIsWriteable(const char *path) bool GetFileSize(const char *path, std::uintmax_t *size) { #ifdef _WIN32 +#if defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0) + HANDLE handle = ::CreateFileA(path, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (handle == INVALID_HANDLE_VALUE) { + LogError("File not found: {}", GetLastError()); + return false; + } + DWORD fileSizeHigh; + const DWORD fileSizeLow = ::GetFileSize(handle, &fileSizeHigh); + if (fileSizeLow == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) { + LogError("GetFileSize failed for {}: {}", path, GetLastError()); + ::CloseHandle(handle); + return false; + } + *size = (static_cast(fileSizeHigh) << 32) | fileSizeLow; + return true; +#else WIN32_FILE_ATTRIBUTE_DATA attr; #ifdef DEVILUTIONX_WINDOWS_NO_WCHAR if (!GetFileAttributesExA(path, GetFileExInfoStandard, &attr)) { @@ -199,6 +218,7 @@ bool GetFileSize(const char *path, std::uintmax_t *size) // C4293 in msvc when shifting a 32 bit type by 32 bits. *size = static_cast(attr.nFileSizeHigh) << (sizeof(attr.nFileSizeHigh) * 8) | attr.nFileSizeLow; return true; +#endif #else struct ::stat statResult; if (::stat(path, &statResult) == -1) @@ -279,11 +299,18 @@ void RecursivelyCreateDir(const char *path) bool ResizeFile(const char *path, std::uintmax_t size) { #ifdef _WIN32 +#if defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0) + if (size > std::numeric_limits::max()) { + return false; + } + auto lisize = static_cast(size); +#else LARGE_INTEGER lisize; lisize.QuadPart = static_cast(size); if (lisize.QuadPart < 0) { return false; } +#endif #ifdef DEVILUTIONX_WINDOWS_NO_WCHAR HANDLE file = ::CreateFileA(path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); #else @@ -296,7 +323,13 @@ bool ResizeFile(const char *path, std::uintmax_t size) #endif if (file == INVALID_HANDLE_VALUE) { return false; - } else if (::SetFilePointerEx(file, lisize, NULL, FILE_BEGIN) == 0 || ::SetEndOfFile(file) == 0) { + } else if ( +#if defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0) + ::SetFilePointer(file, lisize, NULL, FILE_BEGIN) == 0 +#else + ::SetFilePointerEx(file, lisize, NULL, FILE_BEGIN) == 0 +#endif + || ::SetEndOfFile(file) == 0) { ::CloseHandle(file); return false; } @@ -311,9 +344,10 @@ bool ResizeFile(const char *path, std::uintmax_t size) void RenameFile(const char *from, const char *to) { +#ifdef _WIN32 #ifdef DEVILUTIONX_WINDOWS_NO_WCHAR ::MoveFile(from, to); -#elif defined(_WIN32) +#else const auto fromUtf16 = ToWideChar(from); const auto toUtf16 = ToWideChar(to); if (fromUtf16 == nullptr || toUtf16 == nullptr) { @@ -321,6 +355,7 @@ void RenameFile(const char *from, const char *to) return; } ::MoveFileW(&fromUtf16[0], &toUtf16[0]); +#endif // _WIN32 #elif defined(DVL_HAS_FILESYSTEM) std::error_code ec; std::filesystem::rename(std::filesystem::u8path(from), std::filesystem::u8path(to), ec); @@ -331,11 +366,12 @@ void RenameFile(const char *from, const char *to) void CopyFileOverwrite(const char *from, const char *to) { +#ifdef _WIN32 #ifdef DEVILUTIONX_WINDOWS_NO_WCHAR if (!::CopyFile(from, to, /*bFailIfExists=*/false)) { LogError("Failed to copy {} to {}", from, to); } -#elif defined(_WIN32) +#else const auto fromUtf16 = ToWideChar(from); const auto toUtf16 = ToWideChar(to); if (fromUtf16 == nullptr || toUtf16 == nullptr) { @@ -345,6 +381,7 @@ void CopyFileOverwrite(const char *from, const char *to) if (!::CopyFileW(&fromUtf16[0], &toUtf16[0], /*bFailIfExists=*/false)) { LogError("Failed to copy {} to {}", from, to); } +#endif // _WIN32 #elif defined(__APPLE__) ::copyfile(from, to, nullptr, COPYFILE_ALL); #elif defined(DVL_HAS_FILESYSTEM) diff --git a/Source/utils/sdl2_to_1_2_backports.cpp b/Source/utils/sdl2_to_1_2_backports.cpp index cfe5c0472..9c7f7e477 100644 --- a/Source/utils/sdl2_to_1_2_backports.cpp +++ b/Source/utils/sdl2_to_1_2_backports.cpp @@ -1,18 +1,24 @@ -#include "./sdl2_to_1_2_backports.h" +#include "utils/sdl2_to_1_2_backports.h" #include #include +#include +#include -#include "./console.h" - -#if defined(_WIN32) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR) +#if defined(_WIN32) #define WIN32_LEAN_AND_MEAN #define NOMINMAX 1 +#ifndef DEVILUTIONX_WINDOWS_NO_WCHAR #define UNICODE 1 #include +#endif #include #endif +#include + +#include "utils/console.h" + #define DEFAULT_PRIORITY SDL_LOG_PRIORITY_CRITICAL #define DEFAULT_ASSERT_PRIORITY SDL_LOG_PRIORITY_WARN #define DEFAULT_APPLICATION_PRIORITY SDL_LOG_PRIORITY_INFO @@ -696,7 +702,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) #else namespace { -#if !defined(__QNXNTO__) && !defined(__amigaos__) +#if !defined(__QNXNTO__) && !defined(__amigaos__) && !(defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0)) char *readSymLink(const char *path) { // From sdl2-2.0.9/src/filesystem/unix/SDL_sysfilesystem.c @@ -736,7 +742,17 @@ char *SDL_GetBasePath() char *retval = NULL; -#if defined(__FREEBSD__) +#if defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0) + TCHAR buffer[MAX_PATH] = { 0 }; + GetModuleFileName(NULL, buffer, MAX_PATH); + const size_t len = std::string_view(buffer).size(); + retval = static_cast(SDL_malloc(len + 1)); + if (!retval) { + SDL_OutOfMemory(); + return NULL; + } + SDL_memcpy(retval, buffer, len + 1); +#elif defined(__FREEBSD__) char fullpath[PATH_MAX]; size_t buflen = sizeof(fullpath); const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; @@ -747,8 +763,7 @@ char *SDL_GetBasePath() return NULL; } } -#endif -#if defined(__OPENBSD__) +#elif defined(__OPENBSD__) char **retvalargs; size_t len; const int mib[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; @@ -765,8 +780,7 @@ char *SDL_GetBasePath() SDL_free(retvalargs); } -#endif -#if defined(__SOLARIS__) +#elif defined(__SOLARIS__) const char *path = getexecname(); if ((path != NULL) && (path[0] == '/')) { /* must be absolute path... */ retval = SDL_strdup(path); @@ -775,8 +789,7 @@ char *SDL_GetBasePath() return NULL; } } -#endif -#if defined(__3DS__) +#elif defined(__3DS__) retval = SDL_strdup("file:sdmc:/3ds/devilutionx/"); #elif defined(__amigaos__) retval = SDL_strdup("PROGDIR:"); @@ -892,20 +905,28 @@ char *SDL_GetPrefPath(const char *org, const char *app) } if (*org) { - SDL_snprintf(retval, len, "%s%s%s/%s", envr, append, org, app); + *fmt::format_to_n(retval, len - 1, "{}{}{}/{}", envr, append, org, app).out = '\0'; } else { - SDL_snprintf(retval, len, "%s%s%s", envr, append, app); + *fmt::format_to_n(retval, len - 1, "{}{}{}", envr, append, app).out = '\0'; } for (ptr = retval + 1; *ptr; ptr++) { if (*ptr == '/') { *ptr = '\0'; +#if defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0) + if (mkdir(retval) != 0 && errno != EEXIST) +#else if (mkdir(retval, 0700) != 0 && errno != EEXIST) +#endif goto error; *ptr = '/'; } } +#if defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0) + if (mkdir(retval) != 0 && errno != EEXIST) { +#else if (mkdir(retval, 0700) != 0 && errno != EEXIST) { +#endif error: SDL_SetError("Couldn't create directory '%s': '%s'", retval, strerror(errno)); SDL_free(retval); diff --git a/Source/utils/stdcompat/filesystem.hpp b/Source/utils/stdcompat/filesystem.hpp index 938f029f7..b3f19a652 100644 --- a/Source/utils/stdcompat/filesystem.hpp +++ b/Source/utils/stdcompat/filesystem.hpp @@ -6,7 +6,8 @@ || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000) #define DVL_NO_FILESYSTEM #endif -#elif defined(NXDK) || (defined(_MSVC_LANG) && _MSVC_LANG < 201703L) +#elif defined(NXDK) || (defined(_MSVC_LANG) && _MSVC_LANG < 201703L) \ + || (defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0)) #define DVL_NO_FILESYSTEM #endif