Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run Doom #323

Open
tomaka opened this issue Mar 17, 2020 · 13 comments
Open

Run Doom #323

tomaka opened this issue Mar 17, 2020 · 13 comments
Labels
T-enhancement New feature or request

Comments

@tomaka
Copy link
Owner

tomaka commented Mar 17, 2020

The video game.

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

@tomaka tomaka added the T-enhancement New feature or request label Mar 17, 2020
@tomaka
Copy link
Owner Author

tomaka commented Mar 21, 2020

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
Copy link
Owner Author

tomaka commented Mar 21, 2020

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
Copy link
Owner Author

tomaka commented Mar 21, 2020

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
Copy link
Owner Author

tomaka commented Mar 21, 2020

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
Copy link
Owner Author

tomaka commented Mar 21, 2020

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
Copy link
Owner Author

tomaka commented Mar 22, 2020

#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
Copy link
Owner Author

tomaka commented Mar 22, 2020

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
Copy link
Owner Author

tomaka commented Mar 22, 2020

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

@tomaka
Copy link
Owner Author

tomaka commented Apr 22, 2020

#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
Copy link
Owner Author

tomaka commented Apr 22, 2020

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
Copy link
Owner Author

tomaka commented Apr 26, 2020

New hash with keyboard inputs support: 3LeP9quP46fTLZvjabc1cPRvuMKfPpTqWPVHYZwdWw1x

@tomaka
Copy link
Owner Author

tomaka commented May 8, 2020

New hash after #443: Ed5Zt6AULQkrQGDEFdBh2NAmQ1SDwkyq2hQ7ZzPgy8Rp

@tomaka
Copy link
Owner Author

tomaka commented Dec 20, 2020

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant