diff --git a/.editorconfig b/.editorconfig index 959e97e84ea..efd434d7897 100644 --- a/.editorconfig +++ b/.editorconfig @@ -67,6 +67,9 @@ end_of_line = crlf [*.tsv] trim_trailing_whitespace = false +[*.plist] +end_of_line = lf + [AppRun] end_of_line = lf diff --git a/3rdParty/Lua/CMakeLists.txt b/3rdParty/Lua/CMakeLists.txt index 2689c093c17..7dd61770735 100644 --- a/3rdParty/Lua/CMakeLists.txt +++ b/3rdParty/Lua/CMakeLists.txt @@ -15,7 +15,12 @@ FetchContent_Declare_ExcludeFromAll(Lua ) FetchContent_MakeAvailable_ExcludeFromAll(Lua) -if(ANDROID AND ("${ANDROID_ABI}" STREQUAL "armeabi-v7a" OR "${ANDROID_ABI}" STREQUAL "x86")) +if(CMAKE_SYSTEM_NAME MATCHES "Darwin" AND DARWIN_MAJOR_VERSION VERSION_EQUAL 8) + # We need legacy-support from MacPorts for: + # localtime_r gmtime_r + find_package(MacportsLegacySupport REQUIRED) + target_link_libraries(lua_static PRIVATE MacportsLegacySupport::MacportsLegacySupport) +elseif(ANDROID AND ("${ANDROID_ABI}" STREQUAL "armeabi-v7a" OR "${ANDROID_ABI}" STREQUAL "x86")) target_compile_definitions(lua_internal INTERFACE -DLUA_USE_C89) elseif(NINTENDO_3DS OR VITA OR NINTENDO_SWITCH OR NXDK) target_compile_definitions(lua_static PUBLIC -DLUA_USE_C89) diff --git a/3rdParty/googletest/CMakeLists.txt b/3rdParty/googletest/CMakeLists.txt index ed3463cf2e9..26c31d28492 100644 --- a/3rdParty/googletest/CMakeLists.txt +++ b/3rdParty/googletest/CMakeLists.txt @@ -2,8 +2,8 @@ include(functions/FetchContent_ExcludeFromAll_backport) FetchContent_Declare_ExcludeFromAll( googletest - URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz - URL_HASH MD5=c8340a482851ef6a3fe618a082304cfc + URL https://github.com/google/googletest/releases/download/v1.15.2/googletest-1.15.2.tar.gz + URL_HASH MD5=7e11f6cfcf6498324ac82d567dcb891e ) set(INSTALL_GTEST OFF) diff --git a/CMake/Platforms.cmake b/CMake/Platforms.cmake index 76cd0d98a59..0c4f352a29e 100644 --- a/CMake/Platforms.cmake +++ b/CMake/Platforms.cmake @@ -88,4 +88,16 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") # to detect available APIs. string(REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_SYSTEM_VERSION}") string(REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\2" DARWIN_MINOR_VERSION "${CMAKE_SYSTEM_VERSION}") + + if(DARWIN_MAJOR_VERSION VERSION_EQUAL 8) + include(platforms/macos_tiger) + endif() + + # For older macOS, we assume MacPorts because Homebrew only supports newer version + if(DARWIN_MAJOR_VERSION VERSION_LESS 11) + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/platforms/macports/finders") + + # On MacPorts, libfmt is in a subdirectory: + list(APPEND CMAKE_MODULE_PATH "/opt/local/lib/libfmt11/cmake") + endif() endif() diff --git a/CMake/platforms/macos_tiger.cmake b/CMake/platforms/macos_tiger.cmake new file mode 100644 index 00000000000..2367ac5a57d --- /dev/null +++ b/CMake/platforms/macos_tiger.cmake @@ -0,0 +1,20 @@ +# ASAN and UBSAN are not supported by macports gcc14 on PowerPC. +set(ASAN OFF) +set(UBSAN OFF) + +# SDL2 does not build for Tiger, so we use SDL1 instead. +set(USE_SDL1 ON) + +# ZeroTier is yet to be tested. +set(DISABLE_ZERO_TIER ON) + +# Use vendored libfmt until this issue is resolved: +# https://trac.macports.org/ticket/71503 +set(DEVILUTIONX_SYSTEM_LIBFMT OFF) +set(DEVILUTIONX_STATIC_LIBFMT ON) + +# https://trac.macports.org/ticket/71511 +set(DEVILUTIONX_SYSTEM_GOOGLETEST OFF) +set(DEVILUTIONX_STATIC_GOOGLETEST OFF) +set(DEVILUTIONX_SYSTEM_BENCHMARK OFF) +set(DEVILUTIONX_STATIC_BENCHMARK OFF) diff --git a/CMake/platforms/macports/finders/FindMacportsLegacySupport.cmake b/CMake/platforms/macports/finders/FindMacportsLegacySupport.cmake new file mode 100644 index 00000000000..34dbc1fe2d5 --- /dev/null +++ b/CMake/platforms/macports/finders/FindMacportsLegacySupport.cmake @@ -0,0 +1,30 @@ +# Provides missing functions, such as localtime_r +if(NOT TARGET MacportsLegacySupport::MacportsLegacySupport) + set(MacportsLegacySupport_INCLUDE_DIR /opt/local/include/LegacySupport) + mark_as_advanced(MacportsLegacySupport_INCLUDE_DIR) + + find_library(MacportsLegacySupport_LIBRARY NAMES MacportsLegacySupport + PATHS /opt/local/lib) + mark_as_advanced(MacportsLegacySupport_LIBRARY) + + include(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS( + MacportsLegacySupport + DEFAULT_MSG + MacportsLegacySupport_LIBRARY MacportsLegacySupport_INCLUDE_DIR) + + if(MacportsLegacySupport_FOUND) + set(MacportsLegacySupport_LIBRARIES ${MacportsLegacySupport_LIBRARY}) + set(MacportsLegacySupport_INCLUDE_DIRS ${MacportsLegacySupport_INCLUDE_DIR}) + add_library(MacportsLegacySupport::MacportsLegacySupport UNKNOWN IMPORTED) + set_target_properties( + MacportsLegacySupport::MacportsLegacySupport PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${MacportsLegacySupport_INCLUDE_DIR}" + ) + set_target_properties( + MacportsLegacySupport::MacportsLegacySupport PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${MacportsLegacySupport_LIBRARY}" + ) + endif() +endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 54f8cb638fd..9eb7d73fafe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -343,7 +343,6 @@ else() Source/main.cpp Packaging/windows/devilutionx.exe.manifest Packaging/windows/devilutionx.rc - Packaging/apple/AppIcon.icns Packaging/apple/LaunchScreen.storyboard) if(CMAKE_STRIP AND NOT DEVILUTIONX_DISABLE_STRIP) @@ -382,7 +381,6 @@ include(functions/set_relative_file_macro) set_relative_file_macro(${BIN_TARGET}) if(APPLE) - set_source_files_properties("./Packaging/apple/AppIcon.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources) set(MACOSX_BUNDLE_GUI_IDENTIFIER com.diasurgical.devilutionx) set(MACOSX_BUNDLE_COPYRIGHT Unlicense) set(MACOSX_BUNDLE_BUNDLE_NAME devilutionx) @@ -399,7 +397,15 @@ if(APPLE) set(MACOSX_BUNDLE_REQUIRED_PLATFORM Carbon) set(CMAKE_OSX_DEPLOYMENT_TARGET "10.12.0") endif() - set_target_properties(${BIN_TARGET} PROPERTIES MACOSX_BUNDLE_ICON_FILE "AppIcon.icns") + if(DARWIN_MAJOR_VERSION VERSION_LESS 9) + # Finder on OSX Tiger can only handle icns files with up to 128x128 icons. + set(_icon_file AppIcon_128) + else() + set(_icon_file AppIcon) + endif() + target_sources(${BIN_TARGET} PRIVATE "Packaging/apple/${_icon_file}.icns") + set_source_files_properties("./Packaging/apple/${_icon_file}.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + set_target_properties(${BIN_TARGET} PROPERTIES MACOSX_BUNDLE_ICON_FILE "${_icon_file}.icns") set_target_properties(${BIN_TARGET} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Packaging/apple/Info.plist") install (TARGETS ${BIN_TARGET} DESTINATION ./) diff --git a/Packaging/apple/AppIcon_128.icns b/Packaging/apple/AppIcon_128.icns new file mode 100644 index 00000000000..76108cf0a33 Binary files /dev/null and b/Packaging/apple/AppIcon_128.icns differ diff --git a/Packaging/apple/Info.plist b/Packaging/apple/Info.plist index 91e32a9810c..52754cc115c 100644 --- a/Packaging/apple/Info.plist +++ b/Packaging/apple/Info.plist @@ -39,7 +39,7 @@ NSHumanReadableCopyright ${MACOSX_BUNDLE_COPYRIGHT} SDL_FILESYSTEM_BASE_DIR_TYPE - parent + resource NSSupportsAutomaticGraphicsSwitching UIApplicationSupportsIndirectInputEvents diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index f6276943606..07a4dde8cd1 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -335,6 +335,13 @@ if(USE_SDL1) target_link_libraries(DevilutionX::SDL INTERFACE libdevilutionx_sdl2_to_1_2_backports ) + if(APPLE) + enable_language(OBJC) + target_sources(libdevilutionx_sdl2_to_1_2_backports PRIVATE + platform/macos_sdl1/SDL_filesystem.m) + target_link_libraries(libdevilutionx_sdl2_to_1_2_backports PRIVATE + "-framework Foundation") + endif() endif() add_devilutionx_object_library(libdevilutionx_codec diff --git a/Source/init.cpp b/Source/init.cpp index 1e6488d58f7..02eafbc9d5c 100644 --- a/Source/init.cpp +++ b/Source/init.cpp @@ -130,7 +130,7 @@ std::vector GetMPQSearchPaths() if (paths[0] == paths[1] || (paths.size() == 3 && (paths[0] == paths[2] || paths[1] == paths[2]))) paths.pop_back(); -#if defined(__unix__) && !defined(__ANDROID__) +#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) // `XDG_DATA_HOME` is usually the root path of `paths::PrefPath()`, so we only // add `XDG_DATA_DIRS`. const char *xdgDataDirs = std::getenv("XDG_DATA_DIRS"); diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 33777b571fb..94144901f09 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -37,6 +37,23 @@ namespace devilution { namespace { +#if defined(__APPLE__) && defined(USE_SDL1) +// On Tiger PPC, SDL_PushEvent from a background thread appears to do nothing. +#define SDL_PUSH_EVENT_BG_THREAD_WORKS 0 +#else +#define SDL_PUSH_EVENT_BG_THREAD_WORKS 1 +#endif + +#if !SDL_PUSH_EVENT_BG_THREAD_WORKS +// This workaround is not completely thread-safe but the worst +// that can happen is we miss some WM_PROGRESS events, +// which is not a problem. +struct { + std::atomic type; + std::string error; +} NextCustomEvent; +#endif + constexpr uint32_t MaxProgress = 534; constexpr uint32_t ProgressStepSize = 23; @@ -391,16 +408,31 @@ void DoLoad(interface_mode uMsg) } if (!loadResult.has_value()) { +#if SDL_PUSH_EVENT_BG_THREAD_WORKS SDL_Event event; event.type = CustomEventToSdlEvent(WM_ERROR); event.user.data1 = new std::string(std::move(loadResult).error()); - SDL_PushEvent(&event); + if (SDL_PushEvent(&event) < 0) { + LogError("Failed to send WM_ERROR {}", SDL_GetError()); + SDL_ClearError(); + } +#else + NextCustomEvent.error = std::move(loadResult).error(); + NextCustomEvent.type = static_cast(WM_ERROR); +#endif return; } +#if SDL_PUSH_EVENT_BG_THREAD_WORKS SDL_Event event; event.type = CustomEventToSdlEvent(WM_DONE); - SDL_PushEvent(&event); + if (SDL_PushEvent(&event) < 0) { + LogError("Failed to send WM_DONE {}", SDL_GetError()); + SDL_ClearError(); + } +#else + NextCustomEvent.type = static_cast(WM_DONE); +#endif } struct { @@ -561,9 +593,16 @@ void IncProgress(uint32_t steps) if (sgdwProgress > MaxProgress) sgdwProgress = MaxProgress; if (!HeadlessMode && sgdwProgress != prevProgress) { +#if SDL_PUSH_EVENT_BG_THREAD_WORKS SDL_Event event; event.type = CustomEventToSdlEvent(WM_PROGRESS); - SDL_PushEvent(&event); + if (SDL_PushEvent(&event) < 0) { + LogError("Failed to send WM_PROGRESS {}", SDL_GetError()); + SDL_ClearError(); + } +#else + NextCustomEvent.type = static_cast(WM_PROGRESS); +#endif } } @@ -589,6 +628,10 @@ void ShowProgress(interface_mode uMsg) ProgressEventHandlerState.done = false; ProgressEventHandlerState.drawnProgress = 0; +#if !SDL_PUSH_EVENT_BG_THREAD_WORKS + NextCustomEvent.type = -1; +#endif + #ifndef USE_SDL1 DeactivateVirtualGamepad(); FreeVirtualGamepadTextures(); @@ -623,21 +666,35 @@ void ShowProgress(interface_mode uMsg) LogVerbose("Load thread finished in {}ms", SDL_GetTicks() - start); }); + const auto processEvent = [&](const SDL_Event &event) { + CheckShouldSkipRendering(); + if (event.type != SDL_QUIT) { + HandleMessage(event, SDL_GetModState()); + } + if (ProgressEventHandlerState.done) { + loadThread.join(); + return false; + } + return true; + }; + while (true) { CheckShouldSkipRendering(); SDL_Event event; // We use the real `SDL_PollEvent` here instead of `FetchEvent` // to process real events rather than the recorded ones in demo mode. while (SDL_PollEvent(&event)) { - CheckShouldSkipRendering(); - if (event.type != SDL_QUIT) { - HandleMessage(event, SDL_GetModState()); - } - if (ProgressEventHandlerState.done) { - loadThread.join(); - return; + if (!processEvent(event)) return; + } +#if !SDL_PUSH_EVENT_BG_THREAD_WORKS + if (const int customEventType = NextCustomEvent.type.exchange(-1); customEventType != -1) { + event.type = CustomEventToSdlEvent(static_cast(customEventType)); + if (static_cast(customEventType) == static_cast(WM_ERROR)) { + event.user.data1 = &NextCustomEvent.error; } + if (!processEvent(event)) return; } +#endif } } diff --git a/Source/platform/macos_sdl1/SDL_filesystem.m b/Source/platform/macos_sdl1/SDL_filesystem.m new file mode 100644 index 00000000000..1bf4ed6e93d --- /dev/null +++ b/Source/platform/macos_sdl1/SDL_filesystem.m @@ -0,0 +1,138 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + An altered version based on: + https://github.com/libsdl-org/SDL/blob/3c142abcb2b0b0ad7e08b096ea8d9a1a1e1af1ef/src/filesystem/cocoa/SDL_sysfilesystem.m + + Modifications: + 1. Changes to compile with gcc (@autoreleasepool -> NSAutoreleasePool) + 2. Targets SDL-1.2 rather than SDL2 (SDL_InvalidParamError -> SDL_SetError) +*/ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* System dependent filesystem routines */ + +#include +#include +#include + +#include + +char *SDL_GetBasePath(void) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSBundle *bundle = [NSBundle mainBundle]; + const char *baseType = [[[bundle infoDictionary] objectForKey:@"SDL_FILESYSTEM_BASE_DIR_TYPE"] UTF8String]; + const char *base = NULL; + char *retval = NULL; + + if (baseType == NULL) { + baseType = "resource"; + } + if (SDL_strcasecmp(baseType, "bundle") == 0) { + base = [[bundle bundlePath] fileSystemRepresentation]; + } else if (SDL_strcasecmp(baseType, "parent") == 0) { + base = [[[bundle bundlePath] stringByDeletingLastPathComponent] fileSystemRepresentation]; + } else { + /* this returns the exedir for non-bundled and the resourceDir for bundled apps */ + base = [[bundle resourcePath] fileSystemRepresentation]; + } + + if (base) { + const size_t len = SDL_strlen(base) + 2; + retval = (char *)SDL_malloc(len); + if (retval == NULL) { + SDL_OutOfMemory(); + } else { + SDL_snprintf(retval, len, "%s/", base); + } + } + + [pool drain]; + return retval; +} + +char *SDL_GetPrefPath(const char *org, const char *app) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + char *retval = NULL; + NSArray *array; + + if (!app) { + SDL_SetError("SDL_GetPrefPath: app argument cannot be null"); + return NULL; + } + if (!org) { + org = ""; + } + +#if !TARGET_OS_TV + array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); +#else + /* tvOS does not have persistent local storage! + * The only place on-device where we can store data is + * a cache directory that the OS can empty at any time. + * + * It's therefore very likely that save data will be erased + * between sessions. If you want your app's save data to + * actually stick around, you'll need to use iCloud storage. + */ + { + static SDL_bool shown = SDL_FALSE; + if (!shown) { + shown = SDL_TRUE; + SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "tvOS does not have persistent local storage! Use iCloud storage if you want your data to persist between sessions.\n"); + } + } + + array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); +#endif /* !TARGET_OS_TV */ + + if ([array count] > 0) { /* we only want the first item in the list. */ + NSString *str = [array objectAtIndex:0]; + const char *base = [str fileSystemRepresentation]; + if (base) { + const size_t len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4; + retval = (char *)SDL_malloc(len); + if (retval == NULL) { + SDL_OutOfMemory(); + } else { + char *ptr; + if (*org) { + SDL_snprintf(retval, len, "%s/%s/%s/", base, org, app); + } else { + SDL_snprintf(retval, len, "%s/%s/", base, app); + } + for (ptr = retval + 1; *ptr; ptr++) { + if (*ptr == '/') { + *ptr = '\0'; + mkdir(retval, 0700); + *ptr = '/'; + } + } + mkdir(retval, 0700); + } + } + } + + [pool drain]; + return retval; +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/Source/utils/paths.cpp b/Source/utils/paths.cpp index a5bd0db8560..d0f680555b8 100644 --- a/Source/utils/paths.cpp +++ b/Source/utils/paths.cpp @@ -1,5 +1,9 @@ #include "utils/paths.h" +#include +#include +#include + #include #include "appfat.h" @@ -130,6 +134,23 @@ const std::string &AssetsPath() assetsPath.emplace("D:\\assets\\"); #elif defined(__3DS__) || defined(__SWITCH__) assetsPath.emplace("romfs:/"); +#elif defined(__APPLE__) && defined(USE_SDL1) + // In `Info.plist` we have + // + // SDL_FILESYSTEM_BASE_DIR_TYPE + // resource + // + // This means `SDL_GetBasePath()` returns exedir for non-bundled + // and the `app_dir.app/Resources/` for bundles. + // + // Our built-in resources are directly in the `devilutionx.app/Resources` directory + // and are normally looked up via a relative lookup in `FindAsset`. + // In SDL2, this is implemented by calling `SDL_OpenFPFromBundleOrFallback` + // from `SDL_RWFromFile` but SDL1 doesn't do it, so we set the directory explicitly. + // + // Note that SDL3 reverts to SDL1 behaviour! + // https://github.com/libsdl-org/SDL/blob/962268ca21ed10b9cee31198c22681099293f20a/docs/README-migration.md?plain=1#L1623 + assetsPath.emplace(FromSDL(SDL_GetBasePath())); #else assetsPath.emplace(FromSDL(SDL_GetBasePath()) + ("assets" DIRECTORY_SEPARATOR_STR)); #endif diff --git a/Source/utils/paths.h b/Source/utils/paths.h index ca4cc36003b..35edfec3052 100644 --- a/Source/utils/paths.h +++ b/Source/utils/paths.h @@ -1,6 +1,5 @@ #pragma once -#include #include namespace devilution { diff --git a/Source/utils/sdl2_to_1_2_backports.cpp b/Source/utils/sdl2_to_1_2_backports.cpp index ee47b5d7260..f8de050bebd 100644 --- a/Source/utils/sdl2_to_1_2_backports.cpp +++ b/Source/utils/sdl2_to_1_2_backports.cpp @@ -544,7 +544,7 @@ int WIN_SetError(const char *prefix) } // namespace -char *SDL_GetBasePath(void) +extern "C" char *SDL_GetBasePath(void) { // From sdl2-2.0.9/src/filesystem/windows/SDL_sysfilesystem.c @@ -611,7 +611,7 @@ char *SDL_GetBasePath(void) return retval; } -char *SDL_GetPrefPath(const char *org, const char *app) +extern "C" char *SDL_GetPrefPath(const char *org, const char *app) { // From sdl2-2.0.9/src/filesystem/windows/SDL_sysfilesystem.c @@ -699,7 +699,8 @@ char *SDL_GetPrefPath(const char *org, const char *app) return retval; } -#else +// For Apple, definitions are in Source/platform/macos_sdl1/SDL_filesystem.m +#elif !defined(__APPLE__) namespace { #if !defined(__QNXNTO__) && !defined(__amigaos__) && !(defined(WINVER) && WINVER <= 0x0500 && (!defined(_WIN32_WINNT) || _WIN32_WINNT == 0)) @@ -736,7 +737,7 @@ char *readSymLink(const char *path) #endif } // namespace -char *SDL_GetBasePath() +extern "C" char *SDL_GetBasePath() { // From sdl2-2.0.9/src/filesystem/unix/SDL_sysfilesystem.c @@ -851,7 +852,7 @@ char *SDL_GetBasePath() return retval; } -char *SDL_GetPrefPath(const char *org, const char *app) +extern "C" char *SDL_GetPrefPath(const char *org, const char *app) { // From sdl2-2.0.9/src/filesystem/unix/SDL_sysfilesystem.c /* diff --git a/Source/utils/sdl2_to_1_2_backports.h b/Source/utils/sdl2_to_1_2_backports.h index a1b9e31d574..e089a5101d9 100644 --- a/Source/utils/sdl2_to_1_2_backports.h +++ b/Source/utils/sdl2_to_1_2_backports.h @@ -322,5 +322,5 @@ int SDL_BlitScaled(SDL_Surface *src, SDL_Rect *srcrect, Sint64 SDL_RWsize(SDL_RWops *context); -char *SDL_GetBasePath(); -char *SDL_GetPrefPath(const char *org, const char *app); +extern "C" char *SDL_GetBasePath(); +extern "C" char *SDL_GetPrefPath(const char *org, const char *app); diff --git a/docs/building.md b/docs/building.md index 7904f5a9bd8..e87f099002b 100644 --- a/docs/building.md +++ b/docs/building.md @@ -528,6 +528,49 @@ Executing `Packaging/miyoo_mini/build.sh` will create the folder `build-miyoo-mi OnionOS Port Collection. +
macOS 10.4 Tiger + +For macOS Tiger, DevilutionX can be compiled using the compiler and libraries from [MacPorts](https://www.macports.org/). + +For PowerPC, you can use precompiled dependencies from here: + +http://macports-tiger-ppc.glebm.com/ + +After installing MacPorts, run: + +~~~ bash +# Some packages may require you to manually deactivate certain ports during installation. +# Remember to reactivate them after installing. +sudo port install curl curl-ca-bundle gcc14 cmake \ + libsdl12 libsdl_image libsodium bzip2 zlib lua54 + +# Set GCC 14 as the default GCC: +sudo port select --set gcc mp-gcc14 +~~~ + + + +Then, build DevilutionX: + +~~~ bash +CC=gcc cmake -S. -Bbuild-rel -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DCPACK=ON -DMACOSX_STANDALONE_APP_BUNDLE=ON +cmake --build build-rel -j "$(sysctl -n hw.ncpu)" + +# `sudo` is required to produce a bundle with all the shared libraries. +sudo cmake --build build-rel --target package -j "$(sysctl -n hw.ncpu)" +~~~ + +To run tools from the `tools/` directory (only needed for development), you also need Python: + +~~~ bash +sudo port install python312 +sudo port select --set python python312 +sudo port select --set python3 python312 +~~~ + +
+
CMake build options ### General diff --git a/test/items_test.cpp b/test/items_test.cpp index c829520b4c1..0a3caa2bc47 100644 --- a/test/items_test.cpp +++ b/test/items_test.cpp @@ -1,6 +1,8 @@ -#include +#include #include +#include + #include "engine/random.hpp" #include "items.h" #include "player.h" diff --git a/test/timedemo_test.cpp b/test/timedemo_test.cpp index 79eb5d334e8..afb60a00a46 100644 --- a/test/timedemo_test.cpp +++ b/test/timedemo_test.cpp @@ -23,7 +23,14 @@ bool Dummy_GetHeroInfo(_uiheroinfo *pInfo) void RunTimedemo(std::string timedemoFolderName) { - if (SDL_Init(SDL_INIT_EVENTS) <= -1) { + if (SDL_Init( +#ifdef USE_SDL1 + 0 +#else + SDL_INIT_EVENTS +#endif + ) + <= -1) { ErrSdl(); } std::string unitTestFolderCompletePath = paths::BasePath() + "/test/fixtures/timedemo/" + timedemoFolderName;