diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2e6bb59f5..67f7d405b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -549,18 +549,17 @@ set( PLAT_SDL_SOURCES sdl/crashcatcher.c sdl/hardware.cpp sdl/i_cd.cpp - sdl/i_main.cpp - sdl/i_movie.cpp - sdl/i_system.cpp - sdl/sdlvideo.cpp - sdl/st_start.cpp sdl/i_gui.cpp sdl/i_input.cpp sdl/i_joystick.cpp - sdl/i_timer.cpp ) + sdl/i_main.cpp + sdl/i_movie.cpp + sdl/i_system.cpp + sdl/i_timer.cpp + sdl/sdlvideo.cpp + sdl/st_start.cpp ) set( PLAT_MAC_SOURCES - cocoa/iwadpicker_cocoa.mm - cocoa/i_system_cocoa.mm ) + cocoa/iwadpicker_cocoa.mm ) set( PLAT_COCOA_SOURCES cocoa/hid/HID_Config_Utilities.c cocoa/hid/HID_Error_Handler.c @@ -575,8 +574,9 @@ set( PLAT_COCOA_SOURCES cocoa/i_cd.cpp cocoa/i_joystick.cpp cocoa/i_movie.cpp - cocoa/st_start.cpp + cocoa/i_system.cpp cocoa/i_timer.cpp + cocoa/st_start.cpp cocoa/zdoom.icns ) if( WIN32 ) @@ -601,6 +601,7 @@ elseif( APPLE ) else( OSX_COCOA_BACKEND ) set( SYSTEM_SOURCES_DIR sdl ) set( SYSTEM_SOURCES ${PLAT_SDL_SOURCES} ) + set( PLAT_MAC_SOURCES ${PLAT_MAC_SOURCES} cocoa/i_system_cocoa.mm ) set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_COCOA_SOURCES} ) endif( OSX_COCOA_BACKEND ) diff --git a/src/cocoa/i_backend_cocoa.mm b/src/cocoa/i_backend_cocoa.mm index be2d14276..3f4574e04 100644 --- a/src/cocoa/i_backend_cocoa.mm +++ b/src/cocoa/i_backend_cocoa.mm @@ -56,15 +56,19 @@ #include "cmdlib.h" #include "d_event.h" #include "d_gui.h" +#include "d_main.h" #include "dikeys.h" #include "doomdef.h" +#include "doomerrors.h" #include "doomstat.h" +#include "m_argv.h" #include "s_sound.h" #include "textures.h" #include "v_video.h" #include "version.h" #include "i_rbopts.h" #include "i_osversion.h" +#include "i_system.h" #undef Class @@ -190,8 +194,12 @@ typedef NSInteger NSApplicationActivationPolicy; RenderBufferOptions rbOpts; -EXTERN_CVAR(Bool, fullscreen) -EXTERN_CVAR(Bool, vid_hidpi) +EXTERN_CVAR(Bool, fullscreen ) +EXTERN_CVAR(Bool, vid_hidpi ) +EXTERN_CVAR(Bool, vid_vsync ) +EXTERN_CVAR(Int, vid_adapter ) +EXTERN_CVAR(Int, vid_defwidth ) +EXTERN_CVAR(Int, vid_defheight) CVAR(Bool, use_mouse, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, m_noprescale, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -217,9 +225,90 @@ extern constate_e ConsoleState; EXTERN_CVAR(Int, m_use_mouse); +void I_StartupJoysticks(); void I_ShutdownJoysticks(); +// --------------------------------------------------------------------------- + + +DArgs *Args; // command line arguments + +namespace +{ + +// The maximum number of functions that can be registered with atterm. +static const size_t MAX_TERMS = 64; + +static void (*TermFuncs[MAX_TERMS])(); +static const char *TermNames[MAX_TERMS]; +static size_t NumTerms; + +void call_terms() +{ + while (NumTerms > 0) + { + TermFuncs[--NumTerms](); + } +} + +} // unnamed namespace + + +void addterm(void (*func)(), const char *name) +{ + // Make sure this function wasn't already registered. + + for (size_t i = 0; i < NumTerms; ++i) + { + if (TermFuncs[i] == func) + { + return; + } + } + + if (NumTerms == MAX_TERMS) + { + func(); + I_FatalError("Too many exit functions registered."); + } + + TermNames[NumTerms] = name; + TermFuncs[NumTerms] = func; + + ++NumTerms; +} + +void popterm() +{ + if (NumTerms) + { + --NumTerms; + } +} + + +void I_SetMainWindowVisible(bool); + +void Mac_I_FatalError(const char* const message) +{ + I_SetMainWindowVisible(false); + + const CFStringRef errorString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, + message, kCFStringEncodingASCII, kCFAllocatorNull); + + if (NULL != errorString) + { + CFOptionFlags dummy; + + CFUserNotificationDisplayAlert( 0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, + CFSTR("Fatal Error"), errorString, CFSTR("Exit"), NULL, NULL, &dummy); + + CFRelease(errorString); + } +} + + namespace { @@ -241,6 +330,112 @@ size_t s_skipMouseMoves; NSCursor* s_cursor; +void NewFailure() +{ + I_FatalError("Failed to allocate memory from system heap"); +} + + +int OriginalMain(int argc, char** argv) +{ + printf(GAMENAME" %s - %s - Cocoa version\nCompiled on %s\n", + GetVersionString(), GetGitTime(), __DATE__); + + seteuid(getuid()); + std::set_new_handler(NewFailure); + + // Set LC_NUMERIC environment variable in case some library decides to + // clear the setlocale call at least this will be correct. + // Note that the LANG environment variable is overridden by LC_* + setenv("LC_NUMERIC", "C", 1); + setlocale(LC_ALL, "C"); + + if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE|SDL_INIT_JOYSTICK) == -1) + { + fprintf (stderr, "Could not initialize SDL:\n%s\n", SDL_GetError()); + return -1; + } + atterm(SDL_Quit); + + printf("\n"); + + SDL_DisplayMode videoInfo = {}; + + if (0 == SDL_GetDesktopDisplayMode(vid_adapter, &videoInfo)) + { + vid_defwidth = videoInfo.w; + vid_defheight = videoInfo.h; + vid_vsync = true; + fullscreen = true; + } + + try + { + Args = new DArgs(argc, argv); + + /* + killough 1/98: + + This fixes some problems with exit handling + during abnormal situations. + + The old code called I_Quit() to end program, + while now I_Quit() is installed as an exit + handler and exit() is called to exit, either + normally or abnormally. Seg faults are caught + and the error handler is used, to prevent + being left in graphics mode or having very + loud SFX noise because the sound card is + left in an unstable state. + */ + + atexit (call_terms); + atterm (I_Quit); + + // Should we even be doing anything with progdir on Unix systems? + char program[PATH_MAX]; + if (realpath (argv[0], program) == NULL) + strcpy (program, argv[0]); + char *slash = strrchr (program, '/'); + if (slash != NULL) + { + *(slash + 1) = '\0'; + progdir = program; + } + else + { + progdir = "./"; + } + + I_StartupJoysticks(); + C_InitConsole(80 * 8, 25 * 8, false); + D_DoomMain(); + } + catch(const CDoomError& error) + { + const char* const message = error.GetMessage(); + + if (NULL != message) + { + fprintf(stderr, "%s\n", message); + Mac_I_FatalError(message); + } + + exit(-1); + } + catch(...) + { + call_terms(); + throw; + } + + return 0; +} + + +// --------------------------------------------------------------------------- + + void CheckGUICapture() { const bool wantCapture = (MENU_Off == menuactive) @@ -1131,7 +1326,7 @@ static bool s_fullscreenNewAPI; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; - exit(SDL_main(s_argc, s_argv)); + exit(OriginalMain(s_argc, s_argv)); } @@ -1613,33 +1808,9 @@ bool I_SetCursor(FTexture* cursorpic) // --------------------------------------------------------------------------- -const char* I_GetBackEndName() -{ - return "Native Cocoa"; -} - - -// --------------------------------------------------------------------------- - - extern "C" { -static timeval s_startTicks; - -uint32_t SDL_GetTicks() -{ - timeval now; - gettimeofday(&now, NULL); - - const uint32_t ticks = - (now.tv_sec - s_startTicks.tv_sec ) * 1000 - + (now.tv_usec - s_startTicks.tv_usec) / 1000; - - return ticks; -} - - int SDL_Init(Uint32 flags) { ZD_UNUSED(flags); @@ -1667,11 +1838,6 @@ const char* SDL_GetError() } -const char* SDL_GetCurrentVideoDriver() -{ - return "Native OpenGL"; -} - int SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode *mode) { // NOTE: Only required fields are assigned @@ -2099,8 +2265,6 @@ const DarwinVersion darwinVersion = GetDarwinVersion(); int main(int argc, char** argv) { - gettimeofday(&s_startTicks, NULL); - for (int i = 0; i <= argc; ++i) { const char* const argument = argv[i]; diff --git a/src/cocoa/i_system.cpp b/src/cocoa/i_system.cpp new file mode 120000 index 000000000..b95185a13 --- /dev/null +++ b/src/cocoa/i_system.cpp @@ -0,0 +1 @@ +../sdl/i_system.cpp \ No newline at end of file diff --git a/src/cocoa/i_timer.cpp b/src/cocoa/i_timer.cpp index 0699a9967..c63561077 100644 --- a/src/cocoa/i_timer.cpp +++ b/src/cocoa/i_timer.cpp @@ -4,8 +4,6 @@ #include #include -#include - #include "basictypes.h" #include "basicinlines.h" #include "doomdef.h" @@ -13,23 +11,36 @@ #include "templates.h" +static timeval s_startTicks; + + unsigned int I_MSTime() { - return SDL_GetTicks(); + timeval now; + gettimeofday(&now, NULL); + + const uint32_t ticks = + (now.tv_sec - s_startTicks.tv_sec ) * 1000 + + (now.tv_usec - s_startTicks.tv_usec) / 1000; + + return ticks; } unsigned int I_FPSTime() { - return SDL_GetTicks(); + timeval now; + gettimeofday(&now, NULL); + + return static_cast( + (now.tv_sec) * 1000 + (now.tv_usec) / 1000); } -bool g_isTicFrozen; - - namespace { +bool s_isTicFrozen; + timespec GetNextTickTime() { static const long MILLISECONDS_IN_SECOND = 1000; @@ -91,7 +102,7 @@ void* TimerThreadFunc(void*) pthread_mutex_lock(&s_timerMutex); pthread_cond_timedwait(&s_timerEvent, &s_timerMutex, &timeToNextTick); - if (!g_isTicFrozen) + if (!s_isTicFrozen) { // The following GCC/Clang intrinsic can be used instead of OS X specific function: // __sync_add_and_fetch(&s_tics, 1); @@ -101,7 +112,7 @@ void* TimerThreadFunc(void*) OSAtomicIncrement32(&s_tics); } - s_timerStart = SDL_GetTicks(); + s_timerStart = I_MSTime(); pthread_cond_broadcast(&s_timerEvent); pthread_mutex_unlock(&s_timerMutex); @@ -122,7 +133,7 @@ int GetTimeThreaded(bool saveMS) int WaitForTicThreaded(int prevTic) { - assert(!g_isTicFrozen); + assert(!s_isTicFrozen); while (s_tics <= prevTic) { @@ -136,7 +147,7 @@ int WaitForTicThreaded(int prevTic) void FreezeTimeThreaded(bool frozen) { - g_isTicFrozen = frozen; + s_isTicFrozen = frozen; } } // unnamed namespace @@ -144,7 +155,7 @@ void FreezeTimeThreaded(bool frozen) fixed_t I_GetTimeFrac(uint32* ms) { - const uint32_t now = SDL_GetTicks(); + const uint32_t now = I_MSTime(); if (NULL != ms) { @@ -157,11 +168,13 @@ fixed_t I_GetTimeFrac(uint32* ms) } -void I_InitTimer () +void I_InitTimer() { assert(!s_timerInitialized); s_timerInitialized = true; + gettimeofday(&s_startTicks, NULL); + pthread_cond_init (&s_timerEvent, NULL); pthread_mutex_init(&s_timerMutex, NULL); @@ -172,7 +185,7 @@ void I_InitTimer () I_FreezeTime = FreezeTimeThreaded; } -void I_ShutdownTimer () +void I_ShutdownTimer() { if (!s_timerInitialized) { diff --git a/src/sdl/i_gui.cpp b/src/sdl/i_gui.cpp index c2b91b39c..f9e6714b4 100644 --- a/src/sdl/i_gui.cpp +++ b/src/sdl/i_gui.cpp @@ -59,8 +59,3 @@ void I_SetMainWindowVisible(bool visible) { } - -const char* I_GetBackEndName() -{ - return "SDL"; -} diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp index 33395e0f1..10a9b8c75 100644 --- a/src/sdl/i_main.cpp +++ b/src/sdl/i_main.cpp @@ -235,13 +235,7 @@ static void unprotect_rtext() void I_StartupJoysticks(); void I_ShutdownJoysticks(); -const char* I_GetBackEndName(); - -#ifdef USE_NATIVE_COCOA -int SDL_main (int argc, char **argv) -#else int main (int argc, char **argv) -#endif { #if !defined (__APPLE__) { @@ -250,8 +244,8 @@ int main (int argc, char **argv) } #endif // !__APPLE__ - printf(GAMENAME" %s - %s - %s version\nCompiled on %s\n", - GetVersionString(), GetGitTime(), I_GetBackEndName(), __DATE__); + printf(GAMENAME" %s - %s - SDL version\nCompiled on %s\n", + GetVersionString(), GetGitTime(), __DATE__); seteuid (getuid ()); std::set_new_handler (NewFailure); @@ -280,24 +274,6 @@ int main (int argc, char **argv) printf("Using video driver %s\n", SDL_GetCurrentVideoDriver()); printf("\n"); - -#ifdef __APPLE__ - EXTERN_CVAR( Int, vid_adapter ) - SDL_DisplayMode videoInfo = {}; - if ( SDL_GetDesktopDisplayMode (vid_adapter, &videoInfo) == 0 ) - { - EXTERN_CVAR( Int, vid_defwidth ) - EXTERN_CVAR( Int, vid_defheight ) - EXTERN_CVAR( Int, vid_defbits ) - EXTERN_CVAR( Bool, vid_vsync ) - EXTERN_CVAR( Bool, fullscreen ) - - vid_defwidth = videoInfo.w; - vid_defheight = videoInfo.h; - vid_vsync = true; - fullscreen = true; - } -#endif // __APPLE__ try { diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 41fdef323..c2ce4aa9f 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -41,7 +41,6 @@ #include "doomerrors.h" #include -#include "SDL.h" #include "doomtype.h" #include "doomstat.h" #include "version.h"