summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild_all.sh8
-rw-r--r--examples/echo.c8
-rw-r--r--examples/game_of_life.c20
-rw-r--r--examples/graph.c6
-rw-r--r--examples/julia_set.c26
-rw-r--r--examples/labyrinth.c20
-rw-r--r--examples/particles.c12
-rw-r--r--examples/pixels.c44
-rw-r--r--examples/proto.c5
-rw-r--r--examples/screenshot.c8
-rw-r--r--examples/sinewave.c30
-rw-r--r--examples/ui.c6
-rw-r--r--index.htm43
-rw-r--r--reduced_system_layer.c380
-rwxr-xr-xstackless_coroutine.c68
15 files changed, 336 insertions, 348 deletions
diff --git a/build_all.sh b/build_all.sh
index eb44f68..d5c2305 100755
--- a/build_all.sh
+++ b/build_all.sh
@@ -32,12 +32,8 @@ mkdir -p bin/web
# gcc $FLAGS_X11 -o ./bin/x11/graph ./examples/graph.c
# gcc $FLAGS_X11 -o ./bin/x11/julia_set ./examples/julia_set.c
-# gcc $FLAGS_X11 -o ./bin/x11/game_of_life ./examples/game_of_life.c
-# gcc $FLAGS_X11 -o ./bin/x11/labyrinth ./examples/labyrinth.c
# gcc $FLAGS_X11 -o ./bin/x11/sinewave ./examples/sinewave.c
-# gcc $FLAGS_X11 -o ./bin/x11/pixels ./examples/pixels.c
# gcc $FLAGS_X11 -o ./bin/x11/ui ./examples/ui.c
-# gcc $FLAGS_X11 -o ./bin/x11/proto ./examples/proto.c
# gcc $FLAGS_X11 -o ./bin/x11/particles ./examples/particles.c
# gcc $FLAGS_X11 -o ./bin/x11/echo ./examples/echo.c
@@ -45,9 +41,5 @@ gcc $FLAGS_X11 -o ./bin/x11/screenshot ./examples/screenshot.c
# clang $FLAGS_WEB -o ./bin/web/graph.wasm ./examples/graph.c
# clang $FLAGS_WEB -o ./bin/web/julia_set.wasm ./examples/julia_set.c
-# clang $FLAGS_WEB -o ./bin/web/game_of_life.wasm ./examples/game_of_life.c
-# clang $FLAGS_WEB -o ./bin/web/labyrinth.wasm ./examples/labyrinth.c
# clang $FLAGS_WEB -o ./bin/web/sinewave.wasm ./examples/sinewave.c
-# clang $FLAGS_WEB -o ./bin/web/pixels.wasm ./examples/pixels.c
# clang $FLAGS_WEB -o ./bin/web/ui.wasm ./examples/ui.c
-# clang $FLAGS_WEB -o ./bin/web/proto.wasm ./examples/proto.c
diff --git a/examples/echo.c b/examples/echo.c
index 10f3cd5..1671be7 100644
--- a/examples/echo.c
+++ b/examples/echo.c
@@ -41,7 +41,7 @@ i32 main(i32 argc, c8 **argv) {
printf("Receiving UDP messages on port %d\n\n", PORT);
for (;;) {
- i64 n = p_recv(
+ i64 n = network_recv(
0,
(IP_Address) {
.protocol = IPv4_UDP,
@@ -61,7 +61,7 @@ i32 main(i32 argc, c8 **argv) {
buf[n] = '\0';
printf("%s\n", buf);
} else
- p_sleep_for(10);
+ suspend_thread_for_milliseconds(10);
}
} break;
@@ -75,7 +75,7 @@ i32 main(i32 argc, c8 **argv) {
if (strcmp(buf, "!quit") == 0)
break;
- p_send(
+ network_send(
0,
(IP_Address) {
.protocol = IPv4_UDP,
@@ -94,6 +94,6 @@ i32 main(i32 argc, c8 **argv) {
default:;
}
- p_cleanup();
+ shutdown_all_systems();
return 0;
}
diff --git a/examples/game_of_life.c b/examples/game_of_life.c
deleted file mode 100644
index d95fb9e..0000000
--- a/examples/game_of_life.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "../reduced_system_layer.c"
-
-void update_and_render_frame(void) {
- p_handle_events();
- p_render_frame();
- p_sleep_for(0);
-}
-
-i32 main(i32 argc, c8 **argv) {
- (void) argc;
- (void) argv;
-
- g_platform = (Platform) {
- .title = "Conway's Game of Life",
- };
-
- p_event_loop();
-
- return 0;
-}
diff --git a/examples/graph.c b/examples/graph.c
index f196d3d..c1c84f2 100644
--- a/examples/graph.c
+++ b/examples/graph.c
@@ -371,7 +371,7 @@ i64 drag_x0 = 0;
i64 drag_y0 = 0;
void update_and_render_frame(void) {
- p_wait_events();
+ wait_main_window_events();
// Input events
@@ -520,7 +520,7 @@ void update_and_render_frame(void) {
draw_graph();
- p_render_frame();
+ render_main_window_frame();
}
i32 main(i32 argc, c8 **argv) {
@@ -539,7 +539,7 @@ i32 main(i32 argc, c8 **argv) {
add_edge(0, 2);
add_edge(1, 2);
- p_event_loop();
+ run_main_window_event_loop();
return 0;
}
diff --git a/examples/julia_set.c b/examples/julia_set.c
index 288dac2..81aa02c 100644
--- a/examples/julia_set.c
+++ b/examples/julia_set.c
@@ -11,6 +11,13 @@ f64 radius = 2.;
i64 limit = 1024;
i64 time_0;
+void inc_f64(f64 *x, i8 s) {
+ u64 *u = (u64 *) x;
+ if (((*u >> 52) & 2047) == 2047)
+ return;
+ *u += *x > 0 ? s : -s;
+}
+
void apply_scale(f64 delta) {
while (delta > SCALE_LIMIT) {
apply_scale(SCALE_LIMIT);
@@ -22,21 +29,24 @@ void apply_scale(f64 delta) {
}
f64 ds = view_s * delta * .1;
- if (view_s + ds < 1e-12)
+ if (view_s + ds <= 0.0)
return;
f64 dx = (g_platform.cursor_x * 1. - g_platform.real_width * .5);
f64 dy = (g_platform.cursor_y * 1. - g_platform.real_height * .5);
view_x -= view_s * dx;
view_y -= view_s * dy;
- view_s += ds;
+ if (view_s == view_s + ds)
+ inc_f64(&view_s, ds > 0 ? 1 : -1);
+ else
+ view_s += ds;
view_x += view_s * dx;
view_y += view_s * dy;
}
void update_and_render_frame(void) {
- i32 num_events = p_handle_events();
+ i32 num_events = handle_main_window_events();
- i64 time_elapsed = p_time() - time_0;
+ i64 time_elapsed = current_utc_time_in_milliseconds() - time_0;
time_0 += time_elapsed;
b8 left = g_platform.key_down[KEY_LEFT];
@@ -45,7 +55,7 @@ void update_and_render_frame(void) {
b8 down = g_platform.key_down[KEY_DOWN];
if (!left && !right && !up && !down && num_events == 0) {
- p_sleep_for(1);
+ suspend_thread_for_milliseconds(1);
return;
}
@@ -98,7 +108,7 @@ void update_and_render_frame(void) {
g_platform.pixels[j * g_platform.frame_width + i] = vec4_from_vec3_f32(rgb_f32_from_u32(c), 1.f);
}
- p_render_frame();
+ render_main_window_frame();
}
i32 main(i32 argc, c8 **argv) {
@@ -109,9 +119,9 @@ i32 main(i32 argc, c8 **argv) {
.title = "Julia Set",
};
- time_0 = p_time();
+ time_0 = current_utc_time_in_milliseconds();
- p_event_loop();
+ run_main_window_event_loop();
return 0;
}
diff --git a/examples/labyrinth.c b/examples/labyrinth.c
deleted file mode 100644
index 01af7c6..0000000
--- a/examples/labyrinth.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "../reduced_system_layer.c"
-
-void update_and_render_frame(void) {
- p_handle_events();
- p_render_frame();
- p_sleep_for(0);
-}
-
-i32 main(i32 argc, c8 **argv) {
- (void) argc;
- (void) argv;
-
- g_platform = (Platform) {
- .title = "Labyrinth",
- };
-
- p_event_loop();
-
- return 0;
-}
diff --git a/examples/particles.c b/examples/particles.c
index 894fee0..753698d 100644
--- a/examples/particles.c
+++ b/examples/particles.c
@@ -22,9 +22,9 @@ vec4_f32 background = { .0f, .0f, .08f, 1.f };
i64 time_0;
void update_and_render_frame(void) {
- p_handle_events();
+ handle_main_window_events();
- i64 time_elapsed = p_time() - time_0;
+ i64 time_elapsed = current_utc_time_in_milliseconds() - time_0;
time_0 += time_elapsed;
if (g_platform.key_pressed[BUTTON_LEFT]) {
@@ -109,7 +109,7 @@ void update_and_render_frame(void) {
}
}
- p_render_frame();
+ render_main_window_frame();
}
i32 main(i32 argc, c8 **argv) {
@@ -122,11 +122,11 @@ i32 main(i32 argc, c8 **argv) {
.exact_resolution = 1,
};
- time_0 = p_time();
+ time_0 = current_utc_time_in_milliseconds();
- srand(p_time());
+ srand(time_0);
- p_event_loop();
+ run_main_window_event_loop();
return 0;
}
diff --git a/examples/pixels.c b/examples/pixels.c
deleted file mode 100644
index 0579361..0000000
--- a/examples/pixels.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#define MIN_PIXEL_SIZE 16
-#include "../graphics.c"
-
-i64 t = 0;
-f64 x = 100.;
-f64 y = 100.;
-
-void update_and_render_frame(void) {
- p_handle_events();
-
- i64 time_elapsed = p_time() - t;
- t += time_elapsed;
-
- if (g_platform.key_down[KEY_LEFT]) x -= .01 * time_elapsed;
- if (g_platform.key_down[KEY_RIGHT]) x += .01 * time_elapsed;
- if (g_platform.key_down[KEY_UP]) y -= .01 * time_elapsed;
- if (g_platform.key_down[KEY_DOWN]) y += .01 * time_elapsed;
-
- Brush white = RGB(1.f, 1.f, 1.f);
- Brush black = RGB(0.f, 0.f, 0.f);
-
- white.quick = 1;
-
- fill_rectangle(white, 0., 0., g_platform.real_width, g_platform.real_height);
- fill_rectangle(black, x, y, 40., 40.);
-
- p_render_frame();
- p_sleep_for(0);
-}
-
-i32 main(i32 argc, c8 **argv) {
- (void) argc;
- (void) argv;
-
- g_platform = (Platform) {
- .title = "Pixels",
- };
-
- t = p_time();
-
- p_event_loop();
-
- return 0;
-}
diff --git a/examples/proto.c b/examples/proto.c
deleted file mode 100644
index dbb64a8..0000000
--- a/examples/proto.c
+++ /dev/null
@@ -1,5 +0,0 @@
-int main(int argc, char **argv) {
- (void) argc;
- (void) argv;
- return 0;
-}
diff --git a/examples/screenshot.c b/examples/screenshot.c
index 33bbe99..c3c0ebd 100644
--- a/examples/screenshot.c
+++ b/examples/screenshot.c
@@ -6,11 +6,11 @@ b8 has_screenshot = 0;
void update_and_render_frame(void) {
if (!has_screenshot) {
- p_screenshot(MAX_NUM_PIXELS, &width, &height, g_platform.sketch);
+ take_screenshot(MAX_NUM_PIXELS, &width, &height, g_platform.sketch);
has_screenshot = 1;
}
- p_handle_events();
+ handle_main_window_events();
draw_pixels((Brush) { .quick = 1, }, 0, 0, g_platform.real_width, g_platform.real_height, (Pixel_Buffer) {
.width = width,
@@ -19,7 +19,7 @@ void update_and_render_frame(void) {
.pixels = g_platform.sketch,
});
- p_render_frame();
+ render_main_window_frame();
}
i32 main(i32 argc, c8 **argv) {
@@ -30,7 +30,7 @@ i32 main(i32 argc, c8 **argv) {
.title = "Screenshot",
};
- p_event_loop();
+ run_main_window_event_loop();
return 0;
}
diff --git a/examples/sinewave.c b/examples/sinewave.c
index f2b2580..0c33803 100644
--- a/examples/sinewave.c
+++ b/examples/sinewave.c
@@ -1,9 +1,6 @@
#include "../graphics.c"
-i64 time_0 = 0;
-i64 audio_samples = 0;
-
-f32 frames[SOUND_SAMPLE_RATE * NUM_SOUND_CHANNELS] = {0};
+f32 frames[PRIMARY_SOUND_SAMPLE_RATE * NUM_PRIMARY_SOUND_CHANNELS] = {0};
b8 ui_button(f64 x, f64 y, f64 width, f64 height) {
b8 has_cursor = g_platform.cursor_x >= x && g_platform.cursor_x < x + width &&
@@ -22,21 +19,18 @@ b8 ui_button(f64 x, f64 y, f64 width, f64 height) {
}
void update_and_render_frame(void) {
- i32 num_events = p_handle_events();
+ i32 num_events = handle_main_window_events();
if (num_events > 0) {
fill_rectangle(RGB(.1f, .1f, .1f), 0, 0, g_platform.frame_width, g_platform.frame_height);
if (ui_button(100, 100, 200, 200))
- p_queue_sound(0, SOUND_SAMPLE_RATE, frames);
+ queue_primary_sound(0, PRIMARY_SOUND_SAMPLE_RATE, frames);
}
- i64 samples_elapsed = ((p_time() - time_0) * SOUND_SAMPLE_RATE) / 1000 - audio_samples;
- audio_samples += samples_elapsed;
-
- p_handle_sound();
- p_render_frame();
- p_sleep_for(0);
+ handle_primary_sound();
+ render_main_window_frame();
+ suspend_thread_for_milliseconds(0);
}
i32 main(i32 argc, c8 **argv) {
@@ -44,14 +38,14 @@ i32 main(i32 argc, c8 **argv) {
(void) argv;
g_platform = (Platform) {
- .title = "Sine Wave",
- .graceful_exit = 1,
+ .title = "Sine Wave",
+ .graceful_shutdown = 1,
};
f64 frequency = 440.;
- for (i64 i = 0; i < SOUND_SAMPLE_RATE; ++i) {
- f64 t = ((f64) i) / SOUND_SAMPLE_RATE;
+ for (i64 i = 0; i < PRIMARY_SOUND_SAMPLE_RATE; ++i) {
+ f64 t = ((f64) i) / PRIMARY_SOUND_SAMPLE_RATE;
f64 x = sin(t * (M_PI * 2.) * frequency);
if (t < .005)
x *= t / .005;
@@ -61,8 +55,6 @@ i32 main(i32 argc, c8 **argv) {
frames[i * 2 + 1] = (f32) (x * .5);
}
- time_0 = p_time();
-
- p_event_loop();
+ run_main_window_event_loop();
return 0;
}
diff --git a/examples/ui.c b/examples/ui.c
index 022a463..a3ca476 100644
--- a/examples/ui.c
+++ b/examples/ui.c
@@ -12,7 +12,7 @@ i64 cursor = 0;
i64 selection = 0;
void update_and_render_frame(void) {
- p_wait_events();
+ wait_main_window_events();
Brush background = RGB(.2f, .1f, 0.f);
background.quick = 1;
@@ -226,7 +226,7 @@ void update_and_render_frame(void) {
draw_text_area((Brush) { .color = color, }, x0, y0, w, h, 10., 10., text_len, text);
draw_text_cursor((Brush) { .xor_color = 1, .color = { 1.f, 1.f, 1.f, 1.f }, }, x0, y0, w, h, 10., 10., cursor, selection, text_len, text);
- p_render_frame();
+ render_main_window_frame();
}
i32 main(i32 argc, c8 **argv) {
@@ -237,7 +237,7 @@ i32 main(i32 argc, c8 **argv) {
.title = "UI",
};
- p_event_loop();
+ run_main_window_event_loop();
return 0;
}
diff --git a/index.htm b/index.htm
index 5e0dd3c..2e3ebe8 100644
--- a/index.htm
+++ b/index.htm
@@ -34,7 +34,7 @@
fd_seek : () => { throw new Error("Unexpected fd_seek call"); },
},
env : {
- p_clipboard_write_text_impl : (size, text) => {
+ write_clipboard_text_impl : (size, text) => {
let text_buffer = new ArrayBuffer(size);
new Uint8Array(text_buffer).set(new Uint8Array(this.memory_buffer, text, size));
@@ -43,7 +43,7 @@
text_buffer : text_buffer,
});
},
- p_time : () => { return BigInt(Date.now()); },
+ current_time_in_milliseconds : () => { return BigInt(Date.now()); },
floor : Math.floor,
ceil : Math.ceil,
@@ -275,25 +275,26 @@
wasm,
{
env : {
- p_clipboard_write_impl : () => {},
- p_time : () => {},
- floor : () => {},
- ceil : () => {},
- trunc : () => {},
- sqrt : () => {},
- cbrt : () => {},
- pow : () => {},
- log : () => {},
- log2 : () => {},
- log10 : () => {},
- exp : () => {},
- sin : () => {},
- cos : () => {},
- tan : () => {},
- asin : () => {},
- acos : () => {},
- atan : () => {},
- atan2 : () => {},
+ write_clipboard_impl : () => {},
+ current_time_in_milliseconds : () => {},
+
+ floor : () => {},
+ ceil : () => {},
+ trunc : () => {},
+ sqrt : () => {},
+ cbrt : () => {},
+ pow : () => {},
+ log : () => {},
+ log2 : () => {},
+ log10 : () => {},
+ exp : () => {},
+ sin : () => {},
+ cos : () => {},
+ tan : () => {},
+ asin : () => {},
+ acos : () => {},
+ atan : () => {},
+ atan2 : () => {},
},
}
);
diff --git a/reduced_system_layer.c b/reduced_system_layer.c
index 38b80dd..fff4f44 100644
--- a/reduced_system_layer.c
+++ b/reduced_system_layer.c
@@ -23,6 +23,18 @@
// - Optimized to use in a single source file.
// Installation process? Ctrl+C, Ctrl+V, done.
//
+// STYLE CONVENTIONS
+//
+// - Capitalized_Snake_Case - Type name.
+// - snake_case - Non-type name.
+// - UPPER_SNAKE_CASE - Macro or constant.
+// - g_ prefix - Global variable name.
+//
+// Most procedures have long and descriptive names.
+// Some procedures have prefixes according to their domain.
+//
+// There may be exceptions if convenient.
+//
// ----------------------------------------------------------------
//
// To-Do list
@@ -62,10 +74,21 @@
// - Windows audio
// - Recording
// - Device selection
+// - Switching canvases - Web
// - Networking
// - Windows sockets
// - TCP
-// - Switching canvases - Web
+// - fetch - via libcurl on native platforms
+// - Cross-platform networking - UDP + TCP + WebSocket
+// Requires:
+// - [ ] Sockets - UDP, TCP
+// - [ ] HTTP client
+// - [ ] HTTP server
+// - [ ] Web sockets
+// - [ ] Key exchange
+// - [ ] Cipher suite (Lattice-based?)
+// - [ ] TLS
+// - [ ] Web sockets over TLS
// - Long term
// - dlopen - load libraries conditionally
// - X11
@@ -79,14 +102,11 @@
// - Process
// - Shared memory
// - Shared mutex
-// - Stackless coroutines
// - Big integer
// - Mersenne Twister 64
// - Arithmetic coding
// - Threads - https://nachtimwald.com/2019/04/05/cross-platform-thread-wrapper
-// - HTTP
// - Cryptography - https://github.com/jedisct1/supercop
-// - Web sockets
// - macOS support
// - Mobile devices support
//
@@ -101,6 +121,7 @@
// - Utility
// - UTF-8
// - Testing
+// - Stackless coroutines
// - Graphics
// - Font
// - Adaptive resolution
@@ -197,12 +218,18 @@ i32 main(i32 argc, c8 **argv);
#define NO_X11 0
#endif
+#ifndef STATIC_MEMORY_BUFFER_SIZE
+#define STATIC_MEMORY_BUFFER_SIZE (10 * 1024 * 1024)
+#endif
+
+// ----------------------------------------------------------------
+// TEMP: Static buffers.
+
#ifndef MAX_NUM_PIXELS
#define MAX_NUM_PIXELS (4 * 1024 * 1024)
#endif
#ifndef MAX_INPUT_SIZE
-// How many input events can be buffered during one frame.
#define MAX_INPUT_SIZE 256
#endif
@@ -222,6 +249,16 @@ i32 main(i32 argc, c8 **argv);
#define MAX_NUM_KEYS 512
#endif
+#ifndef MAX_NUM_PRIMARY_SOUND_FRAMES
+#define MAX_NUM_PRIMARY_SOUND_FRAMES (4 * 2 * 44100)
+#endif
+
+#ifndef DROP_FILES_BUFFER_SIZE
+#define DROP_FILES_BUFFER_SIZE (8 * 1024 * 1024)
+#endif
+
+// ----------------------------------------------------------------
+
#ifndef MIN_PIXEL_SIZE
#define MIN_PIXEL_SIZE (1.0)
#endif
@@ -238,19 +275,19 @@ i32 main(i32 argc, c8 **argv);
#define PIXEL_SIZE_DELTA (0.05)
#endif
-#ifndef MIN_FRAME_DURATION
// The pixel size will decrease when the frame duration is lower.
+#ifndef MIN_FRAME_DURATION
#define MIN_FRAME_DURATION 17
#endif
-#ifndef MAX_FRAME_DURATION
// The pixel size will increase when the frame duration is higher.
-#define MAX_FRAME_DURATION 34
+#ifndef MAX_FRAME_DURATION
+#define MAX_FRAME_DURATION 32
#endif
-#ifndef FRAME_DURATION_HARD_LIMIT
// The pixel size value will reset if the frame duration is higher.
-#define FRAME_DURATION_HARD_LIMIT 400
+#ifndef FRAME_DURATION_HARD_LIMIT
+#define FRAME_DURATION_HARD_LIMIT 200
#endif
#ifndef NUM_FRAMES_AVERAGED
@@ -258,33 +295,19 @@ i32 main(i32 argc, c8 **argv);
#endif
#ifndef AVERAGE_FRAME_BIAS
-#if defined(__wasm__)
-// NOTE: Web frame rate is quite unstable, so
-// we always pick the longest frame.
-#define AVERAGE_FRAME_BIAS (0.00)
-#else
#define AVERAGE_FRAME_BIAS (0.02)
#endif
-#endif
-
-#ifndef NUM_SOUND_CHANNELS
-#define NUM_SOUND_CHANNELS 2
-#endif
-#ifndef SOUND_SAMPLE_RATE
-#define SOUND_SAMPLE_RATE 44100
+#ifndef NUM_PRIMARY_SOUND_CHANNELS
+#define NUM_PRIMARY_SOUND_CHANNELS 2
#endif
-#ifndef SOUND_AVAIL_MIN
-#define SOUND_AVAIL_MIN 512
+#ifndef PRIMARY_SOUND_SAMPLE_RATE
+#define PRIMARY_SOUND_SAMPLE_RATE 44100
#endif
-#ifndef MAX_NUM_SOUND_FRAMES
-#define MAX_NUM_SOUND_FRAMES (4 * SOUND_SAMPLE_RATE * NUM_SOUND_CHANNELS)
-#endif
-
-#ifndef DROP_FILES_BUFFER_SIZE
-#define DROP_FILES_BUFFER_SIZE (8 * 1024 * 1024)
+#ifndef PRIMARY_SOUND_AVAIL_MIN
+#define PRIMARY_SOUND_AVAIL_MIN 512
#endif
#ifndef MOUSE_WHEEL_FACTOR
@@ -570,7 +593,7 @@ typedef struct {
i32 frame_height;
f64 pixel_size;
b8 exact_resolution;
- b8 graceful_exit;
+ b8 graceful_shutdown;
b8 done;
b8 has_focus;
@@ -603,6 +626,9 @@ typedef struct {
f32 clipboard_sound [MAX_CLIPBOARD_SIZE];
b8 key_down [MAX_NUM_KEYS];
b8 key_pressed [MAX_NUM_KEYS];
+
+ i64 memory_buffer_size;
+ u8 *memory_buffer;
} Platform;
// UTF-8
@@ -612,35 +638,41 @@ UTF8_Char utf8_read (i64 len, c8 *s);
i8 utf8_write(c32 c, c8 *buffer);
// Time and sleep
-i64 p_time(void);
-void p_yield(void);
-void p_sleep_for(i64 duration);
+i64 current_utc_time_in_milliseconds(void);
+void yield_thread_execution(void);
+void suspend_thread_for_milliseconds(i64 duration);
// Window
-void p_init(void);
-void p_cleanup(void);
-i32 p_handle_events(void);
-i32 p_wait_events(void);
-void p_render_frame(void);
+void init_main_window(void);
+i32 handle_main_window_events(void);
+i32 wait_main_window_events(void);
+void render_main_window_frame(void);
// Convenient helper procedure for the event loop
-void p_event_loop(void);
+void run_main_window_event_loop(void);
// Clipboard
-void p_clipboard_write_text(i64 size, c8 *data);
-void p_clipboard_write_image(i64 width, i64 heiht, vec4_f32 *pixels);
-void p_clipboard_write_sound(i8 num_channels, i64 num_samples, f32 *frames);
+void write_clipboard_text(i64 size, c8 *data);
+void write_clipboard_image(i64 width, i64 heiht, vec4_f32 *pixels);
+void write_clipboard_sound(i8 num_channels, i64 num_samples, f32 *frames);
// Take a screenshot
-void p_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels);
+void take_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels);
// Sound
-void p_handle_sound(void);
-void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames);
+void handle_primary_sound(void);
+void queue_primary_sound(i64 delay_in_samples, i64 num_samples, f32 *frames);
+
+// Networking
+i64 network_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address);
+i64 network_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port);
+
+// NOTE: This will shutdown main window, networking and audio.
+// If g_platform.graceful_shutdown is 0, this does nothing.
+void shutdown_all_systems(void);
-// UDP sockets
-i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address);
-i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port);
+// Memory
+void *seldom_memory_allocate(i64 size, i64 alignment, i64 previous_size, void *previous_data);
#ifdef REDUCED_SYSTEM_LAYER_HEADER
extern Platform g_platform;
@@ -669,23 +701,23 @@ Platform g_platform = {0};
static i64 _sound_clock_time = 0;
static i64 _sound_clock_carry = 0;
static i64 _sound_position = 0;
-static i64 _frame_index = 0;
+static i64 _frame_index = 0;
-static f32 _sound_ring [MAX_NUM_SOUND_FRAMES] = {0};
+static f32 _sound_ring [MAX_NUM_PRIMARY_SOUND_FRAMES] = {0};
static u8 _drop_files_buffer [DROP_FILES_BUFFER_SIZE] = {0};
-static i64 _frame_duration [NUM_FRAMES_AVERAGED] = {0};
+static i64 _frame_duration [NUM_FRAMES_AVERAGED] = {0};
-void p_event_loop(void) {
- p_init();
+void run_main_window_event_loop(void) {
+ init_main_window();
#if !defined(__wasm__)
while (!g_platform.done) update_and_render_frame();
- p_cleanup();
+ shutdown_all_systems();
#endif
}
// ================================================================
//
-// Utilities
+// Log
//
// ================================================================
@@ -702,6 +734,45 @@ void p_event_loop(void) {
} while (0)
#endif
+// ================================================================
+//
+// Seldom memory allocator
+//
+// ================================================================
+
+typedef struct {
+ i64 offset;
+ i64 size;
+} Memory_Slot_;
+
+static u8 memory_buffer_[STATIC_MEMORY_BUFFER_SIZE] = {0};
+
+static i64 num_memory_slots_(void) {
+ return *(i64 *) &g_platform.memory_buffer[g_platform.memory_buffer_size - 8];
+}
+
+void *seldom_memory_allocate(i64 size, i64 alignment, i64 previous_size, void *previous_data) {
+ if (g_platform.memory_buffer_size < 0)
+ LOG_ERROR("Invalid memory buffer size.");
+ if (g_platform.memory_buffer == NULL && g_platform.memory_buffer_size > 0)
+ LOG_ERROR("Invalid memory buffer.");
+
+ if (g_platform.memory_buffer == NULL || g_platform.memory_buffer_size <= 0) {
+ g_platform.memory_buffer_size = sizeof memory_buffer_;
+ g_platform.memory_buffer = memory_buffer_;
+ }
+
+ // TODO
+ LOG_ERROR("Not implemented.");
+ return NULL;
+}
+
+// ================================================================
+//
+// Utilities
+//
+// ================================================================
+
i8 utf8_size(c32 c) {
if ((c & 0x00007f) == c) return 1;
if ((c & 0x0007ff) == c) return 2;
@@ -825,13 +896,13 @@ static i64 average_frame_duration_(i64 duration) {
static i64 sound_samples_elapsed_(void) {
if (_sound_clock_time == 0) {
- _sound_clock_time = p_time();
+ _sound_clock_time = current_utc_time_in_milliseconds();
_sound_clock_carry = 0;
return 0;
}
- i64 time_elapsed = p_time() - _sound_clock_time;
- i64 delta = time_elapsed * SOUND_SAMPLE_RATE + _sound_clock_carry;
+ i64 time_elapsed = current_utc_time_in_milliseconds() - _sound_clock_time;
+ i64 delta = time_elapsed * PRIMARY_SOUND_SAMPLE_RATE + _sound_clock_carry;
i64 num_samples = delta / 1000;
_sound_clock_time += time_elapsed;
@@ -922,12 +993,11 @@ static void drop_files_empty_data_after_(i64 index) {
return;
}
- for (i64 i = index + 1; i < g_platform.num_drop_files; ++i) {
+ for (i64 i = index + 1; i < g_platform.num_drop_files; ++i)
if (g_platform.drop_files[i].data_size != 0) {
LOG_ERROR("Sanity");
g_platform.drop_files[i].data_size = 0;
}
- }
}
static void drop_files_set_name_(i64 index, i64 name_len, c8 *name) {
@@ -1032,17 +1102,17 @@ static void pixel_size_calubrate_(i64 current_frame_duration) {
#include <sched.h>
#include <unistd.h>
-i64 p_time(void) {
+i64 current_utc_time_in_milliseconds(void) {
struct timespec t;
timespec_get(&t, TIME_UTC);
- return 1000 * t.tv_sec + t.tv_nsec / 1000000;
+ return 1000ll * t.tv_sec + t.tv_nsec / 1000000ll;
}
-void p_yield(void) {
+void yield_thread_execution(void) {
sched_yield();
}
-void p_sleep_for(i64 duration) {
+void suspend_thread_for_milliseconds(i64 duration) {
if (duration == 0)
usleep(0);
if (duration <= 0)
@@ -1061,7 +1131,7 @@ void p_sleep_for(i64 duration) {
// ================================================================
//
-// UDP sockets
+// Networking
//
// ================================================================
@@ -1080,18 +1150,18 @@ typedef struct {
IP_Address address;
} Socket_Slot;
-static b8 _sockets_ready = 0;
+static b8 _network_ready = 0;
static Socket_Slot _sockets[MAX_NUM_SOCKETS] = {0};
-static void sockets_init(void) {
- if (_sockets_ready)
+static void network_init_(void) {
+ if (_network_ready)
return;
signal(SIGPIPE, SIG_IGN);
- _sockets_ready = 1;
+ _network_ready = 1;
}
-static void sockets_cleanup(void) {
+static void network_cleanup_(void) {
for (i64 i = 0; i < MAX_NUM_SOCKETS; ++i)
if (_sockets[i].ready) {
close(_sockets[i].socket);
@@ -1099,8 +1169,8 @@ static void sockets_cleanup(void) {
}
}
-static b8 sockets_open(u16 slot, IP_Address address, u16 *local_port) {
- sockets_init();
+static b8 network_open_(u16 slot, IP_Address address, u16 *local_port) {
+ network_init_();
b8 change_address =
!_sockets[slot].ready
@@ -1175,7 +1245,7 @@ static b8 sockets_open(u16 slot, IP_Address address, u16 *local_port) {
return 1;
}
-i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address) {
+i64 network_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address) {
if (slot >= MAX_NUM_SOCKETS) {
LOG_ERROR("Invalid slot %d.", (i32) (u32) slot);
return 0;
@@ -1186,7 +1256,7 @@ i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP
return 0;
}
- if (!sockets_open(slot, address, local_port))
+ if (!network_open_(slot, address, local_port))
return 0;
if (size <= 0)
return 0;
@@ -1238,7 +1308,7 @@ i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP
return received;
}
-i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
+i64 network_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
if (slot >= MAX_NUM_SOCKETS) {
LOG_ERROR("Invalid slot %d.", (i32) (u32) slot);
return 0;
@@ -1252,7 +1322,7 @@ i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
IP_Address local_address = address;
local_address.port = 0;
- if (!sockets_open(slot, local_address, local_port))
+ if (!network_open_(slot, local_address, local_port))
return 0;
if (size <= 0)
return 0;
@@ -1311,10 +1381,10 @@ i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
#include <alsa/asoundlib.h>
-static b8 _sound_ready = 0;
-static snd_pcm_t *_sound_out = NULL;
+static b8 _sound_ready = 0;
+static snd_pcm_t *_sound_out = NULL;
-static void sound_init(void) {
+static void sound_init_(void) {
if (_sound_ready)
return;
@@ -1343,11 +1413,11 @@ static void sound_init(void) {
if (s < 0)
LOG_ERROR("snd_pcm_hw_params_set_format failed: %s", snd_strerror(s));
- s = snd_pcm_hw_params_set_rate(_sound_out, hw_params, SOUND_SAMPLE_RATE, 0);
+ s = snd_pcm_hw_params_set_rate(_sound_out, hw_params, PRIMARY_SOUND_SAMPLE_RATE, 0);
if (s < 0)
LOG_ERROR("snd_pcm_hw_params_set_rate failed: %s", snd_strerror(s));
- s = snd_pcm_hw_params_set_channels(_sound_out, hw_params, NUM_SOUND_CHANNELS);
+ s = snd_pcm_hw_params_set_channels(_sound_out, hw_params, NUM_PRIMARY_SOUND_CHANNELS);
if (s < 0)
LOG_ERROR("snd_pcm_hw_params_set_channels failed: %s", snd_strerror(s));
@@ -1361,7 +1431,7 @@ static void sound_init(void) {
if (s < 0)
LOG_ERROR("snd_pcm_sw_params_current failed: %s", snd_strerror(s));
- s = snd_pcm_sw_params_set_avail_min(_sound_out, sw_params, SOUND_AVAIL_MIN);
+ s = snd_pcm_sw_params_set_avail_min(_sound_out, sw_params, PRIMARY_SOUND_AVAIL_MIN);
if (s < 0)
LOG_ERROR("snd_pcm_sw_params_set_avail_min failed: %s", snd_strerror(s));
@@ -1376,7 +1446,7 @@ static void sound_init(void) {
_sound_ready = 1;
}
-static void sound_cleanup(void) {
+static void sound_cleanup_(void) {
if (!_sound_ready)
return;
@@ -1397,34 +1467,34 @@ static void sound_cleanup(void) {
_sound_ready = 0;
}
-void p_handle_sound(void) {
- sound_init();
+void handle_primary_sound(void) {
+ sound_init_();
g_platform.num_sound_samples_elapsed = sound_samples_elapsed_();
- i64 num_frames = g_platform.num_sound_samples_elapsed * NUM_SOUND_CHANNELS;
+ i64 num_frames = g_platform.num_sound_samples_elapsed * NUM_PRIMARY_SOUND_CHANNELS;
- if (num_frames > MAX_NUM_SOUND_FRAMES) {
+ if (num_frames > MAX_NUM_PRIMARY_SOUND_FRAMES) {
LOG_ERROR("Sound buffer overflow.");
- num_frames = MAX_NUM_SOUND_FRAMES;
+ num_frames = MAX_NUM_PRIMARY_SOUND_FRAMES;
}
i32 s;
- if (num_frames <= MAX_NUM_SOUND_FRAMES - _sound_position) {
- s = snd_pcm_writei(_sound_out, _sound_ring + _sound_position, num_frames / NUM_SOUND_CHANNELS);
+ if (num_frames <= MAX_NUM_PRIMARY_SOUND_FRAMES - _sound_position) {
+ s = snd_pcm_writei(_sound_out, _sound_ring + _sound_position, num_frames / NUM_PRIMARY_SOUND_CHANNELS);
if (s < 0)
LOG_ERROR("snd_pcm_writei failed: %s", snd_strerror(s));
memset(_sound_ring + _sound_position, 0, num_frames * sizeof *_sound_ring);
} else {
- i64 part_one = MAX_NUM_SOUND_FRAMES - _sound_position;
+ i64 part_one = MAX_NUM_PRIMARY_SOUND_FRAMES - _sound_position;
i64 part_two = num_frames - part_one;
- s = snd_pcm_writei(_sound_out, _sound_ring + _sound_position, part_one / NUM_SOUND_CHANNELS);
+ s = snd_pcm_writei(_sound_out, _sound_ring + _sound_position, part_one / NUM_PRIMARY_SOUND_CHANNELS);
if (s < 0)
LOG_ERROR("snd_pcm_writei failed: %s", snd_strerror(s));
- s = snd_pcm_writei(_sound_out, _sound_ring, part_two / NUM_SOUND_CHANNELS);
+ s = snd_pcm_writei(_sound_out, _sound_ring, part_two / NUM_PRIMARY_SOUND_CHANNELS);
if (s < 0)
LOG_ERROR("snd_pcm_writei failed: %s", snd_strerror(s));
@@ -1432,17 +1502,17 @@ void p_handle_sound(void) {
memset(_sound_ring, 0, part_two * sizeof *_sound_ring);
}
- _sound_position = (_sound_position + num_frames) % MAX_NUM_SOUND_FRAMES;
+ _sound_position = (_sound_position + num_frames) % MAX_NUM_PRIMARY_SOUND_FRAMES;
}
-void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
+void queue_primary_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
if (num_samples < 0)
LOG_ERROR("Invalid num samples %lld.", num_samples);
if (frames == NULL)
return;
if (delay_in_samples < 0) {
- frames += -delay_in_samples * NUM_SOUND_CHANNELS;
+ frames += -delay_in_samples * NUM_PRIMARY_SOUND_CHANNELS;
num_samples -= delay_in_samples;
delay_in_samples = 0;
}
@@ -1450,22 +1520,22 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
if (num_samples <= 0)
return;
- i64 num_frames = num_samples * NUM_SOUND_CHANNELS;
+ i64 num_frames = num_samples * NUM_PRIMARY_SOUND_CHANNELS;
- if (num_frames > MAX_NUM_SOUND_FRAMES) {
+ if (num_frames > MAX_NUM_PRIMARY_SOUND_FRAMES) {
LOG_ERROR("Sound buffer overflow.");
return;
}
- sound_init();
+ sound_init_();
- i64 begin = (_sound_position + delay_in_samples) % MAX_NUM_SOUND_FRAMES;
+ i64 begin = (_sound_position + delay_in_samples) % MAX_NUM_PRIMARY_SOUND_FRAMES;
- if (num_frames <= MAX_NUM_SOUND_FRAMES - begin)
+ if (num_frames <= MAX_NUM_PRIMARY_SOUND_FRAMES - begin)
for (i64 i = 0; i < num_frames; ++i)
_sound_ring[begin + i] += frames[i];
else {
- i64 part_one = MAX_NUM_SOUND_FRAMES - begin;
+ i64 part_one = MAX_NUM_PRIMARY_SOUND_FRAMES - begin;
i64 part_two = num_frames - part_one;
for (i64 i = 0; i < part_one; ++i)
@@ -2087,7 +2157,7 @@ i32 x11_error_handler_(Display *display, XErrorEvent *event) {
return 0;
}
-void p_init(void) {
+void init_main_window(void) {
for (i64 i = 0; i < NUM_FRAMES_AVERAGED; ++i)
_frame_duration[i] = (MIN_FRAME_DURATION + MAX_FRAME_DURATION) / 2;
@@ -2241,6 +2311,11 @@ void p_init(void) {
_window = XCreateWindow(_display, _root_window, x, y, g_platform.frame_width, g_platform.frame_height, 0, depth, InputOutput, visual, CWEventMask, &(XSetWindowAttributes) { .event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | VisibilityChangeMask | FocusChangeMask | StructureNotifyMask | SubstructureNotifyMask, });
+ if (_window == 0) {
+ LOG_ERROR("XCreateWindow failed.");
+ return;
+ }
+
_im = XOpenIM(_display, NULL, NULL, NULL);
if (_im == NULL) {
@@ -2309,8 +2384,10 @@ void p_init(void) {
_mapped = 0;
}
-void p_cleanup(void) {
- if (!g_platform.graceful_exit)
+void shutdown_all_systems(void) {
+ g_platform.done = 1;
+
+ if (!g_platform.graceful_shutdown)
return;
if (_window != 0)
@@ -2318,17 +2395,18 @@ void p_cleanup(void) {
if (_display != NULL)
XCloseDisplay (_display);
+ _window = 0;
_display = NULL;
- sockets_cleanup();
- sound_cleanup();
+ network_cleanup_();
+ sound_cleanup_();
}
-i32 p_handle_events(void) {
+i32 handle_main_window_events(void) {
if (_display == NULL)
return 0;
- _frame_time = p_time();
+ _frame_time = current_utc_time_in_milliseconds();
i32 num_events = 0;
@@ -2848,11 +2926,11 @@ i32 p_handle_events(void) {
return num_events;
}
-i32 p_wait_events(void) {
+i32 wait_main_window_events(void) {
i32 num_events = 0;
for (;;) {
- num_events = p_handle_events();
+ num_events = handle_main_window_events();
if (num_events != 0)
break;
usleep(0);
@@ -2861,7 +2939,7 @@ i32 p_wait_events(void) {
return num_events;
}
-void p_render_frame(void) {
+void render_main_window_frame(void) {
if (g_platform.done)
return;
@@ -2891,10 +2969,10 @@ void p_render_frame(void) {
XPutImage(_display, _window, _gc, &_image, 0, 0, 0, 0, _image.width, _image.height);
XFlush(_display);
- pixel_size_calubrate_(p_time() - _frame_time);
+ pixel_size_calubrate_(current_utc_time_in_milliseconds() - _frame_time);
}
-void p_clipboard_write_text(i64 size, c8 *data) {
+void write_clipboard_text(i64 size, c8 *data) {
if (size > MAX_CLIPBOARD_SIZE) {
LOG_ERROR("Size is too big %lld.", size);
return;
@@ -2951,7 +3029,7 @@ b8 x11_screenshot_(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels
// ================================================================
#if defined(__linux__) && (!NO_X11 || !NO_WAYLAND)
-void p_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels) {
+void take_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels) {
if (width == NULL || height == NULL) {
LOG_ERROR("Invalid arguments.");
return;
@@ -3090,11 +3168,11 @@ __attribute__((export_name("js_key_map"))) void *js_key_map(void) {
}
__attribute__((export_name("js_sound_sample_rate"))) f64 js_sound_sample_rate(void) {
- return (f64) SOUND_SAMPLE_RATE;
+ return (f64) PRIMARY_SOUND_SAMPLE_RATE;
}
__attribute__((export_name("js_num_sound_channels"))) i32 js_num_sound_channels(void) {
- return NUM_SOUND_CHANNELS;
+ return NUM_PRIMARY_SOUND_CHANNELS;
}
#endif // defined(__wasm__)
@@ -3125,26 +3203,30 @@ static c8 _href [4096] = {0};
static u32 _pixels_scaled [MAX_NUM_PIXELS] = {0};
static u32 _pixels_internal [MAX_NUM_PIXELS] = {0};
static b8 _key_pressed [MAX_NUM_KEYS] = {0};
-static f32 _sound_buffer [MAX_NUM_SOUND_FRAMES] = {0};
+static f32 _sound_buffer [MAX_NUM_PRIMARY_SOUND_FRAMES] = {0};
static u8 _drop_buffer [DROP_FILES_BUFFER_SIZE] = {0};
-i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address) {
+void shutdown_all_systems(void) {
+ g_platform.done = 1;
+}
+
+i64 network_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address) {
LOG_ERROR("Web sockets are not implemented.");
return 0;
}
-i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
+i64 network_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
LOG_ERROR("Web sockets are not implemented.");
return 0;
}
-i64 p_time(void);
+i64 current_utc_time_in_milliseconds(void);
-void p_sleep_for(i64 duration) {
+void suspend_thread_for_milliseconds(i64 duration) {
if (duration <= 0)
return;
- i64 t = p_time();
+ i64 t = current_utc_time_in_milliseconds();
if (_timeout < t)
_timeout = t + duration;
@@ -3152,7 +3234,7 @@ void p_sleep_for(i64 duration) {
_timeout += duration;
}
-void p_init(void) {
+void init_main_window(void) {
(void) rgb_f32_from_u32_;
++_num_events;
@@ -3162,10 +3244,10 @@ void p_init(void) {
for (i64 i = 0; i < NUM_FRAMES_AVERAGED; ++i)
_frame_duration[i] = (MIN_FRAME_DURATION + MAX_FRAME_DURATION) / 2;
- _sound_read = (MAX_NUM_SOUND_FRAMES + ((-SOUND_AVAIL_MIN) % MAX_NUM_SOUND_FRAMES)) % MAX_NUM_SOUND_FRAMES;
+ _sound_read = (MAX_NUM_PRIMARY_SOUND_FRAMES + ((-PRIMARY_SOUND_AVAIL_MIN) % MAX_NUM_PRIMARY_SOUND_FRAMES)) % MAX_NUM_PRIMARY_SOUND_FRAMES;
}
-i32 p_handle_events(void) {
+i32 handle_main_window_events(void) {
if (g_platform.files_dropped)
drop_files_clean_();
@@ -3198,13 +3280,13 @@ i32 p_handle_events(void) {
return n;
}
-i32 p_wait_events(void) {
+i32 wait_main_window_events(void) {
_wait_events = 1;
- return p_handle_events();
+ return handle_main_window_events();
}
-void p_render_frame(void) {
+void render_main_window_frame(void) {
if (_frame_width == g_platform.frame_width && _frame_height == g_platform.frame_height) {
i64 size = g_platform.frame_width * g_platform.frame_height;
for (i64 i = 0; i < size; ++i)
@@ -3224,9 +3306,9 @@ void p_render_frame(void) {
}
}
-void p_clipboard_write_text_impl(i32 size, c8 *data);
+void write_clipboard_text_impl(i32 size, c8 *data);
-void p_clipboard_write_text(i64 size, c8 *data) {
+void write_clipboard_text(i64 size, c8 *data) {
if (size < 0 || data == NULL)
return;
if (size > MAX_CLIPBOARD_SIZE)
@@ -3236,10 +3318,10 @@ void p_clipboard_write_text(i64 size, c8 *data) {
for (i64 i = 0; i < size; ++i)
g_platform.clipboard[i] = data[i];
- p_clipboard_write_text_impl((i32) size, data);
+ write_clipboard_text_impl((i32) size, data);
}
-void p_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels) {
+void take_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels) {
if (width == NULL || height == NULL) {
LOG_ERROR("Invalid arguments.");
return;
@@ -3249,17 +3331,17 @@ void p_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels)
*height = 0;
}
-void p_handle_sound(void) {
+void handle_primary_sound(void) {
g_platform.num_sound_samples_elapsed = sound_samples_elapsed_();
- _sound_position = (_sound_position + g_platform.num_sound_samples_elapsed * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
+ _sound_position = (_sound_position + g_platform.num_sound_samples_elapsed * NUM_PRIMARY_SOUND_CHANNELS) % MAX_NUM_PRIMARY_SOUND_FRAMES;
}
-void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
+void queue_primary_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
if (frames == NULL)
return;
if (delay_in_samples < 0) {
- frames += -delay_in_samples * NUM_SOUND_CHANNELS;
+ frames += -delay_in_samples * NUM_PRIMARY_SOUND_CHANNELS;
num_samples -= delay_in_samples;
delay_in_samples = 0;
}
@@ -3267,19 +3349,19 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
if (num_samples <= 0)
return;
- i64 num_frames = num_samples * NUM_SOUND_CHANNELS;
- if (num_frames > MAX_NUM_SOUND_FRAMES) {
+ i64 num_frames = num_samples * NUM_PRIMARY_SOUND_CHANNELS;
+ if (num_frames > MAX_NUM_PRIMARY_SOUND_FRAMES) {
LOG_ERROR("Sound buffer overflow.");
return;
}
- i64 begin = (_sound_position + delay_in_samples * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
+ i64 begin = (_sound_position + delay_in_samples * NUM_PRIMARY_SOUND_CHANNELS) % MAX_NUM_PRIMARY_SOUND_FRAMES;
- if (num_frames <= MAX_NUM_SOUND_FRAMES - begin)
+ if (num_frames <= MAX_NUM_PRIMARY_SOUND_FRAMES - begin)
for (i64 i = 0; i < num_frames; ++i)
_sound_ring[begin + i] += frames[i];
else {
- i64 part_one = MAX_NUM_SOUND_FRAMES - begin;
+ i64 part_one = MAX_NUM_PRIMARY_SOUND_FRAMES - begin;
i64 part_two = num_frames - part_one;
for (i64 i = 0; i < part_one; ++i)
@@ -3290,7 +3372,7 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
}
__attribute__((export_name("js_max_num_sound_frames"))) i32 js_max_num_sound_frames(void) {
- return MAX_NUM_SOUND_FRAMES;
+ return MAX_NUM_PRIMARY_SOUND_FRAMES;
}
__attribute__((export_name("js_sound_buffer"))) void *js_sound_buffer(void) {
@@ -3318,7 +3400,7 @@ __attribute__((export_name("js_pixels"))) void *js_pixels(void) {
}
__attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 frame_height, i32 num_samples) {
- i64 frame_time = p_time();
+ i64 frame_time = current_utc_time_in_milliseconds();
if (frame_width > 0 && frame_height > 0 && frame_width * frame_height <= MAX_NUM_PIXELS) {
_frame_width = frame_width;
@@ -3337,17 +3419,17 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram
}
// Convert interleaved frames to non-interleaved.
- for (i64 j = 0; j < NUM_SOUND_CHANNELS; ++j)
+ for (i64 j = 0; j < NUM_PRIMARY_SOUND_CHANNELS; ++j)
for (i64 i = 0; i < num_samples; ++i) {
- i64 n = (_sound_read + i * NUM_SOUND_CHANNELS + j) % MAX_NUM_SOUND_FRAMES;
+ i64 n = (_sound_read + i * NUM_PRIMARY_SOUND_CHANNELS + j) % MAX_NUM_PRIMARY_SOUND_FRAMES;
_sound_buffer[j * num_samples + i] = _sound_ring[n];
_sound_ring[n] = 0.f;
}
- _sound_read = (_sound_read + num_samples * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
+ _sound_read = (_sound_read + num_samples * NUM_PRIMARY_SOUND_CHANNELS) % MAX_NUM_PRIMARY_SOUND_FRAMES;
if (do_render)
- pixel_size_calubrate_(p_time() - frame_time);
+ pixel_size_calubrate_(current_utc_time_in_milliseconds() - frame_time);
}
__attribute__((export_name("js_mousemove"))) void js_mousemove(i32 x, i32 y) {
diff --git a/stackless_coroutine.c b/stackless_coroutine.c
index 705d11c..d819f35 100755
--- a/stackless_coroutine.c
+++ b/stackless_coroutine.c
@@ -246,9 +246,9 @@ static void stackless_coroutine_dispatch(void *promise) {
promise_ = (Promise_Of(coro_)) { CORO_INITIAL_(0, coro_), __VA_ARGS__ }; \
} while (0)
-#define CORO_INIT_ID(promise_, id_, ...) \
- do { \
- promise_ = (Promise_Of(coro_)) { CORO_INITIAL_CORO_INITIAL_(id_), coro_), __VA_ARGS__ }; \
+#define CORO_INIT_ID(promise_, id_, ...) \
+ do { \
+ promise_ = (Promise_Of(coro_)) { CORO_INITIAL_(id_, coro_), __VA_ARGS__ }; \
} while (0)
#define coro_finished(promise_) ((promise_)._index == -1)
@@ -291,37 +291,6 @@ CORO_IMPL(test_foo) {
async_return(42);
} CORO_END
-CORO_DECL_STATIC(int, test_bar, );
-
-CORO_IMPL(test_bar) {
- yield_void;
- async_return(42);
-} CORO_END
-
-CORO_STATIC(int, test_gen, int i; int min; int max;) {
- for (self->i = self->min; self->i < self->max; self->i++)
- yield(self->i);
- async_return(self->max);
-} CORO_END
-
-CORO_STATIC_VOID(test_task, ) {
- yield_void;
- yield_void;
- async_return_void;
-} CORO_END
-
-CORO_STATIC_VOID(test_nest_task, Promise_Of(test_task) promise;) {
- CORO_INIT(self->promise, test_task, );
- await(self->promise);
- await(self->promise);
- await(self->promise);
-} CORO_END
-
-CORO_STATIC(int, test_nest_generator, Promise_Of(test_gen) promise;) {
- CORO_INIT(self->promise, test_gen, .min = 1, .max = 3);
- yield_await(self->promise);
-} CORO_END
-
TEST("coroutine init") {
Promise_Of(test_foo) promise;
CORO_INIT(promise, test_foo, );
@@ -342,6 +311,13 @@ TEST("coroutine execute and return") {
REQUIRE(coro_finished(promise));
}
+CORO_DECL_STATIC(int, test_bar, );
+
+CORO_IMPL(test_bar) {
+ yield_void;
+ async_return(42);
+} CORO_END
+
TEST("coroutine execute two steps") {
Promise_Of(test_bar) promise;
CORO_INIT(promise, test_bar, .return_value = 0);
@@ -351,6 +327,12 @@ TEST("coroutine execute two steps") {
REQUIRE(promise.return_value == 42);
}
+CORO_STATIC(int, test_gen, int i; int min; int max;) {
+ for (self->i = self->min; self->i < self->max; self->i++)
+ yield(self->i);
+ async_return(self->max);
+} CORO_END
+
TEST("coroutine generator") {
int i;
Promise_Of(test_gen) promise;
@@ -368,6 +350,12 @@ TEST("coroutine status finished") {
REQUIRE(coro_finished(promise));
}
+CORO_STATIC_VOID(test_task, ) {
+ yield_void;
+ yield_void;
+ async_return_void;
+} CORO_END
+
TEST("coroutine task") {
Promise_Of(test_task) promise;
CORO_INIT(promise, test_task, );
@@ -379,6 +367,13 @@ TEST("coroutine task") {
REQUIRE(coro_finished(promise));
}
+CORO_STATIC_VOID(test_nest_task, Promise_Of(test_task) promise;) {
+ CORO_INIT(self->promise, test_task, );
+ await(self->promise);
+ await(self->promise);
+ await(self->promise);
+} CORO_END
+
TEST("coroutine nested task") {
Promise_Of(test_nest_task) promise;
CORO_INIT(promise, test_nest_task, );
@@ -390,6 +385,11 @@ TEST("coroutine nested task") {
REQUIRE(coro_finished(promise));
}
+CORO_STATIC(int, test_nest_generator, Promise_Of(test_gen) promise;) {
+ CORO_INIT(self->promise, test_gen, .min = 1, .max = 3);
+ yield_await(self->promise);
+} CORO_END
+
TEST("coroutine nested generator") {
Promise_Of(test_nest_generator) promise;
CORO_INIT(promise, test_nest_generator, );