Subject: [bug#61243] Add WASM-4 fantasy console and prerequisites

From: "Thompson, David" <[email-masked]>
Date: Thu, 2 Feb 2023 18:31:33 -0500

Hello all,

This set of 4 patches adds WASM-4 (https://wasm4.org/), a fantasy
console that runs game "cartridges" compiled to WebAssembly.  It's a
fun way to learn about WebAssembly using a relatively simple system.
I've seen a WASM-4 game that was assembled using Racket, which I
thought was pretty neat.  It would be even cooler if someone did
something like that with Guile!

Packaging this thing was not exactly straightforward due to dependency
bundling via git submodules, but I was able to unbundle everything.

- Dave
From 110f6962f309ac3a7cb858210eed31b1098514f8 Mon Sep 17 00:00:00 2001
From: David Thompson <[email-masked]>
Date: Thu, 2 Feb 2023 14:27:13 -0500
Subject: [PATCH 2/4] gnu: Add minifb.

* gnu/packages/graphics.scm (minifb): New variable.
---
 gnu/packages/graphics.scm | 44 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/gnu/packages/graphics.scm b/gnu/packages/graphics.scm
index ebf571d93e..1c5f429084 100644
--- a/gnu/packages/graphics.scm
+++ b/gnu/packages/graphics.scm
@@ -34,6 +34,7 @@
 ;;; Copyright © 2022 Paul A. Patience <[email-masked]>
 ;;; Copyright © 2022 dan <[email-masked]>
 ;;; Copyright © 2023 Sharlatan Hellseher <[email-masked]>
+;;; Copyright © 2023 David Thompson <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -234,6 +235,49 @@ (define-public directfb
     (home-page "https://github.com/deniskropp/DirectFB")
     (license license:lgpl2.1+)))
 
+(define-public minifb
+  (let ((commit "43f8c1309341f4709a471b592d04434326042483")
+        (revision "1"))
+    (package
+      (name "minifb")
+      (version (git-version "0" revision commit))
+      (source (origin
+                (method git-fetch)
+                (uri
+                 (git-reference
+                  (url "https://github.com/emoon/minifb")
+                  (commit commit)))
+                (file-name (git-file-name name version))
+                (sha256
+                 (base32 "1z0720azsgi83yg4ysmfvpvsg0566s2cq59xx52w8w5rpkla4cjh"))))
+      (build-system cmake-build-system)
+      (arguments
+       '(#:configure-flags '("-DMINIFB_BUILD_EXAMPLES=0")
+         #:phases
+         (modify-phases %standard-phases
+           (replace 'install
+             (lambda* (#:key outputs #:allow-other-keys)
+               (let* ((out (assoc-ref outputs "out"))
+                      (includedir (string-append out "/include"))
+                      (libdir (string-append out "/lib")))
+                 (mkdir-p includedir)
+                 (mkdir-p libdir)
+                 (for-each (lambda (header)
+                             (copy-file header
+                                        (string-append includedir "/"
+                                                       (basename header))))
+                           (find-files "../source/include" "\\.h$"))
+                 (copy-file "libminifb.a" (string-append libdir "/libminifb.a"))))))
+         ;; No check target.
+         #:tests? #f))
+      ;; libminifb.a won't work without these libraries, so propagate them.
+      (propagated-inputs (list libx11 libxkbcommon mesa))
+      (synopsis "Small library for rendering pixels to a framebuffer")
+      (description "MiniFB (Mini FrameBuffer) is a small, cross-platform
+library that makes it easy to render (32-bit) pixels in a window.")
+      (home-page "https://github.com/emoon/minifb")
+      (license license:expat))))
+
 (define-public flux
   (package
     (name "flux")
-- 
2.39.1

From e021e8a679693e92af76e7444eab86245d3763c7 Mon Sep 17 00:00:00 2001
From: David Thompson <[email-masked]>
Date: Thu, 2 Feb 2023 17:50:03 -0500
Subject: [PATCH 4/4] gnu: Add wasm4.

* gnu/packages/emulators.scm (wasm4): New variable.
---
 gnu/packages/emulators.scm | 54 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/gnu/packages/emulators.scm b/gnu/packages/emulators.scm
index 7c04465526..47cb175d81 100644
--- a/gnu/packages/emulators.scm
+++ b/gnu/packages/emulators.scm
@@ -3,7 +3,7 @@
 ;;; Copyright © 2015 Paul van der Walt <[email-masked]>
 ;;; Copyright © 2015, 2016, 2021 Sou Bunnbu <[email-masked]>
 ;;; Copyright © 2015, 2016 Taylan Ulrich Bayırlı/Kammer <[email-masked]>
-;;; Copyright © 2015, 2018 David Thompson <[email-masked]>
+;;; Copyright © 2015, 2018, 2023 David Thompson <[email-masked]>
 ;;; Copyright © 2016 Manolis Fragkiskos Ragkousis <[email-masked]>
 ;;; Copyright © 2016, 2017, 2018, 2020 Efraim Flashner <[email-masked]>
 ;;; Copyright © 2017-2023 Nicolas Goaziou <[email-masked]>
@@ -74,6 +74,7 @@ (define-module (gnu packages emulators)
   #:use-module (gnu packages gl)
   #:use-module (gnu packages glib)
   #:use-module (gnu packages gnome)
+  #:use-module (gnu packages graphics)
   #:use-module (gnu packages gtk)
   #:use-module (gnu packages image)
   #:use-module (gnu packages libedit)
@@ -1506,6 +1507,57 @@ (define-public retroarch
 multi-system game/emulator system.")
     (license license:gpl3+)))
 
+(define-public wasm4
+  (package
+    (name "wasm4")
+    (version "2.5.4")
+    (source (origin
+              (method git-fetch)
+              (uri (git-reference
+                    (url "https://github.com/aduros/wasm4")
+                    (commit (string-append "v" version))))
+              (file-name (git-file-name name version))
+              (sha256
+               (base32
+                "0ycnznwy4i4fw6l507y5xm986rxqvnpl971725q8xinsnq2swpnl"))))
+    (build-system cmake-build-system)
+    (arguments
+     (list
+      #:tests? #f ; no check target
+      #:configure-flags
+      #~(list (string-append "-DCMAKE_C_FLAGS="
+                             "-I" #$minifb "/include "
+                             "-I" #$wasm3 "/include"))
+      #:phases
+      '(modify-phases %standard-phases
+         ;; WASM4's source is a combination of multiple runtimes.  We want to
+         ;; build the native one.
+         (add-after 'unpack 'chdir-to-native-runtime
+           (lambda _
+             (chdir "runtimes/native")))
+         ;; WASM4 uses git submodules to bundle several dependencies, which we
+         ;; have instead made dedicated packages for.  This phase hacks the
+         ;; build system to use our own stuff.
+         (add-after 'chdir-to-native-runtime 'unbundle
+           (lambda _
+             (substitute* "CMakeLists.txt"
+               ;; These directories do not exist because we aren't pulling in
+               ;; submodules.
+               (("add_subdirectory\\(vendor/minifb\\)") "")
+               (("add_subdirectory\\(vendor/cubeb\\)") "")
+               ;; Add additional libraries needed to successfully link the
+               ;; wasm4 executable using the unbundled dependencies.
+               (("target_link_libraries\\(wasm4 minifb cubeb\\)")
+                "target_link_libraries(wasm4 m GL X11 xkbcommon minifb cubeb m3)")))))))
+    (inputs (list cubeb minifb wasm3))
+    (synopsis "WebAssembly fantasy console")
+    (description "WASM-4 is a low-level fantasy game console for building
+small games with WebAssembly.  Game cartridges (ROMs) are small,
+self-contained .wasm files that can be built with any programming language
+that compiles to WebAssembly.")
+    (home-page "https://wasm4.org")
+    (license license:isc)))
+
 (define-public scummvm
   (package
     (name "scummvm")
-- 
2.39.1

From fa77f71c3f16db398eae0ed11453b8db077c6fe3 Mon Sep 17 00:00:00 2001
From: David Thompson <[email-masked]>
Date: Thu, 2 Feb 2023 15:06:59 -0500
Subject: [PATCH 3/4] gnu: Add cubeb.

* gnu/packages/audio.scm (cubeb): New variable.
---
 gnu/packages/audio.scm | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/gnu/packages/audio.scm b/gnu/packages/audio.scm
index 4fbfefafa3..9c4bfa7609 100644
--- a/gnu/packages/audio.scm
+++ b/gnu/packages/audio.scm
@@ -41,6 +41,7 @@
 ;;; Copyright © 2022 Simon Streit <[email-masked]>
 ;;; Copyright © 2022 Andy Tai <[email-masked]>
 ;;; Copyright © 2023 Sergiu Ivanov <[email-masked]>
+;;; Copyright © 2023 David Thompson <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -6159,3 +6160,39 @@ (define-public streamripper
 separation data, and uses that as a marker for where the track should
 be separated.")
     (license license:gpl2+)))
+
+(define-public cubeb
+  (let ((commit "9e29d728b0025c674904f83f5a13a88d1a6a5edc")
+        (revision "1"))
+    (package
+      (name "cubeb")
+      (version (git-version "0" revision commit))
+      (source (origin
+                (method git-fetch)
+                (uri (git-reference
+                      (url "https://github.com/mozilla/cubeb")
+                      (commit commit)))
+                (file-name (git-file-name name version))
+                (sha256
+                 (base32
+                  "1sxkr3h8a4hd3c3a3cjydrszz6npxk3vh6ra3y67lds3zgc69c7n"))))
+      (build-system cmake-build-system)
+      (arguments
+       '(#:configure-flags
+         ;; Sanitizers-cmake requires a git submodule.
+         '("-DUSE_SANITIZERS=0"
+           ;; Tests require a git submodule for googletest.
+           "-DBUILD_TESTS=0"
+           ;; Use our speex, not a bundled one.
+           "-DBUNDLE_SPEEX=0"
+           ;; A static library would be built by default.
+           "-DBUILD_SHARED_LIBS=1"
+           ;; Explicitly link against audio libraries so they are on the
+           ;; runpath.  Otherwise cubeb tries to dlopen them at runtime.
+           "-DCMAKE_SHARED_LINKER_FLAGS=-lasound -lpulse -lspeex")
+         #:tests? #f))
+      (inputs (list alsa-lib pulseaudio speex))
+      (synopsis "Cross-platform audio library")
+      (description "Cubeb is Mozilla's cross-platforom audio library.")
+      (home-page "https://github.com/mozilla/cubeb")
+      (license license:isc))))
-- 
2.39.1

From e227587b4e50313fdbda4acf7992b7a4ded23260 Mon Sep 17 00:00:00 2001
From: David Thompson <[email-masked]>
Date: Thu, 2 Feb 2023 14:04:48 -0500
Subject: [PATCH 1/4] gnu: Add wasm3.

* gnu/packages/web.scm (wasm3): New variable.
---
 gnu/packages/web.scm | 48 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/gnu/packages/web.scm b/gnu/packages/web.scm
index a29f53108c..c527ff80df 100644
--- a/gnu/packages/web.scm
+++ b/gnu/packages/web.scm
@@ -61,6 +61,7 @@
 ;;; Copyright © 2022 jgart <[email-masked]>
 ;;; Copyright © 2023 Paul A. Patience <[email-masked]>
 ;;; Copyright © 2022 Bruno Victal <[email-masked]>
+;;; Copyright © 2023 David Thompson <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -1557,6 +1558,53 @@ (define-public wabt
 other systems that want to manipulate WebAssembly files.")
     (license license:asl2.0)))
 
+(define-public wasm3
+  (package
+    (name "wasm3")
+    (version "0.5.0")
+    (source
+     (origin
+       (method git-fetch)
+       (uri (git-reference
+             (url "https://github.com/wasm3/wasm3")
+             (commit (string-append "v" version))))
+       (file-name (git-file-name name version))
+       (sha256
+        (base32 "07zzmk776j8ydyxhrnnjiscbhhmz182a62r6aix6kfk5kq2cwia2"))))
+    (build-system cmake-build-system)
+    (arguments
+     ;; The default WASI option "uvwasi" causes CMake to initiate a 'git
+     ;; clone' which cannot happen within the build container.
+     '(#:configure-flags '("-DBUILD_WASI=simple")
+       ;; No check target.  There are tests but they require a network
+       ;; connection to download the WebAssembly core test suite.
+       #:tests? #f
+       ;; There is no install target.  Instead, we have to manually copy the
+       ;; wasm3 build artifacts to the output directory.
+       #:phases
+       (modify-phases %standard-phases
+         (replace 'install
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (bindir (string-append out "/bin"))
+                    (includedir (string-append out "/include"))
+                    (libdir (string-append out "/lib")))
+               (mkdir-p bindir)
+               (mkdir-p includedir)
+               (mkdir-p libdir)
+               (copy-file "wasm3" (string-append bindir "/wasm3"))
+               (for-each (lambda (header)
+                           (copy-file header
+                                      (string-append includedir "/"
+                                                     (basename header))))
+                         (find-files "../source/source" "\\.h$"))
+               (copy-file "source/libm3.a"
+                          (string-append libdir "/libm3.a"))))))))
+    (home-page "https://github.com/wasm3/wasm3")
+    (synopsis "WebAssembly interpreter")
+    (description "WASM3 is a fast WebAssembly interpreter.")
+    (license license:expat)))
+
 (define-public websocketpp
   (package
     (name "websocketpp")
-- 
2.39.1