From 41abfb196c524cf16107675b8e5b356827a04cd0 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Thu, 16 Jan 2025 04:57:15 +0100 Subject: Refactor --- reduced_system_layer.c | 184 +++++++++++++++++++++++++++---------------------- 1 file changed, 101 insertions(+), 83 deletions(-) (limited to 'reduced_system_layer.c') diff --git a/reduced_system_layer.c b/reduced_system_layer.c index b828781..8853166 100644 --- a/reduced_system_layer.c +++ b/reduced_system_layer.c @@ -5,7 +5,7 @@ // This is a reduced system layer. // It allows you to create a window, draw graphics in it, handle // input events, write samples to audio output, send and receive -// UDP packets. +// UDP packets, etc. All code is single-threaded. // // Primary target platforms: Linux (X11), Windows, Web. // @@ -49,8 +49,10 @@ // - Sound // - Windows audio // - Recording +// - Device selection // - Networking // - Windows sockets +// - TCP // - Long term // - Allocator // - Parsing @@ -84,7 +86,7 @@ // - WebAssembly // - Sound // - ALSA -// - WebAssembly audio +// - Web audio // - Networking // - Unix UDP sockets // - UTF-8 @@ -154,7 +156,7 @@ extern "C" { // // ================================================================ -// NOTE: This procedure is required for the WebAssembly compatibility. +// NOTE: This procedure is required for the Web compatibility. void update_and_render_frame(void); #if defined(__wasm__) @@ -492,6 +494,21 @@ typedef struct { u8 *data; } Drop_File; +typedef struct { + c32 code; + i8 len; +} UTF8_Char; + +typedef struct { + u16 protocol; + u16 port; + union { + u32 v4_address_as_u32; + u8 v4_address[4]; + u8 v6_address[16]; + }; +} IP_Address; + typedef struct { c8 *title; i32 frame_width; @@ -514,40 +531,23 @@ typedef struct { i32 cursor_dy; i64 wheel_dx; i64 wheel_dy; - i64 sound_clock_time; - i64 sound_clock_carry; i64 num_sound_samples_elapsed; - i64 sound_position; i64 num_drop_files; Drop_File *drop_files; vec4_f32 pixels [MAX_NUM_PIXELS]; - f32 sound_ring [MAX_NUM_SOUND_FRAMES]; Input_Key input [MAX_INPUT_SIZE]; c8 clipboard [MAX_CLIPBOARD_SIZE]; b8 key_down [MAX_NUM_KEYS]; b8 key_pressed [MAX_NUM_KEYS]; - - // TODO: Allocator for big buffers - u8 drop_files_buffer[DROP_FILES_BUFFER_SIZE]; } Platform; -typedef struct { - u16 protocol; - u16 port; - union { - u32 v4_address_as_u32; - u8 v4_address[4]; - u8 v6_address[16]; - }; -} IP_Address; - // UTF-8 // NOTE: We need UTF-8 because we use Xutf8LookupString on Xlib. -i32 utf8_size(c32 c); -c32 utf8_read(i64 len, c8 *s); -i32 utf8_write(c32 c, c8 *buffer); +i8 utf8_size (c32 c); +UTF8_Char utf8_read (i64 len, c8 *s); +i8 utf8_write(c32 c, c8 *buffer); // Time and sleep i64 p_time(void); @@ -575,7 +575,9 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames); 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); +#ifdef REDUCED_SYSTEM_LAYER_HEADER extern Platform g_platform; +#endif // ================================================================ @@ -597,6 +599,13 @@ extern Platform g_platform; Platform g_platform = {0}; +static i64 _sound_clock_time = 0; +static i64 _sound_clock_carry = 0; +static i64 _sound_position = 0; + +static f32 _sound_ring [MAX_NUM_SOUND_FRAMES] = {0}; +static u8 _drop_files_buffer [DROP_FILES_BUFFER_SIZE] = {0}; + void p_event_loop(void) { p_init(); #if !defined(__wasm__) @@ -624,43 +633,55 @@ void p_event_loop(void) { } while (0) #endif -c32 utf8_read(i64 len, c8 *s) { +i8 utf8_size(c32 c) { + if ((c & 0x00007f) == c) return 1; + if ((c & 0x0007ff) == c) return 2; + if ((c & 0x00ffff) == c) return 3; + if ((c & 0x1fffff) == c) return 4; + return 0; +} + +UTF8_Char utf8_read(i64 len, c8 *s) { if (len >= 1 && (s[0] & 0x80) == 0) - return s[0]; + return (UTF8_Char) { + .code = s[0], + .len = 1, + }; if (len >= 2 && (s[0] & 0xe0) == 0xc0 && (s[1] & 0xc0) == 0x80) - return (s[1] & 0x3f) - | ((s[0] & 0x1f) << 6); + return (UTF8_Char) { + .code = (s[1] & 0x3f) + | ((s[0] & 0x1f) << 6), + .len = 2, + }; if (len >= 3 && (s[0] & 0xf0) == 0xe0 && (s[1] & 0xc0) == 0x80 && (s[2] & 0xc0) == 0x80) - return (s[2] & 0x3f) - | ((s[1] & 0x3f) << 6) - | ((s[0] & 0x0f) << 12); + return (UTF8_Char) { + .code = (s[2] & 0x3f) + | ((s[1] & 0x3f) << 6) + | ((s[0] & 0x0f) << 12), + .len = 3, + }; if (len >= 4 && (s[0] & 0xf8) == 0xf0 && (s[1] & 0xc0) == 0x80 && (s[2] & 0xc0) == 0x80 && (s[3] & 0xc0) == 0x80) - return (s[3] & 0x3f) - | ((s[2] & 0x3f) << 6) - | ((s[1] & 0x3f) << 12) - | ((s[0] & 0x07) << 18); - return 0; -} - -i32 utf8_size(c32 c) { - if ((c & 0x00007f) == c) return 1; - if ((c & 0x0007ff) == c) return 2; - if ((c & 0x00ffff) == c) return 3; - if ((c & 0x1fffff) == c) return 4; - return 0; + return (UTF8_Char) { + .code = (s[3] & 0x3f) + | ((s[2] & 0x3f) << 6) + | ((s[1] & 0x3f) << 12) + | ((s[0] & 0x07) << 18), + .len = 4, + }; + return (UTF8_Char) {0}; } -i32 utf8_write(c32 c, c8 *buffer) { +i8 utf8_write(c32 c, c8 *buffer) { if ((c & 0x7f) == c) { buffer[0] = (c8) c; return 1; @@ -703,18 +724,18 @@ u32 rgb_u32_from_f32_(vec3_f32 c) { } static i64 sound_samples_elapsed_(void) { - if (g_platform.sound_clock_time == 0) { - g_platform.sound_clock_time = p_time(); - g_platform.sound_clock_carry = 0; + if (_sound_clock_time == 0) { + _sound_clock_time = p_time(); + _sound_clock_carry = 0; return 0; } - i64 time_elapsed = p_time() - g_platform.sound_clock_time; - i64 delta = time_elapsed * SOUND_SAMPLE_RATE + g_platform.sound_clock_carry; + i64 time_elapsed = p_time() - _sound_clock_time; + i64 delta = time_elapsed * SOUND_SAMPLE_RATE + _sound_clock_carry; i64 num_samples = delta / 1000; - g_platform.sound_clock_time += time_elapsed; - g_platform.sound_clock_carry = delta % 1000; + _sound_clock_time += time_elapsed; + _sound_clock_carry = delta % 1000; return num_samples; } @@ -763,8 +784,8 @@ static void drop_files_set_num_(i64 num) { i64 src_size = (i64) sizeof(Drop_File) * g_platform.num_drop_files; i64 dst_size = (i64) sizeof(Drop_File) * num; - u8 *src = g_platform.drop_files_buffer + (DROP_FILES_BUFFER_SIZE - src_size); - u8 *dst = g_platform.drop_files_buffer + (DROP_FILES_BUFFER_SIZE - num * (i64) sizeof(Drop_File)); + u8 *src = _drop_files_buffer + (DROP_FILES_BUFFER_SIZE - src_size); + u8 *dst = _drop_files_buffer + (DROP_FILES_BUFFER_SIZE - num * (i64) sizeof(Drop_File)); for (i64 i = 0; i < src_size; ++i) dst[i] = src[i]; @@ -825,7 +846,7 @@ static void drop_files_set_name_(i64 index, i64 name_size, c8 *name) { } g_platform.drop_files[index].name_size = name_size + 1; - g_platform.drop_files[index].name = (c8 *) g_platform.drop_files_buffer + offset; + g_platform.drop_files[index].name = (c8 *) _drop_files_buffer + offset; for (i64 i = 0; i < name_size; ++i) g_platform.drop_files[index].name[i] = name[i]; @@ -851,7 +872,7 @@ static void drop_files_set_data_(i64 index, i64 data_size) { } g_platform.drop_files[index].data_size = data_size; - g_platform.drop_files[index].data = g_platform.drop_files_buffer + offset; + g_platform.drop_files[index].data = _drop_files_buffer + offset; } // ================================================================ @@ -966,7 +987,7 @@ static b8 sockets_open(u16 slot, IP_Address address, u16 *local_port) { _sockets[slot].socket = socket(address.protocol == IPv4_UDP ? AF_INET : AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (_sockets[slot].socket == -1) { - LOG_ERROR("socket failed (errno %d)", errno); + LOG_ERROR("socket failed (errno %d).", errno); return 0; } @@ -983,14 +1004,14 @@ static b8 sockets_open(u16 slot, IP_Address address, u16 *local_port) { if (bind(_sockets[slot].socket, p, p_len) == -1) { close(_sockets[slot].socket); - LOG_ERROR("bind failed (errno %d)", errno); + LOG_ERROR("bind failed (errno %d).", errno); return 0; } if (getsockname(_sockets[slot].socket, p, &(socklen_t) {p_len}) == -1) { close(_sockets[slot].socket); - LOG_ERROR("getsockname failed (errno %d)", errno); + LOG_ERROR("getsockname failed (errno %d).", errno); return 0; } @@ -1152,8 +1173,6 @@ static void sound_init(void) { if (_sound_ready) return; - g_platform.sound_position = 0; - i32 s; s = snd_pcm_open(&_sound_out, "default", SND_PCM_STREAM_PLAYBACK, 0); @@ -1246,29 +1265,29 @@ void p_handle_sound(void) { i32 s; - if (num_frames <= MAX_NUM_SOUND_FRAMES - g_platform.sound_position) { - s = snd_pcm_writei(_sound_out, g_platform.sound_ring + g_platform.sound_position, num_frames / NUM_SOUND_CHANNELS); + 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 (s < 0) LOG_ERROR("snd_pcm_writei failed: %s", snd_strerror(s)); - memset(g_platform.sound_ring + g_platform.sound_position, 0, num_frames * sizeof *g_platform.sound_ring); + memset(_sound_ring + _sound_position, 0, num_frames * sizeof *_sound_ring); } else { - i64 part_one = MAX_NUM_SOUND_FRAMES - g_platform.sound_position; + i64 part_one = MAX_NUM_SOUND_FRAMES - _sound_position; i64 part_two = num_frames - part_one; - s = snd_pcm_writei(_sound_out, g_platform.sound_ring + g_platform.sound_position, part_one / NUM_SOUND_CHANNELS); + s = snd_pcm_writei(_sound_out, _sound_ring + _sound_position, part_one / NUM_SOUND_CHANNELS); if (s < 0) LOG_ERROR("snd_pcm_writei failed: %s", snd_strerror(s)); - s = snd_pcm_writei(_sound_out, g_platform.sound_ring, part_two / NUM_SOUND_CHANNELS); + s = snd_pcm_writei(_sound_out, _sound_ring, part_two / NUM_SOUND_CHANNELS); if (s < 0) LOG_ERROR("snd_pcm_writei failed: %s", snd_strerror(s)); - memset(g_platform.sound_ring + g_platform.sound_position, 0, part_one * sizeof *g_platform.sound_ring); - memset(g_platform.sound_ring, 0, part_two * sizeof *g_platform.sound_ring); + memset(_sound_ring + _sound_position, 0, part_one * sizeof *_sound_ring); + memset(_sound_ring, 0, part_two * sizeof *_sound_ring); } - g_platform.sound_position = (g_platform.sound_position + num_frames) % MAX_NUM_SOUND_FRAMES; + _sound_position = (_sound_position + num_frames) % MAX_NUM_SOUND_FRAMES; } void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) { @@ -1295,19 +1314,19 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) { sound_init(); - i64 begin = (g_platform.sound_position + delay_in_samples) % MAX_NUM_SOUND_FRAMES; + i64 begin = (_sound_position + delay_in_samples) % MAX_NUM_SOUND_FRAMES; if (num_frames <= MAX_NUM_SOUND_FRAMES - begin) for (i64 i = 0; i < num_frames; ++i) - g_platform.sound_ring[begin + i] += frames[i]; + _sound_ring[begin + i] += frames[i]; else { i64 part_one = MAX_NUM_SOUND_FRAMES - begin; i64 part_two = num_frames - part_one; for (i64 i = 0; i < part_one; ++i) - g_platform.sound_ring[begin + i] += frames[i]; + _sound_ring[begin + i] += frames[i]; for (i64 i = 0; i < part_two; ++i) - g_platform.sound_ring[i] += frames[part_one + i]; + _sound_ring[i] += frames[part_one + i]; } } @@ -1726,7 +1745,7 @@ i32 p_handle_events(void) { .scroll = !!(ev.xkey.state & Mod3Mask), .meta = !!(ev.xkey.state & Mod4Mask), .key = k, - .c = utf8_read(len, buf), + .c = utf8_read(len, buf).code, }; } } @@ -2251,8 +2270,7 @@ void p_sleep_for(i64 duration) { void p_init(void) { ++_num_events; - g_platform.done = 1; - g_platform.sound_position = 0; + g_platform.done = 1; _sound_read = (MAX_NUM_SOUND_FRAMES + ((-SOUND_AVAIL_MIN) % MAX_NUM_SOUND_FRAMES)) % MAX_NUM_SOUND_FRAMES; } @@ -2314,7 +2332,7 @@ void p_clipboard_write(i64 size, c8 *data) { void p_handle_sound(void) { g_platform.num_sound_samples_elapsed = sound_samples_elapsed_(); - g_platform.sound_position = (g_platform.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_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES; } void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) { @@ -2334,19 +2352,19 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) { if (num_frames > MAX_NUM_SOUND_FRAMES) return; - i64 begin = (g_platform.sound_position + delay_in_samples * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES; + i64 begin = (_sound_position + delay_in_samples * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES; if (num_frames <= MAX_NUM_SOUND_FRAMES - begin) for (i64 i = 0; i < num_frames; ++i) - g_platform.sound_ring[begin + i] += frames[i]; + _sound_ring[begin + i] += frames[i]; else { i64 part_one = MAX_NUM_SOUND_FRAMES - begin; i64 part_two = num_frames - part_one; for (i64 i = 0; i < part_one; ++i) - g_platform.sound_ring[begin + i] += frames[i]; + _sound_ring[begin + i] += frames[i]; for (i64 i = 0; i < part_two; ++i) - g_platform.sound_ring[i] += frames[part_one + i]; + _sound_ring[i] += frames[part_one + i]; } } @@ -2545,8 +2563,8 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram for (i64 j = 0; j < NUM_SOUND_CHANNELS; ++j) for (i64 i = 0; i < num_samples; ++i) { i64 n = (_sound_read + i * NUM_SOUND_CHANNELS + j) % MAX_NUM_SOUND_FRAMES; - _sound_buffer[j * num_samples + i] = g_platform.sound_ring[n]; - g_platform.sound_ring[n] = 0.f; + _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; -- cgit v1.2.3