summaryrefslogtreecommitdiff
path: root/reduced_system_layer.c
diff options
context:
space:
mode:
Diffstat (limited to 'reduced_system_layer.c')
-rwxr-xr-xreduced_system_layer.c186
1 files changed, 120 insertions, 66 deletions
diff --git a/reduced_system_layer.c b/reduced_system_layer.c
index 9eabca9..3d020bd 100755
--- a/reduced_system_layer.c
+++ b/reduced_system_layer.c
@@ -75,6 +75,7 @@
#/ - Graphics
#/ - Font
#/ - Adaptive resolution
+#/ - Oklab color
#/
#/ ----------------------------------------------------------------
#/
@@ -124,7 +125,7 @@ typedef unsigned u32;
typedef unsigned long long u64;
typedef char c8;
typedef int c32;
-typedef signed char b8;
+typedef unsigned char b8;
typedef float f32;
typedef double f64;
@@ -170,23 +171,59 @@ typedef struct { f64 v[16]; } mat4;
extern "C" {
#endif
-enum {
- MAX_NUM_PIXELS = 10 * 1024 * 1024,
- MAX_INPUT_SIZE = 256,
- MAX_CLIPBOARD_SIZE = 10 * 1024 * 1024,
- MAX_NUM_SOCKETS = 64,
- MAX_NUM_KEYS = 512,
- MAX_PIXEL_SIZE = 16,
+#ifndef MAX_NUM_PIXELS
+#define MAX_NUM_PIXELS (10 * 1024 * 1024)
+#endif
- MIN_FRAME_DURATION = 9,
- MAX_FRAME_DURATION = 38,
+#ifndef MAX_INPUT_SIZE
+#define MAX_INPUT_SIZE 256
+#endif
- AUDIO_NUM_CHANNELS = 2,
- AUDIO_SAMPLE_RATE = 44100,
- AUDIO_AVAIL_MIN = 512,
+#ifndef MAX_CLIPBOARD_SIZE
+#define MAX_CLIPBOARD_SIZE (10 * 1024 * 1024)
+#endif
- MAX_NUM_AUDIO_FRAMES = 10 * AUDIO_SAMPLE_RATE * AUDIO_NUM_CHANNELS, // 10 seconds
+#ifndef MAX_NUM_SOCKETS
+#define MAX_NUM_SOCKETS 64
+#endif
+
+#ifndef MAX_NUM_KEYS
+#define MAX_NUM_KEYS 512
+#endif
+
+#ifndef MIN_PIXEL_SIZE
+#define MIN_PIXEL_SIZE 1
+#endif
+
+#ifndef MAX_PIXEL_SIZE
+#define MAX_PIXEL_SIZE 16
+#endif
+
+#ifndef MIN_FRAME_DURATION
+#define MIN_FRAME_DURATION 9
+#endif
+
+#ifndef MAX_FRAME_DURATION
+#define MAX_FRAME_DURATION 38
+#endif
+
+#ifndef NUM_SOUND_CHANNELS
+#define NUM_SOUND_CHANNELS 2
+#endif
+#ifndef SOUND_SAMPLE_RATE
+#define SOUND_SAMPLE_RATE 44100
+#endif
+
+#ifndef SOUND_AVAIL_MIN
+#define SOUND_AVAIL_MIN 512
+#endif
+
+#ifndef MAX_NUM_SOUND_FRAMES
+#define MAX_NUM_SOUND_FRAMES (10 * SOUND_SAMPLE_RATE * NUM_SOUND_CHANNELS)
+#endif
+
+enum {
IPv4_UDP = 1,
IPv6_UDP = 2,
@@ -329,15 +366,17 @@ typedef struct {
typedef struct {
c8 * title;
+ i32 real_width;
+ i32 real_height;
i32 frame_width;
i32 frame_height;
- vec3_f32 * pixels;
+ vec4_f32 * pixels;
i64 input_size;
Input_Key *input;
i64 clipboard_size;
c8 * clipboard;
b8 done;
- b8 exact_resolution; // TODO
+ b8 exact_resolution;
b8 graceful_exit;
b8 has_focus;
b8 has_cursor;
@@ -408,6 +447,7 @@ i32 main(i32 argc, c8 **argv);
f64 floor(f64 x);
f64 ceil(f64 x);
f64 sqrt(f64 x);
+f64 cbrt(f64 x);
f64 pow(f64 x, f64 y);
f64 log(f64 x);
f64 log2(f64 x);
@@ -457,9 +497,9 @@ void update_and_render_frame(void) {
for (i64 j = 0; j < g_platform.frame_height; ++j)
for (i64 i = 0; i < g_platform.frame_width; ++i)
if (i < x || i >= x + w || j < y || j >= y + h)
- g_platform.pixels[j * g_platform.frame_width + i] = (vec3_f32) { .8f, .8f, .8f };
+ g_platform.pixels[j * g_platform.frame_width + i] = (vec4_f32) { .8f, .8f, .8f, 1.f };
else
- g_platform.pixels[j * g_platform.frame_width + i] = (vec3_f32) { .27f, .21f, .24f };
+ g_platform.pixels[j * g_platform.frame_width + i] = (vec4_f32) { .27f, .21f, .24f, 1.f };
p_render_frame();
p_sleep_for(0);
@@ -888,7 +928,7 @@ i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
static b8 _sound_ready = 0;
static i64 _sound_position = 0;
-static f32 _sound_ring[MAX_NUM_AUDIO_FRAMES] = {0};
+static f32 _sound_ring[MAX_NUM_SOUND_FRAMES] = {0};
static snd_pcm_t *_sound_out = NULL;
static void sound_init(void) {
@@ -922,11 +962,11 @@ static void sound_init(void) {
if (s < 0)
fprintf(stderr, "%s:%d, %s: snd_pcm_hw_params_set_format failed: %s\n", __FILE__, __LINE__, __func__, snd_strerror(s));
- s = snd_pcm_hw_params_set_rate(_sound_out, hw_params, AUDIO_SAMPLE_RATE, 0);
+ s = snd_pcm_hw_params_set_rate(_sound_out, hw_params, SOUND_SAMPLE_RATE, 0);
if (s < 0)
fprintf(stderr, "%s:%d, %s: snd_pcm_hw_params_set_rate failed: %s\n", __FILE__, __LINE__, __func__, snd_strerror(s));
- s = snd_pcm_hw_params_set_channels(_sound_out, hw_params, AUDIO_NUM_CHANNELS);
+ s = snd_pcm_hw_params_set_channels(_sound_out, hw_params, NUM_SOUND_CHANNELS);
if (s < 0)
fprintf(stderr, "%s:%d, %s: snd_pcm_hw_params_set_channels failed: %s\n", __FILE__, __LINE__, __func__, snd_strerror(s));
@@ -940,7 +980,7 @@ static void sound_init(void) {
if (s < 0)
fprintf(stderr, "%s:%d, %s: snd_pcm_sw_params_current failed: %s\n", __FILE__, __LINE__, __func__, snd_strerror(s));
- s = snd_pcm_sw_params_set_avail_min(_sound_out, sw_params, AUDIO_AVAIL_MIN);
+ s = snd_pcm_sw_params_set_avail_min(_sound_out, sw_params, SOUND_AVAIL_MIN);
if (s < 0)
fprintf(stderr, "%s:%d, %s: snd_pcm_sw_params_set_avail_min failed: %s\n", __FILE__, __LINE__, __func__, snd_strerror(s));
@@ -979,30 +1019,30 @@ static void sound_cleanup(void) {
void p_handle_audio(i64 samples_elapsed) {
sound_init();
- i64 num_frames = samples_elapsed * AUDIO_NUM_CHANNELS;
+ i64 num_frames = samples_elapsed * NUM_SOUND_CHANNELS;
- if (num_frames > MAX_NUM_AUDIO_FRAMES) {
+ if (num_frames > MAX_NUM_SOUND_FRAMES) {
fprintf(stderr, "%s:%d, %s: Sound buffer overflow.\n", __FILE__, __LINE__, __func__);
- num_frames = MAX_NUM_AUDIO_FRAMES;
+ num_frames = MAX_NUM_SOUND_FRAMES;
}
i32 s;
- if (num_frames <= MAX_NUM_AUDIO_FRAMES - _sound_position) {
- s = snd_pcm_writei(_sound_out, _sound_ring + _sound_position, num_frames / AUDIO_NUM_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)
fprintf(stderr, "%s:%d, %s: snd_pcm_writei failed: %s\n", __FILE__, __LINE__, __func__, snd_strerror(s));
memset(_sound_ring + _sound_position, 0, num_frames * sizeof *_sound_ring);
} else {
- i64 part_one = MAX_NUM_AUDIO_FRAMES - _sound_position;
+ i64 part_one = MAX_NUM_SOUND_FRAMES - _sound_position;
i64 part_two = num_frames - part_one;
- s = snd_pcm_writei(_sound_out, _sound_ring + _sound_position, part_one / AUDIO_NUM_CHANNELS);
+ s = snd_pcm_writei(_sound_out, _sound_ring + _sound_position, part_one / NUM_SOUND_CHANNELS);
if (s < 0)
fprintf(stderr, "%s:%d, %s: snd_pcm_writei failed: %s\n", __FILE__, __LINE__, __func__, snd_strerror(s));
- s = snd_pcm_writei(_sound_out, _sound_ring, part_two / AUDIO_NUM_CHANNELS);
+ s = snd_pcm_writei(_sound_out, _sound_ring, part_two / NUM_SOUND_CHANNELS);
if (s < 0)
fprintf(stderr, "%s:%d, %s: snd_pcm_writei failed: %s\n", __FILE__, __LINE__, __func__, snd_strerror(s));
@@ -1010,7 +1050,7 @@ void p_handle_audio(i64 samples_elapsed) {
memset(_sound_ring, 0, part_two * sizeof *_sound_ring);
}
- _sound_position = (_sound_position + num_frames) % MAX_NUM_AUDIO_FRAMES;
+ _sound_position = (_sound_position + num_frames) % MAX_NUM_SOUND_FRAMES;
}
void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
@@ -1020,7 +1060,7 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
return;
if (delay_in_samples < 0) {
- frames += -delay_in_samples * AUDIO_NUM_CHANNELS;
+ frames += -delay_in_samples * NUM_SOUND_CHANNELS;
num_samples -= delay_in_samples;
delay_in_samples = 0;
}
@@ -1028,22 +1068,22 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
if (num_samples <= 0)
return;
- i64 num_frames = num_samples * AUDIO_NUM_CHANNELS;
+ i64 num_frames = num_samples * NUM_SOUND_CHANNELS;
- if (num_frames > MAX_NUM_AUDIO_FRAMES) {
+ if (num_frames > MAX_NUM_SOUND_FRAMES) {
fprintf(stderr, "%s:%d, %s: Sound buffer overflow.\n", __FILE__, __LINE__, __func__);
return;
}
sound_init();
- i64 begin = (_sound_position + delay_in_samples) % MAX_NUM_AUDIO_FRAMES;
+ i64 begin = (_sound_position + delay_in_samples) % MAX_NUM_SOUND_FRAMES;
- if (num_frames <= MAX_NUM_AUDIO_FRAMES - begin)
+ if (num_frames <= MAX_NUM_SOUND_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_one = MAX_NUM_SOUND_FRAMES - begin;
i64 part_two = num_frames - part_one;
for (i64 i = 0; i < part_one; ++i)
@@ -1070,7 +1110,7 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
static i16 _key_table[MAX_NUM_KEYS] = {0};
static b8 _key_repeat[MAX_NUM_KEYS] = {0};
static i64 _frame_time = 0;
-static vec3_f32 _pixels[MAX_NUM_PIXELS] = {0};
+static vec4_f32 _pixels[MAX_NUM_PIXELS] = {0};
static i32 _pixel_size = 0;
static u32 _pixels_scaled[MAX_NUM_PIXELS] = {0};
static u32 _pixels_internal[MAX_NUM_PIXELS] = {0};
@@ -1568,13 +1608,20 @@ i32 p_handle_events(void) {
i32 width = _image.width;
i32 height = _image.height;
- if (_pixel_size <= 1)
- _pixel_size = 1;
- else {
+ if (_pixel_size <= MIN_PIXEL_SIZE)
+ _pixel_size = MIN_PIXEL_SIZE;
+
+ if (_pixel_size > 1) {
width = (i32) floor(((f64) _image.width) / _pixel_size + .5);
height = (i32) floor(((f64) _image.height) / _pixel_size + .5);
}
+ if (g_platform.real_width != _image.width || g_platform.real_height != _image.height) {
+ ++num_events;
+ g_platform.real_width = _image.width;
+ g_platform.real_height = _image.height;
+ }
+
if (g_platform.frame_width != width || g_platform.frame_height != height) {
++num_events;
g_platform.frame_width = width;
@@ -1605,11 +1652,11 @@ void p_render_frame(void) {
if (g_platform.frame_width == _image.width && g_platform.frame_height == _image.height) {
i64 size = g_platform.frame_width * g_platform.frame_height;
for (i64 i = 0; i < size; ++i)
- _pixels_internal[i] = rgb_u32_from_f32(_pixels[i]);
+ _pixels_internal[i] = rgb_u32_from_f32((vec3_f32) { _pixels[i].x, _pixels[i].y, _pixels[i].z });
} else {
i64 size = g_platform.frame_width * g_platform.frame_height;
for (i64 i = 0; i < size; ++i)
- _pixels_scaled[i] = rgb_u32_from_f32(_pixels[i]);
+ _pixels_scaled[i] = rgb_u32_from_f32((vec3_f32) { _pixels[i].x, _pixels[i].y, _pixels[i].z });
for (i64 j = 0; j < _image.height; ++j) {
i64 j0 = (j * g_platform.frame_height) / _image.height;
@@ -1628,7 +1675,7 @@ void p_render_frame(void) {
if (_pixel_size < MAX_PIXEL_SIZE && frame_duration > MAX_FRAME_DURATION)
++_pixel_size;
- else if (_pixel_size > 1 && frame_duration < MIN_FRAME_DURATION)
+ else if (_pixel_size > MIN_PIXEL_SIZE && frame_duration < MIN_FRAME_DURATION)
--_pixel_size;
}
}
@@ -1670,8 +1717,8 @@ 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};
+f32 _sound_ring[MAX_NUM_SOUND_FRAMES] = {0};
+f32 _sound_buffer[MAX_NUM_SOUND_FRAMES] = {0};
i32 p_time_impl(void);
@@ -1689,7 +1736,7 @@ void p_init(void) {
g_platform.input = _input;
g_platform.clipboard = _clipboard_buffer;
g_platform.done = 1;
- _sound_position = AUDIO_AVAIL_MIN % MAX_NUM_AUDIO_FRAMES;
+ _sound_position = SOUND_AVAIL_MIN % MAX_NUM_SOUND_FRAMES;
_sound_read = 0;
}
@@ -1717,11 +1764,11 @@ void p_render_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)
- _pixels_internal[i] = 0xff000000u | rgb_u32_from_f32(_pixels[i]);
+ _pixels_internal[i] = 0xff000000u | rgb_u32_from_f32((vec3_f32) { _pixels[i].x, _pixels[i].y, _pixels[i].z });
} else {
i64 size = g_platform.frame_width * g_platform.frame_height;
for (i64 i = 0; i < size; ++i)
- _pixels_scaled[i] = rgb_u32_from_f32(_pixels[i]);
+ _pixels_scaled[i] = rgb_u32_from_f32((vec3_f32) { _pixels[i].x, _pixels[i].y, _pixels[i].z });
for (i64 j = 0; j < _frame_height; ++j) {
i64 j0 = (j * g_platform.frame_height) / _frame_height;
@@ -1752,7 +1799,7 @@ void p_handle_audio(i64 samples_elapsed) {
if (samples_elapsed <= 0)
return;
- _sound_position = (_sound_position + samples_elapsed * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES;
+ _sound_position = (_sound_position + samples_elapsed * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
}
void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
@@ -1760,7 +1807,7 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
return;
if (delay_in_samples < 0) {
- frames += -delay_in_samples * AUDIO_NUM_CHANNELS;
+ frames += -delay_in_samples * NUM_SOUND_CHANNELS;
num_samples -= delay_in_samples;
delay_in_samples = 0;
}
@@ -1768,17 +1815,17 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
if (num_samples <= 0)
return;
- i64 num_frames = num_samples * AUDIO_NUM_CHANNELS;
- if (num_frames > MAX_NUM_AUDIO_FRAMES)
+ i64 num_frames = num_samples * NUM_SOUND_CHANNELS;
+ if (num_frames > MAX_NUM_SOUND_FRAMES)
return;
- i64 begin = (_sound_position + delay_in_samples * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES;
+ i64 begin = (_sound_position + delay_in_samples * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
- if (num_frames <= MAX_NUM_AUDIO_FRAMES - begin)
+ if (num_frames <= MAX_NUM_SOUND_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_one = MAX_NUM_SOUND_FRAMES - begin;
i64 part_two = num_frames - part_one;
for (i64 i = 0; i < part_one; ++i)
@@ -1810,13 +1857,20 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram
i32 width = _frame_width;
i32 height = _frame_height;
- if (_pixel_size <= 1)
- _pixel_size = 1;
- else {
+ if (_pixel_size <= MIN_PIXEL_SIZE)
+ _pixel_size = MIN_PIXEL_SIZE;
+
+ if (_pixel_size > 1) {
width = (i32) floor(((f64) _frame_width) / _pixel_size + .5);
height = (i32) floor(((f64) _frame_height) / _pixel_size + .5);
}
+ if (g_platform.real_width != _frame_width || g_platform.real_height != _frame_height) {
+ ++num_events;
+ g_platform.real_width = frame_width;
+ g_platform.real_height = frame_height;
+ }
+
if (g_platform.frame_width != width || g_platform.frame_height != height) {
++_num_events;
g_platform.frame_width = width;
@@ -1834,21 +1888,21 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram
}
// Convert interleaved frames to non-interleaved.
- for (i64 j = 0; j < AUDIO_NUM_CHANNELS; ++j)
+ for (i64 j = 0; j < NUM_SOUND_CHANNELS; ++j)
for (i64 i = 0; i < num_samples; ++i) {
- i64 n = (_sound_read + i * AUDIO_NUM_CHANNELS + j) % MAX_NUM_AUDIO_FRAMES;
+ i64 n = (_sound_read + i * NUM_SOUND_CHANNELS + j) % MAX_NUM_SOUND_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;
+ _sound_read = (_sound_read + num_samples * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
if (!g_platform.exact_resolution && do_render) {
i64 frame_duration = p_time() - frame_time;
if (_pixel_size < MAX_PIXEL_SIZE && frame_duration > MAX_FRAME_DURATION)
++_pixel_size;
- else if (_pixel_size > 1 && frame_duration < MIN_FRAME_DURATION)
+ else if (_pixel_size > MIN_PIXEL_SIZE && frame_duration < MIN_FRAME_DURATION)
--_pixel_size;
}
}
@@ -1907,15 +1961,15 @@ __attribute__((export_name("js_keyup"))) void js_keyup(u32 key, u32 mod) {
}
__attribute__((export_name("js_sample_rate"))) f64 js_sample_rate(void) {
- return (f64) AUDIO_SAMPLE_RATE;
+ return (f64) SOUND_SAMPLE_RATE;
}
__attribute__((export_name("js_num_channels"))) i32 js_num_channels(void) {
- return AUDIO_NUM_CHANNELS;
+ return NUM_SOUND_CHANNELS;
}
__attribute__((export_name("js_max_num_audio_frames"))) i32 js_max_num_audio_frames(void) {
- return MAX_NUM_AUDIO_FRAMES;
+ return MAX_NUM_SOUND_FRAMES;
}
__attribute__((export_name("js_sound_buffer"))) void *js_sound_buffer(void) {