Add support for compiling on macOS
This pull request introduces changes to enable compiling The Force Engine on macOS. It's a cleanup of #472 (thank you @mlauss2 for your help!)
Hardware: Intel Mac / macOS Sequoia 15.1 / XCode 16.1 SDL2: version 2.30.9, SDL2_image: version 2.8.2, RtMidi: version 6.0.0
I like it (obviously). As a next step, some of the #ifdef APPLE could be replaced with a runtime test for OSX. SDL provides SDL_GetPlatform():
bool isosx = (0 == strcmp(SDL_GetPlatform(), "Mac OS X"));
OpenGL_caps.cpp and renderbackend::createwindow come to mind.
This way your code gets compiler coverage on windows/linux too.
something like this:
diff --git a/TheForceEngine/TFE_RenderBackend/Win32OpenGL/openGL_Caps.cpp b/TheForceEngine/TFE_RenderBackend/Win32OpenGL/openGL_Caps.cpp
index 1fe52b54..e74d95b6 100644
--- a/TheForceEngine/TFE_RenderBackend/Win32OpenGL/openGL_Caps.cpp
+++ b/TheForceEngine/TFE_RenderBackend/Win32OpenGL/openGL_Caps.cpp
@@ -1,3 +1,4 @@
+#include <TFE_System/system.h>
#include "openGL_Caps.h"
#include "gl.h"
#include <assert.h>
@@ -39,8 +40,12 @@ namespace OpenGL_Caps
glGetIntegerv(GL_MAJOR_VERSION, &gl_maj);
glGetIntegerv(GL_MINOR_VERSION, &gl_min);
-#ifdef __APPLE__
- if (gl_maj >= 4) {
+
+ if (PLAT_OSX == TFE_System::getPlatform())
+ {
+ if (gl_maj < 4)
+ return;
+
m_supportFlags = CAP_PBO | CAP_VBO | CAP_FBO | CAP_UBO | CAP_NON_POW_2 | CAP_TEXTURE_ARRAY;
if (SDL_GL_ExtensionSupported("GL_EXT_texture_filter_anisotropic")) {
@@ -61,9 +66,9 @@ namespace OpenGL_Caps
if (m_textureBufferMaxSize >= GLSPEC_MAX_TEXTURE_BUFFER_SIZE_MIN) {
m_deviceTier = DEV_TIER_2;
}
+ return;
}
- return;
-#endif
+
if (SDL_GL_ExtensionSupported("GL_ARB_pixel_buffer_object"))
m_supportFlags |= CAP_PBO | CAP_NON_POW_2;
if (SDL_GL_ExtensionSupported("GL_ARB_vertex_buffer_object"))
diff --git a/TheForceEngine/TFE_RenderBackend/Win32OpenGL/renderBackend.cpp b/TheForceEngine/TFE_RenderBackend/Win32OpenGL/renderBackend.cpp
index 4fed0683..33432c9c 100644
--- a/TheForceEngine/TFE_RenderBackend/Win32OpenGL/renderBackend.cpp
+++ b/TheForceEngine/TFE_RenderBackend/Win32OpenGL/renderBackend.cpp
@@ -71,9 +71,7 @@ namespace TFE_RenderBackend
void drawVirtualDisplay();
void setupPostEffectChain(bool useDynamicTexture, bool useBloom);
-#ifdef __APPLE__
static GLuint s_globalVAO = 0;
-#endif
static void printGLInfo(void)
{
@@ -91,6 +89,7 @@ namespace TFE_RenderBackend
{
u32 windowFlags = SDL_WINDOW_OPENGL;
bool windowed = !(state.flags & WINFLAG_FULLSCREEN);
+ bool isosx = (PLAT_OSX == TFE_System::getPlatform());
TFE_Settings_Window* windowSettings = TFE_Settings::getWindowSettings();
@@ -116,13 +115,14 @@ namespace TFE_RenderBackend
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, true);
-#ifdef __APPLE__
- // macOS specific OpenGL context setup
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
-#endif
+ if (isosx)
+ {
+ // macOS specific OpenGL context setup
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
+ }
TFE_System::logWrite(LOG_MSG, "RenderBackend", "SDL Videodriver: %s", SDL_GetCurrentVideoDriver());
SDL_Window* window = SDL_CreateWindow(state.name, x, y, state.width, state.height, windowFlags);
@@ -177,26 +177,27 @@ namespace TFE_RenderBackend
uiScale = 150;
}
-#ifdef __APPLE__
- // macOS specific setup:
- // Create and bind a global VAO for macOS
- glGenVertexArrays(1, &s_globalVAO);
- if (!s_globalVAO)
+ if (isosx)
{
- TFE_System::logWrite(LOG_ERROR, "RenderBackend", "Failed to create global VAO");
- SDL_DestroyWindow(window);
- return nullptr;
- }
- glBindVertexArray(s_globalVAO);
+ // macOS specific setup:
+ // Create and bind a global VAO for macOS
+ glGenVertexArrays(1, &s_globalVAO);
+ if (!s_globalVAO)
+ {
+ TFE_System::logWrite(LOG_ERROR, "RenderBackend", "Failed to create global VAO");
+ SDL_DestroyWindow(window);
+ return nullptr;
+ }
+ glBindVertexArray(s_globalVAO);
- // handle Retina displays
- s32 drawableWidth, drawableHeight;
- SDL_GL_GetDrawableSize(window, &drawableWidth, &drawableHeight);
- if (drawableWidth > state.width)
- {
- uiScale = (uiScale * drawableWidth) / state.width;
+ // handle Retina displays
+ s32 drawableWidth, drawableHeight;
+ SDL_GL_GetDrawableSize(window, &drawableWidth, &drawableHeight);
+ if (drawableWidth > state.width)
+ {
+ uiScale = (uiScale * drawableWidth) / state.width;
+ }
}
-#endif
#ifndef _WIN32
SDL_SetWindowFullscreen(window, windowed ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
@@ -1066,9 +1067,8 @@ namespace TFE_RenderBackend
void bindGlobalVAO(void)
{
-#ifdef __APPLE__
- glBindVertexArray(s_globalVAO);
-#endif
+ if (s_globalVAO)
+ glBindVertexArray(s_globalVAO);
}
} // namespace
diff --git a/TheForceEngine/TFE_System/system.cpp b/TheForceEngine/TFE_System/system.cpp
index 4ce39dce..00985577 100644
--- a/TheForceEngine/TFE_System/system.cpp
+++ b/TheForceEngine/TFE_System/system.cpp
@@ -45,6 +45,7 @@ namespace TFE_System
static s32 s_missedFrameCount = 0;
static char s_versionString[64];
+ static TFE_Platform s_platform; // win/lin/osx
void init(f32 refreshRate, bool synced, const char* versionString)
{
@@ -62,6 +63,17 @@ namespace TFE_System
TFE_COUNTER(s_missedFrameCount, "Miss-Predicted Vysnc Intervals");
strcpy(s_versionString, versionString);
+
+ const char *sdlplat = SDL_GetPlatform();
+ if (0 == strcmp(sdlplat, "Windows"))
+ s_platform = PLAT_WIN;
+ else if (0 == strcmp(sdlplat, "Mac OS X"))
+ s_platform = PLAT_OSX;
+ else if (0 == strcmp(sdlplat, "Linux"))
+ s_platform = PLAT_LIN;
+ else
+ s_platform = PLAT_UNK;
+ TFE_System::logWrite(LOG_MSG, "Startup", "SDL Platform: '%s' (%u)", sdlplat, s_platform);
}
void shutdown()
@@ -102,6 +114,11 @@ namespace TFE_System
return dt;
}
+ TFE_Platform getPlatform(void)
+ {
+ return s_platform;
+ }
+
void update()
{
// This assumes that SDL_GetPerformanceCounter() is monotonic.
diff --git a/TheForceEngine/TFE_System/system.h b/TheForceEngine/TFE_System/system.h
index 6d2e558d..d39e52fe 100644
--- a/TheForceEngine/TFE_System/system.h
+++ b/TheForceEngine/TFE_System/system.h
@@ -28,6 +28,14 @@ enum LogWriteType
LOG_COUNT
};
+enum TFE_Platform
+{
+ PLAT_WIN = 0,
+ PLAT_LIN,
+ PLAT_OSX,
+ PLAT_UNK
+};
+
namespace TFE_System
{
void init(f32 refreshRate, bool synced, const char* versionString);
@@ -39,6 +47,8 @@ namespace TFE_System
void update();
f64 updateThreadLocal(u64* localTime);
+ TFE_Platform getPlatform(void);
+
// Timing
// --- The current time and delta time are determined once per frame, during the update() function.
// In other words an entire frame operates on a single instance of time.
I pushed my initial draft in commit 34d29a9 just before you sent your changes. I'll take a look at how to merge them.
A bigger issue is that shooting weapons no longer works. I’m not sure yet how or where I broke it, especially since I didn’t touch the game logic.
I pushed my initial draft in commit 34d29a9 just before you sent your changes. I'll take a look at how to merge them.
Oh i meant this is something for later, but yeah like this.
A bigger issue is that shooting weapons no longer works. I’m not sure yet how or where I broke it, especially since I didn’t touch the game logic.
you need this:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 80398f03..9a2030dd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -81,6 +81,7 @@ if(ENABLE_TFE)
# the necessary support file directories into the build env.
execute_process(COMMAND ln -sf ${CMAKE_SOURCE_DIR}/TheForceEngine/Captions)
execute_process(COMMAND ln -sf ${CMAKE_SOURCE_DIR}/TheForceEngine/Documentation)
+ execute_process(COMMAND ln -sf ${CMAKE_SOURCE_DIR}/TheForceEngine/ExternalData)
execute_process(COMMAND ln -sf ${CMAKE_SOURCE_DIR}/TheForceEngine/Fonts)
execute_process(COMMAND ln -sf ${CMAKE_SOURCE_DIR}/TheForceEngine/Mods)
execute_process(COMMAND ln -sf ${CMAKE_SOURCE_DIR}/TheForceEngine/Shaders)
@@ -137,6 +138,7 @@ if(ENABLE_TFE)
install(DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}/TheForceEngine/Captions"
"${CMAKE_CURRENT_SOURCE_DIR}/TheForceEngine/Documentation"
+ "${CMAKE_CURRENT_SOURCE_DIR}/TheForceEngine/ExternalData"
"${CMAKE_CURRENT_SOURCE_DIR}/TheForceEngine/UI_Text"
"${CMAKE_CURRENT_SOURCE_DIR}/TheForceEngine/UI_Images"
"${CMAKE_CURRENT_SOURCE_DIR}/TheForceEngine/EditorDef"
erm, please just keep the first patch for this PR; the others were just ideas for a new PR after this has been merged, and the patch you need to get projectiles again, which is not at all material for this pr.
Alright, I removed the last commit. Let's keep 34d29a9, as it includes unbinding and deleting the global VAO, which should have been there from the beginning.
it's fine for me. I have cooked up something a bit different for 34d29a9 which compiles away to nothing when the platform doesn't match but still gets compiler coverage. I'll prepare a PR once your great work has been merged.
While testing on Apple Silicon, I discovered that the application crashed immediately due to incorrect file paths. I had the right folders with right permissions on my Intel Mac so that's why I didn't notice it. Commit 929bc7c resolves this issue and uses macOS path conventions.
I think this is a good reason to switch to "SDL_GetPrefPath()" (in a separate PR), which does the right thing for all platforms. It will break existing setups though (saved data is located elsewhere).
This PR compiles and runs for me on MacOS Sequoia 15.4.1 on M1 Pro silicon, though the shots don't work, I'm able to fire blaster / punch, but enemies do not take damage and I also do not take damage when enemies shoot at me. Other than that things seem to work (platforming, interacting with doors / buttons / pickups).
@finger563 Thank you for testing on Apple Silicon! The weapon damage issue you've noticed was actually introduced and resolved upstream since this PR was created. Once this PR is merged, the latest upstream changes will include the fix which should resolve the weapon functionality. You can see the required patch by @mlauss2 in the thread above if you want to make it work in the meantime.
Can this PR be rebased on top of master please?