From 11250735682762659e117199ea6189309165c2aa Mon Sep 17 00:00:00 2001 From: veclavtlica Date: Mon, 14 Sep 2026 12:21:49 +0300 Subject: [PATCH] refactor, libc made optional --- Common/Std/libc.c | 20 ++++++++++ Common/Std/stub.c | 10 +++++ Common/Timer/{unix.c => posix.c} | 6 +-- Common/def.h | 17 ++------ Common/fix.c | 44 ++++++++++----------- Common/gem.h | 30 +++++++-------- Common/lzw.c | 30 +++++++-------- Common/mat.h | 20 +++++----- Common/pnt.h | 37 ++++++++---------- Common/std.h | 22 +++++++++-- Common/vec.h | 66 ++++++++++++++------------------ Player/Makefile | 10 ++--- Player/amalgam.c | 10 +++++ Player/draw.c | 8 ++-- 14 files changed, 178 insertions(+), 152 deletions(-) create mode 100644 Common/Std/libc.c create mode 100644 Common/Std/stub.c rename Common/Timer/{unix.c => posix.c} (76%) diff --git a/Common/Std/libc.c b/Common/Std/libc.c new file mode 100644 index 0000000..085608d --- /dev/null +++ b/Common/Std/libc.c @@ -0,0 +1,20 @@ +#include "../std.h" +#include +#include +#include +#include +#include + +void *com_std_realloc(void *ptr, size_t size) { return realloc(ptr, size); } +void com_std_free(void *ptr) { free(ptr); } +void com_std_assert(bool holds) { assert(holds); } +void com_std_printf(char const *fmt, ...) { + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} +double com_std_sqrt(double v) { return sqrt(v); } +double com_std_fabs(double v) { return fabs(v); } +double com_std_sin(double v) { return sin(v); } +double com_std_cos(double v) { return cos(v); } diff --git a/Common/Std/stub.c b/Common/Std/stub.c new file mode 100644 index 0000000..bb21cf6 --- /dev/null +++ b/Common/Std/stub.c @@ -0,0 +1,10 @@ +#include "../std.h" + +void *com_std_realloc(void *ptr, size_t size) { return NULL; } +void com_std_free(void *ptr) {} +void com_std_assert(bool holds) {} +void com_std_printf(char const *fmt, ...) {} +double com_std_sqrt(double v) { return 0; } +double com_std_fabs(double v) { return 0; } +double com_std_sin(double v) { return 0; } +double com_std_cos(double v) { return 0; } diff --git a/Common/Timer/unix.c b/Common/Timer/posix.c similarity index 76% rename from Common/Timer/unix.c rename to Common/Timer/posix.c index d544985..e67ea87 100644 --- a/Common/Timer/unix.c +++ b/Common/Timer/posix.c @@ -1,11 +1,9 @@ +#include "../std.h" #include "timer.h" #include -#include #define __USE_POSIX199309 1 #include -/* TODO: Rename to posix.c */ - uint64_t com_timer_count_ns(void) { struct timespec time; clock_gettime(CLOCK_MONOTONIC, &time); @@ -15,5 +13,5 @@ uint64_t com_timer_count_ns(void) { void com_timer_profile(uint64_t starttime, const char *what) { uint64_t const endtime = com_timer_count_ns(); uint64_t const diff = endtime - starttime; - printf("profile \"%s\" took %fms\n", what, (double)diff / 1000000); + com_std_printf("profile \"%s\" took %fms\n", what, (double)diff / 1000000); } diff --git a/Common/def.h b/Common/def.h index 5545557..41d77a1 100644 --- a/Common/def.h +++ b/Common/def.h @@ -10,17 +10,15 @@ #define COM_DEF_COMPILE_MODERN 1 #endif -#define COM_DEF_TARGET_NATIVE 0 +#define COM_DEF_TARGET_LINUX 0 #define COM_DEF_TARGET_WASM 1 #if defined(__wasm__) -#define COM_DEF_NOSTD 1 #define COM_DEF_TARGET COM_DEF_TARGET_WASM -/* TODO: Move to std.h instead, forbid stdlib on any platform. */ -#define assert(m_t) (m_t) -#define printf(...) ((void)0) +#define com_def_export_sym(m_s) __attribute__((export_name(m_s))) #else -#define COM_DEF_TARGET COM_DEF_TARGET_NATIVE +#define COM_DEF_TARGET COM_DEF_TARGET_LINUX +#define com_def_export_sym(m_s) __attribute__((visibility("default"))) #endif /* TODO: uppercase? */ @@ -33,13 +31,6 @@ #define com_def_vector(v_t, v_v, v_n) v_t v_v[v_n] #endif -#define COM_DEF_VECTOR_NONE 0 -#define COM_DEF_VECTOR_SSE2 1 - -#ifdef COM_DEF_COMPILE_MODERN -#define COM_DEF_VECTOR_IMPL COM_DEF_VECTOR_SSE2 -#endif - // #define COM_DEF_PROFILE_VAR volatile /* Sadly, doesn't work in some cases */ #define COM_DEF_PROFILE_SINK(m_v) __asm__ volatile("" ::"r"(m_v) : "memory") diff --git a/Common/fix.c b/Common/fix.c index 73cefc0..cfcb927 100644 --- a/Common/fix.c +++ b/Common/fix.c @@ -6,15 +6,10 @@ #include "fix.h" #include "Timer/timer.h" #include "def.h" +#include "std.h" #include #include -#ifndef COM_DEF_NOSTD -#include -#include -#include -#endif - // 4-bit LUT (16 entries) for the normalized range [0.5, 2.0) // It stores the initial guess scaled to Q16.16. static const uint32_t com_fix_sqrt_lut[16] = { @@ -40,7 +35,7 @@ const uint16_t com_fix_sin_lut[128] = { com_fix_t com_fix_sqrt(com_fix_t a) { // 1. Handle sign and edge cases - assert(a >= 0); + com_std_assert(a >= 0); if (a == 0) return 0; @@ -86,7 +81,7 @@ com_fix_t com_fix_sqrt(com_fix_t a) { void com_fix_print(com_fix_t a) { if (a < 0) { - printf("-"); + com_std_printf("-"); a = -a; } int32_t int_part = a >> 16; @@ -95,7 +90,7 @@ void com_fix_print(com_fix_t a) { // Convert fractional 16-bit part to a decimal value (up to 4 decimal places) uint32_t decimal_val = (frac_part * 10000) >> 16; - printf("%d.%04u\n", int_part, decimal_val); + com_std_printf("%d.%04u\n", int_part, decimal_val); } void com_fix_run_bench(void) { @@ -133,7 +128,6 @@ void com_fix_run_bench(void) { } void com_fix_run_tests(void) { -#ifndef COM_DEF_NOSTD { double max_sqrt_deviation = 0.0f; com_fix_t sqrt_accumulator = 0; @@ -141,12 +135,13 @@ void com_fix_run_tests(void) { for (int i = 0; i < COM_FIX_FRACUNIT << 1; ++i) { com_fix_t sqrt = com_fix_sqrt(sqrt_accumulator); double const deviation = - sqrt(com_fix_as_float(sqrt_accumulator)) - com_fix_as_float(sqrt); + com_std_sqrt(com_fix_as_float(sqrt_accumulator)) - + com_fix_as_float(sqrt); if (deviation > max_sqrt_deviation) max_sqrt_deviation = deviation; sqrt_accumulator += sqrt_test_step; } - printf("max sqrt deviation: %f\n", max_sqrt_deviation); + com_std_printf("max sqrt deviation: %f\n", max_sqrt_deviation); } { @@ -156,12 +151,13 @@ void com_fix_run_tests(void) { for (int i = 0; i < 1024 * 32; ++i) { com_fix_t sin = com_fix_sin(sin_accumulator); double const deviation = - fabs(sin(com_fix_as_float(sin_accumulator)) - com_fix_as_float(sin)); + com_std_fabs(com_std_sin(com_fix_as_float(sin_accumulator)) - + com_fix_as_float(sin)); if (deviation > max_sin_deviation) max_sin_deviation = deviation; sin_accumulator += sin_test_step; } - printf("max sin deviation: %f\n", max_sin_deviation); + com_std_printf("max sin deviation: %f\n", max_sin_deviation); } { @@ -171,12 +167,13 @@ void com_fix_run_tests(void) { for (int i = 0; i < 1024 * 32; ++i) { com_fix_t cos = com_fix_cos(cos_accumulator); double const deviation = - fabs(cos(com_fix_as_float(cos_accumulator)) - com_fix_as_float(cos)); + com_std_fabs(com_std_cos(com_fix_as_float(cos_accumulator)) - + com_fix_as_float(cos)); if (deviation > max_cos_deviation) max_cos_deviation = deviation; cos_accumulator += cos_test_step; } - printf("max cos deviation: %f\n", max_cos_deviation); + com_std_printf("max cos deviation: %f\n", max_cos_deviation); } { @@ -187,18 +184,19 @@ void com_fix_run_tests(void) { for (int i = 0; i < 1024 * 32; ++i) { com_fix_t sin, cos; com_fix_sincos(sincos_accumulator, &sin, &cos); - double const sin_deviation = fabs( - sin(com_fix_as_float(sincos_accumulator)) - com_fix_as_float(sin)); - double const cos_deviation = fabs( - cos(com_fix_as_float(sincos_accumulator)) - com_fix_as_float(cos)); + double const sin_deviation = + com_std_fabs(com_std_sin(com_fix_as_float(sincos_accumulator)) - + com_fix_as_float(sin)); + double const cos_deviation = + com_std_fabs(com_std_cos(com_fix_as_float(sincos_accumulator)) - + com_fix_as_float(cos)); if (sin_deviation > max_sin_deviation) max_sin_deviation = sin_deviation; if (cos_deviation > max_cos_deviation) max_cos_deviation = cos_deviation; sincos_accumulator += sincos_test_step; } - printf("max sincos deviations: %f %f\n", max_sin_deviation, - max_cos_deviation); + com_std_printf("max sincos deviations: %f %f\n", max_sin_deviation, + max_cos_deviation); } -#endif } diff --git a/Common/gem.h b/Common/gem.h index 84611d6..7da7d9c 100644 --- a/Common/gem.h +++ b/Common/gem.h @@ -22,9 +22,9 @@ static inline com_vec_t com_gem_vec_project_clip(com_mat_t a, com_vec_t b) { com_vec_t result; #define CASE(m_c, m_n) \ - result.a[m_c] = (((int64_t)a.a[m_n * 4 + 0] * b.s.x) + \ - ((int64_t)a.a[m_n * 4 + 1] * b.s.y) + \ - ((int64_t)a.a[m_n * 4 + 2] * b.s.z) + a.a[m_n * 4 + 3]) >> \ + result.a[m_c] = (((int64_t)a.a[m_n * 4 + 0] * b.a[0]) + \ + ((int64_t)a.a[m_n * 4 + 1] * b.a[1]) + \ + ((int64_t)a.a[m_n * 4 + 2] * b.a[2]) + a.a[m_n * 4 + 3]) >> \ COM_FIX_FRACBITS; CASE(0, 0); @@ -51,9 +51,9 @@ static inline com_vec_t com_gem_vec_project_clip(com_mat_t a, com_vec_t b) { * determining new view-lying clipped triangles. */ static inline uint8_t com_gem_clip_vis_project(com_vec_t a, com_pnt_t *out) { uint8_t mask = 0; - if (a.s.x < -a.s.z || a.s.x > a.s.z) + if (a.a[0] < -a.a[2] || a.a[0] > a.a[2]) mask ^= COM_GEM_VERTEX_CLIPPED_X; - if (a.s.y < -a.s.z || a.s.y > a.s.z) + if (a.a[1] < -a.a[2] || a.a[1] > a.a[2]) mask ^= COM_GEM_VERTEX_CLIPPED_Y; out->a[0] = com_fix_div(a.a[0], a.a[2]) / 480 + 240; out->a[1] = com_fix_div(a.a[1], a.a[2]) / 640 + 320; @@ -62,14 +62,14 @@ static inline uint8_t com_gem_clip_vis_project(com_vec_t a, com_pnt_t *out) { static inline void com_gem_draw_triangle(com_pnt_t v0, com_pnt_t v1, com_pnt_t v2, uint8_t *out) { - int minX = com_vec_min(com_vec_from(v0.s.x, v1.s.x, v2.s.x)); - int minY = com_vec_min(com_vec_from(v0.s.y, v1.s.y, v2.s.y)); - int maxX = com_vec_max(com_vec_from(v0.s.x, v1.s.x, v2.s.x)); - int maxY = com_vec_max(com_vec_from(v0.s.y, v1.s.y, v2.s.y)); + int minX = com_vec_min(com_vec_from(v0.a[0], v1.a[0], v2.a[0])); + int minY = com_vec_min(com_vec_from(v0.a[1], v1.a[1], v2.a[1])); + int maxX = com_vec_max(com_vec_from(v0.a[0], v1.a[0], v2.a[0])); + int maxY = com_vec_max(com_vec_from(v0.a[1], v1.a[1], v2.a[1])); for (int y = minY; y <= maxY; y++) { for (int x = minX; x <= maxX; x++) { - com_pnt_t p = {.s = {x, y}}; + com_pnt_t p = {.a = {x, y}}; // Test the pixel center against all 3 edges com_vec_t ws = com_pnt_edge_weight(v0, v1, v2, p); @@ -89,16 +89,16 @@ static inline void com_gem_draw_triangle_textured(com_pnt_t v0, com_pnt_t v1, com_pnt_t v2, uint8_t *out, com_pnt_t uv0, com_pnt_t uv1, com_pnt_t uv2, uint8_t *tex) { - int minX = com_vec_min(com_vec_from(v0.s.x, v1.s.x, v2.s.x)); - int minY = com_vec_min(com_vec_from(v0.s.y, v1.s.y, v2.s.y)); - int maxX = com_vec_max(com_vec_from(v0.s.x, v1.s.x, v2.s.x)); - int maxY = com_vec_max(com_vec_from(v0.s.y, v1.s.y, v2.s.y)); + int minX = com_vec_min(com_vec_from(v0.a[0], v1.a[0], v2.a[0])); + int minY = com_vec_min(com_vec_from(v0.a[1], v1.a[1], v2.a[1])); + int maxX = com_vec_max(com_vec_from(v0.a[0], v1.a[0], v2.a[0])); + int maxY = com_vec_max(com_vec_from(v0.a[1], v1.a[1], v2.a[1])); com_fix_t const area = com_pnt_area(v0, v1, v2); for (int y = minY; y <= maxY; y++) { for (int x = minX; x <= maxX; x++) { - com_pnt_t p = {.s = {x, y}}; + com_pnt_t p = {.a = {x, y}}; /* TODO: Move to a separate weighting function over vec. */ // Test the pixel center against all 3 edges diff --git a/Common/lzw.c b/Common/lzw.c index 80faf62..c6c9ddd 100644 --- a/Common/lzw.c +++ b/Common/lzw.c @@ -5,17 +5,11 @@ #include "lzw.h" #include "bits.h" +#include "std.h" #include #include #include -#ifndef COM_DEF_NOSTD -#include -#include -#else -#include "std.h" -#endif - /* References: */ /* https://www.w3.org/Graphics/GIF/spec-gif89a.txt */ /* https://www.daubnet.com/en/file-format-gif */ @@ -50,8 +44,9 @@ struct com_lzw_table com_lzw_infer_table(const char *datain, uint32_t sizein) { if (!code_found) { if (table_size >= table_cap) { /* TODO: Ref to prev table gets missed, memory leak scenario */ - if (!(table = realloc(table, sizeof(struct com_lzw_table_entry) * - (table_cap + COM_LZW_TABLE_CAP_GROW)))) + if (!(table = com_std_realloc( + table, sizeof(struct com_lzw_table_entry) * + (table_cap + COM_LZW_TABLE_CAP_GROW)))) goto ERR_ALLOC_INIT_TABLE; table_cap += COM_LZW_TABLE_CAP_GROW; @@ -73,14 +68,14 @@ struct com_lzw_table com_lzw_infer_table(const char *datain, uint32_t sizein) { ERR_ALLOC_INIT_TABLE: if (table_cap > 0) - free(table); + com_std_free(table); return (struct com_lzw_table){0}; } void com_lzw_free_table(struct com_lzw_table *table) { if (!table->table) return; - free(table->table); + com_std_free(table->table); table->size = 0; table->cap = 0; table->init_size = 0; @@ -89,14 +84,14 @@ void com_lzw_free_table(struct com_lzw_table *table) { /* For GIFs, color should already be collapsed to indices at this point */ bool com_lzw_compress(const struct com_lzw_table *table, const char *datain, uint32_t sizein, char **dataout, uint32_t *sizeout) { - assert(datain && dataout && sizeout && sizein > 0); - assert(*dataout == NULL && *sizeout == 0); + com_std_assert(datain && dataout && sizeout && sizein > 0); + com_std_assert(*dataout == NULL && *sizeout == 0); /* TODO: Make sure the table is cleared */ /* Encode step */ uint8_t codesize = com_bits_needed(table->init_size) + 1; - assert(codesize < COM_TABLE_BIT_WIDTH_LIMIT); + com_std_assert(codesize < COM_TABLE_BIT_WIDTH_LIMIT); uint32_t cur_table_idx = 0; /* Head table in which vector we should be looking into */ @@ -131,12 +126,13 @@ bool com_lzw_compress(const struct com_lzw_table *table, const char *datain, // } /* Emit output, drop the string */ - assert(cur_table_idx < (1 << codesize)); - assert(cur_table_idx < table->size); + com_std_assert(cur_table_idx < (1 << codesize)); + com_std_assert(cur_table_idx < table->size); if (output_size == output_cap && output_bitshift + codesize > 8) { /* TODO: catch alloc failure */ - output = realloc(output, output_cap + COM_LZW_OUTPUT_CAP_GROWTH); + output = + com_std_realloc(output, output_cap + COM_LZW_OUTPUT_CAP_GROWTH); output_cap += COM_LZW_OUTPUT_CAP_GROWTH; } diff --git a/Common/mat.h b/Common/mat.h index d4082e7..aae26da 100644 --- a/Common/mat.h +++ b/Common/mat.h @@ -21,7 +21,7 @@ #include "vec.h" #include -typedef union { +typedef struct { com_def_alignedas(64) com_def_vector(com_fix_t, a, 4 * 4); } com_mat_t; @@ -130,17 +130,17 @@ static inline com_mat_t com_mat_look_at(com_vec_t pos, com_vec_t up, com_mat_t result; - result.a[0] = r.s.x; - result.a[1] = u.s.x; - result.a[2] = -target.s.x; + result.a[0] = r.a[0]; + result.a[1] = u.a[0]; + result.a[2] = -target.a[0]; result.a[3] = 0; - result.a[4] = r.s.y; - result.a[5] = u.s.y; - result.a[6] = -target.s.y; + result.a[4] = r.a[1]; + result.a[5] = u.a[1]; + result.a[6] = -target.a[1]; result.a[7] = 0; - result.a[8] = r.s.z; - result.a[9] = u.s.z; - result.a[10] = -target.s.z; + result.a[8] = r.a[2]; + result.a[9] = u.a[2]; + result.a[10] = -target.a[2]; result.a[11] = 0; result.a[12] = -com_vec_dot(r, pos); result.a[13] = -com_vec_dot(u, pos); diff --git a/Common/pnt.h b/Common/pnt.h index 6cbb5ec..6ebccbc 100644 --- a/Common/pnt.h +++ b/Common/pnt.h @@ -10,54 +10,49 @@ #include "vec.h" #include -typedef union { +typedef struct { com_def_alignedas(16) com_def_vector(com_fix_t, a, 2); - com_def_alignedas(16) struct { - com_fix_t x; - com_fix_t y; - } s; } com_pnt_t; static inline com_pnt_t com_pnt_from(com_fix_t x, com_fix_t y) { - return (com_pnt_t){.s = {.x = x, .y = y}}; + return (com_pnt_t){.a = {x, y}}; } static inline com_pnt_t com_pnt_from_vec(com_vec_t a) { - return (com_pnt_t){.s = {.x = a.a[0], .y = a.a[1]}}; + return (com_pnt_t){.a = {a.a[0], a.a[1]}}; } static inline com_pnt_t com_pnt_identity(void) { - return (com_pnt_t){.s = { - .x = COM_FIX_FRACUNIT, - .y = COM_FIX_FRACUNIT, + return (com_pnt_t){.a = { + COM_FIX_FRACUNIT, + COM_FIX_FRACUNIT, }}; } static inline com_pnt_t com_pnt_add(com_pnt_t a, com_pnt_t b) { return (com_pnt_t){ - .s = {.x = com_fix_add(a.s.x, b.s.x), .y = com_fix_add(a.s.y, b.s.y)}}; + .a = {com_fix_add(a.a[0], b.a[0]), com_fix_add(a.a[1], b.a[1])}}; } static inline com_pnt_t com_pnt_sub(com_pnt_t a, com_pnt_t b) { return (com_pnt_t){ - .s = {.x = com_fix_sub(a.s.x, b.s.x), .y = com_fix_sub(a.s.y, b.s.y)}}; + .a = {com_fix_sub(a.a[0], b.a[0]), com_fix_sub(a.a[1], b.a[1])}}; } static inline com_pnt_t com_pnt_mul(com_pnt_t a, com_pnt_t b) { return (com_pnt_t){ - .s = {.x = com_fix_mul(a.s.x, b.s.x), .y = com_fix_mul(a.s.y, b.s.y)}}; + .a = {com_fix_mul(a.a[0], b.a[0]), com_fix_mul(a.a[1], b.a[1])}}; } /* Note: this does not clamp for over/underflow cases */ static inline com_pnt_t com_pnt_div(com_pnt_t a, com_pnt_t b) { return (com_pnt_t){ - .s = {.x = com_fix_div(a.s.x, b.s.x), .y = com_fix_div(a.s.y, b.s.y)}}; + .a = {com_fix_div(a.a[0], b.a[0]), com_fix_div(a.a[1], b.a[1])}}; } /* Scale pnttor by a fixed point number */ static inline com_pnt_t com_pnt_scl(com_pnt_t a, com_fix_t b) { - return (com_pnt_t){ - .s = {.x = com_fix_mul(a.s.x, b), .y = com_fix_mul(a.s.y, b)}}; + return (com_pnt_t){.a = {com_fix_mul(a.a[0], b), com_fix_mul(a.a[1], b)}}; } static inline com_fix_t com_pnt_min(com_pnt_t a) { @@ -75,17 +70,17 @@ static inline com_fix_t com_pnt_max(com_pnt_t a) { This also produces area of a triangle! */ static inline com_fix_t com_pnt_edge_orient(com_pnt_t l0, com_pnt_t l1, com_pnt_t p) { - return (l0.s.x - l1.s.x) * (p.s.y - l1.s.y) - - (l0.s.y - l1.s.y) * (p.s.x - l1.s.x); + return (l0.a[0] - l1.a[0]) * (p.a[1] - l1.a[1]) - + (l0.a[1] - l1.a[1]) * (p.a[0] - l1.a[0]); } #define com_pnt_area(m_p0, m_p1, m_p2) (com_pnt_edge_orient(m_p0, m_p1, m_p2)) static inline com_vec_t com_pnt_edge_weight(com_pnt_t v0, com_pnt_t v1, com_pnt_t v2, com_pnt_t p) { - return (com_vec_t){.s = {.x = com_pnt_edge_orient(v1, v2, p), - .y = com_pnt_edge_orient(v2, v0, p), - .z = com_pnt_edge_orient(v0, v1, p)}}; + return (com_vec_t){.a = {com_pnt_edge_orient(v1, v2, p), + com_pnt_edge_orient(v2, v0, p), + com_pnt_edge_orient(v0, v1, p)}}; } static inline void com_pnt_print(com_pnt_t a) { diff --git a/Common/std.h b/Common/std.h index 670d47e..b78f430 100644 --- a/Common/std.h +++ b/Common/std.h @@ -1,4 +1,20 @@ +/* + Minimal subset of stdlib, none of which have to be actually implemented, + even memory mnagement. +*/ -/* TODO: Actually implement. */ -#define realloc(m_p, m_b) (NULL) -#define free(m_p) ((void)0) +#include +#include + +extern void *com_std_realloc(void *ptr, size_t size); +extern void com_std_free(void *ptr); + +/* Note: Functions listed below are only available for test builds. */ +/* Trigonometry functions are for reference testing of our own fixed point + * implementations. Do not use otherwise. */ +extern void com_std_assert(bool holds); +extern void com_std_printf(char const *fmt, ...); +extern double com_std_sqrt(double v); +extern double com_std_fabs(double v); +extern double com_std_sin(double v); +extern double com_std_cos(double v); diff --git a/Common/vec.h b/Common/vec.h index 6d0a038..241e932 100644 --- a/Common/vec.h +++ b/Common/vec.h @@ -11,79 +11,72 @@ #include "fix.h" #include -typedef union { +typedef struct { com_def_alignedas(16) com_def_vector(com_fix_t, a, 3); - com_def_alignedas(16) struct { - com_fix_t x; - com_fix_t y; - com_fix_t z; - } s; } com_vec_t; static inline com_vec_t com_vec_from(com_fix_t x, com_fix_t y, com_fix_t z) { - return (com_vec_t){.s = {.x = x, .y = y, .z = z}}; + return (com_vec_t){.a = {x, y, z}}; } static inline com_vec_t com_vec_scalar(com_fix_t s) { - return (com_vec_t){.s = {.x = s, .y = s, .z = s}}; + return (com_vec_t){.a = {s, s, s}}; } static inline com_vec_t com_vec_identity(void) { - return (com_vec_t){.s = {.x = COM_FIX_FRACUNIT, - .y = COM_FIX_FRACUNIT, - .z = COM_FIX_FRACUNIT}}; + return (com_vec_t){ + .a = {COM_FIX_FRACUNIT, COM_FIX_FRACUNIT, COM_FIX_FRACUNIT}}; } static inline com_vec_t com_vec_add(com_vec_t a, com_vec_t b) { - return (com_vec_t){.s = {.x = com_fix_add(a.s.x, b.s.x), - .y = com_fix_add(a.s.y, b.s.y), - .z = com_fix_add(a.s.z, b.s.z)}}; + return (com_vec_t){.a = {com_fix_add(a.a[0], b.a[0]), + com_fix_add(a.a[1], b.a[1]), + com_fix_add(a.a[2], b.a[2])}}; } static inline com_vec_t com_vec_sub(com_vec_t a, com_vec_t b) { - return (com_vec_t){.s = {.x = com_fix_sub(a.s.x, b.s.x), - .y = com_fix_sub(a.s.y, b.s.y), - .z = com_fix_sub(a.s.z, b.s.z)}}; + return (com_vec_t){.a = {com_fix_sub(a.a[0], b.a[0]), + com_fix_sub(a.a[1], b.a[1]), + com_fix_sub(a.a[2], b.a[2])}}; } static inline com_vec_t com_vec_mul(com_vec_t a, com_vec_t b) { - return (com_vec_t){.s = {.x = com_fix_mul(a.s.x, b.s.x), - .y = com_fix_mul(a.s.y, b.s.y), - .z = com_fix_mul(a.s.z, b.s.z)}}; + return (com_vec_t){.a = {com_fix_mul(a.a[0], b.a[0]), + com_fix_mul(a.a[1], b.a[1]), + com_fix_mul(a.a[2], b.a[2])}}; } /* Note: this does not clamp for over/underflow cases */ static inline com_vec_t com_vec_div(com_vec_t a, com_vec_t b) { - return (com_vec_t){.s = {.x = com_fix_div(a.s.x, b.s.x), - .y = com_fix_div(a.s.y, b.s.y), - .z = com_fix_div(a.s.z, b.s.z)}}; + return (com_vec_t){.a = {com_fix_div(a.a[0], b.a[0]), + com_fix_div(a.a[1], b.a[1]), + com_fix_div(a.a[2], b.a[2])}}; } /* Scale vector by a fixed point number */ static inline com_vec_t com_vec_scl(com_vec_t a, com_fix_t b) { - return (com_vec_t){.s = {.x = com_fix_mul(a.s.x, b), - .y = com_fix_mul(a.s.y, b), - .z = com_fix_mul(a.s.z, b)}}; + return (com_vec_t){.a = {com_fix_mul(a.a[0], b), com_fix_mul(a.a[1], b), + com_fix_mul(a.a[2], b)}}; } /* Shows how much given vectors are correlated in direction to each other */ /* Resulted range depends on input, it's in -1 to 1 for normalized * input and otherwise is -ab to +ab */ static inline com_fix_t com_vec_dot(com_vec_t a, com_vec_t b) { - return (((int64_t)a.s.x * b.s.x) + ((int64_t)a.s.y * b.s.y) + - ((int64_t)a.s.z * b.s.z)) >> + return (((int64_t)a.a[0] * b.a[0]) + ((int64_t)a.a[1] * b.a[1]) + + ((int64_t)a.a[2] * b.a[2])) >> COM_FIX_FRACBITS; } /* Cross product produces a perpendicular for normalized vectors, or 0 for * parallel vectors */ static inline com_vec_t com_vec_crs(com_vec_t a, com_vec_t b) { - int64_t const cx = ((int64_t)a.s.y * b.s.z) - ((int64_t)a.s.z - b.s.y); - int64_t const cy = ((int64_t)a.s.z * b.s.x) - ((int64_t)a.s.x - b.s.z); - int64_t const cz = ((int64_t)a.s.x * b.s.y) - ((int64_t)a.s.y - b.s.x); - return (com_vec_t){.s = {.x = (com_fix_t)(cx >> COM_FIX_FRACBITS), - .y = (com_fix_t)(cy >> COM_FIX_FRACBITS), - .z = (com_fix_t)(cz >> COM_FIX_FRACBITS)}}; + int64_t const cx = ((int64_t)a.a[1] * b.a[2]) - ((int64_t)a.a[2] - b.a[1]); + int64_t const cy = ((int64_t)a.a[2] * b.a[0]) - ((int64_t)a.a[0] - b.a[2]); + int64_t const cz = ((int64_t)a.a[0] * b.a[1]) - ((int64_t)a.a[1] - b.a[0]); + return (com_vec_t){.a = {(com_fix_t)(cx >> COM_FIX_FRACBITS), + (com_fix_t)(cy >> COM_FIX_FRACBITS), + (com_fix_t)(cz >> COM_FIX_FRACBITS)}}; } /* Normalize vector, making it a unit one (of length 1). */ @@ -91,9 +84,8 @@ static inline com_vec_t com_vec_crs(com_vec_t a, com_vec_t b) { static inline com_vec_t com_vec_nrm(com_vec_t a) { com_fix_t const n = com_fix_sqrt(com_vec_dot(a, a)); // return com_vec_scl(a, com_fix_div(COM_FIX_FRACUNIT, n)); - return (com_vec_t){.s = {.x = com_fix_div(a.s.x, n), - .y = com_fix_div(a.s.y, n), - .z = com_fix_div(a.s.z, n)}}; + return (com_vec_t){.a = {com_fix_div(a.a[0], n), com_fix_div(a.a[1], n), + com_fix_div(a.a[2], n)}}; } static inline com_fix_t com_vec_min(com_vec_t a) { diff --git a/Player/Makefile b/Player/Makefile index 3753c97..5abb770 100644 --- a/Player/Makefile +++ b/Player/Makefile @@ -1,26 +1,26 @@ CC = clang # todo: Only link to libm on debug. -CFLAGS = -Wall -std=c99 -g3 -O3 +CFLAGS = -Wall -std=c99 -g3 -O3 -flto=full DEPS = ../Common/lzw.h ../Common/mat.h ../Common/vec.h ../Common/fix.h ../Common/def.h ../Common/bits.h \ ../Common/gem.h \ ../Common/Timer/timer.h \ ./Display/display.h \ ./draw.h SRC = ../Common/lzw.c ../Common/fix.c ../Common/mat.c ./draw.c -OBJ = ../Common/lzw.o ../Common/fix.o ../Common/mat.o ./draw.o -LINUX = ./Main/linux.o ./amalgam.o Display/x11.o ../Common/Timer/unix.o +LINUX = ./amalgam.c WASM = ./amalgam.c DOS = maindos.c Display/dos.c %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) -linux: CFLAGS += -msse2 -lm -lX11 +# TODO: Make it work with no stdlib. +linux: CFLAGS += -msse2 -lm -lX11 # -nostdlib linux: $(LINUX) | $(SRC) $(CC) -o player $^ $(CFLAGS) # Note: lld package might need to be downloaded. -wasm: CFLAGS += --target=wasm32 -nostdlib -Wl,--no-entry +wasm: CFLAGS += --target=wasm32 -nostdlib -Wl,--no-entry -msimd128 wasm: $(CC) -o player.wasm $(WASM) $(CFLAGS) diff --git a/Player/amalgam.c b/Player/amalgam.c index 4c15404..fda2437 100644 --- a/Player/amalgam.c +++ b/Player/amalgam.c @@ -2,7 +2,17 @@ Amalgamation file, compiling all in single unit. */ +#include "../Common/def.h" #include "../Common/fix.c" #include "../Common/lzw.c" #include "../Common/mat.c" #include "./draw.c" + +#if COM_DEF_TARGET == COM_DEF_TARGET_LINUX +#include "../Common/Std/libc.c" +#include "../Common/Timer/posix.c" +#include "./Display/x11.c" +#include "./Main/linux.c" +#elif COM_DEF_TARGET == COM_DEF_TARGET_WASM +#include "../Common/Std/stub.c" +#endif diff --git a/Player/draw.c b/Player/draw.c index ff29427..3d56a94 100644 --- a/Player/draw.c +++ b/Player/draw.c @@ -6,14 +6,14 @@ #if COM_DEF_TARGET == COM_DEF_TARGET_WASM uint8_t plr_draw_buffer[640 * 480 * 4]; -__attribute__((export_name("plr_draw_get_pixel_buffer"))) uint8_t * -plr_draw_get_pixel_buffer(void) { +com_def_export_sym( + "plr_draw_get_pixel_buffer") uint8_t *plr_draw_get_pixel_buffer(void) { return plr_draw_buffer; } #endif -__attribute__((export_name("plr_draw_screen"))) void -plr_draw_screen(uint8_t *pixel_buffer) { +com_def_export_sym("plr_draw_screen") void plr_draw_screen( + uint8_t *pixel_buffer) { for (int y = 0; y < 480; y++) { for (int x = 0; x < 640; x++) { int pixel_index = (y * 640 + x) * 4;