redshirt icon indicating copy to clipboard operation
redshirt copied to clipboard

Run Doom

Open tomaka opened this issue 5 years ago • 13 comments

The video game.

Link: https://doom.fandom.com/wiki/Wasm-doom

tomaka avatar Mar 17 '20 15:03 tomaka

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

tomaka avatar Mar 21 '20 09:03 tomaka

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)))

tomaka avatar Mar 21 '20 09:03 tomaka

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)))

tomaka avatar Mar 21 '20 10:03 tomaka

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.

tomaka avatar Mar 21 '20 11:03 tomaka

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] 

tomaka avatar Mar 21 '20 17:03 tomaka

#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.

tomaka avatar Mar 22 '20 14:03 tomaka

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.

tomaka avatar Mar 22 '20 14:03 tomaka

Screenshot from 2020-03-22 17-57-51

tomaka avatar Mar 22 '20 18:03 tomaka

#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.

tomaka avatar Apr 22 '20 16:04 tomaka

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.

tomaka avatar Apr 22 '20 18:04 tomaka

New hash with keyboard inputs support: 3LeP9quP46fTLZvjabc1cPRvuMKfPpTqWPVHYZwdWw1x

tomaka avatar Apr 26 '20 14:04 tomaka

New hash after https://github.com/tomaka/redshirt/pull/443: Ed5Zt6AULQkrQGDEFdBh2NAmQ1SDwkyq2hQ7ZzPgy8Rp

tomaka avatar May 08 '20 10:05 tomaka

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

tomaka avatar Dec 20 '20 13:12 tomaka