Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ OPT_LEVEL=3
if test "$GCC" = "yes"
then
WARNINGS="-Wall -Wdeclaration-after-statement -Wredundant-decls"
CFLAGS="-O$OPT_LEVEL -g $WARNINGS $orig_CFLAGS"
# -std=gnu99: modern clang defaults to C23, where true/false are
# keywords and collide with the boolean enum in doomtype.h.
# -fno-strict-aliasing: the id-era code type-puns byte buffers through
# int16/int32 pointers everywhere (e.g. wipe_shittyColMajorXform); at
# -O3 modern LLVM exploits that UB and miscompiles the screen-wipe
# into a transposed, never-finishing mess.
CFLAGS="-O$OPT_LEVEL -std=gnu99 -fno-strict-aliasing $WARNINGS $orig_CFLAGS"
fi

# PKG_CHECK_MODULES(SDL, [sdl2 >= 2.0.7])
Expand Down Expand Up @@ -115,10 +121,19 @@ AS_IF([test "x$with_libpng" != xno], [

# TODO: We currently link everything against libraries that don't need it.
# Use the specific library CFLAGS/LIBS variables instead of setting them here.
EMFLAGS="-gsource-map -s INVOKE_RUN=1 -s USE_SDL=2 -s USE_SDL_MIXER=2 -s LEGACY_GL_EMULATION=0 -s USE_SDL_NET=2 -s ASSERTIONS=0 -s WASM=1 -s ALLOW_MEMORY_GROWTH=0 -s FORCE_FILESYSTEM=1 -s EXTRA_EXPORTED_RUNTIME_METHODS=[['FS','ccall']] -s SAFE_HEAP=1 -s EXIT_RUNTIME=1 -s STACK_OVERFLOW_CHECK=1 -s PROXY_POSIX_SOCKETS=0 -s USE_PTHREADS=0 -s PROXY_TO_PTHREAD=0 -s TOTAL_MEMORY=64MB -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s ASYNCIFY -O3 --source-map-base /"
# Release flags: no SAFE_HEAP/STACK_OVERFLOW_CHECK/source maps (debug-only, large
# runtime cost), closure for smaller JS glue. ASYNCIFY is still required for
# emscripten_sleep() on startup and netgame wait paths (see I_Sleep).
# Do NOT add -flto: cross-TU LTO at -O3 turns undefined behavior in this
# 1993-era codebase into a compile-time `unreachable` trap in main() (verified:
# the LTO build crashes immediately after Z_Init).
# STACK_SIZE=5MB restores the pre-3.1.25 Emscripten default; the modern 64KB
# default is too small for Doom's init path.
EMFLAGS="-s INVOKE_RUN=1 -s USE_SDL=2 -s USE_SDL_MIXER=2 -s LEGACY_GL_EMULATION=0 -s USE_SDL_NET=2 -s ASSERTIONS=0 -s WASM=1 -s ALLOW_MEMORY_GROWTH=0 -s FORCE_FILESYSTEM=1 -s EXPORTED_RUNTIME_METHODS=[['FS','ccall']] -s EXIT_RUNTIME=1 -s PROXY_POSIX_SOCKETS=0 -s USE_PTHREADS=0 -s PROXY_TO_PTHREAD=0 -s INITIAL_MEMORY=64MB -s STACK_SIZE=5MB -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s ASYNCIFY -O3"
EMLDFLAGS="--closure 1"

CFLAGS="$CFLAGS $SDL_CFLAGS ${SAMPLERATE_CFLAGS:-} ${PNG_CFLAGS:-} $EMFLAGS"
LDFLAGS="$LDFLAGS $SDL_LIBS ${SAMPLERATE_LIBS:-} ${PNG_LIBS:-} $EMFLAGS -lwebsocket.js"
LDFLAGS="$LDFLAGS $SDL_LIBS ${SAMPLERATE_LIBS:-} ${PNG_LIBS:-} $EMFLAGS $EMLDFLAGS -lwebsocket.js"

AC_CHECK_LIB(m, log)

Expand Down
17 changes: 8 additions & 9 deletions src/d_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -661,16 +661,15 @@ void TryRunTics(void)

if (lowtic < gametic / ticdup) I_Error("TryRunTics: lowtic < gametic");

// Still no tics to run? Sleep until some are available.
// Still no tics to run? Return to the browser event loop instead
// of sleeping: I_Sleep() is emscripten_sleep(), which Asyncify
// implements by unwinding and rewinding the entire call stack.
// This loop is reached on almost every frame (the 60Hz+ rAF main
// loop outpaces the 35Hz tic rate), so sleeping here put that
// unwind cost on the hot path. The main loop calls TryRunTics()
// again on the next frame, which serves the same purpose.
if (lowtic < gametic / ticdup + counts) {
// If we're in a netgame, we might spin forever waiting for
// new network data to be received. So don't stay in here
// forever - give the menu a chance to work.
if (I_GetTime() / ticdup - entertic >= MAX_NETGAME_STALL_TICS) {
return;
}

I_Sleep(1);
return;
}
}

Expand Down
13 changes: 8 additions & 5 deletions src/doom/d_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,11 +375,14 @@ void D_RunFrame()
static boolean wipe;

if (wipe) {
do {
nowtime = I_GetTime();
tics = nowtime - wipestart;
I_Sleep(1);
} while (tics <= 0);
// No game tic has elapsed yet: return to the browser event loop
// rather than Asyncify-sleeping (stack unwind/rewind) inside the
// frame. The main loop re-enters D_RunFrame on the next rAF frame.
nowtime = I_GetTime();
tics = nowtime - wipestart;
if (tics <= 0) {
return;
}

wipestart = nowtime;
wipe = !wipe_ScreenWipe(wipe_Melt, 0, 0, SCREENWIDTH, SCREENHEIGHT, tics);
Expand Down
5 changes: 4 additions & 1 deletion src/doom/r_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,10 @@ typedef struct
// If false use 0 for any position.
// Note: as eight entries are available,
// we might as well insert the same name eight times.
boolean rotate;
// int, not boolean: R_InstallSpriteLump memsets this to -1 as an
// "uninitialized" marker and compares against it; a 1-byte bool
// cannot hold -1.
int rotate;

// Lump to use for view angles 0-7.
short lump[8];
Expand Down
19 changes: 6 additions & 13 deletions src/doomtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,22 +100,15 @@

#include <inttypes.h>

#if defined(__cplusplus) || defined(__bool_true_false_are_defined)

// Use builtin bool type with C++.
// boolean must be the same size in every translation unit. The old
// conditional (enum when <stdbool.h> hadn't been included yet, bool when it
// had) made boolean 4 bytes in some TUs and 1 byte in others, so 4-byte
// stores to shared globals like netgame clobbered adjacent globals
// (caught by ASan as a global-buffer-overflow). Always use bool.
#include <stdbool.h>

typedef bool boolean;

#else

typedef enum
{
false,
true
} boolean;

#endif

typedef uint8_t byte;
typedef uint8_t pixel_t;
typedef int16_t dpixel_t;
Expand Down
23 changes: 17 additions & 6 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,25 @@
<script>
var commonArgs = ["-iwad", "doom1.wad", "-window", "-nogui", "-nomusic", "-config", "default.cfg", "-servername", "doomflare"];

// Surface wasm crash stacks in the console; "Uncaught (in promise)"
// errors from the async runtime are otherwise swallowed with no trace.
window.addEventListener("unhandledrejection", (e) => {
console.error("UNHANDLED: " + (e.reason && (e.reason.stack || e.reason)));
});
window.addEventListener("error", (e) => {
console.error("ERROR: " + (e.error && e.error.stack ? e.error.stack : e.message));
});

var Module = {
onRuntimeInitialized: () => {
callMain(commonArgs);
},
noInitialRun: true,
// main() runs automatically (INVOKE_RUN) once the preloaded
// files below are ready; callMain is no longer exported by
// recent Emscripten versions.
arguments: commonArgs,
preRun: () => {
Module.FS.createPreloadedFile("", "doom1.wad", "doom1.wad", true, true);
Module.FS.createPreloadedFile("", "default.cfg", "default.cfg", true, true);
// Emscripten 6.x renamed FS.createPreloadedFile to
// FS.preloadFile, exported on Module as FS_preloadFile.
Module.FS_preloadFile("", "doom1.wad", "doom1.wad", true, true);
Module.FS_preloadFile("", "default.cfg", "default.cfg", true, true);
},
printErr: function (text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(" ");
Expand Down