From 61ee96e60e2c4216f7e78c42ceddb1dba0d7e606 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 20 Mar 2025 10:07:52 -0400 Subject: [PATCH 01/28] vcpkg: we need to compile curl with mbedtls for WASM --- vcpkg.json | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/vcpkg.json b/vcpkg.json index 3b79ec83f..40db9ea12 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -8,11 +8,16 @@ "name": "curl", "platform": "!wasm32" }, - "libgme", { - "name":"libopenmpt", - "platform": "!wasm32" + "name": "curl", + "default-features": false, + "platform": "wasm32", + "features": [ + "mbedtls" + ] }, + "libgme", + "libopenmpt", "libpng", "miniupnpc", { @@ -28,7 +33,6 @@ "platform": "!windows" } ], - "platform": "!wasm32", "version>=": "2.30.6#2" }, { @@ -38,29 +42,16 @@ "name":"fluidsynth", "platform": "!static" }, - { - "name":"libflac", - "platform": "!wasm32" - }, + "libflac", "libgme", "libmodplug", - { - "name":"libvorbis", - "platform": "!wasm32" - }, + "libvorbis", "libxmp", - { - "name":"mpg123", - "platform": "!wasm32" - }, - { - "name":"opusfile", - "platform": "!wasm32" - }, + "mpg123", + "opusfile", "pxtone", "timidity" ], - "platform": "!wasm32", "version>=": "2.6.0#0" }, "zlib" From dc661b7d37740d7f852b9cdcfeb303f9cdaa9ad9 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 20 Mar 2025 10:08:29 -0400 Subject: [PATCH 02/28] Add support for emscripten SDK --- src/doomtype.h | 2 +- src/sdl/i_system.c | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/doomtype.h b/src/doomtype.h index 415669ac4..9edbd3231 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -110,7 +110,7 @@ int startswith (const char *base, const char *tag); int endswith (const char *base, const char *tag); char *xstrtok(char *line, const char *delims); -#if defined (_WIN32) || defined (__HAIKU__) +#if defined (_WIN32) || defined (__HAIKU__) || defined (__EMSCRIPTEN__) #define HAVE_DOSSTR_FUNCS #endif diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index b2396e269..f5e6614d7 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -79,7 +79,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #define HAVE_SDLCPUINFO #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) -#if defined (__linux__) || defined (__HAIKU__) +#if defined (__linux__) || defined (__HAIKU__) || defined (__EMSCRIPTEN__) #include #else #include @@ -111,9 +111,11 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include #include #ifndef __HAIKU__ // haiku's crash dialog is just objectively better +#ifndef __EMSCRIPTEN__ // WASM does not have a rell fork() #define NEWSIGNALHANDLER #endif #endif +#endif #ifndef NOMUMBLE #ifdef __linux__ // need -lrt @@ -145,12 +147,14 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) +#if !defined (__EMSCRIPTEN__) #ifndef NOEXECINFO #include #endif #include #define UNIXBACKTRACE #endif +#endif // Locations to directly check for srb2.pk3 in const char *wadDefaultPaths[] = { From cc03ec365dcf7b0bf024cf2396a5dc2f5b91ff95 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 20 Mar 2025 21:23:49 -0400 Subject: [PATCH 03/28] vcpkg: add version check for curl for mbedtls feature --- vcpkg.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/vcpkg.json b/vcpkg.json index 40db9ea12..0a153f542 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -11,28 +11,28 @@ { "name": "curl", "default-features": false, - "platform": "wasm32", "features": [ "mbedtls" - ] + ], + "platform": "wasm32", + "version>=": "7.74.0#5" }, "libgme", "libopenmpt", "libpng", "miniupnpc", + { + "name": "sdl2", + "platform": "!linux" + }, { "name": "sdl2", "default-features": false, "features": [ - { - "name": "wayland", - "platform": "linux" - }, - { - "name": "x11", - "platform": "!windows" - } + "wayland", + "x11" ], + "platform": "linux", "version>=": "2.30.6#2" }, { From f26711ef881f5f7fd5402438087a0ef093b073b2 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 22 Mar 2025 22:54:50 -0400 Subject: [PATCH 04/28] vcpkg: do not compile libflac with old version of emscripten --- vcpkg.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/vcpkg.json b/vcpkg.json index 0a153f542..5bd5d45be 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -39,10 +39,13 @@ "name": "sdl2-mixer-ext", "features": [ { - "name":"fluidsynth", + "name": "fluidsynth", "platform": "!static" }, - "libflac", + { + "name": "libflac", + "platform": "!emscripten" + }, "libgme", "libmodplug", "libvorbis", From cb28bad2fdd7f889f5d2844d675bdbe5997f3eb9 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 25 Mar 2025 15:55:25 -0400 Subject: [PATCH 05/28] Make a backup of the SOC tables is too big for WASM32 --- src/doomdef.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/doomdef.h b/src/doomdef.h index 81ab7bbfb..973d95eab 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -703,7 +703,9 @@ extern int /// This stops the game from storing backups of the states, sprites, and mobjinfo tables. /// Though this info is compressed under normal circumstances, it's still a lot of extra /// memory that never gets touched. +#if !(defined (__EMSCRIPTEN__) && (__SIZEOF_SIZE_T__ == 4)) #define ALLOW_RESETDATA +#endif /// Experimental tweaks to analog mode. (Needs a lot of work before it's ready for primetime.) //#define REDSANALOG From 8143e34e399b891ecaa403ad0f8ab8c7993616c1 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 25 Mar 2025 15:56:11 -0400 Subject: [PATCH 06/28] hardware: cleanup STATIC_OPENGL code --- src/hardware/r_opengl/r_opengl.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 02a32957a..1de2f1d62 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -227,7 +227,6 @@ FUNCPRINTF static void GL_MSG_Error(const char *format, ...) /* 1.0 functions */ /* Miscellaneous */ #define pglClearColor glClearColor -//glClear #define pglColorMask glColorMask #define pglAlphaFunc glAlphaFunc #define pglBlendFunc glBlendFunc @@ -237,9 +236,7 @@ FUNCPRINTF static void GL_MSG_Error(const char *format, ...) #define pglEnable glEnable #define pglDisable glDisable #define pglGetFloatv glGetFloatv -//glGetIntegerv -//glGetString -#define pglHint glHint +#define pglPolygonMode glPolygonMode /* Depth Buffer */ #define pglClearDepth glClearDepth @@ -283,6 +280,7 @@ FUNCPRINTF static void GL_MSG_Error(const char *format, ...) /* Texture mapping */ #define pglTexEnvi glTexEnvi #define pglTexParameteri glTexParameteri +#define pglTexImage1D glTexImage1D #define pglTexImage2D glTexImage2D #define pglTexSubImage2D glTexSubImage2D @@ -668,6 +666,7 @@ void SetupGLFunc4(void) { /* 1.2 funcs */ pglTexImage3D = GetGLFunc("glTexImage3D"); + /* 1.3 funcs */ pglActiveTexture = GetGLFunc("glActiveTexture"); pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); From 5595855878853b19ba29c9d31baeab8559d0a477 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 25 Mar 2025 15:56:46 -0400 Subject: [PATCH 07/28] Some runtime platform do not have thread support --- src/sdl/i_system.c | 2 -- src/sdl/i_threads.c | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index f5e6614d7..1e0fe874c 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2444,10 +2444,8 @@ INT32 I_StartupSystem(void) SDL_version SDLlinked; SDL_VERSION(&SDLcompiled) SDL_GetVersion(&SDLlinked); -#ifdef HAVE_THREADS I_start_threads(); I_AddExitFunc(I_stop_threads); -#endif I_StartupConsole(); #ifdef NEWSIGNALHANDLER // This is useful when debugging. It lets GDB attach to diff --git a/src/sdl/i_threads.c b/src/sdl/i_threads.c index c05936072..99b445103 100644 --- a/src/sdl/i_threads.c +++ b/src/sdl/i_threads.c @@ -185,7 +185,10 @@ I_spawn_thread ( ); if (! th->thread) + { + I_OutputMsg("I_spawn_thread failed to make thread %s: %s\n", name, SDL_GetError()); abort(); + } } } I_unlock_mutex(i_thread_pool_mutex); From 538f1b6985bfe38abdbdb973ab807128beb81518 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 27 Mar 2025 13:29:45 -0400 Subject: [PATCH 08/28] Check at runtime if we can make threads --- src/CMakeLists.txt | 3 - src/Makefile.d/dedicated.mk | 3 - src/Makefile.d/sdl.mk | 3 - src/console.c | 5 -- src/console.h | 2 - src/d_main.c | 12 ---- src/dedicated/i_system.c | 2 - src/dedicated/i_threads.c | 10 +++- src/doomtype.h | 5 ++ src/f_finale.c | 4 -- src/f_wipe.c | 4 -- src/i_threads.h | 6 +- src/m_menu.c | 95 ++++++++++++++++-------------- src/m_menu.h | 2 - src/netcode/client_connection.c | 60 +++++++++---------- src/netcode/d_clisrv.c | 4 -- src/netcode/d_netfil.c | 5 +- src/netcode/http-mserv.c | 18 ------ src/netcode/i_tcp.c | 7 ++- src/netcode/mserv.c | 101 +++++++++++++++----------------- src/netcode/mserv.h | 2 - src/sdl/i_threads.c | 32 +++++++++- 22 files changed, 185 insertions(+), 200 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fbc341733..b02d0f69c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -192,9 +192,6 @@ endif() target_compile_definitions(SRB2SDL2 PRIVATE -D_LARGEFILE64_SOURCE) -set(SRB2_HAVE_THREADS ON) -target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_THREADS) - if("${SRB2_CONFIG_HWRENDER}") target_compile_definitions(SRB2SDL2 PRIVATE -DHWRENDER) add_subdirectory(hardware) diff --git a/src/Makefile.d/dedicated.mk b/src/Makefile.d/dedicated.mk index 698ea5531..af7904887 100644 --- a/src/Makefile.d/dedicated.mk +++ b/src/Makefile.d/dedicated.mk @@ -13,10 +13,7 @@ ifdef MINGW libs+=-mconsole endif -ifndef NOTHREADS -opts+=-DHAVE_THREADS sources+=dedicated/i_threads.c -endif NOOPENMPT=1 NOGME=1 diff --git a/src/Makefile.d/sdl.mk b/src/Makefile.d/sdl.mk index d5e83989c..d07d23f51 100644 --- a/src/Makefile.d/sdl.mk +++ b/src/Makefile.d/sdl.mk @@ -43,10 +43,7 @@ sources+=sdl/mixer_sound.c endif endif -ifndef NOTHREADS -opts+=-DHAVE_THREADS sources+=sdl/i_threads.c -endif ifdef SDL_PKGCONFIG $(eval $(call Use_pkg_config,SDL)) diff --git a/src/console.c b/src/console.c index 50ecfec9c..182995063 100644 --- a/src/console.c +++ b/src/console.c @@ -45,15 +45,10 @@ #define MAXHUDLINES 20 -#ifdef HAVE_THREADS I_mutex con_mutex; # define Lock_state() I_lock_mutex(&con_mutex) # define Unlock_state() I_unlock_mutex(con_mutex) -#else/*HAVE_THREADS*/ -# define Lock_state() -# define Unlock_state() -#endif/*HAVE_THREADS*/ static boolean con_started = false; // console has been initialised boolean con_startup = false; // true at game startup diff --git a/src/console.h b/src/console.h index 2af01f1a3..77ed29d7c 100644 --- a/src/console.h +++ b/src/console.h @@ -21,9 +21,7 @@ void CON_StopRefresh(void); boolean CON_Responder(event_t *ev); -#ifdef HAVE_THREADS extern I_mutex con_mutex; -#endif // set true when screen size has changed, to adapt console extern boolean con_recalc; diff --git a/src/d_main.c b/src/d_main.c index d75a4d501..9164f1306 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -244,15 +244,11 @@ void D_ProcessEvents(void) } // Menu input -#ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); -#endif { eaten = M_Responder(ev); } -#ifdef HAVE_THREADS I_unlock_mutex(m_menu_mutex); -#endif if (eaten) continue; // menu ate the event @@ -264,15 +260,11 @@ void D_ProcessEvents(void) } // console input -#ifdef HAVE_THREADS I_lock_mutex(&con_mutex); -#endif { eaten = CON_Responder(ev); } -#ifdef HAVE_THREADS I_unlock_mutex(con_mutex); -#endif if (eaten) continue; // ate the event @@ -596,13 +588,9 @@ static void D_Display(void) // vid size change is now finished if it was on... vid.recalc = 0; -#ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); -#endif M_Drawer(); // menu is drawn even on top of everything -#ifdef HAVE_THREADS I_unlock_mutex(m_menu_mutex); -#endif // focus lost moved to M_Drawer CON_Drawer(); diff --git a/src/dedicated/i_system.c b/src/dedicated/i_system.c index 643e24f5a..d35b647b4 100644 --- a/src/dedicated/i_system.c +++ b/src/dedicated/i_system.c @@ -1181,10 +1181,8 @@ static void I_RegisterSignals (void) INT32 I_StartupSystem(void) { -#ifdef HAVE_THREADS I_start_threads(); I_AddExitFunc(I_stop_threads); -#endif I_StartupConsole(); I_RegisterSignals(); #ifndef NOMUMBLE diff --git a/src/dedicated/i_threads.c b/src/dedicated/i_threads.c index 55c0a069e..0e0b0bbe3 100644 --- a/src/dedicated/i_threads.c +++ b/src/dedicated/i_threads.c @@ -42,10 +42,11 @@ static void *HandleThread(void *data) return NULL; } -void I_spawn_thread(const char *name, I_thread_fn entry, void *userdata) +int I_spawn_thread(const char *name, I_thread_fn entry, void *userdata) { thread_t *thread; (void)name; + pthread_mutex_lock(&thread_lock); thread = thread_list; while (thread != NULL) @@ -69,6 +70,13 @@ void I_spawn_thread(const char *name, I_thread_fn entry, void *userdata) thread->userdata = userdata; pthread_create(&thread->thread, NULL, HandleThread, thread); pthread_mutex_unlock(&thread_lock); + + return true; +} + +int I_can_thread(void) +{ + return true; } int I_thread_is_stopped(void) diff --git a/src/doomtype.h b/src/doomtype.h index 9edbd3231..ca80a6084 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -245,6 +245,8 @@ enum {false = 0, true = 1}; #define FUNCNOINLINE __attribute__((noinline)) + #define FUNCWARNRV __attribute__((warn_unused_result)) + #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) // >= GCC 4.4 #ifdef __i386__ // i386 only #define FUNCTARGET(X) __attribute__ ((__target__ (X))) @@ -296,6 +298,9 @@ enum {false = 0, true = 1}; #ifndef FUNCTARGET #define FUNCTARGET(x) #endif +#ifndef FUNCWARNRV +#define FUNCWARNRV +#endif #ifndef ATTRPACK #define ATTRPACK #endif diff --git a/src/f_finale.c b/src/f_finale.c index c6d957292..264c18d53 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -919,13 +919,9 @@ void F_IntroTicker(void) I_OsPolling(); I_UpdateNoBlit(); -#ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); -#endif M_Drawer(); // menu is drawn even on top of wipes -#ifdef HAVE_THREADS I_unlock_mutex(m_menu_mutex); -#endif I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001 if (moviemode) // make sure we save frames for the white hold too diff --git a/src/f_wipe.c b/src/f_wipe.c index 1ea32d0eb..dc588c13b 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -601,13 +601,9 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) if (drawMenu) { -#ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); -#endif M_Drawer(); // menu is drawn even on top of wipes -#ifdef HAVE_THREADS I_unlock_mutex(m_menu_mutex); -#endif } I_FinishUpdate(); // page flip or blit buffer diff --git a/src/i_threads.h b/src/i_threads.h index fe6ab4fb0..079b18771 100644 --- a/src/i_threads.h +++ b/src/i_threads.h @@ -9,8 +9,6 @@ /// \file i_threads.h /// \brief Multithreading abstraction -#ifdef HAVE_THREADS - #ifndef I_THREADS_H #define I_THREADS_H @@ -19,10 +17,11 @@ typedef void (*I_thread_fn)(void *userdata); typedef void * I_mutex; typedef void * I_cond; +int I_can_thread (void) FUNCWARNRV; void I_start_threads (void); void I_stop_threads (void); -void I_spawn_thread (const char *name, I_thread_fn, void *userdata); +int I_spawn_thread (const char *name, I_thread_fn, void *userdata) FUNCWARNRV; /* check in your thread whether to return early */ int I_thread_is_stopped (void); @@ -36,4 +35,3 @@ void I_wake_one_cond (I_cond *); void I_wake_all_cond (I_cond *); #endif/*I_THREADS_H*/ -#endif/*HAVE_THREADS*/ diff --git a/src/m_menu.c b/src/m_menu.c index be1b421f7..57ebe1527 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -123,9 +123,7 @@ typedef enum NUM_QUITMESSAGES } text_enum; -#ifdef HAVE_THREADS I_mutex m_menu_mutex; -#endif M_waiting_mode_t m_waiting_mode = M_NOT_WAITING; @@ -3802,29 +3800,32 @@ void M_SetupNextMenu(menu_t *menudef) { INT16 i; -#if defined (MASTERSERVER) && defined (HAVE_THREADS) - if (currentMenu == &MP_RoomDef || currentMenu == &MP_ConnectDef) +#if defined (MASTERSERVER) + if (I_can_thread()) { - I_lock_mutex(&ms_QueryId_mutex); + if (currentMenu == &MP_RoomDef || currentMenu == &MP_ConnectDef) { - ms_QueryId++; - } - I_unlock_mutex(ms_QueryId_mutex); - } - - if (currentMenu == &MP_ConnectDef) - { - I_lock_mutex(&ms_ServerList_mutex); - { - if (ms_ServerList) + I_lock_mutex(&ms_QueryId_mutex); { - free(ms_ServerList); - ms_ServerList = NULL; + ms_QueryId++; } + I_unlock_mutex(ms_QueryId_mutex); + } + + if (currentMenu == &MP_ConnectDef) + { + I_lock_mutex(&ms_ServerList_mutex); + { + if (ms_ServerList) + { + free(ms_ServerList); + ms_ServerList = NULL; + } + } + I_unlock_mutex(ms_ServerList_mutex); } - I_unlock_mutex(ms_ServerList_mutex); } -#endif/*HAVE_THREADS*/ +#endif/*MASTERSERVER*/ if (currentMenu->quitroutine) { @@ -3891,7 +3892,7 @@ void M_Ticker(void) if (currentMenu == &OP_ScreenshotOptionsDef) M_SetupScreenshotMenu(); -#if defined (MASTERSERVER) && defined (HAVE_THREADS) +#if defined (MASTERSERVER) if (!netgame) return; @@ -11378,7 +11379,7 @@ static boolean M_CheckMODVersion(int id) } #endif/*UPDATE_ALERT*/ -#if defined (MASTERSERVER) && defined (HAVE_THREADS) +#if defined (MASTERSERVER) static void Check_new_version_thread (int *id) { @@ -11435,7 +11436,7 @@ Check_new_version_thread (int *id) free(id); } -#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ +#endif/*defined (MASTERSERVER)*/ static void M_ConnectMenu(INT32 choice) { @@ -11477,7 +11478,7 @@ UINT32 roomIds[NUM_LIST_ROOMS]; static void M_RoomMenu(INT32 choice) { INT32 i; -#if defined (MASTERSERVER) && defined (HAVE_THREADS) +#if defined (MASTERSERVER) int *id; #endif @@ -11500,44 +11501,50 @@ static void M_RoomMenu(INT32 choice) M_SetupNextMenu(&MP_RoomDef); #ifdef MASTERSERVER -#ifdef HAVE_THREADS + if (I_can_thread()) + { #ifdef UPDATE_ALERT - m_waiting_mode = M_WAITING_VERSION; + m_waiting_mode = M_WAITING_VERSION; #else/*UPDATE_ALERT*/ - m_waiting_mode = M_WAITING_ROOMS; + m_waiting_mode = M_WAITING_ROOMS; #endif/*UPDATE_ALERT*/ - MP_RoomMenu[0].text = ""; + MP_RoomMenu[0].text = ""; - id = malloc(sizeof *id); + id = malloc(sizeof *id); - I_lock_mutex(&ms_QueryId_mutex); - { - *id = ms_QueryId; + I_lock_mutex(&ms_QueryId_mutex); + { + *id = ms_QueryId; + } + I_unlock_mutex(ms_QueryId_mutex); + + (void)I_spawn_thread("check-new-version", + (I_thread_fn)Check_new_version_thread, id); } - I_unlock_mutex(ms_QueryId_mutex); - - I_spawn_thread("check-new-version", - (I_thread_fn)Check_new_version_thread, id); -#else/*HAVE_THREADS*/ + else + { #ifdef UPDATE_ALERT - if (M_CheckMODVersion(0)) + if (M_CheckMODVersion(0)) #endif/*UPDATE_ALERT*/ - { - GetRoomsList(currentMenu->prevMenu == &MP_ServerDef, 0); + { + GetRoomsList(currentMenu->prevMenu == &MP_ServerDef, 0); + } } -#endif/*HAVE_THREADS*/ #endif/*MASTERSERVER*/ } static void M_ChooseRoom(INT32 choice) { -#if defined (MASTERSERVER) && defined (HAVE_THREADS) - I_lock_mutex(&ms_QueryId_mutex); +#if defined (MASTERSERVER) + if (I_can_thread()) { - ms_QueryId++; + I_lock_mutex(&ms_QueryId_mutex); + { + ms_QueryId++; + } + I_unlock_mutex(ms_QueryId_mutex); } - I_unlock_mutex(ms_QueryId_mutex); #endif if (choice == 0) diff --git a/src/m_menu.h b/src/m_menu.h index dc8bef8b1..ecfe182d3 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -352,9 +352,7 @@ void M_ClearMenus(boolean callexitmenufunc); // Maybe this goes here????? Who knows. boolean M_MouseNeeded(void); -#ifdef HAVE_THREADS extern I_mutex m_menu_mutex; -#endif extern menu_t *currentMenu; diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index c740d53a6..2fe2c0968 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -392,7 +392,7 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) M_SortServerList(); } -#if defined (MASTERSERVER) && defined (HAVE_THREADS) +#if defined (MASTERSERVER) struct Fetch_servers_ctx { int room; @@ -437,7 +437,7 @@ Fetch_servers_thread (struct Fetch_servers_ctx *ctx) free(ctx); } -#endif // defined (MASTERSERVER) && defined (HAVE_THREADS) +#endif // defined (MASTERSERVER) void CL_QueryServerList (msg_server_t *server_list) { @@ -493,34 +493,38 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) #ifdef MASTERSERVER if (internetsearch) { -#ifdef HAVE_THREADS - struct Fetch_servers_ctx *ctx; - - ctx = malloc(sizeof *ctx); - - // This called from M_Refresh so I don't use a mutex - m_waiting_mode = M_WAITING_SERVERS; - - I_lock_mutex(&ms_QueryId_mutex); + if (I_can_thread()) { - ctx->id = ms_QueryId; + struct Fetch_servers_ctx *ctx; + + ctx = malloc(sizeof *ctx); + + // This called from M_Refresh so I don't use a mutex + m_waiting_mode = M_WAITING_SERVERS; + + I_lock_mutex(&ms_QueryId_mutex); + { + ctx->id = ms_QueryId; + } + I_unlock_mutex(ms_QueryId_mutex); + + ctx->room = room; + + (void)I_spawn_thread("fetch-servers", (I_thread_fn)Fetch_servers_thread, ctx); } - I_unlock_mutex(ms_QueryId_mutex); - - ctx->room = room; - - I_spawn_thread("fetch-servers", (I_thread_fn)Fetch_servers_thread, ctx); -#else - msg_server_t *server_list; - - server_list = GetShortServersList(room, 0); - - if (server_list) + else { - CL_QueryServerList(server_list); - free(server_list); + msg_server_t *server_list; + + server_list = GetShortServersList(room, 0); + + if (server_list) + { + CL_QueryServerList(server_list); + free(server_list); + } } -#endif + } #endif // MASTERSERVER } @@ -1187,13 +1191,9 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic F_TitleScreenDrawer(); } CL_DrawConnectionStatus(); -#ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); -#endif M_Drawer(); //Needed for drawing messageboxes on the connection screen -#ifdef HAVE_THREADS I_unlock_mutex(m_menu_mutex); -#endif I_UpdateNoVsync(); // page flip or blit buffer if (moviemode) M_SaveFrame(); diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 6702e2591..7c469699d 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -1645,13 +1645,9 @@ void NetUpdate(void) if (nowtime != resptime) { resptime = nowtime; -#ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); -#endif M_Ticker(); -#ifdef HAVE_THREADS I_unlock_mutex(m_menu_mutex); -#endif CON_Ticker(); } diff --git a/src/netcode/d_netfil.c b/src/netcode/d_netfil.c index bfb67838f..1ed138f5f 100644 --- a/src/netcode/d_netfil.c +++ b/src/netcode/d_netfil.c @@ -1605,6 +1605,9 @@ boolean CURLPrepareFile(const char* url, int dfilenum) { HTTP_login *login; + if (!I_can_thread()) + return false; + #ifdef PARANOIA if (M_CheckParm("-nodownload")) I_Error("Attempted to download files in -nodownload mode"); @@ -1675,7 +1678,7 @@ boolean CURLPrepareFile(const char* url, int dfilenum) filedownload.current = dfilenum; filedownload.http_running = true; - I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL); + (void)I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL); return true; } diff --git a/src/netcode/http-mserv.c b/src/netcode/http-mserv.c index 0fe1e9934..eeac2beb5 100644 --- a/src/netcode/http-mserv.c +++ b/src/netcode/http-mserv.c @@ -70,9 +70,7 @@ static boolean hms_allow_ipv6; static boolean hms_allow_ipv4; static char *hms_api; -#ifdef HAVE_THREADS static I_mutex hms_api_mutex; -#endif static char *hms_server_token; #ifndef NO_IPV6 @@ -201,9 +199,7 @@ HMS_connect (int proto, const char *format, ...) token_length = 0; } -#ifdef HAVE_THREADS I_lock_mutex(&hms_api_mutex); -#endif init_user_agent_once(); @@ -215,9 +211,7 @@ HMS_connect (int proto, const char *format, ...) sprintf(url, "%s/", hms_api); -#ifdef HAVE_THREADS I_unlock_mutex(hms_api_mutex); -#endif va_start (ap, format); seek += vsprintf(&url[seek], format, ap); @@ -379,7 +373,6 @@ HMS_fetch_rooms (int joining, int query_id) */ if (joining || id_no != 0) { -#ifdef HAVE_THREADS I_lock_mutex(&ms_QueryId_mutex); { if (query_id != ms_QueryId) @@ -389,7 +382,6 @@ HMS_fetch_rooms (int joining, int query_id) if (! doing_shit) break; -#endif room_list[i].header.buffer[0] = 1; @@ -413,9 +405,7 @@ HMS_fetch_rooms (int joining, int query_id) if (doing_shit) { -#ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); -#endif { for (i = 0; room_list[i].header.buffer[0]; i++) { @@ -427,9 +417,7 @@ HMS_fetch_rooms (int joining, int query_id) } } } -#ifdef HAVE_THREADS I_unlock_mutex(m_menu_mutex); -#endif } } else @@ -710,7 +698,6 @@ HMS_fetch_servers (msg_server_t *list, int room_number, int query_id) if (address && port && title && version) { -#ifdef HAVE_THREADS I_lock_mutex(&ms_QueryId_mutex); { if (query_id != ms_QueryId) @@ -720,7 +707,6 @@ HMS_fetch_servers (msg_server_t *list, int room_number, int query_id) if (! doing_shit) break; -#endif if (strcmp(version, local_version) == 0) { @@ -809,16 +795,12 @@ HMS_compare_mod_version (char *buffer, size_t buffer_size) void HMS_set_api (char *api) { -#ifdef HAVE_THREADS I_lock_mutex(&hms_api_mutex); -#endif { free(hms_api); hms_api = api; } -#ifdef HAVE_THREADS I_unlock_mutex(hms_api_mutex); -#endif } #endif/*MASTERSERVER*/ diff --git a/src/netcode/i_tcp.c b/src/netcode/i_tcp.c index 38d4bbbaa..81ebada4b 100644 --- a/src/netcode/i_tcp.c +++ b/src/netcode/i_tcp.c @@ -274,9 +274,14 @@ static void init_upnpc_once(struct upnpdata *upnpdata); static void I_InitUPnP(void) { + if (!I_can_thread()) + { + UPNP_support = false; + return; + } upnpuser = malloc(sizeof *upnpuser); upnpuser->upnpc_started = 0; - I_spawn_thread("init_upnpc_once", (I_thread_fn)init_upnpc_once, upnpuser); + (void)I_spawn_thread("init_upnpc_once", (I_thread_fn)init_upnpc_once, upnpuser); } static void diff --git a/src/netcode/mserv.c b/src/netcode/mserv.c index f17db4b6e..966168c82 100644 --- a/src/netcode/mserv.c +++ b/src/netcode/mserv.c @@ -35,16 +35,11 @@ static boolean MSUpdateAgain; static time_t MSLastPing; -#ifdef HAVE_THREADS static I_mutex MSMutex; static I_cond MSCond; # define Lock_state() I_lock_mutex (&MSMutex) # define Unlock_state() I_unlock_mutex (MSMutex) -#else/*HAVE_THREADS*/ -# define Lock_state() -# define Unlock_state() -#endif/*HAVE_THREADS*/ static void Command_Listserv_f(void); @@ -72,13 +67,11 @@ consvar_t cv_masterserver_room_id = CVAR_INIT ("masterserver_room_id", "-1", CV_ static INT16 ms_RoomId = -1; -#if defined (MASTERSERVER) && defined (HAVE_THREADS) int ms_QueryId; I_mutex ms_QueryId_mutex; msg_server_t *ms_ServerList; I_mutex ms_ServerList_mutex; -#endif UINT16 current_port = 0; @@ -110,13 +103,9 @@ void AddMServCommands(void) static void WarnGUI (void) { -#ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); -#endif M_StartMessage(M_GetText("There was a problem connecting to\nthe Master Server\n\nCheck the console for details.\n"), NULL, MM_NOTHING); -#ifdef HAVE_THREADS I_unlock_mutex(m_menu_mutex); -#endif } #define NUM_LIST_SERVER MAXSERVERLIST @@ -160,14 +149,12 @@ char *GetMODVersion(int id) c = HMS_compare_mod_version(buffer, 16); -#ifdef HAVE_THREADS I_lock_mutex(&ms_QueryId_mutex); { if (id != ms_QueryId) c = -1; } I_unlock_mutex(ms_QueryId_mutex); -#endif if (c > 0) return buffer; @@ -294,9 +281,7 @@ Finish_unlist (void) } Unlock_state(); -#ifdef HAVE_THREADS I_wake_all_cond(&MSCond); -#endif } Lock_state(); @@ -307,7 +292,6 @@ Finish_unlist (void) Unlock_state(); } -#ifdef HAVE_THREADS static int * Server_id (void) { @@ -402,48 +386,56 @@ Change_masterserver_thread (char *api) HMS_set_api(api); } -#endif/*HAVE_THREADS*/ void RegisterServer(void) { #ifdef MASTERSERVER -#ifdef HAVE_THREADS - I_spawn_thread( - "register-server", - (I_thread_fn)Register_server_thread, - New_server_id() - ); -#else - Finish_registration(); -#endif + if (I_can_thread()) + { + (void)I_spawn_thread( + "register-server", + (I_thread_fn)Register_server_thread, + New_server_id() + ); + } + else + { + Finish_registration(); + } #endif/*MASTERSERVER*/ } static void UpdateServer(void) { -#ifdef HAVE_THREADS - I_spawn_thread( - "update-server", - (I_thread_fn)Update_server_thread, - Server_id() - ); -#else - Finish_update(); -#endif + if (I_can_thread()) + { + (void)I_spawn_thread( + "update-server", + (I_thread_fn)Update_server_thread, + Server_id() + ); + } + else + { + Finish_update(); + } } void UnregisterServer(void) { #ifdef MASTERSERVER -#ifdef HAVE_THREADS - I_spawn_thread( - "unlist-server", - (I_thread_fn)Unlist_server_thread, - Server_id() - ); -#else - Finish_unlist(); -#endif + if (I_can_thread()) + { + (void)I_spawn_thread( + "unlist-server", + (I_thread_fn)Unlist_server_thread, + Server_id() + ); + } + else + { + Finish_unlist(); + } #endif/*MASTERSERVER*/ } @@ -490,15 +482,18 @@ void MasterClient_Ticker(void) static void Set_api (const char *api) { -#ifdef HAVE_THREADS - I_spawn_thread( - "change-masterserver", - (I_thread_fn)Change_masterserver_thread, - strdup(api) - ); -#else - HMS_set_api(strdup(api)); -#endif + if (I_can_thread()) + { + (void)I_spawn_thread( + "change-masterserver", + (I_thread_fn)Change_masterserver_thread, + strdup(api) + ); + } + else + { + HMS_set_api(strdup(api)); + } } #endif/*MASTERSERVER*/ diff --git a/src/netcode/mserv.h b/src/netcode/mserv.h index ed3c9b27b..8065bdc4e 100644 --- a/src/netcode/mserv.h +++ b/src/netcode/mserv.h @@ -71,13 +71,11 @@ extern consvar_t cv_masterserver_timeout; extern consvar_t cv_masterserver_debug; extern consvar_t cv_masterserver_token; -#ifdef HAVE_THREADS extern int ms_QueryId; extern I_mutex ms_QueryId_mutex; extern msg_server_t *ms_ServerList; extern I_mutex ms_ServerList_mutex; -#endif void RegisterServer(void); void UnregisterServer(void); diff --git a/src/sdl/i_threads.c b/src/sdl/i_threads.c index 99b445103..1ba21d5d1 100644 --- a/src/sdl/i_threads.c +++ b/src/sdl/i_threads.c @@ -155,7 +155,7 @@ Worker ( return 0; } -void +int I_spawn_thread ( const char * name, I_thread_fn entry, @@ -164,10 +164,15 @@ I_spawn_thread ( Link link; Thread th; + if (! I_can_thread()) + return false; + th = malloc(sizeof *th); if (! th) - abort();/* this is pretty GNU of me */ + { + return false; + } th->entry = entry; th->userdata = userdata; @@ -192,6 +197,14 @@ I_spawn_thread ( } } I_unlock_mutex(i_thread_pool_mutex); + + return true; +} + +int +I_can_thread (void) +{ + return SDL_ThreadID() != 0; } int @@ -207,6 +220,9 @@ I_start_threads (void) i_mutex_pool_mutex = SDL_CreateMutex(); i_cond_pool_mutex = SDL_CreateMutex(); + if (! I_can_thread()) + return; + if (!( i_thread_pool_mutex && i_mutex_pool_mutex && @@ -287,6 +303,9 @@ I_lock_mutex ( ){ SDL_mutex * mutex; + if (! I_can_thread()) + return; + mutex = Identity( &i_mutex_pool, i_mutex_pool_mutex, @@ -302,6 +321,9 @@ void I_unlock_mutex ( I_mutex id ){ + if (! I_can_thread()) + return; + if (SDL_UnlockMutex(id) == -1) abort(); } @@ -330,6 +352,9 @@ I_wake_one_cond ( ){ SDL_cond * cond; + if (! I_can_thread()) + return; + cond = Identity( &i_cond_pool, i_cond_pool_mutex, @@ -347,6 +372,9 @@ I_wake_all_cond ( ){ SDL_cond * cond; + if (! I_can_thread()) + return; + cond = Identity( &i_cond_pool, i_cond_pool_mutex, From cc026cf5d2a66cc70728add95db0ab4b4d9f1019 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 27 Mar 2025 13:30:50 -0400 Subject: [PATCH 09/28] Emscripten: disable TERMIOS support --- src/sdl/i_system.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 1e0fe874c..76e2f37d7 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -103,6 +103,10 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif #endif +#ifdef __EMSCRIPTEN__ +#undef HAVE_TERMIOS // do not read on /dev/tty, JavaScript alert() are blocking +#endif + #if defined(UNIXCOMMON) #include #endif @@ -799,6 +803,11 @@ static inline void I_StartupConsole(void) framebuffer = M_CheckParm("-framebuffer"); +#ifdef __EMSCRIPTEN__ + framebuffer = SDL_FALSE; + consolevent = SDL_TRUE; +#endif + if (framebuffer) consolevent = SDL_FALSE; } @@ -972,7 +981,9 @@ void I_OutputMsg(const char *fmt, ...) #endif if (!framebuffer) + { fprintf(stderr, "%s", txt); + } #ifdef HAVE_TERMIOS if (consolevent && txt[len-1] == '\n') { From 3942f5f7e7389c8318de9da3e7b0d83792d78acc Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 27 Mar 2025 13:31:24 -0400 Subject: [PATCH 10/28] Clang: it may have already defined true/false --- src/doomtype.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/doomtype.h b/src/doomtype.h index ca80a6084..df97398d4 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -156,6 +156,7 @@ typedef int32_t boolean; #endif #ifndef __cplusplus +#ifndef __bool_true_false_are_defined #ifndef _WIN32 enum {false = 0, true = 1}; #else @@ -163,6 +164,7 @@ enum {false = 0, true = 1}; #define true TRUE #endif #endif +#endif /* 7.18.2.1 Limits of exact-width integer types */ From 80412998c9472a11642d2597bbff457cb7e42951 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 27 Mar 2025 16:17:37 -0400 Subject: [PATCH 11/28] emscripten: use native function for sleep(ms) and exit(0) --- src/sdl/i_system.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 76e2f37d7..c9f62596c 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -23,6 +23,10 @@ /// \file /// \brief SRB2 system stuff for SDL +#ifdef __EMSCRIPTEN__ +#include +#endif + #include #ifdef _WIN32 @@ -2310,7 +2314,11 @@ void I_StartupTimer(void) void I_Sleep(UINT32 ms) { +#if defined (__EMSCRIPTEN__) && 0 + emscripten_sleep(ms); +#else SDL_Delay(ms); +#endif } void I_SleepDuration(precise_t duration) @@ -2519,7 +2527,12 @@ void I_Quit(void) free(myargv); // Deallocate allocated memory death: W_Shutdown(); +#ifdef __EMSCRIPTEN__ + emscripten_cancel_main_loop(); + emscripten_force_exit(0); +#else exit(0); +#endif } void I_WaitVBL(INT32 count) From 49e224e67cb333076afb6b145752d60bc81e1b7e Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 27 Mar 2025 16:20:04 -0400 Subject: [PATCH 12/28] Emscripten: slip D_SRB2Loop core loop into D_RunFrame --- src/d_main.c | 62 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 9164f1306..669583d5e 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -15,6 +15,10 @@ /// plus functions to parse command line parameters, configure game /// parameters, and call the startup functions. +#ifdef __EMSCRIPTEN__ +#include +#endif + #if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) #include #include @@ -693,16 +697,11 @@ static void D_Display(void) tic_t rendergametic; +static void D_RunFrame(void); +static tic_t oldentertics = 0; + void D_SRB2Loop(void) { - tic_t entertic = 0, oldentertics = 0, realtics = 0, rendertimeout = INFTICS; - double deltatics = 0.0; - double deltasecs = 0.0; - static lumpnum_t gstartuplumpnum; - - boolean interp = false; - boolean doDisplay = false; - if (dedicated) server = true; @@ -746,13 +745,55 @@ void D_SRB2Loop(void) /* Smells like a hack... Don't fade Sonic's ass into the title screen. */ if (gamestate != GS_TITLESCREEN) { - gstartuplumpnum = W_CheckNumForPatchName("STARTUP"); + lumpnum_t gstartuplumpnum = W_CheckNumForPatchName("STARTUP"); if (gstartuplumpnum == LUMPERROR) gstartuplumpnum = W_GetNumForPatchName("MISSING"); V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(gstartuplumpnum, PU_PATCH)); } - +#ifdef __EMSCRIPTEN__ + emscripten_set_main_loop(D_RunFrame, 0, 1); +#else for (;;) + { + D_RunFrame(); + } +#endif +} + +static boolean D_LockFrame = false; + +#ifdef __EMSCRIPTEN__ + +void change_resolution(int x, int y) +{ + setmodeneeded = VID_GetModeForSize(x, y) + 1; +} + +void pause_loop(void) +{ + D_LockFrame = true; + //emscripten_sleep(1000); + emscripten_pause_main_loop(); +} + +void resume_loop(void) +{ + D_LockFrame = false; + //emscripten_sleep(1000); + emscripten_resume_main_loop(); +} +#endif + +static void D_RunFrame(void) +{ + static tic_t entertic = 0, realtics = 0, rendertimeout = INFTICS; + static double deltatics = 0.0; + static double deltasecs = 0.0; + + static boolean interp = false; + static boolean doDisplay = false; + + if (!D_LockFrame) { // capbudget is the minimum precise_t duration of a single loop iteration precise_t capbudget; @@ -908,6 +949,7 @@ void D_SRB2Loop(void) deltasecs = (double)((INT64)(finishprecise - enterprecise)) / I_GetPrecisePrecision(); deltatics = deltasecs * NEWTICRATE; } + return; } // From 2749ed14389223f148d7aa45a07888cc9aeca708 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 27 Mar 2025 23:09:57 -0400 Subject: [PATCH 13/28] Emscripten: get software mode working --- src/d_main.c | 23 ++++++++++++------- src/netcode/i_tcp.c | 6 +++++ src/sdl/i_system.c | 5 ----- src/sdl/i_video.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 13 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 669583d5e..d5787fc65 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -737,12 +737,23 @@ void D_SRB2Loop(void) // hack to start on a nice clear console screen. COM_ImmedExecute("cls;version"); +#ifdef __EMSCRIPTEN__ + EM_ASM( + try { + StartedMainLoopCallback(); + } catch (err) { + console.log('Faild to find StartedMainLoopCallback()'); + } + ); +#endif + I_FinishUpdate(); // page flip or blit buffer /* LMFAO this was showing garbage under OpenGL because I_FinishUpdate was called afterward */ /* Smells like a hack... Don't fade Sonic's ass into the title screen. */ + if (gamestate != GS_TITLESCREEN) { lumpnum_t gstartuplumpnum = W_CheckNumForPatchName("STARTUP"); @@ -763,24 +774,20 @@ void D_SRB2Loop(void) static boolean D_LockFrame = false; #ifdef __EMSCRIPTEN__ - -void change_resolution(int x, int y) -{ - setmodeneeded = VID_GetModeForSize(x, y) + 1; -} - -void pause_loop(void) +int pause_loop(void) { D_LockFrame = true; //emscripten_sleep(1000); emscripten_pause_main_loop(); + return 0; } -void resume_loop(void) +int resume_loop(void) { D_LockFrame = false; //emscripten_sleep(1000); emscripten_resume_main_loop(); + return 0; } #endif diff --git a/src/netcode/i_tcp.c b/src/netcode/i_tcp.c index 81ebada4b..604f9fa2f 100644 --- a/src/netcode/i_tcp.c +++ b/src/netcode/i_tcp.c @@ -1118,6 +1118,12 @@ static boolean UDP_Socket(void) boolean I_InitTcpDriver(void) { boolean tcp_was_up = init_tcp_driver; + +#ifdef __EMSCRIPTEN__ + I_OutputMsg("Compiled without networking support\n"); + return false; +#endif + if (!init_tcp_driver) { #ifdef USE_WINSOCK diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index c9f62596c..3def7e3bd 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2527,12 +2527,7 @@ void I_Quit(void) free(myargv); // Deallocate allocated memory death: W_Shutdown(); -#ifdef __EMSCRIPTEN__ - emscripten_cancel_main_loop(); - emscripten_force_exit(0); -#else exit(0); -#endif } void I_WaitVBL(INT32 count) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 82583ccb4..28a628176 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -20,6 +20,10 @@ /// \file /// \brief SRB2 graphics stuff for SDL +#ifdef __EMSCRIPTEN__ +#include +#endif + #include #include @@ -1973,3 +1977,53 @@ UINT32 I_GetRefreshRate(void) // trouble querying mode over and over again. return refresh_rate; } + +#ifdef __EMSCRIPTEN__ +int change_resolution(int x, int y) +{ + vid.width = x; + vid.height = y; + return VID_CheckRenderer(); +} + +void inject_text(const char *text) +{ + event_t event; + size_t len = 0; + event.type = ev_text; + { + event.key = text[len]; + D_PostEvent(&event); + len++; + } while (text[len] != 0x00); +} + +void inject_keycode(int key, int type) +{ + event_t event; + if (type == true) + { + event.type = ev_keyup; + } + else if (type == false) + { + event.type = ev_keydown; + } + else + { + return; + } + event.key = key; + if (event.key) D_PostEvent(&event); +} + +void unlock_mouse(void) +{ + SDLforceUngrabMouse(); +} + +void lock_mouse(void) +{ + SDLdoGrabMouse(); +} +#endif From c99e29b74fab56c8a921c6447587b4982ca27d31 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 29 Mar 2025 14:00:20 -0400 Subject: [PATCH 14/28] Emscripten: use EMSCRIPTEN_KEEALIVE --- src/command.c | 10 +++++++++- src/d_main.c | 6 ++---- src/sdl/i_video.c | 42 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/command.c b/src/command.c index ab6cfc08a..be892e57a 100644 --- a/src/command.c +++ b/src/command.c @@ -16,6 +16,10 @@ /// /// code shamelessly inspired by the QuakeC sources, thanks Id :) +#ifdef __EMSCRIPTEN__ +#include +#endif + #include "doomdef.h" #include "doomstat.h" #include "command.h" @@ -277,7 +281,11 @@ void COM_BufExecute(void) /** Executes a string immediately. Used for skirting around WAIT commands. */ -void COM_ImmedExecute(const char *ptext) +void +#ifdef __EMSCRIPTEN__ +EMSCRIPTEN_KEEPALIVE +#endif +COM_ImmedExecute(const char *ptext) { size_t i = 0, j = 0; char line[1024] = ""; diff --git a/src/d_main.c b/src/d_main.c index d5787fc65..5d8211393 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -774,18 +774,16 @@ void D_SRB2Loop(void) static boolean D_LockFrame = false; #ifdef __EMSCRIPTEN__ -int pause_loop(void) +int EMSCRIPTEN_KEEPALIVE pause_loop(void) { D_LockFrame = true; - //emscripten_sleep(1000); emscripten_pause_main_loop(); return 0; } -int resume_loop(void) +int EMSCRIPTEN_KEEPALIVE resume_loop(void) { D_LockFrame = false; - //emscripten_sleep(1000); emscripten_resume_main_loop(); return 0; } diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 28a628176..7a5ddaa74 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1979,14 +1979,40 @@ UINT32 I_GetRefreshRate(void) } #ifdef __EMSCRIPTEN__ -int change_resolution(int x, int y) +int EMSCRIPTEN_KEEPALIVE change_resolution(int x, int y) { - vid.width = x; - vid.height = y; - return VID_CheckRenderer(); + int newmode = -1; + + if ( x < BASEVIDWIDTH*1 && y < BASEVIDHEIGHT*1) + newmode = VID_GetModeForSize(BASEVIDWIDTH*1, BASEVIDHEIGHT*1); + else if (x < BASEVIDWIDTH*2 && y < BASEVIDHEIGHT*2) + newmode = VID_GetModeForSize(BASEVIDWIDTH*1, BASEVIDHEIGHT*1); + else if (x < BASEVIDWIDTH*3 && y < BASEVIDHEIGHT*3) + newmode = VID_GetModeForSize(BASEVIDWIDTH*2, BASEVIDHEIGHT*2); +#if 0 + else if (x < BASEVIDWIDTH*4 && y < BASEVIDHEIGHT*4) + newmode = VID_GetModeForSize(BASEVIDWIDTH*3, BASEVIDHEIGHT*3); + else if (x < BASEVIDWIDTH*5 && y < BASEVIDHEIGHT*5) + newmode = VID_GetModeForSize(BASEVIDWIDTH*4, BASEVIDHEIGHT*4); + else if (x < BASEVIDWIDTH*6 && y < BASEVIDHEIGHT*6) + newmode = VID_GetModeForSize(BASEVIDWIDTH*5, BASEVIDHEIGHT*5); + else + newmode = VID_GetModeForSize(BASEVIDWIDTH*6, BASEVIDHEIGHT*6); +#else + else + newmode = VID_GetModeForSize(BASEVIDWIDTH*2, BASEVIDHEIGHT*2); +#endif + + if (newmode != -1) + setmodeneeded = newmode; + + if (setmodeneeded) + return 1; + + return 0; } -void inject_text(const char *text) +void EMSCRIPTEN_KEEPALIVE inject_text(const char *text) { event_t event; size_t len = 0; @@ -1998,7 +2024,7 @@ void inject_text(const char *text) } while (text[len] != 0x00); } -void inject_keycode(int key, int type) +void EMSCRIPTEN_KEEPALIVE inject_keycode(int key, int type) { event_t event; if (type == true) @@ -2017,12 +2043,12 @@ void inject_keycode(int key, int type) if (event.key) D_PostEvent(&event); } -void unlock_mouse(void) +void EMSCRIPTEN_KEEPALIVE unlock_mouse(void) { SDLforceUngrabMouse(); } -void lock_mouse(void) +void EMSCRIPTEN_KEEPALIVE lock_mouse(void) { SDLdoGrabMouse(); } From f694529727683752f2d13d3ec41f47f36ef046dc Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 29 Mar 2025 14:00:52 -0400 Subject: [PATCH 15/28] SDL2: use SDL_GetSystemRAM() to get total RAM --- src/sdl/i_system.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 3def7e3bd..ccf4be27b 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -3239,7 +3239,13 @@ size_t I_GetFreeMem(size_t *total) #else // Guess 48 MB. if (total) + { +#if SDL_VERSION_ATLEAST(2,0,1) + *total = SDL_GetSystemRAM(); +#else *total = 48<<20; +#endif + } return 48<<20; #endif } From 6d073e18ec86364d4cd2c47353d1050d1acbdfdd Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 29 Mar 2025 14:01:31 -0400 Subject: [PATCH 16/28] Emscripten: get timing info and use 640x400 video mode --- src/sdl/i_video.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 7a5ddaa74..149efc1e2 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -479,6 +479,35 @@ static void SurfaceInfo(const SDL_Surface *infoSurface, const char *SurfaceText) CONS_Printf("%s", M_GetText(" Colorkey RLE acceleration blit\n")); } +static void TimingInfo(void) +{ +#ifdef __EMSCRIPTEN__ + int mode = -1, value = -1; + emscripten_get_main_loop_timing(&mode, &value); + CONS_Printf("\x82" "Currect Timing Mode\n"); + if (mode == -1) + { + CONS_Printf(" Unknown\n"); + } + else if (mode == EM_TIMING_SETTIMEOUT) + { + CONS_Printf(" everty %d ms\n", value); + } + else if (mode == EM_TIMING_RAF) + { + CONS_Printf(" every %d vsync\n", value); + } + else if (mode == EM_TIMING_SETIMMEDIATE) + { + CONS_Printf(" Unknown value %d\n", value); + } + else + { + CONS_Printf(" Unknown mode %d\n", mode); + } +#endif +} + static void VID_Command_Info_f (void) { #if 0 @@ -526,6 +555,7 @@ static void VID_Command_Info_f (void) SurfaceInfo(bufSurface, M_GetText("Current Engine Mode")); SurfaceInfo(vidSurface, M_GetText("Current Video Mode")); #endif + TimingInfo(); } static void VID_Command_ModeList_f(void) @@ -1836,7 +1866,11 @@ void I_StartupGraphics(void) I_ShutdownTTF(); #endif +#ifdef __EMSCRIPTEN__ + VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH*2, BASEVIDHEIGHT*2)); +#else VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT)); +#endif if (M_CheckParm("-nomousegrab")) mousegrabok = SDL_FALSE; From 3fb55f005c9d61e9bc2d1eaa4bf04bf0ec45cac0 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 29 Mar 2025 14:02:04 -0400 Subject: [PATCH 17/28] Emscripten: kill runtime in I_Quit() --- src/sdl/i_system.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index ccf4be27b..27a900c85 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2527,7 +2527,11 @@ void I_Quit(void) free(myargv); // Deallocate allocated memory death: W_Shutdown(); +#ifdef __EMSCRIPTEN__ + emscripten_force_exit(0); +#else exit(0); +#endif } void I_WaitVBL(INT32 count) From fc35c09a5894774512ed9c2e2b3f5c511fee3c07 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 29 Mar 2025 14:03:29 -0400 Subject: [PATCH 18/28] Emscripten: use stdout for I_OutputMsg() --- src/sdl/i_system.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 27a900c85..eeb19b581 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -807,11 +807,6 @@ static inline void I_StartupConsole(void) framebuffer = M_CheckParm("-framebuffer"); -#ifdef __EMSCRIPTEN__ - framebuffer = SDL_FALSE; - consolevent = SDL_TRUE; -#endif - if (framebuffer) consolevent = SDL_FALSE; } @@ -984,10 +979,13 @@ void I_OutputMsg(const char *fmt, ...) } #endif +#ifdef __EMSCRIPTEN__ + fprintf(stdout, "%s", txt); +#else if (!framebuffer) - { fprintf(stderr, "%s", txt); - } +#endif + #ifdef HAVE_TERMIOS if (consolevent && txt[len-1] == '\n') { From 611ac65ed1ad2a675bdeb41a31cd5e77222c65b1 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 29 Mar 2025 14:31:06 -0400 Subject: [PATCH 19/28] Emscripten: use emscripten_sleep() for I_Sleep() --- src/sdl/i_system.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index eeb19b581..b5b2e7ca6 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2312,11 +2312,13 @@ void I_StartupTimer(void) void I_Sleep(UINT32 ms) { -#if defined (__EMSCRIPTEN__) && 0 - emscripten_sleep(ms); -#else - SDL_Delay(ms); +#if defined (__EMSCRIPTEN__) + if (emscripten_has_asyncify()) + { + return emscripten_sleep(ms); + } #endif + SDL_Delay(ms); } void I_SleepDuration(precise_t duration) From ad4188af3bcce5179199c553f3876a139a84f869 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 30 Mar 2025 10:23:25 -0400 Subject: [PATCH 20/28] inline archive functions --- src/p_saveg.c | 86 +++++++++++++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 650622f59..c33cc0f82 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -302,7 +302,7 @@ typedef enum DRONE = 0x80, } player_saveflags; -static inline void P_ArchivePlayer(save_t *save_p) +FUNCINLINE static ATTRINLINE void P_ArchivePlayer(save_t *save_p) { const player_t *player = &players[consoleplayer]; SINT8 pllives = player->lives; @@ -334,7 +334,7 @@ static inline void P_ArchivePlayer(save_t *save_p) P_WriteINT32(save_p, player->continues); } -static inline void P_UnArchivePlayer(save_t *save_p) +FUNCINLINE static ATTRINLINE void P_UnArchivePlayer(save_t *save_p) { #ifdef NEWSKINSAVES INT16 backwardsCompat = P_ReadUINT16(save_p); @@ -2088,7 +2088,7 @@ typedef enum tc_end } specials_e; -static inline UINT32 SaveMobjnum(const mobj_t *mobj) +FUNCINLINE static ATTRINLINE UINT32 SaveMobjnum(const mobj_t *mobj) { if (mobj) return mobj->mobjnum; return 0; @@ -2106,7 +2106,7 @@ static UINT32 SaveLine(const line_t *line) return 0xFFFFFFFF; } -static inline UINT32 SavePlayer(const player_t *player) +FUNCINLINE static ATTRINLINE UINT32 SavePlayer(const player_t *player) { if (player) return (UINT32)(player - players); return 0xFFFFFFFF; @@ -2646,7 +2646,7 @@ static void SaveGlowThinker(save_t *save_p, const thinker_t *th, const UINT8 typ P_WriteINT16(save_p, ht->speed); } -static inline void SaveFireflickerThinker(save_t *save_p, const thinker_t *th, const UINT8 type) +FUNCINLINE static ATTRINLINE void SaveFireflickerThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const fireflicker_t *ht = (const void *)th; P_WriteUINT8(save_p, type); @@ -2696,7 +2696,7 @@ static void SaveCrumbleThinker(save_t *save_p, const thinker_t *th, const UINT8 P_WriteUINT8(save_p, ht->flags); } -static inline void SaveScrollThinker(save_t *save_p, const thinker_t *th, const UINT8 type) +FUNCINLINE static ATTRINLINE void SaveScrollThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const scroll_t *ht = (const void *)th; P_WriteUINT8(save_p, type); @@ -2712,7 +2712,7 @@ static inline void SaveScrollThinker(save_t *save_p, const thinker_t *th, const P_WriteUINT8(save_p, ht->type); } -static inline void SaveFrictionThinker(save_t *save_p, const thinker_t *th, const UINT8 type) +FUNCINLINE static ATTRINLINE void SaveFrictionThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const friction_t *ht = (const void *)th; P_WriteUINT8(save_p, type); @@ -2723,7 +2723,7 @@ static inline void SaveFrictionThinker(save_t *save_p, const thinker_t *th, cons P_WriteUINT8(save_p, ht->roverfriction); } -static inline void SavePusherThinker(save_t *save_p, const thinker_t *th, const UINT8 type) +FUNCINLINE static ATTRINLINE void SavePusherThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const pusher_t *ht = (const void *)th; P_WriteUINT8(save_p, type); @@ -2828,7 +2828,7 @@ static void SavePlaneDisplaceThinker(save_t *save_p, const thinker_t *th, const P_WriteUINT8(save_p, ht->type); } -static inline void SaveDynamicLineSlopeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) +FUNCINLINE static ATTRINLINE void SaveDynamicLineSlopeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const dynlineplanethink_t* ht = (const void*)th; @@ -2839,7 +2839,7 @@ static inline void SaveDynamicLineSlopeThinker(save_t *save_p, const thinker_t * P_WriteFixed(save_p, ht->extent); } -static inline void SaveDynamicVertexSlopeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) +FUNCINLINE static ATTRINLINE void SaveDynamicVertexSlopeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { size_t i; const dynvertexplanethink_t* ht = (const void*)th; @@ -2854,7 +2854,7 @@ static inline void SaveDynamicVertexSlopeThinker(save_t *save_p, const thinker_t P_WriteUINT8(save_p, ht->relative); } -static inline void SavePolyrotatetThinker(save_t *save_p, const thinker_t *th, const UINT8 type) +FUNCINLINE static ATTRINLINE void SavePolyrotatetThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polyrotate_t *ht = (const void *)th; P_WriteUINT8(save_p, type); @@ -3219,7 +3219,7 @@ mobj_t *P_FindNewPosition(UINT32 oldposition) return NULL; } -static inline mobj_t *LoadMobj(UINT32 mobjnum) +FUNCINLINE static ATTRINLINE mobj_t *LoadMobj(UINT32 mobjnum) { if (mobjnum == 0) return NULL; return (mobj_t *)(size_t)mobjnum; @@ -3237,13 +3237,13 @@ static line_t *LoadLine(UINT32 line) return &lines[line]; } -static inline player_t *LoadPlayer(UINT32 player) +FUNCINLINE static ATTRINLINE player_t *LoadPlayer(UINT32 player) { if (player >= MAXPLAYERS) return NULL; return &players[player]; } -static inline pslope_t *LoadSlope(UINT32 slopeid) +FUNCINLINE static ATTRINLINE pslope_t* LoadSlope(UINT32 slopeid) { pslope_t *p = slopelist; if (slopeid > slopecount) return NULL; @@ -3887,7 +3887,7 @@ static thinker_t* LoadScrollThinker(save_t *save_p, actionf_p1 thinker) return &ht->thinker; } -static inline thinker_t* LoadFrictionThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadFrictionThinker(save_t *save_p, actionf_p1 thinker) { friction_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3915,7 +3915,7 @@ static thinker_t* LoadPusherThinker(save_t *save_p, actionf_p1 thinker) return &ht->thinker; } -static inline thinker_t* LoadLaserThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadLaserThinker(save_t *save_p, actionf_p1 thinker) { laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3925,7 +3925,7 @@ static inline thinker_t* LoadLaserThinker(save_t *save_p, actionf_p1 thinker) return &ht->thinker; } -static inline thinker_t* LoadLightlevelThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadLightlevelThinker(save_t *save_p, actionf_p1 thinker) { lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3940,7 +3940,7 @@ static inline thinker_t* LoadLightlevelThinker(save_t *save_p, actionf_p1 thinke return &ht->thinker; } -static inline thinker_t* LoadExecutorThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadExecutorThinker(save_t *save_p, actionf_p1 thinker) { executor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3951,7 +3951,7 @@ static inline thinker_t* LoadExecutorThinker(save_t *save_p, actionf_p1 thinker) return &ht->thinker; } -static inline thinker_t* LoadDisappearThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadDisappearThinker(save_t *save_p, actionf_p1 thinker) { disappear_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3965,7 +3965,7 @@ static inline thinker_t* LoadDisappearThinker(save_t *save_p, actionf_p1 thinker return &ht->thinker; } -static inline thinker_t* LoadFadeThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadFadeThinker(save_t *save_p, actionf_p1 thinker) { sector_t *ss; fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); @@ -4007,7 +4007,7 @@ static inline thinker_t* LoadFadeThinker(save_t *save_p, actionf_p1 thinker) return &ht->thinker; } -static inline thinker_t* LoadFadeColormapThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadFadeColormapThinker(save_t *save_p, actionf_p1 thinker) { fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -4022,7 +4022,7 @@ static inline thinker_t* LoadFadeColormapThinker(save_t *save_p, actionf_p1 thin return &ht->thinker; } -static inline thinker_t* LoadPlaneDisplaceThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadPlaneDisplaceThinker(save_t *save_p, actionf_p1 thinker) { planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -4035,7 +4035,7 @@ static inline thinker_t* LoadPlaneDisplaceThinker(save_t *save_p, actionf_p1 thi return &ht->thinker; } -static inline thinker_t* LoadDynamicLineSlopeThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadDynamicLineSlopeThinker(save_t *save_p, actionf_p1 thinker) { dynlineplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -4047,7 +4047,7 @@ static inline thinker_t* LoadDynamicLineSlopeThinker(save_t *save_p, actionf_p1 return &ht->thinker; } -static inline thinker_t* LoadDynamicVertexSlopeThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadDynamicVertexSlopeThinker(save_t *save_p, actionf_p1 thinker) { size_t i; dynvertexplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); @@ -4063,7 +4063,7 @@ static inline thinker_t* LoadDynamicVertexSlopeThinker(save_t *save_p, actionf_p return &ht->thinker; } -static inline thinker_t* LoadPolyrotatetThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadPolyrotatetThinker(save_t *save_p, actionf_p1 thinker) { polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -4087,7 +4087,7 @@ static thinker_t* LoadPolymoveThinker(save_t *save_p, actionf_p1 thinker) return &ht->thinker; } -static inline thinker_t* LoadPolywaypointThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadPolywaypointThinker(save_t *save_p, actionf_p1 thinker) { polywaypoint_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -4102,7 +4102,7 @@ static inline thinker_t* LoadPolywaypointThinker(save_t *save_p, actionf_p1 thin return &ht->thinker; } -static inline thinker_t* LoadPolyslidedoorThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadPolyslidedoorThinker(save_t *save_p, actionf_p1 thinker) { polyslidedoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -4122,7 +4122,7 @@ static inline thinker_t* LoadPolyslidedoorThinker(save_t *save_p, actionf_p1 thi return &ht->thinker; } -static inline thinker_t* LoadPolyswingdoorThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadPolyswingdoorThinker(save_t *save_p, actionf_p1 thinker) { polyswingdoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -4137,7 +4137,7 @@ static inline thinker_t* LoadPolyswingdoorThinker(save_t *save_p, actionf_p1 thi return &ht->thinker; } -static inline thinker_t* LoadPolydisplaceThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadPolydisplaceThinker(save_t *save_p, actionf_p1 thinker) { polydisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -4149,7 +4149,7 @@ static inline thinker_t* LoadPolydisplaceThinker(save_t *save_p, actionf_p1 thin return &ht->thinker; } -static inline thinker_t* LoadPolyrotdisplaceThinker(save_t *save_p, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE thinker_t *LoadPolyrotdisplaceThinker(save_t *save_p, actionf_p1 thinker) { polyrotdisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -4432,7 +4432,7 @@ static void P_NetUnArchiveThinkers(save_t *save_p) #define PD_FLAGS 0x01 #define PD_TRANS 0x02 -static inline void P_ArchivePolyObj(save_t *save_p, polyobj_t *po) +FUNCINLINE static ATTRINLINE void P_ArchivePolyObj(save_t *save_p, polyobj_t *po) { UINT8 diff = 0; P_WriteINT32(save_p, po->id); @@ -4454,7 +4454,7 @@ static inline void P_ArchivePolyObj(save_t *save_p, polyobj_t *po) P_WriteINT32(save_p, po->translucency); } -static inline void P_UnArchivePolyObj(save_t *save_p, polyobj_t *po) +FUNCINLINE static ATTRINLINE void P_UnArchivePolyObj(save_t *save_p, polyobj_t *po) { INT32 id; UINT32 angle; @@ -4489,7 +4489,7 @@ static inline void P_UnArchivePolyObj(save_t *save_p, polyobj_t *po) Polyobj_MoveOnLoad(po, angle, x, y); } -static inline void P_ArchivePolyObjects(save_t *save_p) +FUNCINLINE static ATTRINLINE void P_ArchivePolyObjects(save_t *save_p) { INT32 i; @@ -4502,7 +4502,7 @@ static inline void P_ArchivePolyObjects(save_t *save_p) P_ArchivePolyObj(save_p, &PolyObjects[i]); } -static inline void P_UnArchivePolyObjects(save_t *save_p) +FUNCINLINE static ATTRINLINE void P_UnArchivePolyObjects(save_t *save_p) { INT32 i, numSavedPolys; @@ -4518,7 +4518,7 @@ static inline void P_UnArchivePolyObjects(save_t *save_p) P_UnArchivePolyObj(save_p, &PolyObjects[i]); } -static inline void P_FinishMobjs(void) +FUNCINLINE static ATTRINLINE void P_FinishMobjs(void) { thinker_t *currentthinker; mobj_t *mobj; @@ -4633,7 +4633,7 @@ static void P_RelinkPointers(void) } } -static inline void P_NetArchiveSpecials(save_t *save_p) +FUNCINLINE static ATTRINLINE void P_NetArchiveSpecials(save_t *save_p) { size_t i, z; @@ -4719,7 +4719,7 @@ static void P_NetUnArchiveSpecials(save_t *save_p) // ======================================================================= // Misc // ======================================================================= -static inline void P_ArchiveMisc(save_t *save_p, INT16 mapnum) +FUNCINLINE static ATTRINLINE void P_ArchiveMisc(save_t *save_p, INT16 mapnum) { //lastmapsaved = mapnum; lastmaploaded = mapnum; @@ -4732,7 +4732,7 @@ static inline void P_ArchiveMisc(save_t *save_p, INT16 mapnum) P_WriteStringN(save_p, timeattackfolder, sizeof(timeattackfolder)); } -static inline void P_UnArchiveSPGame(save_t *save_p, INT16 mapoverride) +FUNCINLINE static ATTRINLINE void P_UnArchiveSPGame(save_t *save_p, INT16 mapoverride) { char testname[sizeof(timeattackfolder)]; @@ -4862,7 +4862,7 @@ static void P_NetArchiveMisc(save_t *save_p, boolean resending) } } -static inline boolean P_NetUnArchiveMisc(save_t *save_p, boolean reloading) +FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(save_t *save_p, boolean reloading) { INT32 i; @@ -4966,7 +4966,7 @@ static inline boolean P_NetUnArchiveMisc(save_t *save_p, boolean reloading) return true; } -static inline void P_NetArchiveEmblems(save_t *save_p) +FUNCINLINE static ATTRINLINE void P_NetArchiveEmblems(save_t *save_p) { gamedata_t *data = serverGamedata; INT32 i, j; @@ -5087,7 +5087,7 @@ static inline void P_NetArchiveEmblems(save_t *save_p) } } -static inline void P_NetUnArchiveEmblems(save_t *save_p) +FUNCINLINE static ATTRINLINE void P_NetUnArchiveEmblems(save_t *save_p) { gamedata_t *data = serverGamedata; INT32 i, j; @@ -5307,7 +5307,7 @@ static void P_NetUnArchiveSectorPortals(save_t *save_p) } } -static inline void P_ArchiveLuabanksAndConsistency(save_t *save_p) +FUNCINLINE static ATTRINLINE void P_ArchiveLuabanksAndConsistency(save_t *save_p) { UINT8 i, banksinuse = NUM_LUABANKS; @@ -5325,7 +5325,7 @@ static inline void P_ArchiveLuabanksAndConsistency(save_t *save_p) P_WriteUINT8(save_p, 0x1d); // consistency marker } -static inline boolean P_UnArchiveLuabanksAndConsistency(save_t *save_p) +FUNCINLINE static ATTRINLINE boolean P_UnArchiveLuabanksAndConsistency(save_t *save_p) { switch (P_ReadUINT8(save_p)) { From e76b4c0b97c30c0c3b92bd4cccb30e53bfa3f563 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 30 Mar 2025 11:07:52 -0400 Subject: [PATCH 21/28] Threads: add codepaths to free memory on fails --- src/m_menu.c | 7 ++++-- src/netcode/client_connection.c | 5 ++++- src/netcode/d_netfil.c | 32 +++++++++++++++++++++++---- src/netcode/i_tcp.c | 6 ++++- src/netcode/mserv.c | 39 +++++++++++++++++++++++---------- src/sdl/i_threads.c | 8 ++++++- 6 files changed, 76 insertions(+), 21 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 57ebe1527..52e119723 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -11519,8 +11519,11 @@ static void M_RoomMenu(INT32 choice) } I_unlock_mutex(ms_QueryId_mutex); - (void)I_spawn_thread("check-new-version", - (I_thread_fn)Check_new_version_thread, id); + if(!I_spawn_thread("check-new-version", + (I_thread_fn)Check_new_version_thread, id)) + { + free(id); + } } else { diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index 2fe2c0968..c7749d0f0 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -510,7 +510,10 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) ctx->room = room; - (void)I_spawn_thread("fetch-servers", (I_thread_fn)Fetch_servers_thread, ctx); + if (!I_spawn_thread("fetch-servers", (I_thread_fn)Fetch_servers_thread, ctx)) + { + free(ctx); + } } else { diff --git a/src/netcode/d_netfil.c b/src/netcode/d_netfil.c index 1ed138f5f..94e5449a8 100644 --- a/src/netcode/d_netfil.c +++ b/src/netcode/d_netfil.c @@ -1604,6 +1604,7 @@ static int curlprogress_callback(void *clientp, curl_off_t dltotal, curl_off_t d boolean CURLPrepareFile(const char* url, int dfilenum) { HTTP_login *login; + CURLcode cc; if (!I_can_thread()) return false; @@ -1615,13 +1616,28 @@ boolean CURLPrepareFile(const char* url, int dfilenum) if (!multi_handle) { - curl_global_init(CURL_GLOBAL_ALL); - multi_handle = curl_multi_init(); + cc = curl_global_init(CURL_GLOBAL_ALL); + if (cc < 0) + { + I_OutputMsg("libcurl: curl_global_init() returned %d\n", cc); + } + else + { + multi_handle = curl_multi_init(); + } + if (!multi_handle) + { + I_OutputMsg("libcurl: curl_multi_init() failed\n"); + curl_global_cleanup(); + return false; + } } http_handle = curl_easy_init(); - if (http_handle && multi_handle) + if (http_handle) { + CURLMcode mc; + I_mkdir(downloaddir, 0755); curl_curfile = &fileneeded[dfilenum]; @@ -1678,7 +1694,15 @@ boolean CURLPrepareFile(const char* url, int dfilenum) filedownload.current = dfilenum; filedownload.http_running = true; - (void)I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL); + if (!I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL)) + { + mc = curl_multi_cleanup(multi_handle); + if (mc != CURLM_OK) I_OutputMsg("libcurl: %s\n", curl_multi_strerror(mc)); + curl_global_cleanup(); + multi_handle = NULL; + filedownload.http_running = false; + return false; + } return true; } diff --git a/src/netcode/i_tcp.c b/src/netcode/i_tcp.c index 604f9fa2f..bc89fb87e 100644 --- a/src/netcode/i_tcp.c +++ b/src/netcode/i_tcp.c @@ -281,7 +281,11 @@ static void I_InitUPnP(void) } upnpuser = malloc(sizeof *upnpuser); upnpuser->upnpc_started = 0; - (void)I_spawn_thread("init_upnpc_once", (I_thread_fn)init_upnpc_once, upnpuser); + if (!I_spawn_thread("init_upnpc_once", (I_thread_fn)init_upnpc_once, upnpuser)) + { + UPNP_support = false; + free(upnpuser); + } } static void diff --git a/src/netcode/mserv.c b/src/netcode/mserv.c index 966168c82..fdc0304c5 100644 --- a/src/netcode/mserv.c +++ b/src/netcode/mserv.c @@ -392,11 +392,15 @@ void RegisterServer(void) #ifdef MASTERSERVER if (I_can_thread()) { - (void)I_spawn_thread( + void *nsid = New_server_id(); + if (!I_spawn_thread( "register-server", (I_thread_fn)Register_server_thread, - New_server_id() - ); + nsid + )) + { + free(nsid); + } } else { @@ -409,11 +413,15 @@ static void UpdateServer(void) { if (I_can_thread()) { - (void)I_spawn_thread( + void *sid = Server_id(); + if (!I_spawn_thread( "update-server", (I_thread_fn)Update_server_thread, - Server_id() - ); + sid + )) + { + free(sid); + } } else { @@ -426,11 +434,14 @@ void UnregisterServer(void) #ifdef MASTERSERVER if (I_can_thread()) { - (void)I_spawn_thread( + if (!I_spawn_thread( "unlist-server", (I_thread_fn)Unlist_server_thread, Server_id() - ); + )) + { + ; + } } else { @@ -482,17 +493,21 @@ void MasterClient_Ticker(void) static void Set_api (const char *api) { + char *dapi = strdup(api); if (I_can_thread()) { - (void)I_spawn_thread( + if (!I_spawn_thread( "change-masterserver", (I_thread_fn)Change_masterserver_thread, - strdup(api) - ); + dapi + )) + { + free(dapi); + } } else { - HMS_set_api(strdup(api)); + HMS_set_api(dapi); } } diff --git a/src/sdl/i_threads.c b/src/sdl/i_threads.c index 1ba21d5d1..64e9ae142 100644 --- a/src/sdl/i_threads.c +++ b/src/sdl/i_threads.c @@ -171,6 +171,7 @@ I_spawn_thread ( if (! th) { + I_OutputMsg("Failed to make memory for Thread: %s", name); return false; } @@ -192,12 +193,17 @@ I_spawn_thread ( if (! th->thread) { I_OutputMsg("I_spawn_thread failed to make thread %s: %s\n", name, SDL_GetError()); - abort(); } } } I_unlock_mutex(i_thread_pool_mutex); + if (! th->thread) + { + free(th); + return false; + } + return true; } From 26ae0b6ff05d79a858aec7ad92af3d65c9ce0745 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 30 Mar 2025 11:42:17 -0400 Subject: [PATCH 22/28] curl: add code to check the output of curl_easy_*() --- src/netcode/d_netfil.c | 54 +++++++++++++++++++++++++++---------- src/netcode/http-mserv.c | 58 ++++++++++++++++++++++++++++------------ 2 files changed, 81 insertions(+), 31 deletions(-) diff --git a/src/netcode/d_netfil.c b/src/netcode/d_netfil.c index 94e5449a8..622d61d4b 100644 --- a/src/netcode/d_netfil.c +++ b/src/netcode/d_netfil.c @@ -112,6 +112,7 @@ static pauseddownload_t *pauseddownload = NULL; file_download_t filedownload; static CURL *http_handle; +static char curl_errbuf[CURL_ERROR_SIZE]; static CURLM *multi_handle; static UINT32 curl_dlnow; static UINT32 curl_dltotal; @@ -1638,6 +1639,10 @@ boolean CURLPrepareFile(const char* url, int dfilenum) { CURLMcode mc; + cc = curl_easy_setopt(http_handle, CURLOPT_ERRORBUFFER, curl_errbuf); + if (cc != CURLE_OK) I_OutputMsg("libcurl: CURLOPT_ERRORBUFFER failed\n"); + curl_errbuf[0] = 0x00; + I_mkdir(downloaddir, 0755); curl_curfile = &fileneeded[dfilenum]; @@ -1651,44 +1656,62 @@ boolean CURLPrepareFile(const char* url, int dfilenum) for (INT32 j = 0; j < 16; j++) sprintf(&md5tmp[j*2], "%02x", curl_curfile->md5sum[j]); - curl_easy_setopt(http_handle, CURLOPT_URL, va("%s/%s?md5=%s", url, curl_realname, md5tmp)); + cc = curl_easy_setopt(http_handle, CURLOPT_URL, va("%s/%s?md5=%s", url, curl_realname, md5tmp)); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", curl_errbuf); // Only allow HTTP and HTTPS #if (LIBCURL_VERSION_MAJOR <= 7) && (LIBCURL_VERSION_MINOR < 85) - curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS); + cc = curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS); #else - curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS_STR, "http,https"); + cc = curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS_STR, "http,https"); #endif + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", curl_errbuf); // Set user agent, as some servers won't accept invalid user agents. - curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("Sonic Robo Blast 2/%s", VERSIONSTRING)); + cc = curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("Sonic Robo Blast 2/%s", VERSIONSTRING)); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", curl_errbuf); // Authenticate if the user so wishes login = CURLGetLogin(url, NULL); if (login) { - curl_easy_setopt(http_handle, CURLOPT_USERPWD, login->auth); + cc = curl_easy_setopt(http_handle, CURLOPT_USERPWD, login->auth); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", curl_errbuf); } // Follow a redirect request, if sent by the server. - curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1L); + cc = curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1L); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", curl_errbuf); - curl_easy_setopt(http_handle, CURLOPT_FAILONERROR, 1L); + cc = curl_easy_setopt(http_handle, CURLOPT_FAILONERROR, 1L); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", curl_errbuf); CONS_Printf("Downloading addon \"%s\" from %s\n", curl_realname, url); strcatbf(curl_curfile->filename, downloaddir, "/"); curl_curfile->file = fopen(curl_curfile->filename, "wb"); - curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, curl_curfile->file); - curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, curlwrite_data); - curl_easy_setopt(http_handle, CURLOPT_NOPROGRESS, 0L); - curl_easy_setopt(http_handle, CURLOPT_XFERINFOFUNCTION, curlprogress_callback); + + cc = curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, curl_curfile->file); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", curl_errbuf); + + cc = curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, curlwrite_data); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", curl_errbuf); + + cc = curl_easy_setopt(http_handle, CURLOPT_NOPROGRESS, 0L); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", curl_errbuf); + + cc = curl_easy_setopt(http_handle, CURLOPT_XFERINFOFUNCTION, curlprogress_callback); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", curl_errbuf); curl_curfile->status = FS_DOWNLOADING; - curl_multi_add_handle(multi_handle, http_handle); - curl_multi_perform(multi_handle, &curl_runninghandles); + mc = curl_multi_add_handle(multi_handle, http_handle); + if (mc != CURLM_OK) I_OutputMsg("libcurl: %s\n", curl_multi_strerror(mc)); + + mc = curl_multi_perform(multi_handle, &curl_runninghandles); + if (mc != CURLM_OK) I_OutputMsg("libcurl: %s\n", curl_multi_strerror(mc)); + curl_starttime = time(NULL); filedownload.current = dfilenum; @@ -1767,7 +1790,10 @@ void CURLGetFile(void) long response_code = 0; if (easyres == CURLE_HTTP_RETURNED_ERROR) - curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code); + { + CURLcode cc = curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", curl_errbuf); + } if (response_code == 404) curl_curfile->failed = FDOWNLOAD_FAIL_NOTFOUND; diff --git a/src/netcode/http-mserv.c b/src/netcode/http-mserv.c index eeac2beb5..fd0b4aaf7 100644 --- a/src/netcode/http-mserv.c +++ b/src/netcode/http-mserv.c @@ -84,7 +84,8 @@ struct HMS_buffer CURL *curl; char *buffer; int needle; - int end; + int end; + char *errbuf; }; static void @@ -158,6 +159,7 @@ HMS_connect (int proto, const char *format, ...) size_t seek; size_t token_length; struct HMS_buffer *buffer; + CURLcode cc; #ifdef NO_IPV6 if (proto == PROTO_V6) @@ -181,7 +183,7 @@ HMS_connect (int proto, const char *format, ...) curl = curl_easy_init(); - if (! curl) + if (!curl) { Contact_error(); Blame("From curl_easy_init.\n"); @@ -227,40 +229,62 @@ HMS_connect (int proto, const char *format, ...) buffer->end = DEFAULT_BUFFER_SIZE; buffer->buffer = malloc(buffer->end); buffer->needle = 0; + buffer->errbuf = malloc(CURL_ERROR_SIZE); + buffer->errbuf[0] = 0x00; + + cc = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, buffer->errbuf); if (cv_masterserver_debug.value) { - curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(curl, CURLOPT_STDERR, logstream); + cc = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); + + cc = curl_easy_setopt(curl, CURLOPT_STDERR, logstream); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); } - curl_easy_setopt(curl, CURLOPT_URL, url); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + cc = curl_easy_setopt(curl, CURLOPT_URL, url); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); + + cc = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); #ifndef NO_IPV6 if (proto == PROTO_V6 || (proto == PROTO_ANY && !hms_allow_ipv4)) { - curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); + cc = curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); + if (M_CheckParm("-bindaddr6") && M_IsNextParm()) { - curl_easy_setopt(curl, CURLOPT_INTERFACE, M_GetNextParm()); + cc = curl_easy_setopt(curl, CURLOPT_INTERFACE, M_GetNextParm()); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); } } if (proto == PROTO_V4 || (proto == PROTO_ANY && !hms_allow_ipv6)) #endif { - curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + cc = curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); + if (M_CheckParm("-bindaddr") && M_IsNextParm()) { - curl_easy_setopt(curl, CURLOPT_INTERFACE, M_GetNextParm()); + cc = curl_easy_setopt(curl, CURLOPT_INTERFACE, M_GetNextParm()); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); } } - curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer); + cc = curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); - curl_easy_setopt(curl, CURLOPT_USERAGENT, hms_useragent); + cc = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); + + cc = curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); + + cc = curl_easy_setopt(curl, CURLOPT_USERAGENT, hms_useragent); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); curl_free(quack_token); free(url); @@ -282,15 +306,15 @@ HMS_do (struct HMS_buffer *buffer) { Contact_error(); Blame( - "From curl_easy_perform: %s\n", - curl_easy_strerror(cc) + "From curl_easy_perform: %s\n", buffer->errbuf ); return 0; } buffer->buffer[buffer->needle] = '\0'; - curl_easy_getinfo(buffer->curl, CURLINFO_RESPONSE_CODE, &status); + cc = curl_easy_getinfo(buffer->curl, CURLINFO_RESPONSE_CODE, &status); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); if (status != 200) { From 67f1fd0670c58593ed9a47969e43c29709d4b48d Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 30 Mar 2025 11:43:10 -0400 Subject: [PATCH 23/28] curl: add code to check the output of curl_multi_*() --- src/netcode/d_netfil.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/netcode/d_netfil.c b/src/netcode/d_netfil.c index 622d61d4b..27c924dd8 100644 --- a/src/netcode/d_netfil.c +++ b/src/netcode/d_netfil.c @@ -1759,14 +1759,15 @@ void CURLGetFile(void) { if (curl_runninghandles) { - curl_multi_perform(multi_handle, &curl_runninghandles); + mc = curl_multi_perform(multi_handle, &curl_runninghandles); + if (mc != CURLM_OK) I_OutputMsg("libcurl: %s\n", curl_multi_strerror(mc)); /* wait for activity, timeout or "nothing" */ mc = curl_multi_wait(multi_handle, NULL, 0, 1000, NULL); if (mc != CURLM_OK) { - CONS_Alert(CONS_WARNING, "curl_multi_wait() failed, code %d.\n", mc); + CONS_Alert(CONS_WARNING, "curl_multi_wait() failed: %s.\n", curl_multi_strerror(mc)); continue; } curl_curfile->currentsize = curl_dlnow; @@ -1834,7 +1835,8 @@ void CURLGetFile(void) curl_curfile->file = NULL; filedownload.remaining--; - curl_multi_remove_handle(multi_handle, e); + mc = curl_multi_remove_handle(multi_handle, e); + if (mc != CURLM_OK) I_OutputMsg("libcurl: %s\n", curl_multi_strerror(mc)); curl_easy_cleanup(e); if (!filedownload.remaining) @@ -1845,7 +1847,8 @@ void CURLGetFile(void) if (!filedownload.remaining || !filedownload.http_running) { - curl_multi_cleanup(multi_handle); + mc = curl_multi_cleanup(multi_handle); + if (mc != CURLM_OK) I_OutputMsg("libcurl: %s\n", curl_multi_strerror(mc)); curl_global_cleanup(); multi_handle = NULL; } From e2c8d314d2a4b4d45889f332faf42effc5676293 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 30 Mar 2025 14:43:27 -0400 Subject: [PATCH 24/28] Emscripten: compile without MASTERSERVER support --- src/doomdef.h | 2 +- src/netcode/mserv.c | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 973d95eab..07973e11e 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -733,7 +733,7 @@ extern int /// Maintain compatibility with older 2.2 demos #define OLD22DEMOCOMPAT -#ifdef HAVE_CURL +#if defined (HAVE_CURL) && !(defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) #define MASTERSERVER #else #undef UPDATE_ALERT diff --git a/src/netcode/mserv.c b/src/netcode/mserv.c index fdc0304c5..848bfad3a 100644 --- a/src/netcode/mserv.c +++ b/src/netcode/mserv.c @@ -389,7 +389,6 @@ Change_masterserver_thread (char *api) void RegisterServer(void) { -#ifdef MASTERSERVER if (I_can_thread()) { void *nsid = New_server_id(); @@ -406,7 +405,6 @@ void RegisterServer(void) { Finish_registration(); } -#endif/*MASTERSERVER*/ } static void UpdateServer(void) @@ -431,7 +429,6 @@ static void UpdateServer(void) void UnregisterServer(void) { -#ifdef MASTERSERVER if (I_can_thread()) { if (!I_spawn_thread( @@ -447,11 +444,9 @@ void UnregisterServer(void) { Finish_unlist(); } -#endif/*MASTERSERVER*/ } -static boolean -Online (void) +static boolean Online(void) { return ( serverrunning && cv_masterserver_room_id.value > 0 ); } @@ -485,9 +480,7 @@ static inline void SendPingToMasterServer(void) void MasterClient_Ticker(void) { -#ifdef MASTERSERVER SendPingToMasterServer(); -#endif } static void @@ -510,8 +503,12 @@ Set_api (const char *api) HMS_set_api(dapi); } } +#else /*MASTERSERVER*/ -#endif/*MASTERSERVER*/ +void RegisterServer(void) {} +void UnregisterServer(void) {} + +#endif static boolean ServerName_CanChange(const char* newvalue) { @@ -554,7 +551,9 @@ static void RoomId_OnChange(void) { UnregisterServer(); ms_RoomId = cv_masterserver_room_id.value; +#ifdef MASTERSERVER if (Online()) +#endif RegisterServer(); } } From 66be8e8f28a416d63848b25bccfaa797e69e27cf Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 30 Mar 2025 14:44:14 -0400 Subject: [PATCH 25/28] Emscripten: only support thread with Emscripten's pthread enabled --- src/sdl/i_threads.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sdl/i_threads.c b/src/sdl/i_threads.c index 64e9ae142..24c528900 100644 --- a/src/sdl/i_threads.c +++ b/src/sdl/i_threads.c @@ -210,7 +210,11 @@ I_spawn_thread ( int I_can_thread (void) { +#ifdef __EMSCRIPTEN_PTHREADS__ + return true; +#else return SDL_ThreadID() != 0; +#endif } int From 337de68c50902426ac8d11412583496c67bd38e9 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 30 Mar 2025 14:44:51 -0400 Subject: [PATCH 26/28] Emscripten: cancel main loop in I_Quit() --- src/sdl/i_system.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index b5b2e7ca6..83e9437ad 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2528,10 +2528,10 @@ void I_Quit(void) death: W_Shutdown(); #ifdef __EMSCRIPTEN__ + emscripten_cancel_main_loop(); emscripten_force_exit(0); -#else - exit(0); #endif + exit(0); } void I_WaitVBL(INT32 count) From 9fa82ca5db72ea3d5f821bb167113313ab9089ec Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Fri, 4 Apr 2025 18:00:01 +0000 Subject: [PATCH 27/28] dedicated: fix thread build --- src/dedicated/i_threads.c | 1 - src/i_threads.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dedicated/i_threads.c b/src/dedicated/i_threads.c index 0e0b0bbe3..f8d9bc87a 100644 --- a/src/dedicated/i_threads.c +++ b/src/dedicated/i_threads.c @@ -15,7 +15,6 @@ #include "../i_threads.h" #include "../doomdef.h" -#include "../doomtype.h" typedef struct thread_s thread_t; diff --git a/src/i_threads.h b/src/i_threads.h index 079b18771..097d1accc 100644 --- a/src/i_threads.h +++ b/src/i_threads.h @@ -12,6 +12,8 @@ #ifndef I_THREADS_H #define I_THREADS_H +#include "doomtype.h" + typedef void (*I_thread_fn)(void *userdata); typedef void * I_mutex; From 313f2d29a23de9ac44528a46efac278c8c41a22b Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 12 Apr 2025 15:24:54 +0000 Subject: [PATCH 28/28] set CURLOPT_MAXREDIRS to 30 --- src/netcode/http-mserv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/netcode/http-mserv.c b/src/netcode/http-mserv.c index fd0b4aaf7..1623e1dec 100644 --- a/src/netcode/http-mserv.c +++ b/src/netcode/http-mserv.c @@ -277,6 +277,9 @@ HMS_connect (int proto, const char *format, ...) cc = curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value); if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); + cc = curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 30L); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); + cc = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read); if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf);