a-game

2D platformer written from scratch.
git clone git://git.amin.space/a-game.git
Log | Files | Refs | README | LICENSE

commit bcc7a806756427240bb9f33d7c89007d41b97bef
parent 64e92ec7c143e6873858dd3543bf5ade6235e14a
Author: amin <dev@aminmesbah.com>
Date:   Mon,  5 Feb 2024 07:41:40 +0000

Fix wasm builds

- Get rid of bare `inline`, which has a very esoteric purpose in C, and anyway
  was breaking nonoptimized builds.
- Get rid of `inline` altogether. Compilers do their own thing anyway.
- Invoke clang's public API, not the private one that breaks.
- Don't depend on math.h (how did that ever work!?)

FossilOrigin-Name: dbc8a3e3370f2feeadc8fe5920f5dfeab38423d521b4f285a14e5d1507698ab2
Diffstat:
Mbuild_wasm.sh | 52++++++++++++++++++++--------------------------------
Msrc/am_math.h | 130++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/game.c | 6+++---
Msrc/game.h | 3++-
Msrc/input.c | 2+-
Msrc/intrinsics.h | 2+-
Msrc/memory.c | 2+-
Msrc/platform_wasm.c | 30+++++++++++++++++++++++++++---
Msrc/platform_wasm_js_symbols.txt | 13+++++++++----
Msrc/platform_wasm_loader.js | 21++++++++++++++++++---
Msrc/webgl.h | 94++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/world.c | 8++++----
12 files changed, 198 insertions(+), 165 deletions(-)

diff --git a/build_wasm.sh b/build_wasm.sh @@ -15,37 +15,25 @@ cp -r shader/ $wasm_dir cp -r assets/ $wasm_dir clang_version=$(clang -v 2>&1 | head -1 | cut -d " " -f 3) -clang \ - -cc1 \ - -Ofast \ - -emit-llvm-bc \ - -triple=wasm32-unknown-unknown-unknown-wasm \ - -ffreestanding \ - -fno-builtin \ - -std=c11 \ - -internal-isystem /usr/lib/clang/$clang_version/include \ - -internal-externc-isystem /usr/include \ - -DPLATFORM_WASM \ - -o $wasm_dir/wasm.bc \ +clang \ + --no-standard-libraries \ + --target=wasm32 \ + -DPLATFORM_WASM \ + -O3 \ + -ffreestanding \ + -std=c11 \ + -Wl,--allow-undefined-file=src/platform_wasm_js_symbols.txt \ + -Wl,--export=init \ + -Wl,--export=key_callback \ + -Wl,--export=render \ + -Wl,--export=window_resize \ + -Wl,--import-memory \ + -Wl,--no-entry \ + -o $wasm_dir/binary.wasm \ src/platform_wasm.c -llvm-link -o $wasm_dir/wasm.bc $wasm_dir/wasm.bc -opt -O3 -disable-simplify-libcalls $wasm_dir/wasm.bc -o $wasm_dir/wasm.bc -llc -O3 -disable-simplify-libcalls -filetype=obj $wasm_dir/wasm.bc -o $wasm_dir/wasm.o - -wasm-ld \ - --no-entry $wasm_dir/wasm.o \ - -o $wasm_dir/binary.wasm \ - -allow-undefined-file src/platform_wasm_js_symbols.txt \ - --export=init \ - --export=render \ - --export=window_resize \ - --export=key_callback \ - --import-memory - -rm $wasm_dir/*.o -rm $wasm_dir/*.bc - -current_commit=$(git rev-parse HEAD) -echo "<!-- Source Code: https://git.amin.space/a-game/tree/?id=$current_commit -->" \ - >> $wasm_dir/index.html +# TODO: embed the fossil/git commit like we used to back when this was hosted +# in git. +#current_commit=$(git rev-parse HEAD) +#echo "<!-- Source Code: https://git.amin.space/a-game/tree/?id=$current_commit -->" \ +# >> $wasm_dir/index.html diff --git a/src/am_math.h b/src/am_math.h @@ -5,30 +5,30 @@ // TODO: make sure these functions are inlineable and that the compiler does // indeed inline them. -internal inline f32 math_min(f32 a, f32 b) +internal f32 math_min(f32 a, f32 b) { f32 min = a < b ? a : b; return min; } -internal inline f32 math_max(f32 a, f32 b) +internal f32 math_max(f32 a, f32 b) { f32 max = a > b ? a : b; return max; } -internal inline u32 math_pow_of_2(u32 exponent) +internal u32 math_pow_of_2(u32 exponent) { u32 result = 1 << exponent; return result; } -internal inline i32 math_round(f32 n) +internal i32 math_round(f32 n) { return n < 0.0f ? n - 0.5 : n + 0.5; } -internal inline f32 math_wrap(f32 n, f32 min, f32 max) +internal f32 math_wrap(f32 n, f32 min, f32 max) { if (n > max) { @@ -45,26 +45,26 @@ internal inline f32 math_wrap(f32 n, f32 min, f32 max) } // TODO: Test this against floorf -internal inline f32 math_floor(f32 x) +internal f32 math_floor(f32 x) { f32 result = (f32)((i32)x - (x < 0.0f)); return result; } // TODO: Test this against ceilf -internal inline i32 math_ceil(f32 x) +internal i32 math_ceil(f32 x) { i32 result = -math_floor(-x); return result; } -internal inline bool math_f32_is_i32(f32 x) +internal bool math_f32_is_i32(f32 x) { bool result = ((i32)x) == x; return result; } -internal inline m4 math_m4_init_id() +internal m4 math_m4_init_id() { m4 m = {0}; m.E[0][0] = 1.0f; @@ -74,7 +74,7 @@ internal inline m4 math_m4_init_id() return m; } -internal inline void math_m4_valueptr(m4 m, f32* out_valueptr) +internal void math_m4_valueptr(m4 m, f32* out_valueptr) { for (u8 v = 0; v < 16; ++v) { @@ -84,7 +84,7 @@ internal inline void math_m4_valueptr(m4 m, f32* out_valueptr) } } -internal inline bool math_m4m4_eq(m4 mat1, m4 mat2) +internal bool math_m4m4_eq(m4 mat1, m4 mat2) { for (u8 i = 0; i < 4; ++i) { @@ -99,7 +99,7 @@ internal inline bool math_m4m4_eq(m4 mat1, m4 mat2) return true; } -internal inline m4 math_m4m4_m(m4 mat1, m4 mat2) +internal m4 math_m4m4_m(m4 mat1, m4 mat2) { m4 r = { .E[0][0] = (mat1.E[0][0] * mat2.E[0][0]) + (mat1.E[0][1] * mat2.E[1][0]) + (mat1.E[0][2] * mat2.E[2][0]) + (mat1.E[0][3] * mat2.E[3][0]), @@ -125,7 +125,7 @@ internal inline m4 math_m4m4_m(m4 mat1, m4 mat2) return r; } -internal inline v4 math_m4v4_m(m4 m, v4 v) +internal v4 math_m4v4_m(m4 m, v4 v) { v4 r = { .x = (m.E[0][0] * v.x) + (m.E[0][1] * v.y) + (m.E[0][2] * v.z) + (m.E[0][3] * v.w), @@ -136,12 +136,12 @@ internal inline v4 math_m4v4_m(m4 m, v4 v) return r; } -internal inline bool math_approx(f32 n, f32 compare, f32 epsilon) +internal bool math_approx(f32 n, f32 compare, f32 epsilon) { return fabsf(n - compare) <= epsilon; } -internal inline bool math_v2_is_nonzero(v2 v) +internal bool math_v2_is_nonzero(v2 v) { // TODO: Figure out whether this epsilon is universally appropriate. f32 epsilon = 0.000001; @@ -151,7 +151,7 @@ internal inline bool math_v2_is_nonzero(v2 v) ); } -internal inline v2 math_v2_a(v2 vec1, v2 vec2) +internal v2 math_v2_a(v2 vec1, v2 vec2) { v2 r = { .x = vec1.x + vec2.x, @@ -160,24 +160,24 @@ internal inline v2 math_v2_a(v2 vec1, v2 vec2) return r; } -internal inline v2 math_v2_negate(v2 v) +internal v2 math_v2_negate(v2 v) { v2 r = {-v.x, -v.y}; return r; } -internal inline v2 math_v2_s(v2 vec1, v2 vec2) +internal v2 math_v2_s(v2 vec1, v2 vec2) { return math_v2_a(vec1, math_v2_negate(vec2)); } -internal inline v2 math_v2f_m(v2 v, f32 s) +internal v2 math_v2f_m(v2 v, f32 s) { v2 r = {v.x * s, v.y * s}; return r; } -internal inline f32 math_v2_length(v2 v) +internal f32 math_v2_length(v2 v) { // TODO: Use inner product of v with itself return sqrtf((v.x * v.x) + (v.y * v.y)); @@ -185,14 +185,14 @@ internal inline f32 math_v2_length(v2 v) // TODO: handle degenerate case where l is near 0.0f // TODO: scale by 1.0f / l -internal inline v2 math_v2_normalize(v2 v) +internal v2 math_v2_normalize(v2 v) { f32 l = math_v2_length(v); v2 r = {v.x / l, v.y / l}; return r; } -internal inline f32 math_v2_dot(v2 vec1, v2 vec2) +internal f32 math_v2_dot(v2 vec1, v2 vec2) { // dot product, a.k.a. inner product or scalar product f32 dot_product = (vec1.x * vec2.x) + (vec1.y * vec2.y); @@ -204,25 +204,25 @@ internal inline f32 math_v2_dot(v2 vec1, v2 vec2) return dot_product; } -internal inline v2i math_v2i_a(v2i vec1, v2i vec2) +internal v2i math_v2i_a(v2i vec1, v2i vec2) { v2i r = {vec1.x + vec2.x, vec1.y + vec2.y}; return r; } -internal inline bool math_v2i_eq(v2i vec1, v2i vec2) +internal bool math_v2i_eq(v2i vec1, v2i vec2) { bool result = (vec1.x == vec2.x && vec1.y == vec2.y); return result; } -internal inline bool math_v2u_eq(v2u vec1, v2u vec2) +internal bool math_v2u_eq(v2u vec1, v2u vec2) { bool result = (vec1.x == vec2.x && vec1.y == vec2.y); return result; } -internal inline v3 math_v3_cross(v3 vec1, v3 vec2) +internal v3 math_v3_cross(v3 vec1, v3 vec2) { // cross product, a.k.a. outer product or vector product v3 r = { @@ -233,7 +233,7 @@ internal inline v3 math_v3_cross(v3 vec1, v3 vec2) return r; } -internal inline f32 math_v3_length(v3 v) +internal f32 math_v3_length(v3 v) { // TODO: Use inner product of v with itself // NOTE: math_v3_dot(v, v) returns: @@ -246,13 +246,13 @@ internal inline f32 math_v3_length(v3 v) return sqrtf((v.x * v.x) + (v.y * v.y) + (v.z * v.z)); } -internal inline v3 math_v3f_m(v3 v, f32 s) +internal v3 math_v3f_m(v3 v, f32 s) { v3 r = {.x = v.x * s, .y = v.y * s, .z = v.z * s}; return r; } -internal inline v3 math_v3_negate(v3 v) +internal v3 math_v3_negate(v3 v) { v3 r = {.x = -v.x, .y = -v.y, .z = -v.z}; return r; @@ -260,14 +260,14 @@ internal inline v3 math_v3_negate(v3 v) // TODO: handle degenerate case where l is near 0.0f // TODO: scale by 1.0f / l -internal inline v3 math_v3_normalize(v3 v) +internal v3 math_v3_normalize(v3 v) { f32 l = math_v3_length(v); v3 r = {v.x / l, v.y / l, v.z / l}; return r; } -internal inline v3 math_v3_a(v3 vec1, v3 vec2) +internal v3 math_v3_a(v3 vec1, v3 vec2) { v3 r = { .x = vec1.x + vec2.x, @@ -277,12 +277,12 @@ internal inline v3 math_v3_a(v3 vec1, v3 vec2) return r; } -internal inline v3 math_v3_s(v3 vec1, v3 vec2) +internal v3 math_v3_s(v3 vec1, v3 vec2) { return math_v3_a(vec1, math_v3_negate(vec2)); } -internal inline v3 math_v3_from_rgb(i32 rgb) +internal v3 math_v3_from_rgb(i32 rgb) { v3 result = { .x = ((rgb >> 16) & 0xFF) / 255.0f, @@ -292,7 +292,7 @@ internal inline v3 math_v3_from_rgb(i32 rgb) return result; } -internal inline bool math_v4v4_eq(v4 vec1, v4 vec2) +internal bool math_v4v4_eq(v4 vec1, v4 vec2) { for (u8 i = 0; i < 4; ++i) { @@ -304,7 +304,7 @@ internal inline bool math_v4v4_eq(v4 vec1, v4 vec2) return true; } -internal inline void math_clamp(f32 *f, f32 min, f32 max) +internal void math_clamp(f32 *f, f32 min, f32 max) { if (*f < min) { @@ -316,23 +316,23 @@ internal inline void math_clamp(f32 *f, f32 min, f32 max) } } -internal inline f32 math_deg(f32 rad) +internal f32 math_deg(f32 rad) { return rad * (180.0f / M_PI); } -internal inline f32 math_lerpf(f32 f, f32 min, f32 max) +internal f32 math_lerpf(f32 f, f32 min, f32 max) { assert(f >= 0.0f && f <= 1.0f); return (1.0f - f) * min + f * max; } -internal inline f32 math_rad(f32 deg) +internal f32 math_rad(f32 deg) { return deg * (M_PI / 180.0f); } -internal inline m4 math_rotate_x(m4 m, f32 rad) +internal m4 math_rotate_x(m4 m, f32 rad) { f32 c = cosf(rad); f32 s = sinf(rad); @@ -348,7 +348,7 @@ internal inline m4 math_rotate_x(m4 m, f32 rad) return math_m4m4_m(m, r); } -internal inline m4 math_rotate_y(m4 m, f32 rad) +internal m4 math_rotate_y(m4 m, f32 rad) { f32 c = cosf(rad); f32 s = sinf(rad); @@ -364,7 +364,7 @@ internal inline m4 math_rotate_y(m4 m, f32 rad) return math_m4m4_m(m, r); } -internal inline m4 math_rotate_z(m4 m, f32 rad) +internal m4 math_rotate_z(m4 m, f32 rad) { f32 c = cosf(rad); f32 s = sinf(rad); @@ -380,7 +380,7 @@ internal inline m4 math_rotate_z(m4 m, f32 rad) return math_m4m4_m(m, r); } -internal inline m4 math_rotate(m4 m, f32 rad, v3 axis) +internal m4 math_rotate(m4 m, f32 rad, v3 axis) { axis = math_v3_normalize(axis); @@ -404,7 +404,7 @@ internal inline m4 math_rotate(m4 m, f32 rad, v3 axis) return math_m4m4_m(m, r); } -internal inline m4 math_scale(m4 m, v3 v) +internal m4 math_scale(m4 m, v3 v) { m4 r = math_m4_init_id(); r.E[0][0] = v.x; @@ -413,7 +413,7 @@ internal inline m4 math_scale(m4 m, v3 v) return math_m4m4_m(m, r); } -internal inline m4 math_translate(m4 m, v3 v) +internal m4 math_translate(m4 m, v3 v) { m4 r = math_m4_init_id(); r.E[0][3] = v.x; @@ -422,7 +422,7 @@ internal inline m4 math_translate(m4 m, v3 v) return math_m4m4_m(m, r); } -internal inline m4 math_projection_ortho(f32 left, f32 right, f32 bottom, f32 top, f32 near, f32 far) +internal m4 math_projection_ortho(f32 left, f32 right, f32 bottom, f32 top, f32 near, f32 far) { // TODO: This assert fails when you minimise the window in Windows. assert(left != right); @@ -454,7 +454,7 @@ internal inline m4 math_projection_ortho(f32 left, f32 right, f32 bottom, f32 to return r; } -internal inline m4 math_projection_perspective(f32 left, f32 right, f32 bottom, f32 top, f32 near, f32 far) +internal m4 math_projection_perspective(f32 left, f32 right, f32 bottom, f32 top, f32 near, f32 far) { assert(left != right); assert(bottom != top); @@ -485,7 +485,7 @@ internal inline m4 math_projection_perspective(f32 left, f32 right, f32 bottom, return r; } -internal inline m4 math_projection_perspective_fov(f32 fovy, f32 aspect, f32 near, f32 far) +internal m4 math_projection_perspective_fov(f32 fovy, f32 aspect, f32 near, f32 far) { f32 half_height = tanf(fovy / 2.0f) * near; f32 half_width = half_height * aspect; @@ -497,7 +497,7 @@ internal inline m4 math_projection_perspective_fov(f32 fovy, f32 aspect, f32 nea return math_projection_perspective(left, right, bottom, top, near, far); } -internal inline m4 math_camera_look_at(v3 camera_pos, v3 camera_target, v3 up) +internal m4 math_camera_look_at(v3 camera_pos, v3 camera_target, v3 up) { v3 camera_direction = math_v3_normalize(math_v3_s(camera_pos, camera_target)); v3 camera_right = math_v3_normalize(math_v3_cross(up, camera_direction)); @@ -519,7 +519,7 @@ internal inline m4 math_camera_look_at(v3 camera_pos, v3 camera_target, v3 up) return math_m4m4_m(look, math_translate(math_m4_init_id(), math_v3_negate(camera_pos))); } -internal inline bool math_intersect_aabb_aabb(rect r1, rect r2) +internal bool math_intersect_aabb_aabb(rect r1, rect r2) { f32 total_w = (r1.max.x - r1.min.x) + (r2.max.x - r2.min.x); f32 total_h = (r1.max.y - r1.min.y) + (r2.max.y - r2.min.y); @@ -532,7 +532,7 @@ internal inline bool math_intersect_aabb_aabb(rect r1, rect r2) return aabbs_do_indeed_intersect; } -internal inline rect math_minkowski_sum_rect(rect r1, v2 r2_dimensions) +internal rect math_minkowski_sum_rect(rect r1, v2 r2_dimensions) { v2 r2_half = { .width = 0.5f * r2_dimensions.width, @@ -545,14 +545,14 @@ internal inline rect math_minkowski_sum_rect(rect r1, v2 r2_dimensions) return sum; } -internal inline rect math_minkowski_diff_rect(rect r1, v2 r2_dimensions) +internal rect math_minkowski_diff_rect(rect r1, v2 r2_dimensions) { v2 negated_r2_dim = math_v2_negate(r2_dimensions); rect difference = math_minkowski_sum_rect(r1, negated_r2_dim); return difference; } -internal inline rect math_rect_from_center_dim(v2 center, v2 dimensions) +internal rect math_rect_from_center_dim(v2 center, v2 dimensions) { v2 half_d = {dimensions.x * 0.5f, dimensions.y * 0.5f}; rect result = { @@ -571,7 +571,7 @@ enum MathRectEdge MAX_RECT_EDGE, }; -internal inline segment math_rect_get_edge(rect r, enum MathRectEdge e) +internal segment math_rect_get_edge(rect r, enum MathRectEdge e) { v2 nw = {r.min.x, r.max.y}; v2 ne = r.max; @@ -624,7 +624,7 @@ internal v2 math_rect_get_normal(enum MathRectEdge e) return normal; } -internal inline bool math_in_interval_open(f32 n, f32 min, f32 max) +internal bool math_in_interval_open(f32 n, f32 min, f32 max) { assert(min <= max); bool in_open_interval = false; @@ -632,28 +632,28 @@ internal inline bool math_in_interval_open(f32 n, f32 min, f32 max) return in_open_interval; } -internal inline bool math_v2_lt(v2 v, v2 compare) +internal bool math_v2_lt(v2 v, v2 compare) { bool is_lt = false; is_lt = (v.x < compare.x && v.y < compare.y); return is_lt; } -internal inline bool math_v2_le(v2 v, v2 compare) +internal bool math_v2_le(v2 v, v2 compare) { bool is_le = false; is_le = (v.x <= compare.x && v.y <= compare.y); return is_le; } -internal inline bool math_v2_ge(v2 v, v2 compare) +internal bool math_v2_ge(v2 v, v2 compare) { bool is_ge = false; is_ge = (v.x >= compare.x && v.y >= compare.y); return is_ge; } -internal inline i32 math_log2(u32 x) +internal i32 math_log2(u32 x) { i32 result = sizeof(u32) * CHAR_BIT - intr_clz(x) - 1; return result; @@ -661,32 +661,32 @@ internal inline i32 math_log2(u32 x) #define math_is_pow_2(n) ((n) & ((n) - 1)) == 0 -internal inline void math_v2_print(v2 v) +internal void math_v2_print(v2 v) { printf("( %f, %f )\n", v.x, v.y); } -internal inline void math_v2u_print(v2u v) +internal void math_v2u_print(v2u v) { printf("( %u, %u )\n", v.x, v.y); } -internal inline void math_v2i_print(v2i v) +internal void math_v2i_print(v2i v) { printf("( %i, %i )\n", v.x, v.y); } -internal inline void math_v3_print(v3 v) +internal void math_v3_print(v3 v) { printf("( %f, %f, %f )\n", v.x, v.y, v.z); } -internal inline void math_v4_print(v4 v) +internal void math_v4_print(v4 v) { printf("( %f, %f, %f, %f )\n", v.x, v.y, v.z, v.w); } -internal inline void math_rect_print(rect r) +internal void math_rect_print(rect r) { printf("rect:\n"); printf(" min: "); @@ -695,7 +695,7 @@ internal inline void math_rect_print(rect r) math_v2_print(r.max); } -internal inline void math_m4_print(m4 m) +internal void math_m4_print(m4 m) { printf("[\n"); printf(" %f, %f, %f, %f\n", m.E[0][0], m.E[0][1], m.E[0][2], m.E[0][3]); diff --git a/src/game.c b/src/game.c @@ -14,12 +14,12 @@ #include "w_tutorial.h" -internal inline bool timer_is_expired(struct Timer t) +internal bool timer_is_expired(struct Timer t) { return t.elapsed_ms >= t.limit_ms; } -internal inline void timer_init(struct Timer *t, i64 limit_ms) +internal void timer_init(struct Timer *t, i64 limit_ms) { *t = (struct Timer) { .elapsed_ms = 0, @@ -27,7 +27,7 @@ internal inline void timer_init(struct Timer *t, i64 limit_ms) }; } -internal inline void timer_update(struct Timer *t, i64 elapsed_ms) +internal void timer_update(struct Timer *t, i64 elapsed_ms) { t->elapsed_ms += elapsed_ms; } diff --git a/src/game.h b/src/game.h @@ -4,8 +4,9 @@ #include <stddef.h> #include <stdint.h> -// TODO: only include this in the non-wasm builds +#if !defined(PLATFORM_WASM) #include <math.h> +#endif #if !defined(PLATFORM_WASM) #include <assert.h> diff --git a/src/input.c b/src/input.c @@ -1,4 +1,4 @@ -internal inline bool btn_is_down(u32 button_states, enum GameButton b) +internal bool btn_is_down(u32 button_states, enum GameButton b) { assert(b < NUM_GAME_BUTTONS); bool result = button_states & (1 << b); diff --git a/src/intrinsics.h b/src/intrinsics.h @@ -6,7 +6,7 @@ static_assert(__has_builtin(__builtin_clz), "No builtin clz intrinsic"); #define intr_clz(x) __builtin_clz((x)) -internal inline i32 intr_mod(i32 x, i32 y) +internal i32 intr_mod(i32 x, i32 y) { // NOTE(amin): There are multiple valid definitions of an operation that // gets the remainder of an integer division: `x / y`. Such an operation diff --git a/src/memory.c b/src/memory.c @@ -3,7 +3,7 @@ #define mem_move_buffer(d, s, t, c) mem_move((d), (s), sizeof(t) * (c)) // TODO: test that alignment is working properly -internal inline uintptr_t mem_align_address(uintptr_t address, size_t alignment) +internal uintptr_t mem_align_address(uintptr_t address, size_t alignment) { assert(math_is_pow_2(alignment)); // This works since we've asserted alignment is a power of 2 diff --git a/src/platform_wasm.c b/src/platform_wasm.c @@ -4,9 +4,6 @@ #include <stddef.h> #include <stdint.h> -// TODO: only include this in the non-wasm builds -#include <math.h> - #define static_assert _Static_assert // Begin terrible libc substitutions @@ -58,6 +55,33 @@ void *memmove(void *dst, const void *src, size_t n) static_assert(__has_builtin(__builtin_sqrtf), "No builtin sqrtf builtin"); #define sqrtf(x) __builtin_sqrtf((x)) + +float js_cosf(float); +float js_fabsf(float); +float js_powf(float, float); +float js_sinf(float); +float js_tanf(float); +float js_cosf(float); + +float cosf(float x) { + return js_cosf(x); +} + +float fabsf(float x) { + return js_fabsf(x); +} + +float powf(float x, float y) { + return js_powf(x, y); +} + +float sinf(float x) { + return js_sinf(x); +} + +float tanf(float x) { + return js_tanf(x); +} // End terrible libc substitutions #include "platform_info.h" diff --git a/src/platform_wasm_js_symbols.txt b/src/platform_wasm_js_symbols.txt @@ -1,8 +1,16 @@ +js_cosf +js_fabsf +js_get_file_size +js_powf +js_print +js_read_entire_file +js_sinf +js_tanf webglActiveTexture webglAttachShader webglBindBuffer -webglBindVertexArray webglBindTexture +webglBindVertexArray webglBlendColor webglBlendFunc webglBufferData @@ -43,6 +51,3 @@ webglUniformMatrix4fv webglUseProgram webglVertexAttribPointer webglViewport -js_get_file_size -js_read_entire_file -js_print diff --git a/src/platform_wasm_loader.js b/src/platform_wasm_loader.js @@ -213,6 +213,12 @@ imports["webglVertexAttribPointer"] = function(index, size, type, normalized, st imports["webglViewport"] = function(x, y, width, height) { gl.viewport(x, y, width, height); } +imports["js_cosf"] = function(x) { + return Math.cos(x); +} +imports["js_fabsf"] = function(x) { + return Math.abs(x); +} imports["js_get_file_size"] = function(name, name_len) { let file_name = utf8decoder.decode(memory.subarray(name, name + name_len)) let file_size = 0; @@ -222,6 +228,13 @@ imports["js_get_file_size"] = function(name, name_len) { } return file_size; } +imports["js_powf"] = function(x, y) { + return Math.pow(x, y); +} +imports["js_print"] = function(s, len) { + let arr = memory.subarray(s, s + len); + console.log(utf8decoder.decode(arr)); +} imports["js_read_entire_file"] = function(name, name_len, out_buf) { let file_name = utf8decoder.decode(memory.subarray(name, name + name_len)) let file_size = 0; @@ -235,9 +248,11 @@ imports["js_read_entire_file"] = function(name, name_len, out_buf) { } return success; } -imports["js_print"] = function(s, len) { - let arr = memory.subarray(s, s + len); - console.log(utf8decoder.decode(arr)); +imports["js_sinf"] = function(x) { + return Math.sin(x); +} +imports["js_tanf"] = function(x) { + return Math.tan(x); } function error_fatal(message) { console.log(message); diff --git a/src/webgl.h b/src/webgl.h @@ -105,7 +105,7 @@ typedef long GLsizeiptr; // loader) #define WEBGL_CAST_I32(x) (i32)(x) -static inline i32 _webgl_strlen(const char *str) +static i32 _webgl_strlen(const char *str) { i32 len = 0; while(str[len] != '\0') @@ -115,117 +115,117 @@ static inline i32 _webgl_strlen(const char *str) return len; } -void glActiveTexture(GLenum texture) +static void glActiveTexture(GLenum texture) { webglActiveTexture(WEBGL_CAST_I32(texture)); } -inline void glAttachShader(GLuint program, GLuint shader) +static void glAttachShader(GLuint program, GLuint shader) { webglAttachShader(WEBGL_CAST_I32(program), WEBGL_CAST_I32(shader)); } -inline void glBindBuffer(GLenum target, GLuint buffer) +static void glBindBuffer(GLenum target, GLuint buffer) { webglBindBuffer(WEBGL_CAST_I32(target), WEBGL_CAST_I32(buffer)); } -void glBindTexture(GLenum target, GLuint texture) +static void glBindTexture(GLenum target, GLuint texture) { webglBindTexture(WEBGL_CAST_I32(target), WEBGL_CAST_I32(texture)); } -inline void glBindVertexArray(GLuint array) +static void glBindVertexArray(GLuint array) { webglBindVertexArray(WEBGL_CAST_I32(array)); } -inline void glBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +static void glBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { webglBlendColor((f32)red, (f32)green, (f32)blue, (f32)alpha); } -inline void glBlendFunc(GLenum sfactor, GLenum dfactor) +static void glBlendFunc(GLenum sfactor, GLenum dfactor) { webglBlendFunc(WEBGL_CAST_I32(sfactor), WEBGL_CAST_I32(dfactor)); } -inline void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) +static void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) { webglBufferData(WEBGL_CAST_I32(target), WEBGL_CAST_I32(size), WEBGL_CAST_I32(data), WEBGL_CAST_I32(usage)); } -inline void glClear(GLbitfield mask) +static void glClear(GLbitfield mask) { webglClear(WEBGL_CAST_I32(mask)); } -inline void glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +static void glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { webglClearColor((f32)red, (f32)green, (f32)blue, (f32)alpha); } -inline void glCompileShader(GLuint shader) +static void glCompileShader(GLuint shader) { webglCompileShader(WEBGL_CAST_I32(shader)); } -inline GLuint glCreateProgram(void) +static GLuint glCreateProgram(void) { i32 program_id = webglCreateProgram(); return (GLuint)program_id; } -inline GLuint glCreateShader(GLenum type) +static GLuint glCreateShader(GLenum type) { return webglCreateShader(WEBGL_CAST_I32(type)); } -inline void glDeleteBuffers(GLsizei n, const GLuint *buffers) +static void glDeleteBuffers(GLsizei n, const GLuint *buffers) { assert(n == 1); i32 the_buffer = WEBGL_CAST_I32(buffers[0]); webglDeleteBuffer(the_buffer); } -inline void glDeleteShader(GLuint shader) +static void glDeleteShader(GLuint shader) { webglDeleteShader(WEBGL_CAST_I32(shader)); } -inline void glDeleteVertexArrays(GLsizei n, const GLuint *arrays) +static void glDeleteVertexArrays(GLsizei n, const GLuint *arrays) { assert(n == 1); i32 the_array = WEBGL_CAST_I32(arrays[0]); webglDeleteVertexArray(the_array); } -inline void glDepthMask(GLboolean flag) +static void glDepthMask(GLboolean flag) { webglDepthMask(WEBGL_CAST_I32(flag)); } -inline void glDisable(GLenum cap) +static void glDisable(GLenum cap) { webglDisable(WEBGL_CAST_I32(cap)); } -inline void glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) +static void glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) { webglDrawElements(WEBGL_CAST_I32(mode), WEBGL_CAST_I32(count), WEBGL_CAST_I32(type), WEBGL_CAST_I32(indices)); } -inline void glEnable(GLenum cap) +static void glEnable(GLenum cap) { webglEnable(WEBGL_CAST_I32(cap)); } -inline void glEnableVertexAttribArray(GLuint index) +static void glEnableVertexAttribArray(GLuint index) { webglEnableVertexAttribArray(WEBGL_CAST_I32(index)); } -inline void glGenBuffers(GLsizei n, GLuint *buffers) +static void glGenBuffers(GLsizei n, GLuint *buffers) { assert(n == 1); i32 buffer_id = webglCreateBuffer(); @@ -233,19 +233,19 @@ inline void glGenBuffers(GLsizei n, GLuint *buffers) *buffers = (GLuint)buffer_id; } -void glGenerateMipmap(GLenum target) +static void glGenerateMipmap(GLenum target) { webglGenerateMipmap(WEBGL_CAST_I32(target)); } -void glGenTextures(GLsizei n, GLuint *textures) +static void glGenTextures(GLsizei n, GLuint *textures) { assert(n == 1); i32 texture_id = webglCreateTexture(); *textures = (GLuint)texture_id; } -inline void glGenVertexArrays(GLsizei n, GLuint *arrays) +static void glGenVertexArrays(GLsizei n, GLuint *arrays) { assert(n == 1); i32 vao_id = webglCreateVertexArray(); @@ -253,56 +253,56 @@ inline void glGenVertexArrays(GLsizei n, GLuint *arrays) *arrays = (GLuint)vao_id; } -inline void glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) +static void glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { // TODO: implement //webglGetProgramInfoLog(WEBGL_CAST_I32(program), WEBGL_CAST_I32(bufsize), WEBGL_CAST_I32(*length), WEBGL_CAST_I32(*infoLog)); } -inline void glGetProgramiv(GLuint program, GLenum pname, GLint *params) +static void glGetProgramiv(GLuint program, GLenum pname, GLint *params) { *params = webglGetProgramParameter(WEBGL_CAST_I32(program), WEBGL_CAST_I32(pname)); } -inline void glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) +static void glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { webglGetShaderInfoLog(WEBGL_CAST_I32(shader), infoLog); } -inline void glGetShaderiv(GLuint shader, GLenum pname, GLint *params) +static void glGetShaderiv(GLuint shader, GLenum pname, GLint *params) { *params = webglGetShaderParameter(WEBGL_CAST_I32(shader), WEBGL_CAST_I32(pname)); } -inline GLint glGetUniformLocation(GLuint program, const GLchar *name) +static GLint glGetUniformLocation(GLuint program, const GLchar *name) { i32 name_len = _webgl_strlen(name); return webglGetUniformLocation(WEBGL_CAST_I32(program), name, name_len); } -inline void glLinkProgram(GLuint program) +static void glLinkProgram(GLuint program) { webglLinkProgram(WEBGL_CAST_I32(program)); } -inline void glPolygonMode(GLenum face, GLenum mode) +static void glPolygonMode(GLenum face, GLenum mode) { // No Op. This doesn't exist in webgl } -inline void glScissor(GLint x, GLint y, GLsizei width, GLsizei height) +static void glScissor(GLint x, GLint y, GLsizei width, GLsizei height) { webglScissor(WEBGL_CAST_I32(x), WEBGL_CAST_I32(y), WEBGL_CAST_I32(width), WEBGL_CAST_I32(height)); } -inline void glShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length) +static void glShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length) { const GLchar *s = (void *)*string; i32 l = _webgl_strlen(s); webglShaderSource(WEBGL_CAST_I32(shader), s, l); } -void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) +static void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) { webglTexImage2D( WEBGL_CAST_I32(target), @@ -316,7 +316,7 @@ void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei widt WEBGL_CAST_I32(pixels)); } -void glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels) +static void glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels) { webglTexImage3D( WEBGL_CAST_I32(target), @@ -331,52 +331,52 @@ void glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei widt WEBGL_CAST_I32(pixels)); } -void glTexParameteri(GLenum target, GLenum pname, GLint param) +static void glTexParameteri(GLenum target, GLenum pname, GLint param) { webglTexParameteri(WEBGL_CAST_I32(target), WEBGL_CAST_I32(pname), WEBGL_CAST_I32(param)); } -void glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +static void glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { webglTexStorage3D(target, levels, internalformat, width, height, depth); } -void glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels) +static void glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels) { webglTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, WEBGL_CAST_I32(pixels)); } -inline void glUniform1f(GLint location, GLfloat v0) +static void glUniform1f(GLint location, GLfloat v0) { webglUniform1f(WEBGL_CAST_I32(location), (f32)v0); } -inline void glUniform1i(GLint location, GLint v0) +static void glUniform1i(GLint location, GLint v0) { webglUniform1i(WEBGL_CAST_I32(location), WEBGL_CAST_I32(v0)); } -inline void glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) +static void glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) { webglUniform3f(WEBGL_CAST_I32(location), (f32)v0, (f32)v1, (f32)v2); } -inline void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +static void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { webglUniformMatrix4fv(WEBGL_CAST_I32(location), WEBGL_CAST_I32(transpose), value); } -inline void glUseProgram(GLuint program) +static void glUseProgram(GLuint program) { webglUseProgram(WEBGL_CAST_I32(program)); } -inline void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) +static void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) { webglVertexAttribPointer(WEBGL_CAST_I32(index), WEBGL_CAST_I32(size), WEBGL_CAST_I32(type), WEBGL_CAST_I32(normalized), WEBGL_CAST_I32(stride), WEBGL_CAST_I32(pointer)); } -inline void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) +static void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { webglViewport(x, y, WEBGL_CAST_I32(width), WEBGL_CAST_I32(height)); } diff --git a/src/world.c b/src/world.c @@ -29,7 +29,7 @@ internal struct AbsolutePos world_pos_recanonicalize(struct AbsolutePos p) return p_final; } -internal inline v2 world_tile_get_sw_corner(v2 tile_center_pos) +internal v2 world_tile_get_sw_corner(v2 tile_center_pos) { v2 tile_sw_corner = { .x = tile_center_pos.x - (TILE_SIZE * 0.5f), @@ -38,7 +38,7 @@ internal inline v2 world_tile_get_sw_corner(v2 tile_center_pos) return tile_sw_corner; } -internal inline v2 world_tile_get_center(v2 tile_sw_corner_pos) +internal v2 world_tile_get_center(v2 tile_sw_corner_pos) { v2 tile_center = { .x = tile_sw_corner_pos.x + (TILE_SIZE * 0.5f), @@ -63,7 +63,7 @@ internal struct AbsolutePos world_tile_pos_recanonicalize(struct AbsolutePos til return tile_canonical_pos; } -internal inline v2i world_room_get_chunk_index(v2i room_i) +internal v2i world_room_get_chunk_index(v2i room_i) { // NOTE(amin): truncated integer division here is intentional. We want a // square of CHUNK_NUM_ROOMS rooms to all have the same chunk index. @@ -175,7 +175,7 @@ internal size_t world_room_get_index_within_chunk(v2i room_i) return room_i_within_chunk; } -internal inline bool world_room_is_initialized(struct Room *room) +internal bool world_room_is_initialized(struct Room *room) { bool is_initialized = false; if (room->index.y != ROOM_UNINITIALIZED_Y_VALUE)