Run Doom
The video game.
Link: https://doom.fandom.com/wiki/Wasm-doom
DOOM looks simple enough to port that it's probably easier to start from the original source code dump rather than any other port.
Here's a diff that I used to make it compile on a modern Linux machine:
diff --git a/linuxdoom-1.10/Makefile b/linuxdoom-1.10/Makefile
index 8c69794..597aea8 100644
--- a/linuxdoom-1.10/Makefile
+++ b/linuxdoom-1.10/Makefile
@@ -6,9 +6,9 @@
#
CC= gcc # gcc or g++
-CFLAGS=-g -Wall -DNORMALUNIX -DLINUX # -DUSEASM
+CFLAGS=-g -m32 -Wall -DNORMALUNIX -DLINUX # -DUSEASM
LDFLAGS=-L/usr/X11R6/lib
-LIBS=-lXext -lX11 -lnsl -lm
+LIBS=-lXext -lX11 -lm
# subdirectory for objects
O=linux
@@ -92,4 +92,4 @@ $(O)/%.o: %.c
#############################################################
#
-#############################################################
\ No newline at end of file
+#############################################################
diff --git a/linuxdoom-1.10/i_sound.c b/linuxdoom-1.10/i_sound.c
index a327bfa..fda5024 100644
--- a/linuxdoom-1.10/i_sound.c
+++ b/linuxdoom-1.10/i_sound.c
@@ -37,6 +37,7 @@ rcsid[] = "$Id: i_unix.c,v 1.5 1997/02/03 22:45:10 b1 Exp $";
#include <sys/filio.h>
#endif
+#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
@@ -163,7 +164,7 @@ myioctl
int* arg )
{
int rc;
- extern int errno;
+ //extern int errno;
rc = ioctl(fd, command, arg);
if (rc < 0)
diff --git a/linuxdoom-1.10/i_video.c b/linuxdoom-1.10/i_video.c
index 9b311b3..2215de4 100644
--- a/linuxdoom-1.10/i_video.c
+++ b/linuxdoom-1.10/i_video.c
@@ -46,7 +46,7 @@ int XShmGetEventBase( Display* dpy ); // problems with g++?
#include <sys/socket.h>
#include <netinet/in.h>
-#include <errnos.h>
+#include <errno.h>
#include <signal.h>
#include "doomstat.h"
@@ -666,7 +666,7 @@ void grabsharedmemory(int size)
id = shmget((key_t)key, size, IPC_CREAT|0777);
if (id==-1)
{
- extern int errno;
+ //extern int errno;
fprintf(stderr, "errno=%d\n", errno);
I_Error("Could not get any shared memory");
}
It doesn't run, however:
Error: xdoom currently only supports 256-color PseudoColor screens
By downloading and extracting the WASI SDK, and applying the linked diff on the source code, I got DOOM to compile for WASI. The .wasm file is only 650kiB.
Here is the list of imports:
(import "wasi_unstable" "fd_prestat_get" (func $__wasi_fd_prestat_get (type $t6)))
(import "wasi_unstable" "fd_prestat_dir_name" (func $__wasi_fd_prestat_dir_name (type $t0)))
(import "wasi_unstable" "fd_read" (func $__wasi_fd_read (type $t7)))
(import "wasi_unstable" "fd_close" (func $__wasi_fd_close (type $t3)))
(import "wasi_unstable" "fd_write" (func $__wasi_fd_write (type $t7)))
(import "wasi_unstable" "fd_seek" (func $__wasi_fd_seek (type $t8)))
(import "wasi_unstable" "poll_oneoff" (func $__wasi_poll_oneoff (type $t7)))
(import "wasi_unstable" "proc_exit" (func $__wasi_proc_exit (type $t1)))
(import "wasi_unstable" "fd_fdstat_get" (func $__wasi_fd_fdstat_get (type $t6)))
(import "wasi_unstable" "fd_fdstat_set_flags" (func $__wasi_fd_fdstat_set_flags (type $t6)))
(import "wasi_unstable" "fd_filestat_get" (func $__wasi_fd_filestat_get (type $t6)))
(import "wasi_unstable" "clock_time_get" (func $__wasi_clock_time_get (type $t9)))
(import "wasi_unstable" "path_open" (func $__wasi_path_open (type $t10)))
(import "wasi_unstable" "path_filestat_get" (func $__wasi_path_filestat_get (type $t11)))
(import "wasi_unstable" "path_create_directory" (func $__wasi_path_create_directory (type $t0)))
(import "wasi_unstable" "args_sizes_get" (func $__wasi_args_sizes_get (type $t6)))
(import "wasi_unstable" "args_get" (func $__wasi_args_get (type $t6)))
(import "wasi_unstable" "environ_sizes_get" (func $__wasi_environ_sizes_get (type $t6)))
(import "wasi_unstable" "environ_get" (func $__wasi_environ_get (type $t6)))
Using a more recent version of the wasi-libc:
(import "wasi_snapshot_preview1" "proc_exit" (func $__wasi_proc_exit (type $t1)))
(import "wasi_snapshot_preview1" "fd_filestat_get" (func $__wasi_fd_filestat_get (type $t6)))
(import "wasi_snapshot_preview1" "poll_oneoff" (func $__wasi_poll_oneoff (type $t7)))
(import "wasi_snapshot_preview1" "fd_fdstat_get" (func $__wasi_fd_fdstat_get (type $t6)))
(import "wasi_snapshot_preview1" "fd_fdstat_set_flags" (func $__wasi_fd_fdstat_set_flags (type $t6)))
(import "wasi_snapshot_preview1" "clock_time_get" (func $__wasi_clock_time_get (type $t8)))
(import "wasi_snapshot_preview1" "fd_write" (func $__wasi_fd_write (type $t7)))
(import "wasi_snapshot_preview1" "fd_seek" (func $__wasi_fd_seek (type $t9)))
(import "wasi_snapshot_preview1" "fd_read" (func $__wasi_fd_read (type $t7)))
(import "wasi_snapshot_preview1" "fd_close" (func $__wasi_fd_close (type $t3)))
(import "wasi_snapshot_preview1" "path_open" (func $__wasi_path_open (type $t10)))
(import "wasi_snapshot_preview1" "path_filestat_get" (func $__wasi_path_filestat_get (type $t11)))
(import "wasi_snapshot_preview1" "path_create_directory" (func $__wasi_path_create_directory (type $t0)))
(import "wasi_snapshot_preview1" "fd_prestat_get" (func $__wasi_fd_prestat_get (type $t6)))
(import "wasi_snapshot_preview1" "fd_prestat_dir_name" (func $__wasi_fd_prestat_dir_name (type $t0)))
(import "wasi_snapshot_preview1" "args_sizes_get" (func $__wasi_args_sizes_get (type $t6)))
(import "wasi_snapshot_preview1" "args_get" (func $__wasi_args_get (type $t6)))
(import "wasi_snapshot_preview1" "environ_sizes_get" (func $__wasi_environ_sizes_get (type $t6)))
(import "wasi_snapshot_preview1" "environ_get" (func $__wasi_environ_get (type $t6)))
After #335, DOOM seems to write a large amount of data (a few hundred kiBs?) on stderr then a panic happens because of an overflow when reading memory. Probably an undefined behaviour.
After #336, the game seems to run except that there's no sound or graphics:
Running `target/release/redshirt-cli-kernel --module-path=/home/pierre/Projets/DOOM/linuxdoom-1.10/linux/linuxxdoom.wasm`
[#07413156577098584200] [INFO] DOOM Shareware Startup v1.10
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] V_Init: allocate screens.
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] M_LoadDefaults: Load system defaults.
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] Z_Init: Init zone memory allocation daemon.
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] W_Init: Init WADfiles.
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] adding ./doom1.wad
[#07413156577098584200] [INFO] =========================================================================== Shareware!===========================================================================
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] M_Init: Init miscellaneous info.
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] R_Init: Init DOOM refresh daemon -
[#07413156577098584200] [INFO] [
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] ]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] .
[#07413156577098584200] [INFO] .
[#07413156577098584200] [INFO] InitTextures
[#07413156577098584200] [INFO] InitFlats
[#07413156577098584200] [INFO] .
[#07413156577098584200] [INFO] .
[#07413156577098584200] [INFO] .
[#07413156577098584200] [INFO] .
[#07413156577098584200] [INFO] .
[#07413156577098584200] [INFO] .
[#07413156577098584200] [INFO] .
[#07413156577098584200] [INFO] .
[#07413156577098584200] [INFO] InitSprites
[#07413156577098584200] [INFO] InitColormaps
[#07413156577098584200] [INFO] R_InitData
[#07413156577098584200] [INFO] R_InitPointToAngle
[#07413156577098584200] [INFO] R_InitTables
[#07413156577098584200] [INFO] R_InitPlanes
[#07413156577098584200] [INFO] R_InitLightTables
[#07413156577098584200] [INFO] R_InitSkyMap
[#07413156577098584200] [INFO] R_InitTranslationsTables
[#07413156577098584200] [INFO] P_Init: Init Playloop state.
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] I_Init: Setting up machine state.
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] D_CheckNetGame: Checking network game status.
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] startskill 2 deathmatch: 0 startmap: 1 startepisode: 1
[#07413156577098584200] [INFO] player 1 of 1 (1 nodes)
[#07413156577098584200] [INFO] S_Init: Setting up sound.
[#07413156577098584200] [INFO]
[#07413156577098584200] [ERR ] S_Init: default sfx volume 8
[#07413156577098584200] [INFO] HU_Init: Setting up heads up display.
[#07413156577098584200] [INFO]
[#07413156577098584200] [INFO] ST_Init: Init status bar.
[#07413156577098584200] [INFO]
#345 finally fixes an "undefined behaviour". I've been observing.
This story is that before #343 the fd_prestat_get function was writing to the wrong memory location in the Wasm VM. This caused libpreload (contained within wasi-libc) to think that the directory name is empty, which is actually a good thing! Since things were working, I didn't notice the mistake.
I was however noticing some weird changes in the behaviour of the Wasm program, which is now explained by us accidentally overwriting data.
#343 fixed that, and caused the directory name to now be hello as expected. Unfortunately hello caused it to not find ./doom1.wad.
#345 now replaces this directory name with an empty string, which causes libpreload to find the WAD file.
After the spam of PRs, everything seems to be working fine. The next step is now to provide some way to display the screen.
Unfortunately the graphics story of redshirt is not really there yet (cc #187).
We could imagine some quick and hacky framebuffer interface just for making DOOM work.

#418 is eventually needed for DOOM to be able to load the .wad file containing its assets.
As for the DOOM executable itself, I can probably put it on https://github.com/tomaka/redshirt-packages
EDIT: done
Its hash is: 3mSo2ZmNRDmhDVQso8fCqciP5fLMyiT2kkhzCs35FcVe
It is possible to run cargo run --release -- --module-hash 3mSo2ZmNRDmhDVQso8fCqciP5fLMyiT2kkhzCs35FcVe.
It should be possible to legally bundle the .WAD files found at https://freedoom.github.io/
They can be started by passing -file, freedoom1.wad to DOOM.
New hash with keyboard inputs support: 3LeP9quP46fTLZvjabc1cPRvuMKfPpTqWPVHYZwdWw1x
New hash after https://github.com/tomaka/redshirt/pull/443: Ed5Zt6AULQkrQGDEFdBh2NAmQ1SDwkyq2hQ7ZzPgy8Rp
Doom works and this issue is more or less done, but I'm leaving it open because of the problem with the .WAD file. The game tries to load, at initialization, a .WAD file containing all its resources. It is at the moment necessary to tweak the source code of redshirt in order to put a file in the virtual file system of the game.
The last point to tackle is thus to provide some way to fix that. cc #418