summaryrefslogtreecommitdiff
path: root/reduced_system_layer.c
diff options
context:
space:
mode:
Diffstat (limited to 'reduced_system_layer.c')
-rwxr-xr-xreduced_system_layer.c189
1 files changed, 87 insertions, 102 deletions
diff --git a/reduced_system_layer.c b/reduced_system_layer.c
index c272711..30fb48b 100755
--- a/reduced_system_layer.c
+++ b/reduced_system_layer.c
@@ -77,7 +77,7 @@
#/
#/ ----------------------------------------------------------------
#/
-#/ (C) 2024 Mitya Selivanov <guattari.tech>
+#/ (C) 2025 Mitya Selivanov <guattari.tech>
#/
#/ ================================================================
#/
@@ -163,7 +163,7 @@ enum {
AUDIO_NUM_CHANNELS = 2,
AUDIO_SAMPLE_RATE = 44100,
- AUDIO_AVAIL_MIN = 256,
+ AUDIO_AVAIL_MIN = 512,
MAX_NUM_AUDIO_FRAMES = 10 * AUDIO_SAMPLE_RATE * AUDIO_NUM_CHANNELS, // 10 seconds
@@ -399,6 +399,10 @@ f64 atan2(f64 y, f64 x);
#ifndef NULL
#define NULL ((void *) 0)
#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
#endif
#ifdef __cplusplus
@@ -1555,17 +1559,22 @@ void p_clipboard_write(i64 size, c8 *data) {
// ================================================================
//
-// Web canvas
+// WebAssembly
//
// ================================================================
#ifdef __wasm__
-static u32 _buffer[MAX_NUM_PIXELS] = {0};
-static Input_Key _input[MAX_INPUT_SIZE] = {0};
-static i32 _num_events = 0;
-static i32 _input_size = 0;
-static b8 _key_pressed[MAX_NUM_KEYS] = {0};
+static u32 _buffer[MAX_NUM_PIXELS] = {0};
+static Input_Key _input[MAX_INPUT_SIZE] = {0};
+static i32 _num_events = 0;
+static i32 _input_size = 0;
+static b8 _key_pressed[MAX_NUM_KEYS] = {0};
+static b8 _wait_events = 0;
+i64 _sound_position = 0;
+i64 _sound_read = 0;
+f32 _sound_ring[MAX_NUM_AUDIO_FRAMES] = {0};
+f32 _sound_buffer[MAX_NUM_AUDIO_FRAMES] = {0};
i32 p_time_impl(void);
@@ -1573,10 +1582,17 @@ i64 p_time(void) {
return p_time_impl();
}
-void p_sleep_for_impl(i32 duration);
-
void p_sleep_for(i64 duration) {
- p_sleep_for_impl((i32) duration);
+ // TODO
+}
+
+void p_init(void) {
+ ++_num_events;
+ platform.pixels = _buffer;
+ platform.input = _input;
+ platform.done = 1;
+ _sound_position = AUDIO_AVAIL_MIN % MAX_NUM_AUDIO_FRAMES;
+ _sound_read = 0;
}
i32 p_handle_events(void) {
@@ -1591,46 +1607,58 @@ i32 p_handle_events(void) {
return n;
}
-i32 p_wait_events_impl(void);
-
i32 p_wait_events(void) {
- p_wait_events_impl();
+ _wait_events = 1;
+
return p_handle_events();
}
-void p_render_frame_impl(void);
+void p_render_frame(void) { }
-void p_render_frame(void) {
- // Make canvas pixels opaque.
- i64 size = platform.frame_width * platform.frame_height;
- for (i64 i = 0; i < size; ++i)
- platform.pixels[i] |= 0xff000000;
+void p_handle_audio(i64 samples_elapsed) {
+ if (samples_elapsed <= 0)
+ return;
- p_render_frame_impl();
+ _sound_position = (_sound_position + samples_elapsed * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES;
}
- __attribute__((export_name("js_memset"))) void js_memset(void *dst, i32 val, u32 num) {
- if (dst == NULL) return;
- for (u32 i = 0; i < num; ++i)
- ((u8 *) dst)[i] = (u8) val;
-}
+void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
+ if (frames == NULL)
+ return;
+
+ if (delay_in_samples < 0) {
+ frames += -delay_in_samples * AUDIO_NUM_CHANNELS;
+ num_samples -= delay_in_samples;
+ delay_in_samples = 0;
+ }
+
+ if (num_samples <= 0)
+ return;
+
+ i64 num_frames = num_samples * AUDIO_NUM_CHANNELS;
+ if (num_frames > MAX_NUM_AUDIO_FRAMES)
+ return;
+
+ i64 begin = (_sound_position + delay_in_samples * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES;
+
+ if (num_frames <= MAX_NUM_AUDIO_FRAMES - begin)
+ for (i64 i = 0; i < num_frames; ++i)
+ _sound_ring[begin + i] += frames[i];
+ else {
+ i64 part_one = MAX_NUM_AUDIO_FRAMES - begin;
+ i64 part_two = num_frames - part_one;
-__attribute__((export_name("js_memcpy"))) void js_memcpy(void *dst, void const *src, u32 num) {
- if (dst == NULL || src == NULL) return;
- for (u32 i = 0; i < num; ++i)
- ((u8 *) dst)[i] = ((u8 const *) src)[i];
+ for (i64 i = 0; i < part_one; ++i)
+ _sound_ring[begin + i] += frames[i];
+ for (i64 i = 0; i < part_two; ++i)
+ _sound_ring[i] += frames[part_one + i];
+ }
}
__attribute__((export_name("js_main"))) void js_main(c8 *href) {
main(1, &href);
}
-__attribute__((export_name("js_init"))) void js_init(void) {
- platform.pixels = _buffer;
- platform.input = _input;
- platform.done = 1;
-}
-
__attribute__((export_name("js_title"))) void *js_title(void) {
return platform.title;
}
@@ -1639,7 +1667,7 @@ __attribute__((export_name("js_pixels"))) void *js_pixels(void) {
return platform.pixels;
}
-__attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 frame_height) {
+__attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 frame_height, i32 num_samples) {
if (platform.frame_width != frame_width || platform.frame_height != frame_height) {
++_num_events;
platform.frame_width = frame_width;
@@ -1648,7 +1676,25 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram
platform.done = 0;
- update_and_render_frame();
+ if (_num_events > 0 || !_wait_events) {
+ _wait_events = 0;
+ update_and_render_frame();
+
+ // Make canvas pixels opaque.
+ i64 size = platform.frame_width * platform.frame_height;
+ for (i64 i = 0; i < size; ++i)
+ platform.pixels[i] |= 0xff000000;
+ }
+
+ // Convert interleaved frames to non-interleaved.
+ for (i64 j = 0; j < AUDIO_NUM_CHANNELS; ++j)
+ for (i64 i = 0; i < num_samples; ++i) {
+ i64 n = (_sound_read + i * AUDIO_NUM_CHANNELS + j) % MAX_NUM_AUDIO_FRAMES;
+ _sound_buffer[j * num_samples + i] = _sound_ring[n];
+ _sound_ring [n] = 0.f;
+ }
+
+ _sound_read = (_sound_read + num_samples * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES;
}
__attribute__((export_name("js_mousemove"))) void js_mousemove(i32 x, i32 y) {
@@ -1677,6 +1723,7 @@ __attribute__((export_name("js_mouseup"))) void js_mouseup(u32 buttons) {
}
__attribute__((export_name("js_keydown"))) void js_keydown(u32 key, u32 mod) {
+ // TODO
++_num_events;
_key_pressed[key] = 1;
platform.key_down[key] = 1;
@@ -1688,67 +1735,11 @@ __attribute__((export_name("js_keydown"))) void js_keydown(u32 key, u32 mod) {
}
__attribute__((export_name("js_keyup"))) void js_keyup(u32 key, u32 mod) {
+ // TODO
++_num_events;
platform.key_down[key] = 0;
}
-#endif // __wasm__
-
-// ================================================================
-//
-// Web audio
-//
-// ================================================================
-
-#ifdef __wasm__
-
-i64 _sound_position = 0;
-f32 _sound_ring[MAX_NUM_AUDIO_FRAMES] = {0};
-
-void p_handle_audio_impl(i32 samples_elapsed);
-
-void p_handle_audio(i64 samples_elapsed) {
- if (samples_elapsed <= 0)
- return;
-
- p_handle_audio_impl(samples_elapsed);
-
- _sound_position = (_sound_position + samples_elapsed * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES;
-}
-
-void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
- if (frames == NULL)
- return;
-
- if (delay_in_samples < 0) {
- frames += -delay_in_samples * AUDIO_NUM_CHANNELS;
- num_samples -= delay_in_samples;
- delay_in_samples = 0;
- }
-
- if (num_samples <= 0)
- return;
-
- i64 num_frames = num_samples * AUDIO_NUM_CHANNELS;
- if (num_frames > MAX_NUM_AUDIO_FRAMES)
- return;
-
- i64 begin = (_sound_position + AUDIO_AVAIL_MIN + delay_in_samples * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES;
-
- if (num_frames <= MAX_NUM_AUDIO_FRAMES - begin)
- for (i64 i = 0; i < num_frames; ++i)
- _sound_ring[begin + i] += frames[i];
- else {
- i64 part_one = MAX_NUM_AUDIO_FRAMES - begin;
- i64 part_two = num_frames - part_one;
-
- for (i64 i = 0; i < part_one; ++i)
- _sound_ring[begin + i] += frames[i];
- for (i64 i = 0; i < part_two; ++i)
- _sound_ring[i] += frames[part_one + i];
- }
-}
-
__attribute__((export_name("js_sample_rate"))) f64 js_sample_rate(void) {
return (f64) AUDIO_SAMPLE_RATE;
}
@@ -1762,13 +1753,7 @@ __attribute__((export_name("js_max_num_audio_frames"))) i32 js_max_num_audio_fra
}
__attribute__((export_name("js_sound_buffer"))) void *js_sound_buffer(void) {
- return _sound_ring;
-}
-
-__attribute__((export_name("js_sound_sync"))) void js_sound_sync(void) {
- _sound_position = 0;
- for (i64 i = 0; i < MAX_NUM_AUDIO_FRAMES; ++i)
- _sound_ring[i] = 0.f;
+ return _sound_buffer;
}
#endif // __wasm__