refactor, libc made optional

This commit is contained in:
veclavtlica
2026-09-14 12:21:49 +03:00
parent 26f6ba56e9
commit 1125073568
14 changed files with 178 additions and 152 deletions
+20
View File
@@ -0,0 +1,20 @@
#include "../std.h"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <tgmath.h>
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); }
+10
View File
@@ -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; }
+2 -4
View File
@@ -1,11 +1,9 @@
#include "../std.h"
#include "timer.h"
#include <stdint.h>
#include <stdio.h>
#define __USE_POSIX199309 1
#include <time.h>
/* 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);
}
+4 -13
View File
@@ -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")
+20 -22
View File
@@ -6,15 +6,10 @@
#include "fix.h"
#include "Timer/timer.h"
#include "def.h"
#include "std.h"
#include <stdbool.h>
#include <stdint.h>
#ifndef COM_DEF_NOSTD
#include <assert.h>
#include <stdio.h>
#include <tgmath.h>
#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,
com_std_printf("max sincos deviations: %f %f\n", max_sin_deviation,
max_cos_deviation);
}
#endif
}
+15 -15
View File
@@ -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
+12 -16
View File
@@ -5,17 +5,11 @@
#include "lzw.h"
#include "bits.h"
#include "std.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifndef COM_DEF_NOSTD
#include <assert.h>
#include <stdlib.h>
#else
#include "std.h"
#endif
/* References: */
/* https://www.w3.org/Graphics/GIF/spec-gif89a.txt */
/* https://www.daubnet.com/en/file-format-gif */
@@ -50,7 +44,8 @@ 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) *
if (!(table = com_std_realloc(
table, sizeof(struct com_lzw_table_entry) *
(table_cap + COM_LZW_TABLE_CAP_GROW))))
goto ERR_ALLOC_INIT_TABLE;
@@ -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;
}
+10 -10
View File
@@ -21,7 +21,7 @@
#include "vec.h"
#include <stdint.h>
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);
+16 -21
View File
@@ -10,54 +10,49 @@
#include "vec.h"
#include <stdint.h>
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) {
+19 -3
View File
@@ -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 <stdbool.h>
#include <stddef.h>
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);
+29 -37
View File
@@ -11,79 +11,72 @@
#include "fix.h"
#include <stdint.h>
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) {
+5 -5
View File
@@ -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)
+10
View File
@@ -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
+4 -4
View File
@@ -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;