summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-11-01 03:28:20 +0100
committerMitya Selivanov <automainint@guattari.tech>2024-11-01 03:28:20 +0100
commiteb0c1592d49de956c8c4d83a831fab3cf0372acb (patch)
tree51af9b577499b85397267baed0db96046e12aefe
parent3d1e81ef18c4b2138b834459262f262e44a3397d (diff)
downloadreduced_system_layer-eb0c1592d49de956c8c4d83a831fab3cf0372acb.zip
Simple WebAssembly impl
-rw-r--r--Dockerfile2
-rw-r--r--index.htm79
-rw-r--r--nginx.conf1
-rwxr-xr-xreduced_system_layer.c81
4 files changed, 155 insertions, 8 deletions
diff --git a/Dockerfile b/Dockerfile
index 04fb96a..4b0f30f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
FROM emscripten/emsdk as build
COPY reduced_system_layer.c /usr/reduced_system_layer.c
-RUN emcc -o /usr/index.wasm /usr/reduced_system_layer.c
+RUN emcc -D REDUCED_SYSTEM_LAYER_EXAMPLE -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s EXPORTED_FUNCTIONS=_js_main,_js_init,_js_pixels,_js_frame -o /usr/index.wasm /usr/reduced_system_layer.c
FROM nginx:alpine
EXPOSE 80
diff --git a/index.htm b/index.htm
index 7753a28..35fd8ca 100644
--- a/index.htm
+++ b/index.htm
@@ -1,7 +1,80 @@
-<html>
+<!DOCTYPE html>
+<html style="height: 100%; overflow: hidden; overflow-x: hidden;">
<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width,initial-scale=1">
+ <link rel='icon' type='image/gif' href='/favicon.gif'>
+ <title> Reduced System Layer </title>
</head>
- <body>
- Hello, Sailor!
+ <body style="margin: 0; height: 100%; overflow: hidden; overflow-x: hidden;">
+ <canvas style="margin: 0; width: 100%; height: 100%;" id="frame" oncontextmenu="event.preventDefault()"></canvas>
+ <script type="text/javascript">
+ async function run() {
+ let canvas;
+ let program;
+ let memory_view;
+ let pixels_address;
+ let context;
+ let animation_frame;
+
+ canvas = document.getElementById("frame");
+ context = canvas.getContext("2d");
+
+ program = await WebAssembly.instantiateStreaming(
+ fetch("index.wasm"),
+ {
+ "wasi_snapshot_preview1" : {
+ args_sizes_get : (...args) => { console.log(`args_sizes_get: ${args}`); },
+ args_get : (...args) => { console.log(`args_get: ${args}`); },
+ proc_exit : (...args) => { console.log(`proc_exit: ${args}`); },
+ clock_time_get : () => { return Date.now(); },
+ fd_close : (...args) => { console.log(`fd_close: ${args}`); },
+ fd_write : (...args) => { console.log(`fd_write: ${args}`); },
+ fd_seek : (...args) => { console.log(`fd_seek: ${args}`); },
+ },
+ "env" : {
+ p_init : () => {
+ program.instance.exports.js_init();
+ memory_view = new Uint8Array(program.instance.exports.memory.buffer);
+ pixels_address = program.instance.exports.js_pixels();
+ },
+ p_render_frame_impl : () => {
+ canvas.width = window.innerWidth;
+ canvas.height = window.innerHeight;
+
+ let data = new ImageData(
+ new Uint8ClampedArray(
+ memory_view.subarray(
+ pixels_address,
+ pixels_address + 4 * canvas.width * canvas.height
+ )
+ ),
+ canvas.width,
+ canvas.height
+ );
+
+ context.putImageData(data, 0, 0);
+ },
+ p_cleanup : () => {},
+ p_handle_events : () => {},
+ p_wait_events : () => {},
+ p_sleep_for : (time) => {},
+ p_time : Date.now,
+ },
+ }
+ );
+
+ program.instance.exports.js_main();
+
+ animation_frame = (time) => {
+ program.instance.exports.js_frame(canvas.width, canvas.height);
+ window.requestAnimationFrame(animation_frame);
+ };
+
+ window.requestAnimationFrame(animation_frame);
+ }
+
+ run().catch((e) => console.error(e));
+ </script>
</body>
</html>
diff --git a/nginx.conf b/nginx.conf
index 83e6d1b..1297f03 100644
--- a/nginx.conf
+++ b/nginx.conf
@@ -8,6 +8,7 @@ events {
http {
types {
text/html htm;
+ image/gif gif;
application/wasm wasm;
}
default_type application/octet-stream;
diff --git a/reduced_system_layer.c b/reduced_system_layer.c
index 7963a2d..19c8a0c 100755
--- a/reduced_system_layer.c
+++ b/reduced_system_layer.c
@@ -30,7 +30,7 @@
#/ To-Do list
#/
#/ - Examples
-#/ - Conway's Game if Life
+#/ - Conway's Game of Life
#/ - Julia Set
#/ - Labyrinth
#/ - Landscape
@@ -119,6 +119,10 @@ typedef double f64;
//
// ================================================================
+#ifdef __cplusplus
+extern "C" {
+#endif
+
enum {
MAX_NUM_PIXELS = 10 * 1024 * 1024,
MAX_INPUT_SIZE = 256,
@@ -225,6 +229,9 @@ i32 p_handle_events(void);
i32 p_wait_events(void);
void p_render_frame(void);
+// User-defined proc
+void p_frame(void);
+
// Clipboard
void p_clipboard_write(i64 size, c8 *data);
@@ -238,6 +245,10 @@ i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port);
extern Platform platform;
+#ifdef __cplusplus
+}
+#endif
+
// ================================================================
#endif // REDUCED_SYSTEM_LAYER_HEADER_GUARD_
@@ -250,6 +261,27 @@ extern Platform platform;
#ifdef REDUCED_SYSTEM_LAYER_EXAMPLE
+// NOTE
+// This procedure is required for the WebAssembly compatibility.
+void p_frame(void) {
+ p_handle_events();
+
+ i64 w = platform.frame_width / 2;
+ i64 h = platform.frame_height / 2;
+ i64 x = w / 2;
+ i64 y = h / 2;
+
+ for (i64 j = 0; j < platform.frame_height; ++j)
+ for (i64 i = 0; i < platform.frame_width; ++i)
+ if (i < x || i >= x + w || j < y || j >= y + h)
+ platform.pixels[j * platform.frame_width + i] = 0xa0a0a0;
+ else
+ platform.pixels[j * platform.frame_width + i] = 0x131112;
+
+ p_render_frame();
+ p_sleep_for(0);
+}
+
i32 main(i32 argc, c8 **argv) {
(void) argc;
(void) argv;
@@ -263,9 +295,7 @@ i32 main(i32 argc, c8 **argv) {
p_init();
while (!platform.done) {
- p_handle_events();
- p_render_frame();
- p_sleep_for(0);
+ p_frame();
}
p_cleanup();
@@ -1164,6 +1194,49 @@ void p_queue_sound(i64 delay, i64 num_samples, f32 *samples) {
#endif
// ================================================================
+//
+// WebAssembly
+//
+// ================================================================
+
+#ifdef __EMSCRIPTEN__
+
+static u32 _buffer[MAX_NUM_PIXELS] = {0};
+
+void p_render_frame_impl(void);
+
+void p_render_frame(void) {
+ // Make the canvas data opaque.
+ i64 size = platform.frame_width * platform.frame_height;
+ for (i64 i = 0; i < size; ++i)
+ platform.pixels[i] |= 0xff000000;
+
+ p_render_frame_impl();
+}
+
+void js_main(c8 *href) {
+ main(1, &href);
+}
+
+void js_init(void) {
+ platform.pixels = _buffer;
+ platform.done = 1;
+}
+
+void *js_pixels(void) {
+ return platform.pixels;
+}
+
+void js_frame(i32 frame_width, i32 frame_height) {
+ platform.frame_width = frame_width;
+ platform.frame_height = frame_height;
+
+ p_frame();
+}
+
+#endif // __EMSCRIPTEN__
+
+// ================================================================
#endif // REDUCED_SYSTEM_LAYER_IMPL_GUARD_
#endif // REDUCED_SYSTEM_LAYER_HEADER