summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-11-17 05:22:41 +0100
committerMitya Selivanov <automainint@guattari.tech>2024-11-17 05:22:41 +0100
commit94598aa337e0fd02a4bfd38929acfdb8296ee23b (patch)
tree40369c49a5075c1b21dcceed08c8e31119414b2b
parent674f8aa8f7a4e5a7197eae49c116727f4d681831 (diff)
downloadreduced_system_layer-94598aa337e0fd02a4bfd38929acfdb8296ee23b.zip
wasm input
-rwxr-xr-xexamples/landscape.c269
-rw-r--r--index.htm125
-rwxr-xr-xreduced_system_layer.c113
3 files changed, 205 insertions, 302 deletions
diff --git a/examples/landscape.c b/examples/landscape.c
deleted file mode 100755
index 9ee2e98..0000000
--- a/examples/landscape.c
+++ /dev/null
@@ -1,269 +0,0 @@
-#if 0 /*
-#/ ================================================================
-#/
-#/ landscape.c
-#/
-#/ ================================================================
-#/
-#/ Self-compilation shell script
-#/
-SRC=${0##*./}
-BIN=${SRC%.*}
-gcc \
- -Wall -Wextra -Werror -pedantic \
- -Wno-old-style-declaration \
- -Wno-missing-braces \
- -Wno-unused-variable \
- -Wno-unused-but-set-variable \
- -Wno-unused-parameter \
- -Wno-overlength-strings \
- -O3 \
- -fsanitize=undefined,address,leak \
- -lX11 -lm \
- -o $BIN $SRC && \
- ./$BIN $@ && rm $BIN
-exit $? # */
-#endif
-
-#include "../graphics.c"
-
-#define EPS 1e-8
-
-enum {
- MAX_NUM_TILES = 10 * 1024 * 1024,
-};
-
-typedef struct {
- i32 index;
- i32 version;
-} Handle;
-
-typedef union {
- struct { f64 x, y; };
- struct { f64 v[2]; };
-} Vec2;
-
-typedef union {
- struct { f64 x, y, z; };
- struct { f64 r, g, b; };
- struct { f64 v[3]; };
-} Vec3;
-
-typedef union {
- struct { f64 x, y, z, w; };
- struct { f64 r, g, b, a; };
- struct { f64 v[4]; };
-} Vec4;
-
-typedef struct {
- b8 visible;
- f64 x;
- f64 y;
- f64 size;
-} Screen_Area;
-
-typedef struct {
- u32 background;
- i64 system_time;
- i64 time;
- i32 map_num_x;
- i32 map_num_y;
- f64 map[MAX_NUM_TILES];
- f64 screen_distance;
- f64 zoom;
- f64 tilt;
- Vec3 eye_position;
- Vec3 right;
- Vec3 up;
- Vec3 forward;
- Vec3 screen_x_axis;
- Vec3 screen_y_axis;
- Vec3 screen_z_axis;
-} World;
-
-#define CHECK(fail_return, condition) \
- assert(condition); \
- if (!(condition)) \
- return fail_return;
-
-World world = {0};
-
-f64 dot(Vec3 a, Vec3 b) {
- return a.x * b.x + a.y * b.y + a.z * b.z;
-}
-
-Vec3 cross(Vec3 a, Vec3 b) {
- return (Vec3) {
- .x = a.y * b.z - a.z * b.y,
- .y = a.z * b.x - a.x * b.z,
- .z = a.x * b.y - a.y * b.x,
- };
-}
-
-Vec3 neg(Vec3 a) {
- return (Vec3) {
- .x = -a.x,
- .y = -a.y,
- .z = -a.z,
- };
-}
-
-Vec3 add(Vec3 a, Vec3 b) {
- return (Vec3) {
- .x = a.x + b.x,
- .y = a.y + b.y,
- .z = a.z + b.z,
- };
-}
-
-Vec3 sub(Vec3 a, Vec3 b) {
- return (Vec3) {
- .x = a.x - b.x,
- .y = a.y - b.y,
- .z = a.z - b.z,
- };
-}
-
-Vec3 mul(Vec3 a, f64 b) {
- return (Vec3) {
- .x = a.x * b,
- .y = a.y * b,
- .z = a.z * b,
- };
-}
-
-Vec3 v_div(Vec3 a, f64 b) {
- if (b > -EPS && b < EPS) {
- assert(0);
- return (Vec3) {
- .x = 0.,
- .y = 0.,
- .z = 1.,
- };
- }
- return (Vec3) {
- .x = a.x / b,
- .y = a.y / b,
- .z = a.z / b,
- };
-}
-
-Vec3 normal(Vec3 a) {
- return v_div(a, sqrt(dot(a, a)));
-}
-
-void resolve_axes(void) {
- world.right = (Vec3) { .x = 1., .y = 0., .z = 0., };
- world.forward = (Vec3) { .x = 0., .y = 1., .z = 0., };
- world.up = (Vec3) { .x = 0., .y = 0., .z = 1., };
-
- if (world.tilt < 0.0)
- world.tilt += M_PI * 2.0 * floor(-world.tilt / (M_PI * 2.0) + 1.0);
- if (world.tilt >= M_PI * 2.0)
- world.tilt -= M_PI * 2.0 * floor(world.tilt / (M_PI * 2.0));
-
- world.screen_z_axis = (Vec3) {
- .x = 0.,
- .y = sin(world.tilt),
- .z = -cos(world.tilt),
- };
-
- world.screen_y_axis = normal(cross(world.screen_z_axis, world.right));
- world.screen_x_axis = normal(cross(world.screen_y_axis, world.screen_z_axis));
-}
-
-Screen_Area world_to_screen(Vec3 p, f64 size) {
- Vec3 r = sub(p, world.eye_position);
- f64 l = dot(r, world.screen_z_axis);
-
- if (l < EPS)
- return (Screen_Area) { .visible = 0, };
-
- f64 k = (world.screen_distance / l) * world.zoom;
-
- f64 x = k * dot(r, world.screen_x_axis);
- f64 y = k * dot(r, world.screen_y_axis);
-
- f64 hw = platform.frame_width * .5;
- f64 hh = platform.frame_height * .5;
-
- return (Screen_Area) {
- .visible = 1,
- .x = hw + x,
- .y = hh + y,
- .size = k * size,
- };
-}
-
-Vec3 screen_to_world(i32 x, i32 y) {
- f64 fx = ((f64) x - platform.frame_width * .5) / world.zoom;
- f64 fy = ((f64) y - platform.frame_height * .5) / world.zoom;
-
- Vec3 r = add(add(
- mul(world.screen_x_axis, fx),
- mul(world.screen_y_axis, fy)),
- mul(world.screen_z_axis, world.screen_distance)
- );
-
- if (r.z < -EPS || r.z > EPS)
- r = mul(r, -world.eye_position.z / r.z);
-
- return add(world.eye_position, r);
-}
-
-void update_and_render_frame(void) {
- p_handle_events();
-
- i64 time_elapsed = p_time() - world.system_time;
- world.system_time += time_elapsed;
-
- resolve_axes();
-
- if (time_elapsed > 0) {
- if (platform.key_down['w'])
- world.tilt += .001 * time_elapsed;
- if (platform.key_down['s'])
- world.tilt -= .001 * time_elapsed;
-
- f64 k = world.eye_position.z;
- if (world.zoom > EPS)
- k /= world.zoom;
-
- if (platform.wheel_dy != 0)
- world.eye_position.z -= (f64) platform.wheel_dy;
-
- if (platform.key_down[BUTTON_RIGHT]) {
- world.eye_position.x -= platform.cursor_dx * k;
- world.eye_position.y += platform.cursor_dy * k;
- }
-
- world.time += time_elapsed;
- }
-
- for (i32 j = 0; j < platform.frame_height; ++j)
- for (i32 i = 0; i < platform.frame_width; ++i)
- platform.pixels[j * platform.frame_width + i] = world.background;
-
- p_render_frame();
-}
-
-i32 main(i32 argc, c8 **argv) {
- (void) argc;
- (void) argv;
-
- platform = (Platform) {
- .title = "Landscape",
- .frame_width = 960,
- .frame_height = 720,
- };
-
- world.background = u32_from_rgb(.03f, .08f, .01f);
- world.system_time = p_time();
- world.screen_distance = 1.;
- world.zoom = 1e+3;
- world.eye_position = (Vec3) { .z = 10., };
-
- p_event_loop();
-
- return 0;
-}
diff --git a/index.htm b/index.htm
index 2c42d74..c4c323a 100644
--- a/index.htm
+++ b/index.htm
@@ -72,15 +72,25 @@
p_wait_events_impl : () => { wait_for_events = true; },
p_sleep_for : (time) => { sleep_duration += time; },
p_time : Date.now,
- sqrt : Math.sqrt,
- floor : Math.floor,
- ceil : Math.ceil,
- memset : (dst, val, num) => {
- program.instance.exports.js_memset(dst, val, num);
- },
- memcpy : (dst, src, num) => {
- program.instance.exports.js_memcpy(dst, src, num);
- },
+
+ floor : Math.floor,
+ ceil : Math.ceil,
+ sqrt : Math.sqrt,
+ pow : Math.pow,
+ log : Math.log,
+ log2 : Math.log2,
+ log10 : Math.log10,
+ exp : Math.exp,
+ sin : Math.sin,
+ cos : Math.cos,
+ tan : Math.tan,
+ asin : Math.asin,
+ acos : Math.acos,
+ atan : Math.atan,
+ atan2 : Math.atan2,
+
+ memset : (dst, val, num) => { program.instance.exports.js_memset(dst, val, num); },
+ memcpy : (dst, src, num) => { program.instance.exports.js_memcpy(dst, src, num); },
},
}
);
@@ -129,7 +139,102 @@
let key_from_code = (code) => {
switch (code) {
- case "KeyA": return 97;
+ case "Backspace": return 8;
+ case "Tab": return 9;
+ case "Enter": return 10;
+ case "ControlLeft": return 11;
+ case "ControlRight": return 12;
+ case "ShiftLeft": return 13;
+ case "ShiftRight": return 14;
+ case "AltLeft": return 15;
+ case "AltRight": return 16;
+ case "ArrowLeft": return 17;
+ case "ArrowRight": return 18;
+ case "ArrowUp": return 19;
+ case "ArrowDown": return 20;
+ case "Pause": return 21;
+ case "Insert": return 22;
+ case "Home": return 23;
+ case "End": return 24;
+ case "PageUp": return 25;
+ case "PageDown": return 26;
+ case "Escape": return 27;
+ case "PrintScreen": return 28;
+ case "Space": return 32;
+ case "MetaLeft": return 33;
+ case "MetaRight": return 34;
+ case "Quote": return 39;
+ case "Comma": return 44;
+ case "Minus": return 45;
+ case "Period": return 46;
+ case "Slash": return 47;
+ case "Digit0": return 48;
+ case "Digit1": return 49;
+ case "Digit2": return 50;
+ case "Digit3": return 51;
+ case "Digit4": return 52;
+ case "Digit5": return 53;
+ case "Digit6": return 54;
+ case "Digit7": return 55;
+ case "Digit8": return 56;
+ case "Digit9": return 57;
+ case "Semicolon": return 59;
+ case "Equal": return 61;
+ case "BracketLeft": return 91;
+ case "Backslash": return 92;
+ case "BracketRight": return 93;
+ case "Backquote": return 96;
+ case "KeyA": return 97;
+ case "KeyB": return 98;
+ case "KeyC": return 99;
+ case "KeyD": return 100;
+ case "KeyE": return 101;
+ case "KeyF": return 102;
+ case "KeyG": return 103;
+ case "KeyH": return 104;
+ case "KeyI": return 105;
+ case "KeyJ": return 106;
+ case "KeyK": return 107;
+ case "KeyL": return 108;
+ case "KeyM": return 109;
+ case "KeyN": return 110;
+ case "KeyO": return 111;
+ case "KeyP": return 112;
+ case "KeyQ": return 113;
+ case "KeyR": return 114;
+ case "KeyS": return 115;
+ case "KeyT": return 116;
+ case "KeyU": return 117;
+ case "KeyV": return 118;
+ case "KeyW": return 119;
+ case "KeyX": return 120;
+ case "KeyY": return 121;
+ case "KeyZ": return 122;
+ case "Delete": return 127;
+ case "F1": return 145;
+ case "F2": return 146;
+ case "F3": return 147;
+ case "F4": return 148;
+ case "F5": return 149;
+ case "F6": return 150;
+ case "F7": return 151;
+ case "F8": return 152;
+ case "F9": return 153;
+ case "F10": return 154;
+ case "F11": return 155;
+ case "F12": return 156;
+ case "F13": return 157;
+ case "F14": return 158;
+ case "F15": return 159;
+ case "F16": return 160;
+ case "F17": return 161;
+ case "F18": return 162;
+ case "F19": return 163;
+ case "F20": return 164;
+ case "F21": return 165;
+ case "F22": return 166;
+ case "F23": return 167;
+ case "F24": return 168;
}
return 0;
};
diff --git a/reduced_system_layer.c b/reduced_system_layer.c
index 9c1e67e..7b18780 100755
--- a/reduced_system_layer.c
+++ b/reduced_system_layer.c
@@ -33,17 +33,37 @@
#/ - Conway's Game of Life
#/ - Julia Set
#/ - Labyrinth
-#/ - Landscape
-#/ - Features
-#/ - Sound
-#/ - Clipboard daemon
+#/ - Chat
+#/ - Graphics
+#/ - Vector math
+#/ - UI
+#/ - Wayland
+#/ - Windows graphics
+#/ - Sound
+#/ - ALSA -- https://www.alsa-project.org/alsa-doc/alsa-lib/_2test_2pcm_min_8c-example.html
+#/ - Windows audio
+#/ - WebAssembly audio
+#/ - Networking
+#/ - Windows sockets
+#/ - Web Sockets
#/
-#/ ALSA
-#/ https://www.alsa-project.org/alsa-doc/alsa-lib/_2test_2pcm_min_8c-example.html
+#/ Done
+#/
+#/ - Examples
+#/ - Echo
+#/ - UI
+#/ - Particles
+#/ - Graph
+#/ - Graphics
+#/ - Font
+#/ - X11
+#/ - WebAssembly
+#/ - Networking
+#/ - Unix UDP sockets
#/
#/ ----------------------------------------------------------------
#/
-#/ (C) 2024 Mitya Selivanov <guattari.tech>, MIT License
+#/ (C) 2024 Mitya Selivanov <guattari.tech>
#/
#/ ================================================================
#/
@@ -344,9 +364,21 @@ extern Platform platform;
#ifdef __wasm__
i32 main(i32 argc, c8 **argv);
-f64 sqrt(f64 x);
f64 floor(f64 x);
f64 ceil(f64 x);
+f64 sqrt(f64 x);
+f64 pow(f64 x, f64 y);
+f64 log(f64 x);
+f64 log2(f64 x);
+f64 log10(f64 x);
+f64 exp(f64 x);
+f64 sin(f64 x);
+f64 cos(f64 x);
+f64 tan(f64 x);
+f64 asin(f64 x);
+f64 acos(f64 x);
+f64 atan(f64 x);
+f64 atan2(f64 y, f64 x);
#ifndef NULL
#define NULL ((void *) 0)
@@ -546,7 +578,6 @@ void p_sleep_for(i64 duration) {
#include <stdio.h>
#include <string.h>
-#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <netinet/in.h>
@@ -655,8 +686,15 @@ b8 sockets_open(u16 slot, IP_Address address, u16 *local_port) {
}
i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address) {
- assert(slot < MAX_NUM_SOCKETS);
- assert(address.protocol == IPv4_UDP || address.protocol == IPv6_UDP);
+ if (slot >= MAX_NUM_SOCKETS) {
+ fprintf(stderr, "%s:%d, %s: Invalid slot %d.\n", __FILE__, __LINE__, __FUNCTION__, (i32) (u32) slot);
+ return 0;
+ }
+
+ if (address.protocol != IPv4_UDP && address.protocol != IPv6_UDP) {
+ fprintf(stderr, "%s:%d, %s: Invalid address protocol %d.\n", __FILE__, __LINE__, __FUNCTION__, (i32) (u32) address.protocol);
+ return 0;
+ }
if (!sockets_open(slot, address, local_port))
return 0;
@@ -690,7 +728,7 @@ i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP
if (errno == EAGAIN || errno == EWOULDBLOCK)
return 0;
- fprintf(stderr, "ERROR: recvfrom failed (errno %d)\n", errno);
+ fprintf(stderr, "%s:%d, %s: recvfrom failed (errno %d).\n", __FILE__, __LINE__, __FUNCTION__, errno);
return 0;
}
@@ -711,8 +749,15 @@ i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP
}
i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
- assert(slot < MAX_NUM_SOCKETS);
- assert(address.protocol == IPv4_UDP || address.protocol == IPv6_UDP);
+ if (slot >= MAX_NUM_SOCKETS) {
+ fprintf(stderr, "%s:%d, %s: Invalid slot %d.\n", __FILE__, __LINE__, __FUNCTION__, (i32) (u32) slot);
+ return 0;
+ }
+
+ if (address.protocol != IPv4_UDP && address.protocol != IPv6_UDP) {
+ fprintf(stderr, "%s:%d, %s: Invalid address protocol %d.\n", __FILE__, __LINE__, __FUNCTION__, (i32) (u32) address.protocol);
+ return 0;
+ }
IP_Address local_address = address;
local_address.port = 0;
@@ -757,7 +802,7 @@ i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
return 0;
- fprintf(stderr, "ERROR: sendto failed (errno %d)\n", errno);
+ fprintf(stderr, "%s:%d, %s: sendto failed (errno %d).\n", __FILE__, __LINE__, __FUNCTION__, errno);
return 0;
}
@@ -797,7 +842,11 @@ static Atom _target = None;
void p_init(void) {
_display = XOpenDisplay(NULL);
- assert(_display != NULL);
+
+ if (_display == NULL) {
+ fprintf(stderr, "%s:%d, %s: XOpenDisplay failed.\n", __FILE__, __LINE__, __FUNCTION__);
+ return;
+ }
_key_table[XKeysymToKeycode(_display, XK_Left)] = KEY_LEFT;
_key_table[XKeysymToKeycode(_display, XK_Right)] = KEY_RIGHT;
@@ -906,7 +955,11 @@ void p_init(void) {
Visual *visual = DefaultVisual(_display, screen);
_gc = DefaultGC(_display, screen);
- assert(_gc != NULL);
+
+ if (_gc == NULL) {
+ fprintf(stderr, "%s:%d, %s: DefaultGC failed.\n", __FILE__, __LINE__, __FUNCTION__);
+ return;
+ }
XSetGraphicsExposures(_display, _gc, False);
@@ -924,10 +977,18 @@ void p_init(void) {
_window = XCreateWindow(_display, XDefaultRootWindow(_display), x, y, platform.frame_width, platform.frame_height, 0, depth, InputOutput, visual, CWEventMask, &(XSetWindowAttributes) { .event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | VisibilityChangeMask | FocusChangeMask | StructureNotifyMask | SubstructureNotifyMask, });
_im = XOpenIM(_display, NULL, NULL, NULL);
- assert(_im != NULL);
+
+ if (_im == NULL) {
+ fprintf(stderr, "%s:%d, %s: XOpenIM failed.\n", __FILE__, __LINE__, __FUNCTION__);
+ return;
+ }
_ic = XCreateIC(_im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, _window, NULL);
- assert(_ic != NULL);
+
+ if (_ic == NULL) {
+ fprintf(stderr, "%s:%d, %s: XCreateIC failed.\n", __FILE__, __LINE__, __FUNCTION__);
+ return;
+ }
platform.pixels = _buffer;
platform.input = _input;
@@ -986,6 +1047,9 @@ void p_cleanup(void) {
}
i32 p_handle_events(void) {
+ if (_display == NULL)
+ return 0;
+
i32 num_events = 0;
memset(platform.key_pressed, 0, sizeof platform.key_pressed);
@@ -1264,7 +1328,7 @@ i32 p_wait_events(void) {
do {
num_events = p_handle_events();
- sched_yield();
+ usleep(0);
} while (num_events == 0);
return num_events;
@@ -1279,7 +1343,10 @@ void p_render_frame(void) {
}
void p_clipboard_write(i64 size, c8 *data) {
- assert(size <= MAX_CLIPBOARD_SIZE);
+ if (size > MAX_CLIPBOARD_SIZE) {
+ fprintf(stderr, "%s:%d, %s: Size is too big %lld.\n", __FILE__, __LINE__, __FUNCTION__, size);
+ return;
+ }
XSetSelectionOwner(_display, _clipboard, _window, CurrentTime);
@@ -1300,14 +1367,14 @@ void p_clipboard_write(i64 size, c8 *data) {
void p_handle_audio(i64 time_elapsed) {
(void) time_elapsed;
- assert(0);
+ // TODO
}
void p_queue_sound(i64 delay, i64 num_samples, f32 *samples) {
(void) delay;
(void) num_samples;
(void) samples;
- assert(0);
+ // TODO
}
#endif // defined(__linux__)