summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/ui.c6
-rw-r--r--graphics.c168
-rw-r--r--index.htm24
-rw-r--r--reduced_system_layer.c184
4 files changed, 204 insertions, 178 deletions
diff --git a/examples/ui.c b/examples/ui.c
index 8f1294a..0e8e29e 100644
--- a/examples/ui.c
+++ b/examples/ui.c
@@ -81,16 +81,16 @@ void update_and_render_frame(void) {
}
for (i64 n = 0; n < g_platform.clipboard_size;) {
- c32 c = utf8_read(g_platform.clipboard_size - n, g_platform.clipboard + n);
+ UTF8_Char c = utf8_read(g_platform.clipboard_size - n, g_platform.clipboard + n);
if (text_len < (i64) (sizeof text / sizeof *text)) {
for (i64 j = text_len; j > cursor; --j)
text[j] = text[j - 1];
- text[cursor++] = c;
+ text[cursor++] = c.code;
++text_len;
}
- n += utf8_size(c);
+ n += c.len;
}
} break;
diff --git a/graphics.c b/graphics.c
index 6f786c5..40052ad 100644
--- a/graphics.c
+++ b/graphics.c
@@ -83,7 +83,7 @@ void draw_selection_cursor(Brush brush, f64 x, f64 y, f64 width, f64 height, f64
#ifndef GRAPHICS_IMPL_GUARD_
#define GRAPHICS_IMPL_GUARD_
-static f64 min3(f64 a, f64 b, f64 c) {
+static f64 min3_(f64 a, f64 b, f64 c) {
if (a < b && a < c)
return a;
if (b < c)
@@ -91,7 +91,7 @@ static f64 min3(f64 a, f64 b, f64 c) {
return c;
}
-static f64 max3(f64 a, f64 b, f64 c) {
+static f64 max3_(f64 a, f64 b, f64 c) {
if (a > b && a > c)
return a;
if (b > c)
@@ -99,7 +99,7 @@ static f64 max3(f64 a, f64 b, f64 c) {
return c;
}
-static b8 same_sign(f64 a, f64 b) {
+static b8 same_sign_(f64 a, f64 b) {
if (a >= EPSILON && b <= -EPSILON) return 0;
if (a <= -EPSILON && b >= EPSILON) return 0;
return 1;
@@ -109,18 +109,18 @@ static u64 _bitfont[] = {
0xbc0000000000, 0xc00300000, 0x5fd5040093f24fc9, 0xa00a2c2a1a280105, 0xc000415e6f, 0x400000020be0000, 0x1c38a8400000007d, 0x40002043e1020215, 0x408102000000010, 0x9800000000020002, 0xf913e00000033, 0x53200000207c8800, 0x3654880000099, 0x54b800000f840e00, 0xe953c000001a, 0x953e000000674080, 0x1e54b800000f, 0x490000000000240, 0x88a08000000, 0x20a220050a142850, 0x6520800000, 0x912f801eab260be, 0x800034952bf0001f, 0xc850bf0000921427, 0xf00010a54afc0003, 0xd29427800002142b, 0x840007e1023f0000, 0x7d09100000217e, 0x3f000188a08fc000, 0xc30c0cfc00000810, 0x27803f101013f00f, 0xc244bf0000f214, 0x4bf0002f21427800, 0xc254a480006c24, 0x407c00102fc08100, 0xf208080f0000fa0, 0x531007d81c607c0, 0xc208288c031141, 0x83fc00046954b10, 0x180e03000000, 0x41040000000ff04, 0x8102040810000404, 0x2a54600000000101, 0x309123e0000e, 0xc912180000a22447, 0x8000062a54700007, 0xe52a4300000029f0, 0xa0000602043e0001, 0x1d48000002074, 0x1f000003610f8000, 0x13e04f800000010, 0x470000780813e00f, 0x184893e0000e224, 0x23e0001f12243000, 0x82a54100000008, 0x40780000009f0200, 0xe208080e0001f20, 0xa22007981860780, 0x82082888022282, 0x16c200004ca95320, 0x7f000004, 0x408200000086d04, 0x8204,
};
-#define CHAR_NUM_BITS_X 6
-#define CHAR_NUM_BITS_Y 7
-#define CHAR_NUM_BITS (CHAR_NUM_BITS_X * CHAR_NUM_BITS_Y)
+#define CHAR_NUM_BITS_X_ 6
+#define CHAR_NUM_BITS_Y_ 7
+#define CHAR_NUM_BITS_ (CHAR_NUM_BITS_X_ * CHAR_NUM_BITS_Y_)
-static i64 char_column_offset(c32 c, i64 column_index) {
- if (column_index < 0 || column_index >= CHAR_NUM_BITS_X)
+static i64 char_column_offset_(c32 c, i64 column_index) {
+ if (column_index < 0 || column_index >= CHAR_NUM_BITS_X_)
return -1;
- return (c - 32) * CHAR_NUM_BITS + column_index * CHAR_NUM_BITS_Y;
+ return (c - 32) * CHAR_NUM_BITS_ + column_index * CHAR_NUM_BITS_Y_;
}
-static b8 char_bit(i64 column_offset, i64 row_index) {
- if (column_offset < 0 || row_index < 0 || row_index >= CHAR_NUM_BITS_Y)
+static b8 char_bit_(i64 column_offset, i64 row_index) {
+ if (column_offset < 0 || row_index < 0 || row_index >= CHAR_NUM_BITS_Y_)
return 0;
i64 bit_index = column_offset + row_index;
@@ -131,34 +131,34 @@ static b8 char_bit(i64 column_offset, i64 row_index) {
return !!(_bitfont[qword_index] & mask);
}
-static u64 char_column_convolved(c32 c, i64 column_index) {
- if (column_index < 0 || column_index >= CHAR_NUM_BITS_X)
+static u64 char_column_convolved_(c32 c, i64 column_index) {
+ if (column_index < 0 || column_index >= CHAR_NUM_BITS_X_)
return 0;
u64 column = 0;
- i64 offset = char_column_offset(c, column_index);
+ i64 offset = char_column_offset_(c, column_index);
- for (i64 y = 0; y < CHAR_NUM_BITS_Y; ++y)
- if (char_bit(offset, y))
+ for (i64 y = 0; y < CHAR_NUM_BITS_Y_; ++y)
+ if (char_bit_(offset, y))
column |= 3ull << y;
return column;
}
-static b8 char_column_empty(c32 c, i64 column_index) {
- if (column_index < 0 || column_index >= CHAR_NUM_BITS_X)
+static b8 char_column_empty_(c32 c, i64 column_index) {
+ if (column_index < 0 || column_index >= CHAR_NUM_BITS_X_)
return 1;
- i64 offset = char_column_offset(c, column_index);
+ i64 offset = char_column_offset_(c, column_index);
- for (i64 y = 0; y < CHAR_NUM_BITS_Y; ++y)
- if (char_bit(offset, y))
+ for (i64 y = 0; y < CHAR_NUM_BITS_Y_; ++y)
+ if (char_bit_(offset, y))
return 0;
return 1;
}
-static i64 char_width(c32 c) {
+static i64 char_width_(c32 c) {
if (c < 32)
return 0;
if (c == ' ' || c > 127)
@@ -166,22 +166,22 @@ static i64 char_width(c32 c) {
i64 width = 0;
- for (; width < CHAR_NUM_BITS_X; ++width)
- if (char_column_empty(c, width) && char_column_empty(c, width + 1))
+ for (; width < CHAR_NUM_BITS_X_; ++width)
+ if (char_column_empty_(c, width) && char_column_empty_(c, width + 1))
break;
return width;
}
-static i64 char_spacing(i64 num_chars, c32 *text, i64 index) {
+static i64 char_spacing_(i64 num_chars, c32 *text, i64 index) {
if (text == NULL)
return 0;
if (index < 0 || index + 1 >= num_chars)
return 0;
- u64 a = char_column_convolved(text[index], char_width(text[index]) - 1);
- u64 b = char_column_convolved(text[index + 1], 0);
+ u64 a = char_column_convolved_(text[index], char_width_(text[index]) - 1);
+ u64 b = char_column_convolved_(text[index + 1], 0);
if (!!(a & b))
return 1;
@@ -189,7 +189,7 @@ static i64 char_spacing(i64 num_chars, c32 *text, i64 index) {
return 0;
}
-static i64 text_cursor(i64 num_chars, c32 *text) {
+static i64 text_cursor_(i64 num_chars, c32 *text) {
if (text == NULL)
return 0;
@@ -200,20 +200,20 @@ static i64 text_cursor(i64 num_chars, c32 *text) {
if (text[i] == '\n')
cursor = 0;
else if (text[i] == '\b' && i > 0)
- cursor -= char_width(text[i - 1]) + char_spacing(num_chars, text, i - 1);
+ cursor -= char_width_(text[i - 1]) + char_spacing_(num_chars, text, i - 1);
else if (text[i] == '\r')
cursor = 0;
else
- cursor += char_width(' ') + char_spacing(num_chars, text, i);
+ cursor += char_width_(' ') + char_spacing_(num_chars, text, i);
continue;
}
- cursor += char_width(text[i]) + char_spacing(num_chars, text, i);
+ cursor += char_width_(text[i]) + char_spacing_(num_chars, text, i);
}
return cursor;
}
-static i64 enum_text_columns(i64 num_chars, c32 *text) {
+static i64 enum_text_columns_(i64 num_chars, c32 *text) {
if (text == NULL)
return 0;
@@ -229,16 +229,16 @@ static i64 enum_text_columns(i64 num_chars, c32 *text) {
} else if (text[i] == '\b' && i > 0) {
if (cols < n)
cols = n;
- n -= char_width(text[i - 1]) + char_spacing(num_chars, text, i - 1);
+ n -= char_width_(text[i - 1]) + char_spacing_(num_chars, text, i - 1);
} else if (text[i] == '\r') {
if (cols < n)
cols = n;
n = 0;
} else
- n += char_width(' ') + char_spacing(num_chars, text, i);
+ n += char_width_(' ') + char_spacing_(num_chars, text, i);
continue;
}
- n += char_width(text[i]) + char_spacing(num_chars, text, i);
+ n += char_width_(text[i]) + char_spacing_(num_chars, text, i);
}
if (cols < n)
@@ -247,7 +247,7 @@ static i64 enum_text_columns(i64 num_chars, c32 *text) {
return cols;
}
-static i64 enum_text_rows(i64 num_chars, c32 *text) {
+static i64 enum_text_rows_(i64 num_chars, c32 *text) {
if (text == NULL)
return 0;
@@ -257,13 +257,13 @@ static i64 enum_text_rows(i64 num_chars, c32 *text) {
if (i == num_chars || text[i] == '\n') {
if (rows > 0)
++rows;
- rows += CHAR_NUM_BITS_Y;
+ rows += CHAR_NUM_BITS_Y_;
}
return rows;
}
-static void brush_defaults(Brush *b) {
+static void brush_defaults_(Brush *b) {
if (g_platform.frame_width > 0) {
if (b->scale.x == 0.) b->scale.x = ((f64) g_platform.frame_width) / g_platform.real_width;
if (b->scale.y == 0.) b->scale.y = ((f64) g_platform.frame_height) / g_platform.real_height;
@@ -276,11 +276,11 @@ static void brush_defaults(Brush *b) {
}
}
-static void draw_text(Brush brush, f64 x_, f64 y_, f64 scale_x, f64 scale_y, i64 num_chars, c32 *text) {
+static void draw_text_(Brush brush, f64 x_, f64 y_, f64 scale_x, f64 scale_y, i64 num_chars, c32 *text) {
if (text == NULL)
return;
- brush_defaults(&brush);
+ brush_defaults_(&brush);
x_ = brush.position.x + x_ * brush.scale.x;
y_ = brush.position.y + y_ * brush.scale.y;
@@ -294,24 +294,24 @@ static void draw_text(Brush brush, f64 x_, f64 y_, f64 scale_x, f64 scale_y, i64
f64 y = y_;
f64 kx = scale_x;
- f64 h = scale_y * CHAR_NUM_BITS_Y;
+ f64 h = scale_y * CHAR_NUM_BITS_Y_;
for (i64 n = 0; n < num_chars; ++n) {
if (text[n] <= ' ') {
if (text[n] == '\n') {
x = x_;
- y += scale_y * (CHAR_NUM_BITS_Y + 1);
+ y += scale_y * (CHAR_NUM_BITS_Y_ + 1);
}
else if (text[n] == '\b' && n > 0)
- x -= kx * (char_width(text[n - 1]) + char_spacing(num_chars, text, n - 1));
+ x -= kx * (char_width_(text[n - 1]) + char_spacing_(num_chars, text, n - 1));
else if (text[n] == '\r')
x = x_;
else
- x += kx * (char_width(' ') + char_spacing(num_chars, text, n));
+ x += kx * (char_width_(' ') + char_spacing_(num_chars, text, n));
continue;
}
- i64 num_cols = char_width(text[n]);
+ i64 num_cols = char_width_(text[n]);
f64 w = num_cols * kx;
i64 i0 = (i64) floor(x);
@@ -324,20 +324,20 @@ static void draw_text(Brush brush, f64 x_, f64 y_, f64 scale_x, f64 scale_y, i64
if (i >= g_platform.frame_width) break;
i64 column = ((i - i0) * num_cols) / (i1 - i0);
- i64 offset = char_column_offset(text[n], column);
+ i64 offset = char_column_offset_(text[n], column);
for (i64 j = j0; j < j1; ++j) {
if (j < 0) continue;
if (j >= g_platform.frame_height) break;
- i64 row = ((j - j0) * CHAR_NUM_BITS_Y) / (j1 - j0);
+ i64 row = ((j - j0) * CHAR_NUM_BITS_Y_) / (j1 - j0);
- if (char_bit(offset, row))
+ if (char_bit_(offset, row))
put_pixel(brush, i, j);
}
}
- x += kx * (num_cols + char_spacing(num_chars, text, n));
+ x += kx * (num_cols + char_spacing_(num_chars, text, n));
}
}
@@ -355,7 +355,7 @@ static f64 gamma_re_(f64 x) {
// ================================================================
-vec3_f32 gamma_apply (vec3_f32 rgb) {
+vec3_f32 gamma_apply(vec3_f32 rgb) {
return (vec3_f32) {
.x = (f32) gamma_(rgb.x),
.y = (f32) gamma_(rgb.y),
@@ -507,9 +507,9 @@ b8 triangle_contains(f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2, f64 px, f64
f64 pz2 = (px - x2) * (y1 - y2) - (x1 - x2) * (py - y2);
return
- same_sign(z0, pz0)
- && same_sign(z1, pz1)
- && same_sign(z2, pz2);
+ same_sign_(z0, pz0)
+ && same_sign_(z1, pz1)
+ && same_sign_(z2, pz2);
}
b8 ellipse_contains(f64 x0, f64 y0, f64 width, f64 height, f64 px, f64 py) {
@@ -552,7 +552,7 @@ b8 line_contains(f64 x0, f64 y0, f64 x1, f64 y1, f64 width, f64 px, f64 py) {
}
void put_pixel(Brush brush, i64 x, i64 y) {
- brush_defaults(&brush);
+ brush_defaults_(&brush);
if (x < 0 || x >= brush.buffer.width || y < 0 || y >= brush.buffer.height)
return;
@@ -597,7 +597,7 @@ void put_pixel(Brush brush, i64 x, i64 y) {
void draw_pixels(Brush brush, f64 x, f64 y, f64 width, f64 height, Pixel_Buffer src) {
// FIXME PERF
- brush_defaults(&brush);
+ brush_defaults_(&brush);
f64 x0, y0, x1, y1;
@@ -633,7 +633,7 @@ void draw_pixels(Brush brush, f64 x, f64 y, f64 width, f64 height, Pixel_Buffer
}
void fill_rectangle(Brush brush, f64 x, f64 y, f64 width, f64 height) {
- brush_defaults(&brush);
+ brush_defaults_(&brush);
f64 x0, y0, x1, y1;
@@ -724,7 +724,7 @@ void fill_triangle(Brush brush, f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2)
// FIXME PERF:
// Implement better algorithm.
- brush_defaults(&brush);
+ brush_defaults_(&brush);
x0 = brush.position.x + x0 * brush.scale.x;
y0 = brush.position.y + y0 * brush.scale.y;
@@ -735,10 +735,10 @@ void fill_triangle(Brush brush, f64 x0, f64 y0, f64 x1, f64 y1, f64 x2, f64 y2)
x2 = brush.position.x + x2 * brush.scale.x;
y2 = brush.position.y + y2 * brush.scale.y;
- i64 min_x = (i64) floor(min3(x0, x1, x2));
- i64 min_y = (i64) floor(min3(y0, y1, y2));
- i64 max_x = (i64) ceil (max3(x0, x1, x2));
- i64 max_y = (i64) ceil (max3(y0, y1, y2));
+ i64 min_x = (i64) floor(min3_(x0, x1, x2));
+ i64 min_y = (i64) floor(min3_(y0, y1, y2));
+ i64 max_x = (i64) ceil (max3_(x0, x1, x2));
+ i64 max_y = (i64) ceil (max3_(y0, y1, y2));
for (i64 j = min_y; j <= max_y; ++j)
for (i64 i = min_x; i <= max_x; ++i)
@@ -750,7 +750,7 @@ void fill_ellipse(Brush brush, f64 x, f64 y, f64 width, f64 height) {
// FIXME PERF:
// Implement better algorithm.
- brush_defaults(&brush);
+ brush_defaults_(&brush);
f64 x0, y0, x1, y1;
@@ -806,8 +806,8 @@ void draw_text_area(Brush brush, f64 x, f64 y, f64 width, f64 height, f64 max_sc
if (max_scale_x < EPSILON || max_scale_y < EPSILON)
return;
- i64 num_columns = enum_text_columns(num_chars, text);
- i64 num_rows = enum_text_rows(num_chars, text);
+ i64 num_columns = enum_text_columns_(num_chars, text);
+ i64 num_rows = enum_text_rows_(num_chars, text);
f64 scale_x = width / num_columns;
f64 scale_y = height / num_rows;
@@ -820,17 +820,17 @@ void draw_text_area(Brush brush, f64 x, f64 y, f64 width, f64 height, f64 max_sc
kx = k * max_scale_x;
ky = k * max_scale_y;
- draw_text(brush, x, y, kx, ky, num_chars, text);
+ draw_text_(brush, x, y, kx, ky, num_chars, text);
}
void draw_selection_cursor(Brush brush, f64 x, f64 y, f64 width, f64 height, f64 max_scale_x, f64 max_scale_y, i64 cursor, i64 selection, i64 num_chars, c32 *text) {
if (max_scale_x < EPSILON || max_scale_y < EPSILON)
return;
- i64 num_columns = enum_text_columns(num_chars, text);
- i64 num_rows = enum_text_rows(num_chars, text);
- i64 cursor_x = text_cursor(cursor, text);
- i64 cursor_y = enum_text_rows(cursor, text);
+ i64 num_columns = enum_text_columns_(num_chars, text);
+ i64 num_rows = enum_text_rows_(num_chars, text);
+ i64 cursor_x = text_cursor_(cursor, text);
+ i64 cursor_y = enum_text_rows_(cursor, text);
f64 scale_x = width / num_columns;
f64 scale_y = height / num_rows;
@@ -847,54 +847,54 @@ void draw_selection_cursor(Brush brush, f64 x, f64 y, f64 width, f64 height, f64
i64 selection_x, selection_y;
if (selection > 0) {
- selection_x = text_cursor(cursor + selection, text);
- selection_y = enum_text_rows(cursor + selection, text);
+ selection_x = text_cursor_(cursor + selection, text);
+ selection_y = enum_text_rows_(cursor + selection, text);
} else {
selection_x = cursor_x;
selection_y = cursor_y;
- cursor_x = text_cursor(cursor + selection, text);
- cursor_y = enum_text_rows(cursor + selection, text);
+ cursor_x = text_cursor_(cursor + selection, text);
+ cursor_y = enum_text_rows_(cursor + selection, text);
}
if (cursor_y == selection_y)
fill_rectangle(
brush,
x + kx * cursor_x,
- y + ky * cursor_y - ky * (CHAR_NUM_BITS_Y + 1),
+ y + ky * cursor_y - ky * (CHAR_NUM_BITS_Y_ + 1),
kx * (selection_x - cursor_x),
- ky * (CHAR_NUM_BITS_Y + 1)
+ ky * (CHAR_NUM_BITS_Y_ + 1)
);
else {
fill_rectangle(
brush,
x + kx * cursor_x,
- y + ky * cursor_y - ky * (CHAR_NUM_BITS_Y + 1),
+ y + ky * cursor_y - ky * (CHAR_NUM_BITS_Y_ + 1),
kx * (num_columns - cursor_x),
- ky * (CHAR_NUM_BITS_Y + 1)
+ ky * (CHAR_NUM_BITS_Y_ + 1)
);
- for (i64 j = cursor_y + CHAR_NUM_BITS_Y + 1; j < selection_y; j += CHAR_NUM_BITS_Y + 1)
+ for (i64 j = cursor_y + CHAR_NUM_BITS_Y_ + 1; j < selection_y; j += CHAR_NUM_BITS_Y_ + 1)
fill_rectangle(
brush,
x,
- y + ky * j - ky * (CHAR_NUM_BITS_Y + 1),
+ y + ky * j - ky * (CHAR_NUM_BITS_Y_ + 1),
kx * num_columns,
- ky * (CHAR_NUM_BITS_Y + 1)
+ ky * (CHAR_NUM_BITS_Y_ + 1)
);
fill_rectangle(
brush,
x,
- y + ky * selection_y - ky * (CHAR_NUM_BITS_Y + 1),
+ y + ky * selection_y - ky * (CHAR_NUM_BITS_Y_ + 1),
kx * selection_x,
- ky * (CHAR_NUM_BITS_Y + 1)
+ ky * (CHAR_NUM_BITS_Y_ + 1)
);
}
} else
fill_rectangle(
brush,
x + kx * cursor_x,
- y + ky * cursor_y - ky * CHAR_NUM_BITS_Y,
+ y + ky * cursor_y - ky * CHAR_NUM_BITS_Y_,
kx * .5,
- ky * (CHAR_NUM_BITS_Y - 1)
+ ky * (CHAR_NUM_BITS_Y_ - 1)
);
}
diff --git a/index.htm b/index.htm
index 1339f23..4542dc7 100644
--- a/index.htm
+++ b/index.htm
@@ -77,13 +77,19 @@
this.pixels_address = program.exports.js_pixels();
this.frames = new Float32Array(this.memory_buffer, this.sound_buffer_address, program.exports.js_max_num_sound_frames());
- let bytes = new Uint8Array(this.memory_buffer);
let title_address = program.exports.js_title();
- let title_len = 0;
- while (bytes[title_address + title_len] != 0)
- ++title_len;
- let title_buffer = new ArrayBuffer(title_len);
- new Uint8Array(title_buffer).set(bytes.subarray(title_address, title_address + title_len));
+
+ let title_buffer;
+
+ if (title_address != 0) {
+ let bytes = new Uint8Array(this.memory_buffer);
+ let title_len = 0;
+ while (bytes[title_address + title_len] != 0)
+ ++title_len;
+ let title_buffer = new ArrayBuffer(title_len);
+ new Uint8Array(title_buffer).set(bytes.subarray(title_address, title_address + title_len));
+ } else
+ title_buffer = undefined;
this.port.postMessage({
id : "init",
@@ -448,8 +454,10 @@
let message_handlers = {
init : (ev) => {
- document.title = new TextDecoder("utf8").decode(new Uint8Array(ev.title_buffer));
- sound_ready = true;
+ if (ev.title_buffer != undefined)
+ document.title = new TextDecoder("utf8").decode(new Uint8Array(ev.title_buffer));
+
+ sound_ready = true;
window.requestAnimationFrame(animation_frame);
},
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__)
@@ -493,6 +495,21 @@ typedef struct {
} 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;
i32 frame_height;
@@ -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;