some progress
This commit is contained in:
+20
-15
@@ -1,16 +1,8 @@
|
||||
#include "../def.h"
|
||||
#include "../std.h"
|
||||
#include "../str.h"
|
||||
#include <stdarg.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
static inline long com_std_syscall(long number, long arg1, long arg2,
|
||||
long arg3) {
|
||||
long ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(number), "D"(arg1), "S"(arg2), "d"(arg3)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
#include <stdint.h>
|
||||
|
||||
void *com_std_alloc(void *ptr, size_t size) { return NULL; }
|
||||
void com_std_assert(bool holds) {
|
||||
@@ -21,13 +13,26 @@ void com_std_assert(bool holds) {
|
||||
|
||||
/* TODO: Figure out a way to make it easy to deal with. */
|
||||
void com_std_printf(char const *fmt, ...) {
|
||||
// va_list args;
|
||||
// va_start(args, fmt);
|
||||
// vprintf(fmt, args);
|
||||
// va_end(args);
|
||||
com_std_syscall(1, 1, (intptr_t)fmt, com_str_ext_len(fmt));
|
||||
}
|
||||
|
||||
void com_std_print_str(char const *str, uint32_t len, bool newline) {
|
||||
com_std_syscall(1, 1, (intptr_t)str, len);
|
||||
if (newline)
|
||||
com_std_syscall(1, 1, (intptr_t)"\n", 1);
|
||||
}
|
||||
|
||||
double com_std_sqrt(double v) { return __builtin_sqrt(v); }
|
||||
double com_std_fabs(double v) { return __builtin_fabs(v); }
|
||||
#if COM_DEF_COMPILER == COM_DEF_COMPILER_CLANG
|
||||
double com_std_sin(double v) { return __builtin_sin(v); }
|
||||
double com_std_cos(double v) { return __builtin_cos(v); }
|
||||
#else
|
||||
/* TODO: Use fsin/fcos, no matter how slow. */
|
||||
double com_std_sin(double v) { return 0; }
|
||||
double com_std_cos(double v) { return 0; }
|
||||
#endif
|
||||
|
||||
// void memcpy(void *__restrict dest, const void *__restrict src, size_t n) {
|
||||
// __builtin_memcpy(dest, src, n);
|
||||
// };
|
||||
|
||||
@@ -6,5 +6,15 @@ void com_std_printf(char const *fmt, ...) {}
|
||||
|
||||
double com_std_sqrt(double v) { return __builtin_sqrt(v); }
|
||||
double com_std_fabs(double v) { return __builtin_fabs(v); }
|
||||
#if COM_DEF_COMPILER == COM_DEF_COMPILER_CLANG
|
||||
double com_std_sin(double v) { return __builtin_sin(v); }
|
||||
double com_std_cos(double v) { return __builtin_cos(v); }
|
||||
#else
|
||||
/* TODO: Use fsin/fcos, no matter how slow. */
|
||||
double com_std_sin(double v) { return 0; }
|
||||
double com_std_cos(double v) { return 0; }
|
||||
#endif
|
||||
|
||||
// void memcpy(void *__restrict dest, const void *__restrict src, size_t n) {
|
||||
// __builtin_memcpy(dest, src, n);
|
||||
// };
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#include "time.h"
|
||||
#include "../time.h"
|
||||
#include <stdint.h>
|
||||
|
||||
uint64_t com_timer_count_ns(void) { return 0; }
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bin.h"
|
||||
#include "bits.h"
|
||||
#include "buf.h"
|
||||
#include "def.h"
|
||||
#include "std.h"
|
||||
|
||||
bool com_bin_read_i16(com_bin *b, int16_t *value) {
|
||||
int16_t buf;
|
||||
if (!b->interface.readn(b->ctx, (char *)&buf, 2))
|
||||
return false;
|
||||
if (COM_DEF_CPU_LITEND && (b->flags & COM_BIN_BIG_ENDIAN)) {
|
||||
*value = __builtin_bswap16(buf);
|
||||
} else
|
||||
*value = buf;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Same thing, really. */
|
||||
bool com_bin_read_u16(com_bin *b, uint16_t *value) {
|
||||
return (com_bin_read_i16(b, (int16_t *)value));
|
||||
}
|
||||
|
||||
bool com_bin_read_bufb(com_bin *b, struct com_buf *buf, uint32_t bytes) {
|
||||
com_std_assert(buf->typesz == 1);
|
||||
|
||||
if (!com_buf_make_room(buf, bytes))
|
||||
return false;
|
||||
bool s = b->interface.readn(b->ctx, (char *)&buf->data[buf->len], bytes);
|
||||
if (s)
|
||||
buf->len += bytes;
|
||||
return s;
|
||||
}
|
||||
|
||||
bool com_bin_read_bufbi(com_bin *b, struct com_buf *buf, uint32_t *index,
|
||||
uint32_t bytes) {
|
||||
com_std_assert(buf->typesz == 1);
|
||||
|
||||
uint32_t const alignextra =
|
||||
com_bits_nalign(buf->len, COM_DEF_ALIGNMENT) - buf->len;
|
||||
|
||||
if (!com_buf_make_room(buf, alignextra + sizeof(struct com_buf) + bytes))
|
||||
return false;
|
||||
|
||||
buf->len += alignextra;
|
||||
struct com_buf *in = (struct com_buf *)&buf->data[buf->len];
|
||||
buf->len += sizeof(struct com_buf);
|
||||
bool s = b->interface.readn(b->ctx, (char *)&buf->data[buf->len], bytes);
|
||||
if (s) {
|
||||
buf->len += bytes;
|
||||
*in = (struct com_buf){.cap = bytes,
|
||||
.len = bytes,
|
||||
.typesz = 1,
|
||||
.flags = (buf->flags & COM_BUF_STACK) | COM_BUF_SUB};
|
||||
*index = ((ptrdiff_t)in - (ptrdiff_t)buf->data) / sizeof(struct com_buf);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
bool com_bin_skip(com_bin *b, uint32_t bytes) {
|
||||
return b->interface.skipn(b->ctx, bytes);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Generic interface for binary data parsing.
|
||||
*/
|
||||
|
||||
#ifndef COM_BIN_H
|
||||
#define COM_BIN_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "buf.h"
|
||||
|
||||
#define COM_BIN_LIT_ENDIAN (1 << 0)
|
||||
#define COM_BIN_BIG_ENDIAN (1 << 1)
|
||||
#define COM_BIN_NAT_ENDIAN (1 << 2)
|
||||
|
||||
typedef struct com_bin_interface {
|
||||
/* Attempts to read exactly N bytes, returns false if it cannot. */
|
||||
bool (*readn)(void *ctx, char *into, uint32_t bytes);
|
||||
bool (*skipn)(void *ctx, uint32_t bytes);
|
||||
} com_bin_interface;
|
||||
|
||||
typedef struct com_bin {
|
||||
struct com_bin_interface interface;
|
||||
void *ctx;
|
||||
uint32_t flags;
|
||||
} com_bin;
|
||||
|
||||
bool com_bin_read_i16(com_bin *b, int16_t *value);
|
||||
bool com_bin_read_u16(com_bin *b, uint16_t *value);
|
||||
/*
|
||||
Read untyped bytes appending them to buffer.
|
||||
NOTE: Buffer must have typesz of 1. */
|
||||
bool com_bin_read_bufb(com_bin *b, struct com_buf *buf, uint32_t bytes);
|
||||
/*
|
||||
Inline byte buffer read, making a new buffer inside.
|
||||
Resulted index can be safely used in case of future reallocations.
|
||||
NOTE: Buffer must have typesz of 1. */
|
||||
bool com_bin_read_bufbi(com_bin *b, struct com_buf *buf, uint32_t *index,
|
||||
uint32_t bytes);
|
||||
|
||||
/* TODO: Typed variant, use buf for typesz? */
|
||||
/* Skip N bytes. */
|
||||
bool com_bin_skip(com_bin *b, uint32_t n);
|
||||
|
||||
#endif
|
||||
+19
-14
@@ -6,23 +6,28 @@
|
||||
|
||||
/* How many bits needed to represent a given number */
|
||||
/* Alternitive semntic: nearest upper power of two */
|
||||
static inline int com_bits_needed(uint32_t v) {
|
||||
#ifdef COM_DEF_COMPILE_MODERN
|
||||
static inline uint8_t com_bits_needed(uint32_t v) {
|
||||
// #ifdef COM_DEF_COMPILE_MODERN
|
||||
return v == 0 ? 1 : 32 - __builtin_clz(v);
|
||||
#else
|
||||
#endif
|
||||
if (v == 0)
|
||||
return 1;
|
||||
// #else
|
||||
// #endif
|
||||
// if (v == 0)
|
||||
// return 1;
|
||||
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
// v--;
|
||||
// v |= v >> 1;
|
||||
// v |= v >> 2;
|
||||
// v |= v >> 4;
|
||||
// v |= v >> 8;
|
||||
// v |= v >> 16;
|
||||
// v++;
|
||||
|
||||
return v;
|
||||
// return v;
|
||||
}
|
||||
|
||||
/* Next aligned value. */
|
||||
static inline uint32_t com_bits_nalign(uint32_t v, uint8_t a) {
|
||||
return (v + (a - 1)) & ~(a - 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "buf.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct com_buf *com_buf_make(uint32_t cap, uint32_t flags) { return NULL; }
|
||||
|
||||
bool com_buf_make_room(struct com_buf *b, uint32_t n) {
|
||||
if (b->cap - b->len >= n)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void com_buf_free(struct com_buf *b) {}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Generic buffer structure, both dynamic and static.
|
||||
|
||||
Underlying implementation is very simplistic, but it's done so
|
||||
in assumption that we always bulk allocate, with no fragmentation.
|
||||
*/
|
||||
|
||||
#ifndef COM_BUF_H
|
||||
#define COM_BUF_H
|
||||
|
||||
#include "def.h"
|
||||
#include "str.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define COM_BUF_GROWABLE (1 << 0) /* Potentially growable. */
|
||||
#define COM_BUF_STACK (1 << 1) /* Stack residing. */
|
||||
#define COM_BUF_RING (1 << 2) /* Cycling memory. */
|
||||
#define COM_BUF_SUB (1 << 3) /* Buffer inside of a buffer. */
|
||||
|
||||
typedef struct com_buf {
|
||||
uint32_t len; /* Length in typed number of elements. */
|
||||
uint32_t cap; /* Capacity in typed number of elements. */
|
||||
uint32_t flags;
|
||||
union {
|
||||
uint32_t needle; /* Present for ring type. */
|
||||
} type;
|
||||
uint8_t typesz;
|
||||
char data[] __attribute__((aligned(COM_DEF_ALIGNMENT)));
|
||||
} com_buf;
|
||||
|
||||
/* Creates a stack local buffer. It can grow if is set growable, one must still
|
||||
* free it. */
|
||||
#define com_buf_make_on_stack(p_t, p_v, p_c, p_f) \
|
||||
char p_v##_buf[sizeof(p_t) * (p_c)] \
|
||||
__attribute__((aligned(COM_DEF_ALIGNMENT))); \
|
||||
struct com_buf *p_v = (struct com_buf *)&p_v##_buf; \
|
||||
p_v->cap = (p_c); \
|
||||
p_v->flags = p_f | COM_BUF_STACK; \
|
||||
p_v->typesz = sizeof(p_t);
|
||||
|
||||
#define com_buf_index(p_t, p_v, p_i) \
|
||||
(p_t *)(&(p_v)->data[(p_v)->typesz * (p_i)])
|
||||
|
||||
/* Dynamic allocation to persist no matter the function flow. */
|
||||
struct com_buf *com_buf_make(uint32_t cap, uint32_t flags);
|
||||
|
||||
/* Makes sure there's N elements of capacity at least. Returns false if it
|
||||
* cannot do so. */
|
||||
bool com_buf_make_room(struct com_buf *b, uint32_t n);
|
||||
|
||||
/* Drops the memory, not touching the cap. */
|
||||
static inline void com_buf_clear(struct com_buf *b) { b->len = 0; }
|
||||
|
||||
void com_buf_free(struct com_buf *b);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Configuration file.
|
||||
*/
|
||||
|
||||
#ifndef COM_CFG_H
|
||||
#define COM_CFG_H
|
||||
|
||||
/* Render resolution. */
|
||||
#define COM_CFG_WIDTH 640
|
||||
#define COM_CFG_HEIGHT 480
|
||||
|
||||
#endif
|
||||
+34
-14
@@ -1,37 +1,57 @@
|
||||
/*
|
||||
Compiler definitions helpers, for portability.
|
||||
We assume only modern GCC and Clang here.
|
||||
*/
|
||||
|
||||
#ifndef COM_DEF_H
|
||||
#define COM_DEF_H
|
||||
|
||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
|
||||
defined(__GNUC__) || defined(__clang__)
|
||||
#define COM_DEF_COMPILE_MODERN 1
|
||||
#define COM_DEF_COMPILER_CLANG 1
|
||||
#define COM_DEF_COMPILER_GCC 2
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#define COM_DEF_COMPILER COM_DEF_COMPILER_GCC
|
||||
#elif defined(__clang__)
|
||||
#define COM_DEF_COMPILER COM_DEF_COMPILER_CLANG
|
||||
#endif
|
||||
|
||||
#define COM_DEF_TARGET_LINUX 0
|
||||
#define COM_DEF_TARGET_WASM 1
|
||||
#define COM_DEF_TARGET_LINUX 1
|
||||
#define COM_DEF_TARGET_WASM 2
|
||||
|
||||
#if defined(__wasm__)
|
||||
#define COM_DEF_TARGET COM_DEF_TARGET_WASM
|
||||
#define com_def_export_sym(m_s) __attribute__((export_name(m_s)))
|
||||
#else
|
||||
#elif defined(__linux__)
|
||||
#define COM_DEF_TARGET COM_DEF_TARGET_LINUX
|
||||
#define com_def_export_sym(m_s) __attribute__((visibility("default")))
|
||||
#else
|
||||
#error Unknown target.
|
||||
#endif
|
||||
|
||||
/* TODO: uppercase? */
|
||||
#ifdef COM_DEF_COMPILE_MODERN
|
||||
#define com_def_alignedas(v_as) _Alignas(v_as)
|
||||
#define com_def_vector(v_t, v_v, v_n) \
|
||||
v_t v_v __attribute__((vector_size(sizeof(v_t) * v_n)))
|
||||
#define COM_DEF_CPU_AMD64 1
|
||||
#define COM_DEF_CPU_X86 2
|
||||
#define COM_DEF_CPU_WASM32 3
|
||||
|
||||
#if defined(__wasm__)
|
||||
#define COM_DEF_CPU COM_DEF_CPU_WASM32
|
||||
#define COM_DEF_ALIGNMENT 16
|
||||
#define COM_DEF_CPU_LITEND 1
|
||||
#elif defined(__x86_64__) || defined(__amd64__)
|
||||
#define COM_DEF_CPU COM_DEF_CPU_AMD64
|
||||
#define COM_DEF_CPU_LITEND 1
|
||||
#define COM_DEF_ALIGNMENT 32
|
||||
#elif defined(__i386__)
|
||||
#define COM_DEF_CPU COM_DEF_CPU_X86
|
||||
#define COM_DEF_ALIGNMENT 16
|
||||
#define COM_DEF_CPU_LITEND 1
|
||||
#else
|
||||
#define com_def_alignedas(v_as)
|
||||
#define com_def_vector(v_t, v_v, v_n) v_t v_v[v_n]
|
||||
#error Unknown cpu.
|
||||
#endif
|
||||
|
||||
#define com_def_alignedas(v_as) _Alignas(v_as)
|
||||
#define com_def_vector(v_t, v_v, v_b) v_t v_v __attribute__((vector_size(v_b)))
|
||||
|
||||
// #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")
|
||||
#define com_def_profile_sink(m_v) __asm__ volatile("" ::"r"(m_v) : "memory")
|
||||
|
||||
#endif
|
||||
|
||||
+79
-87
@@ -51,12 +51,7 @@ com_fix_t com_fix_sqrt(com_fix_t a) {
|
||||
if (shift & 1)
|
||||
shift -= 1;
|
||||
|
||||
uint32_t normalized_a;
|
||||
if (shift > 0) {
|
||||
normalized_a = a >> shift;
|
||||
} else {
|
||||
normalized_a = a << (-shift);
|
||||
}
|
||||
uint32_t normalized_a = shift > 0 ? a >> shift : a << (-shift);
|
||||
|
||||
// 3. LUT Lookup using 4 MSBs of the normalized value
|
||||
// Extracted index corresponds to the interval [0.5, 2.0)
|
||||
@@ -72,11 +67,8 @@ com_fix_t com_fix_sqrt(com_fix_t a) {
|
||||
|
||||
// 5. Denormalize back to the target scale: result = x * 2^(shift / 2)
|
||||
int32_t final_shift = shift / 2;
|
||||
if (final_shift > 0) {
|
||||
return (int32_t)(x << final_shift);
|
||||
} else {
|
||||
return (int32_t)(x >> (-final_shift));
|
||||
}
|
||||
return final_shift > 0 ? (int32_t)(x << final_shift)
|
||||
: (int32_t)(x >> (-final_shift));
|
||||
}
|
||||
|
||||
void com_fix_print(com_fix_t a) {
|
||||
@@ -97,21 +89,21 @@ void com_fix_run_bench(void) {
|
||||
uint64_t start = com_timer_count_ns();
|
||||
for (int i = 5000000; i--;) {
|
||||
com_fix_t sqrt = com_fix_sqrt(i);
|
||||
COM_DEF_PROFILE_SINK(sqrt);
|
||||
com_def_profile_sink(sqrt);
|
||||
}
|
||||
com_timer_profile(start, "fixed: sqrt");
|
||||
|
||||
start = com_timer_count_ns();
|
||||
for (int i = 50000000; i--;) {
|
||||
com_fix_t sin = com_fix_sin(i);
|
||||
COM_DEF_PROFILE_SINK(sin);
|
||||
com_def_profile_sink(sin);
|
||||
}
|
||||
com_timer_profile(start, "fixed: sin");
|
||||
|
||||
start = com_timer_count_ns();
|
||||
for (int i = 50000000; i--;) {
|
||||
com_fix_t cos = com_fix_cos(i);
|
||||
COM_DEF_PROFILE_SINK(cos);
|
||||
com_def_profile_sink(cos);
|
||||
}
|
||||
com_timer_profile(start, "fixed: cos");
|
||||
|
||||
@@ -121,82 +113,82 @@ void com_fix_run_bench(void) {
|
||||
com_fix_sincos(i, &sin, &cos);
|
||||
com_fix_t sinv = sin;
|
||||
com_fix_t cosv = cos;
|
||||
COM_DEF_PROFILE_SINK(sinv);
|
||||
COM_DEF_PROFILE_SINK(cosv);
|
||||
com_def_profile_sink(sinv);
|
||||
com_def_profile_sink(cosv);
|
||||
}
|
||||
com_timer_profile(start, "fixed: sincos");
|
||||
}
|
||||
|
||||
void com_fix_run_tests(void) {
|
||||
// {
|
||||
// double max_sqrt_deviation = 0.0f;
|
||||
// com_fix_t sqrt_accumulator = 0;
|
||||
// com_fix_t sqrt_test_step = COM_FIX_FRACUNIT >> 2; /* Quarter step */
|
||||
// for (int i = 0; i < COM_FIX_FRACUNIT << 1; ++i) {
|
||||
// com_fix_t sqrt = com_fix_sqrt(sqrt_accumulator);
|
||||
// double const deviation =
|
||||
// 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;
|
||||
// }
|
||||
// com_std_printf("max sqrt deviation: %f\n", max_sqrt_deviation);
|
||||
// }
|
||||
|
||||
// {
|
||||
// double max_sin_deviation = 0.0f;
|
||||
// com_fix_t sin_accumulator = -COM_FIX_PI * 4;
|
||||
// com_fix_t sin_test_step = (COM_FIX_PI << 1) >> 10;
|
||||
// for (int i = 0; i < 1024 * 32; ++i) {
|
||||
// com_fix_t sin = com_fix_sin(sin_accumulator);
|
||||
// double const deviation =
|
||||
// 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;
|
||||
// }
|
||||
// com_std_printf("max sin deviation: %f\n", max_sin_deviation);
|
||||
// }
|
||||
|
||||
// {
|
||||
// double max_cos_deviation = 0.0f;
|
||||
// com_fix_t cos_accumulator = -COM_FIX_PI * 4;
|
||||
// com_fix_t cos_test_step = (COM_FIX_PI << 1) >> 10;
|
||||
// for (int i = 0; i < 1024 * 32; ++i) {
|
||||
// com_fix_t cos = com_fix_cos(cos_accumulator);
|
||||
// double const deviation =
|
||||
// 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;
|
||||
// }
|
||||
// com_std_printf("max cos deviation: %f\n", max_cos_deviation);
|
||||
// }
|
||||
|
||||
// {
|
||||
// double max_sin_deviation = 0.0f;
|
||||
// double max_cos_deviation = 0.0f;
|
||||
// com_fix_t sincos_accumulator = -COM_FIX_PI * 4;
|
||||
// com_fix_t sincos_test_step = (COM_FIX_PI << 1) >> 10;
|
||||
// for (int i = 0; i < 1024 * 32; ++i) {
|
||||
// com_fix_t sin, cos;
|
||||
// com_fix_sincos(sincos_accumulator, &sin, &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;
|
||||
// }
|
||||
// com_std_printf("max sincos deviations: %f %f\n", max_sin_deviation,
|
||||
// max_cos_deviation);
|
||||
// }
|
||||
{
|
||||
double max_sqrt_deviation = 0.0f;
|
||||
com_fix_t sqrt_accumulator = 0;
|
||||
com_fix_t sqrt_test_step = COM_FIX_FRACUNIT >> 2; /* Quarter step */
|
||||
for (int i = 0; i < COM_FIX_FRACUNIT << 1; ++i) {
|
||||
com_fix_t sqrt = com_fix_sqrt(sqrt_accumulator);
|
||||
double const deviation =
|
||||
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;
|
||||
}
|
||||
com_std_printf("max sqrt deviation: %f\n", max_sqrt_deviation);
|
||||
}
|
||||
|
||||
{
|
||||
double max_sin_deviation = 0.0f;
|
||||
com_fix_t sin_accumulator = -COM_FIX_PI * 4;
|
||||
com_fix_t sin_test_step = (COM_FIX_PI << 1) >> 10;
|
||||
for (int i = 0; i < 1024 * 32; ++i) {
|
||||
com_fix_t sin = com_fix_sin(sin_accumulator);
|
||||
double const deviation =
|
||||
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;
|
||||
}
|
||||
com_std_printf("max sin deviation: %f\n", max_sin_deviation);
|
||||
}
|
||||
|
||||
{
|
||||
double max_cos_deviation = 0.0f;
|
||||
com_fix_t cos_accumulator = -COM_FIX_PI * 4;
|
||||
com_fix_t cos_test_step = (COM_FIX_PI << 1) >> 10;
|
||||
for (int i = 0; i < 1024 * 32; ++i) {
|
||||
com_fix_t cos = com_fix_cos(cos_accumulator);
|
||||
double const deviation =
|
||||
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;
|
||||
}
|
||||
com_std_printf("max cos deviation: %f\n", max_cos_deviation);
|
||||
}
|
||||
|
||||
{
|
||||
double max_sin_deviation = 0.0f;
|
||||
double max_cos_deviation = 0.0f;
|
||||
com_fix_t sincos_accumulator = -COM_FIX_PI * 4;
|
||||
com_fix_t sincos_test_step = (COM_FIX_PI << 1) >> 10;
|
||||
for (int i = 0; i < 1024 * 32; ++i) {
|
||||
com_fix_t sin, cos;
|
||||
com_fix_sincos(sincos_accumulator, &sin, &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;
|
||||
}
|
||||
com_std_printf("max sincos deviations: %f %f\n", max_sin_deviation,
|
||||
max_cos_deviation);
|
||||
}
|
||||
}
|
||||
|
||||
+18
-18
@@ -5,13 +5,13 @@
|
||||
#ifndef COM_GEM_H
|
||||
#define COM_GEM_H
|
||||
|
||||
#include "cfg.h"
|
||||
#include "fix.h"
|
||||
#include "mat.h"
|
||||
#include "pnt.h"
|
||||
#include "vec.h"
|
||||
#include "zord.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Projects vertex position to a clip space via reordered row-major MVP matrix.
|
||||
It skips calculation of z depth component, as we assume to never use it.
|
||||
@@ -24,10 +24,10 @@ 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.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;
|
||||
result.a[m_c] = \
|
||||
((com_fix_mul(a.a[m_n * 4 + 0], b.a[0])) + \
|
||||
(com_fix_mul(a.a[m_n * 4 + 1], b.a[1])) + \
|
||||
(com_fix_mul(a.a[m_n * 4 + 2], b.a[2])) + a.a[m_n * 4 + 3]);
|
||||
|
||||
CASE(0, 0);
|
||||
CASE(1, 1);
|
||||
@@ -59,18 +59,18 @@ static inline uint8_t com_gem_clip_vis_project(com_vec_t a, com_pnt_t *out) {
|
||||
mask ^= COM_GEM_VERTEX_CLIPPED_Y;
|
||||
// out->a[0] = com_fix_mul((com_fix_div(a.a[0], a.a[2]) + COM_FIX_FRACUNIT) >>
|
||||
// 1,
|
||||
// 640 * COM_FIX_FRACUNIT);
|
||||
// COM_CFG_WIDTH * COM_FIX_FRACUNIT);
|
||||
// out->a[1] = com_fix_mul((com_fix_div(a.a[1], a.a[2]) + COM_FIX_FRACUNIT) >>
|
||||
// 1,
|
||||
// 480 * COM_FIX_FRACUNIT);
|
||||
out->a[0] =
|
||||
(com_fix_mul(com_fix_div(a.a[0], a.a[2]), 640 * COM_FIX_FRACUNIT) >>
|
||||
// COM_CFG_HEIGHT * COM_FIX_FRACUNIT);
|
||||
out->a[0] = (com_fix_mul(com_fix_div(a.a[0], a.a[2]),
|
||||
COM_CFG_WIDTH * COM_FIX_FRACUNIT) >>
|
||||
COM_FIX_FRACBITS) +
|
||||
320;
|
||||
out->a[1] =
|
||||
(com_fix_mul(com_fix_div(a.a[1], a.a[2]), 480 * COM_FIX_FRACUNIT) >>
|
||||
(COM_CFG_WIDTH / 2);
|
||||
out->a[1] = (com_fix_mul(com_fix_div(a.a[1], a.a[2]),
|
||||
COM_CFG_HEIGHT * COM_FIX_FRACUNIT) >>
|
||||
COM_FIX_FRACBITS) +
|
||||
240;
|
||||
(COM_CFG_HEIGHT / 2);
|
||||
return mask;
|
||||
}
|
||||
|
||||
@@ -91,9 +91,9 @@ static inline void com_gem_draw_triangle(com_pnt_t v0, com_pnt_t v1,
|
||||
// If the point is inside or on all edges, draw the pixel
|
||||
// (Assumes Counter Clockwise vertex ordering)
|
||||
if (ws.a[0] >= 0 && ws.a[1] >= 0 && ws.a[2] >= 0) {
|
||||
out[(y * 640 + x) * 4 + 0] = 125;
|
||||
out[(y * 640 + x) * 4 + 1] = 125;
|
||||
out[(y * 640 + x) * 4 + 2] = 125;
|
||||
out[(y * COM_CFG_WIDTH + x) * 4 + 0] = 125;
|
||||
out[(y * COM_CFG_WIDTH + x) * 4 + 1] = 125;
|
||||
out[(y * COM_CFG_WIDTH + x) * 4 + 2] = 125;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,7 +145,7 @@ com_gem_draw_triangle_textured_edge(com_pnt_t v0, com_pnt_t v1, com_pnt_t v2,
|
||||
// uint32_t idx = com_zord_order(tx, ty);
|
||||
uint32_t idx = ty * 32 + tx;
|
||||
// uint32_t bidx = com_zord_order(x, y);
|
||||
uint32_t bidx = y * 640 + x;
|
||||
uint32_t bidx = y * COM_CFG_WIDTH + x;
|
||||
|
||||
out[bidx * 4 + 0] = tex[idx * 3 + 0];
|
||||
out[bidx * 4 + 1] = tex[idx * 3 + 1];
|
||||
@@ -169,7 +169,7 @@ static inline void draw_span(int32_t x_start_fp, int32_t x_end_fp, int y,
|
||||
|
||||
for (int x = x1; x < x2; x++) {
|
||||
uint32_t idx = 0 * 32 + 0;
|
||||
uint32_t bidx = y * 640 + x;
|
||||
uint32_t bidx = y * COM_CFG_WIDTH + x;
|
||||
out[bidx * 4 + 0] = tex[idx * 3 + 0];
|
||||
out[bidx * 4 + 1] = tex[idx * 3 + 1];
|
||||
out[bidx * 4 + 2] = tex[idx * 3 + 2];
|
||||
|
||||
+10
-12
@@ -22,7 +22,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
com_def_alignedas(64) com_def_vector(com_fix_t, a, 4 * 4);
|
||||
com_def_alignedas(64) com_def_vector(com_fix_t, a, 4 * 4 * sizeof(com_fix_t));
|
||||
} com_mat_t;
|
||||
|
||||
void com_mat_run_bench(void);
|
||||
@@ -30,7 +30,7 @@ void com_mat_run_bench(void);
|
||||
#define COM_MAT_PROFILE_SINK(m_m) \
|
||||
do { \
|
||||
for (int i = 0; i < 16; ++i) \
|
||||
COM_DEF_PROFILE_SINK((m_m).a[i]); \
|
||||
com_def_profile_sink((m_m).a[i]); \
|
||||
} while (0)
|
||||
|
||||
static inline com_mat_t com_mat_identity(void) {
|
||||
@@ -60,11 +60,10 @@ static inline com_mat_t com_mat_mul(com_mat_t a, com_mat_t b) {
|
||||
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
result.a[r + c * 4] = (((int64_t)a.a[r + 0 * 4] * b.a[0 + c * 4]) +
|
||||
((int64_t)a.a[r + 1 * 4] * b.a[1 + c * 4]) +
|
||||
((int64_t)a.a[r + 2 * 4] * b.a[2 + c * 4]) +
|
||||
((int64_t)a.a[r + 3 * 4] * b.a[3 + c * 4])) >>
|
||||
COM_FIX_FRACBITS;
|
||||
result.a[r + c * 4] = ((com_fix_mul(a.a[r + 0 * 4], b.a[0 + c * 4])) +
|
||||
(com_fix_mul(a.a[r + 1 * 4], b.a[1 + c * 4])) +
|
||||
(com_fix_mul(a.a[r + 2 * 4], b.a[2 + c * 4])) +
|
||||
(com_fix_mul(a.a[r + 3 * 4], b.a[3 + c * 4])));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,11 +79,10 @@ static inline com_mat_t com_mat_mul_reodered(com_mat_t a, com_mat_t b) {
|
||||
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
result.a[r + c * 4] = (((int64_t)a.a[0 + r * 4] * b.a[0 + c * 4]) +
|
||||
((int64_t)a.a[1 + r * 4] * b.a[1 + c * 4]) +
|
||||
((int64_t)a.a[2 + r * 4] * b.a[2 + c * 4]) +
|
||||
((int64_t)a.a[3 + r * 4] * b.a[3 + c * 4])) >>
|
||||
COM_FIX_FRACBITS;
|
||||
result.a[r + c * 4] = ((com_fix_mul(a.a[0 + r * 4], b.a[0 + c * 4])) +
|
||||
(com_fix_mul(a.a[1 + r * 4], b.a[1 + c * 4])) +
|
||||
(com_fix_mul(a.a[2 + r * 4], b.a[2 + c * 4])) +
|
||||
(com_fix_mul(a.a[3 + r * 4], b.a[3 + c * 4])));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
com_def_alignedas(16) com_def_vector(com_fix_t, a, 2);
|
||||
com_def_alignedas(16) com_def_vector(com_fix_t, a, 2 * sizeof(com_fix_t));
|
||||
} com_pnt_t;
|
||||
|
||||
static inline com_pnt_t com_pnt_from(com_fix_t x, com_fix_t y) {
|
||||
|
||||
+24
-7
@@ -8,18 +8,35 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if COM_DEF_TARGET == COM_DEF_TARGET_LINUX
|
||||
#include <sys/syscall.h>
|
||||
|
||||
static inline long com_std_syscall(long number, long arg1, long arg2,
|
||||
long arg3) {
|
||||
long ret;
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(number), "D"(arg1), "S"(arg2), "d"(arg3)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TODO: Remove, use buffer semantics instead. */
|
||||
/* Note: Freeing is done by passing 0 size to pointer. */
|
||||
extern void *com_std_alloc(void *ptr, size_t size);
|
||||
void *com_std_alloc(void *ptr, size_t size);
|
||||
|
||||
/* Note: Functions listed below are only available for dev 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);
|
||||
void com_std_assert(bool holds);
|
||||
void com_std_printf(char const *fmt, ...);
|
||||
void com_std_print_str(char const *str, uint32_t len, bool newline);
|
||||
double com_std_sqrt(double v);
|
||||
double com_std_fabs(double v);
|
||||
double com_std_sin(double v);
|
||||
double com_std_cos(double v);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Routines for string processing.
|
||||
|
||||
*_ext_* functions are provided for foreign strings we're not in control of.
|
||||
*/
|
||||
|
||||
#ifndef COM_STR_H
|
||||
#define COM_STR_H
|
||||
|
||||
#include "def.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define COM_STR_GROWABLE (1 << 0) /* Data can grow and be reallocated. */
|
||||
#define COM_STR_STACK (1 << 1) /* Stack residing. */
|
||||
#define COM_STR_SUB (1 << 2) /* Substring of an existing one. */
|
||||
#define COM_STR_NULL_TERMINATED (1 << 3) /* Whether there's NULL at last. */
|
||||
|
||||
/* Internal strings are assumed to have vectorizable alignment. */
|
||||
/* Instead of growing strings on joining we implement ropes. */
|
||||
typedef struct com_str {
|
||||
struct com_str *next;
|
||||
/* Actual size is +1, to fit NULL terminator. */
|
||||
uint32_t len;
|
||||
uint32_t flags;
|
||||
char data[] __attribute__((aligned(COM_DEF_ALIGNMENT)));
|
||||
|
||||
} com_str;
|
||||
|
||||
/* NOTE: Have to be moved to static or global memory. */
|
||||
#define com_str_lit(p_l) {NULL, sizeof(p_l) - 1, COM_STR_NULL_TERMINATED, (p_l)}
|
||||
|
||||
static inline uint32_t com_str_ext_len(char const *s) {
|
||||
char const *p = s;
|
||||
for (; *p != 0; ++p) {
|
||||
}
|
||||
return p - s;
|
||||
}
|
||||
|
||||
/* Returns index of a char or -1 if it's not found. */
|
||||
static inline int32_t com_str_ext_find_char(char const *s, char ch) {
|
||||
for (char const *p = s; *p != 0; ++p)
|
||||
if (*p == ch)
|
||||
return p - s;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Returns true if string 'a' is prefixed by 'b'. */
|
||||
static inline bool com_str_ext_prefixed(char const *__restrict a,
|
||||
struct com_str prefix) {
|
||||
uint32_t n = prefix.len;
|
||||
char *b = prefix.data;
|
||||
while (n && *a && (*a == *b)) {
|
||||
++a;
|
||||
++b;
|
||||
--n;
|
||||
}
|
||||
return n == 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
+7
-10
@@ -12,7 +12,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
com_def_alignedas(16) com_def_vector(com_fix_t, a, 3);
|
||||
com_def_alignedas(16) com_def_vector(com_fix_t, a, 4 * sizeof(com_fix_t));
|
||||
} com_vec_t;
|
||||
|
||||
static inline com_vec_t com_vec_from(com_fix_t x, com_fix_t y, com_fix_t z) {
|
||||
@@ -63,20 +63,17 @@ static inline com_vec_t com_vec_scl(com_vec_t a, com_fix_t b) {
|
||||
/* 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.a[0] * b.a[0]) + ((int64_t)a.a[1] * b.a[1]) +
|
||||
((int64_t)a.a[2] * b.a[2])) >>
|
||||
COM_FIX_FRACBITS;
|
||||
return ((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])));
|
||||
}
|
||||
|
||||
/* 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.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)}};
|
||||
return (com_vec_t){
|
||||
.a = {(com_fix_mul(a.a[1], b.a[2])) - (com_fix_mul(a.a[2], b.a[1])),
|
||||
(com_fix_mul(a.a[2], b.a[0])) - (com_fix_mul(a.a[0], b.a[2])),
|
||||
(com_fix_mul(a.a[0], b.a[1])) - (com_fix_mul(a.a[1], b.a[0]))}};
|
||||
}
|
||||
|
||||
/* Normalize vector, making it a unit one (of length 1). */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef PLR_DISPLAY_H
|
||||
#define PLR_DISPLAY_H
|
||||
|
||||
extern int plr_display_x11_main(int argc, char *argv[]);
|
||||
__attribute__((used)) extern int plr_display_x11_main(int argc, char *argv[]);
|
||||
extern int plr_display_dos_main(int argc, char *argv[]);
|
||||
|
||||
#endif
|
||||
|
||||
+119
-10
@@ -1,22 +1,79 @@
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "../../Common/bin.h"
|
||||
#include "../../Common/buf.h"
|
||||
#include "../../Common/cfg.h"
|
||||
#include "../../Common/lzw.h"
|
||||
#include "../../Common/mat.h"
|
||||
#include "../../Common/std.h"
|
||||
#include "../../Common/str.h"
|
||||
#include "../draw.h"
|
||||
#include "display.h"
|
||||
|
||||
/* https://hereket.com/posts/from-scratch-x11-windowing/ */
|
||||
/* https://gaultier.github.io/blog/write_a_video_game_from_scratch_like_1987.html
|
||||
*/
|
||||
|
||||
bool quited = false;
|
||||
|
||||
/* TODO: Have a cfg.h configuration header setting those. */
|
||||
#define WIDTH 640
|
||||
#define HEIGHT 480
|
||||
bool fileread(void *ctx, char *into, uint32_t bytes) {
|
||||
return com_std_syscall(0, (intptr_t)ctx, (intptr_t)into, bytes);
|
||||
}
|
||||
|
||||
bool fileskip(void *ctx, uint32_t bytes) {
|
||||
return com_std_syscall(8, (intptr_t)ctx, bytes, 1) >= 0;
|
||||
}
|
||||
|
||||
static struct plr_x11_auth_entry {
|
||||
uint16_t family;
|
||||
struct com_buf *auth_name;
|
||||
struct com_buf *auth_data;
|
||||
bool success;
|
||||
} plr_x11_read_auth_entry(struct com_bin *b, struct com_buf *buf) {
|
||||
struct plr_x11_auth_entry result = {0};
|
||||
|
||||
if (!com_bin_read_u16(b, &result.family)) {
|
||||
com_std_printf("Failure to initialize X11\n");
|
||||
goto BREAK;
|
||||
}
|
||||
uint16_t addres_len;
|
||||
if (!com_bin_read_u16(b, &addres_len))
|
||||
goto BREAK;
|
||||
if (!com_bin_skip(b, addres_len))
|
||||
goto BREAK;
|
||||
uint16_t display_len;
|
||||
if (!com_bin_read_u16(b, &display_len))
|
||||
goto BREAK;
|
||||
if (!com_bin_skip(b, display_len))
|
||||
goto BREAK;
|
||||
uint16_t name_len;
|
||||
if (!com_bin_read_u16(b, &name_len))
|
||||
goto BREAK;
|
||||
uint32_t name_idx;
|
||||
if (!com_bin_read_bufbi(b, buf, &name_idx, name_len))
|
||||
goto BREAK;
|
||||
uint16_t data_len;
|
||||
if (!com_bin_read_u16(b, &data_len))
|
||||
goto BREAK;
|
||||
uint32_t data_idx;
|
||||
if (!com_bin_read_bufbi(b, buf, &data_idx, name_len))
|
||||
goto BREAK;
|
||||
|
||||
result.auth_name = com_buf_index(struct com_buf, buf, name_idx);
|
||||
result.auth_data = com_buf_index(struct com_buf, buf, data_idx);
|
||||
result.success = true;
|
||||
return result;
|
||||
BREAK:
|
||||
com_std_printf("Failure to initialize X11\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: correct error handling.
|
||||
extern int plr_display_x11_main(int argc, char *argv[]) {
|
||||
@@ -43,9 +100,61 @@ extern int plr_display_x11_main(int argc, char *argv[]) {
|
||||
// com_vec_t v0 = com_mat_vec_project(com_mat_reoder(m0), com_vec_identity());
|
||||
// com_fix_print(v0.a[0]);
|
||||
|
||||
com_fix_run_tests();
|
||||
com_fix_run_bench();
|
||||
com_mat_run_bench();
|
||||
// com_fix_run_tests();
|
||||
// com_fix_run_bench();
|
||||
// com_mat_run_bench();
|
||||
|
||||
/* TODO: Move init to separate func. */
|
||||
/* Open X11 socket for communication. */
|
||||
int const xfd = com_std_syscall(41, AF_UNIX, SOCK_STREAM, 0);
|
||||
if (xfd < 0) {
|
||||
com_std_printf("Failure to initialize X11\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_un const addr = {.sun_family = AF_UNIX,
|
||||
.sun_path = "/tmp/.X11-unix/X0"};
|
||||
if (com_std_syscall(42, xfd, (intptr_t)&addr, sizeof addr)) {
|
||||
com_std_printf("Failure to initialize X11\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* First we need to authenticate X11 connection, which requires some funk. */
|
||||
/* We assume that $XAUTHORITY is set and I hope it is true. */
|
||||
char *xauthpath = NULL;
|
||||
for (char **envp = &argv[argc + 1]; *envp != NULL; ++envp) {
|
||||
static const struct com_str xauthlit = com_str_lit("XAUTHORITY=");
|
||||
if (com_str_ext_prefixed(*envp, xauthlit)) {
|
||||
xauthpath = &((*envp)[xauthlit.len]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Open it and parse. */
|
||||
int const xauthfd = com_std_syscall(2, (intptr_t)xauthpath, O_RDONLY, 0);
|
||||
if (xauthfd < 0) {
|
||||
com_std_printf("Failure to initialize X11\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
com_buf_make_on_stack(char, xauthbuf, 1024, 0);
|
||||
struct com_bin xauthbin = {
|
||||
.ctx = (void *)(int64_t)xauthfd,
|
||||
.flags = COM_BIN_BIG_ENDIAN,
|
||||
.interface = {.readn = fileread, .skipn = fileskip}};
|
||||
|
||||
struct plr_x11_auth_entry auth_entry =
|
||||
plr_x11_read_auth_entry(&xauthbin, xauthbuf);
|
||||
|
||||
com_std_print_str(auth_entry.auth_name->data, auth_entry.auth_name->len,
|
||||
true);
|
||||
com_std_print_str(auth_entry.auth_data->data, auth_entry.auth_data->len,
|
||||
true);
|
||||
|
||||
com_buf_free(xauthbuf);
|
||||
|
||||
char sendbuf[16 * 1024] = {};
|
||||
char readbuf[16 * 1024] = {};
|
||||
|
||||
// Display *display = XOpenDisplay(NULL);
|
||||
// if (NULL == display) {
|
||||
@@ -90,13 +199,13 @@ extern int plr_display_x11_main(int argc, char *argv[]) {
|
||||
|
||||
// GC gc = XCreateGC(display, window, 0, NULL);
|
||||
|
||||
// Atom wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
|
||||
// XSetWMProtocols(display, window, &wm_delete_window, 1);
|
||||
// Atom wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW",
|
||||
// False); XSetWMProtocols(display, window, &wm_delete_window, 1);
|
||||
|
||||
// // TODO: can't be not true
|
||||
// int bytes_per_pixel = 4;
|
||||
// // char *pixel_buffer = (char *)malloc(WIDTH * HEIGHT * bytes_per_pixel);
|
||||
// char pixel_buffer[WIDTH * HEIGHT * bytes_per_pixel];
|
||||
// // char *pixel_buffer = (char *)malloc(WIDTH * HEIGHT *
|
||||
// bytes_per_pixel); char pixel_buffer[WIDTH * HEIGHT * bytes_per_pixel];
|
||||
|
||||
// XImage *ximage = XCreateImage(display, visual, depth, ZPixmap, 0,
|
||||
// pixel_buffer, WIDTH, HEIGHT, 32, 0);
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "../Display/display.h"
|
||||
|
||||
extern int main(int argc, char **argv) { plr_display_x11_main(argc, argv); }
|
||||
+10
-12
@@ -1,15 +1,13 @@
|
||||
#include "../Display/display.h"
|
||||
|
||||
__attribute__((force_align_arg_pointer)) __attribute__((noreturn)) extern void
|
||||
/* No libc starting point. Jump straight into action! */
|
||||
__attribute__((naked)) __attribute__((force_align_arg_pointer))
|
||||
__attribute__((noreturn)) extern void
|
||||
_start(void) {
|
||||
|
||||
plr_display_x11_main(0, 0);
|
||||
|
||||
__asm__ volatile("mov $60, %%rax\n\t"
|
||||
"xor %%rdi, %%rdi\n\t"
|
||||
"syscall"
|
||||
:
|
||||
:
|
||||
: "%rax", "%rdi");
|
||||
__builtin_unreachable();
|
||||
__asm__ volatile("xor %rbp, %rbp\n"
|
||||
"movq (%rsp), %rdi\n"
|
||||
"leaq 8(%rsp), %rsi\n"
|
||||
"call plr_display_x11_main\n"
|
||||
"movq %rax, %rdi\n"
|
||||
"movq $60, %rax\n"
|
||||
"syscall");
|
||||
}
|
||||
|
||||
+35
-4
@@ -1,6 +1,37 @@
|
||||
CC = clang
|
||||
# todo: Only link to libm on debug.
|
||||
CFLAGS = -Wall -std=c99 -g3 -O3 -flto=full
|
||||
RELEASE ?= 0
|
||||
SQUEEZE ?= 0
|
||||
BITS ?= 64
|
||||
CFLAGS = -Wall -std=gnu99 -flto=thin -ffast-math -fno-ident -fvisibility=hidden
|
||||
ifeq ($(MAKECMDGOALS),linux)
|
||||
ifeq ($(RELEASE), 1)
|
||||
CFLAGS += -Wl,--ignore-data-address-equality -Wl,--ignore-function-address-equality \
|
||||
-Wl,--optimize-bb-jumps
|
||||
endif
|
||||
ifeq ($(SQUEEZE), 1)
|
||||
CFLAGS += -Wl,-T,tiny.ld -Wl,--icf=all -Wl,--bp-compression-sort=both \
|
||||
-Wl,--nmagic
|
||||
endif
|
||||
ifeq ($(BITS), 64)
|
||||
CFLAGS += -m64 -march=x86-64-v3 -mpopcnt
|
||||
else
|
||||
CFLAGS += -m32 -msse2
|
||||
endif
|
||||
endif
|
||||
ifeq ($(MAKECMDGOALS),wasm)
|
||||
ifeq ($(RELEASE), 1)
|
||||
CFLAGS += -Wl,--compress-relocations
|
||||
endif
|
||||
endif
|
||||
ifeq ($(RELEASE), 0)
|
||||
CFLAGS += -g3 -O1
|
||||
else
|
||||
CFLAGS += -Wl,--strip-all -DNDEBUG -O3 -fuse-ld=lld -fmerge-all-constants -Wl,-O3 \
|
||||
-ffunction-sections -fdata-sections -Wl,--gc-sections \
|
||||
-Wl,-mllvm,--vectorize-slp=true \
|
||||
-Wl,-mllvm,--enable-gvn-hoist=true
|
||||
endif
|
||||
# TODO: Just use amalgam build for all?
|
||||
DEPS = ../Common/lzw.h ../Common/mat.h ../Common/vec.h ../Common/fix.h ../Common/def.h ../Common/bits.h \
|
||||
../Common/gem.h \
|
||||
../Common/Timer/time.h \
|
||||
@@ -15,12 +46,12 @@ DOS = maindos.c Display/dos.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
# TODO: Make it work with no stdlib.
|
||||
linux: CFLAGS += -msse2 -mbmi2 -nostdlib
|
||||
linux: CFLAGS += -static -mbmi2 -nostdlib
|
||||
linux: $(LINUX) | $(SRC)
|
||||
$(CC) -o player $^ $(CFLAGS)
|
||||
|
||||
# Note: lld package might need to be downloaded.
|
||||
wasm: CFLAGS += --target=wasm32 -nostdlib -Wl,--no-entry -msimd128
|
||||
wasm: CFLAGS += --target=wasm32 -nostdlib -Wl,--no-entry -msimd128 -mbulk-memory
|
||||
wasm:
|
||||
$(CC) -o player.wasm $(WASM) $(CFLAGS)
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
Amalgamation file, compiling all in single unit.
|
||||
*/
|
||||
|
||||
#include "../Common/bin.c"
|
||||
#include "../Common/buf.c"
|
||||
#include "../Common/def.h"
|
||||
#include "../Common/fix.c"
|
||||
#include "../Common/lzw.c"
|
||||
@@ -14,6 +16,8 @@
|
||||
#include "../Common/Timer/stub.c"
|
||||
#include "./Display/x11.c"
|
||||
#include "./Main/linux.c"
|
||||
// #include "./Main/libc.c"
|
||||
#elif COM_DEF_TARGET == COM_DEF_TARGET_WASM
|
||||
#include "../Common/Std/stub.c"
|
||||
#include "../Common/Timer/stub.c"
|
||||
#endif
|
||||
|
||||
+7
-6
@@ -1,4 +1,5 @@
|
||||
|
||||
#include "../Common/cfg.h"
|
||||
#include "../Common/def.h"
|
||||
#include "../Common/gem.h"
|
||||
#include "../Common/std.h"
|
||||
@@ -6,7 +7,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#if COM_DEF_TARGET == COM_DEF_TARGET_WASM
|
||||
uint8_t plr_draw_buffer[640 * 480 * 4];
|
||||
uint8_t plr_draw_buffer[COM_CFG_WIDTH * COM_CFG_HEIGHT * 4];
|
||||
|
||||
com_def_export_sym(
|
||||
"plr_draw_get_pixel_buffer") uint8_t *plr_draw_get_pixel_buffer(void) {
|
||||
@@ -16,9 +17,9 @@ com_def_export_sym(
|
||||
|
||||
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;
|
||||
for (int y = 0; y < COM_CFG_HEIGHT; y++) {
|
||||
for (int x = 0; x < COM_CFG_WIDTH; x++) {
|
||||
int pixel_index = (y * COM_CFG_WIDTH + x) * 4;
|
||||
|
||||
// Assuming standard Little-Endian 32-bit BGRA format
|
||||
pixel_buffer[pixel_index + 0] = (x) % 256; // Blue
|
||||
@@ -28,8 +29,8 @@ com_def_export_sym("plr_draw_screen") void plr_draw_screen(
|
||||
}
|
||||
}
|
||||
|
||||
com_mat_t proj =
|
||||
com_mat_perspective(640, 480, 1, 100 * COM_FIX_FRACUNIT, COM_FIX_PIHALF);
|
||||
com_mat_t proj = com_mat_perspective(COM_CFG_WIDTH, COM_CFG_HEIGHT, 1,
|
||||
100 * COM_FIX_FRACUNIT, COM_FIX_PIHALF);
|
||||
com_mat_t view = com_mat_look_at(com_vec_from(0, 0, 0),
|
||||
com_vec_from(0, COM_FIX_FRACUNIT, 0),
|
||||
com_vec_from(-COM_FIX_FRACUNIT, 0, 0));
|
||||
|
||||
+4
-1
@@ -1,4 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- TODO: https://j9t.github.io/html-minifier-next/ -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -16,6 +17,8 @@
|
||||
const canvas = document.getElementById('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// TODO: Throttle FPS.
|
||||
|
||||
async function main() {
|
||||
const wasm = await WebAssembly.instantiateStreaming(fetch("player.wasm"));
|
||||
const { memory, plr_draw_screen, plr_draw_get_pixel_buffer } = wasm.instance.exports;
|
||||
@@ -24,7 +27,7 @@
|
||||
const wasmBuffer = new Uint8ClampedArray(
|
||||
memory.buffer,
|
||||
bufferPtr,
|
||||
640 * 480 * 4
|
||||
640 * 480 * 4 // TODO: Retrieve actual values.
|
||||
);
|
||||
const imgData = new ImageData(wasmBuffer, 640, 480);
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FLAGS(5); /* RX: Read/Execute */
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000));
|
||||
. = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
|
||||
|
||||
.text ALIGN(16) : {
|
||||
*(.text*)
|
||||
}
|
||||
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
}
|
||||
|
||||
.data : {
|
||||
*(.data*)
|
||||
}
|
||||
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
/* Discard bloat and unnecessary ELF sections */
|
||||
/DISCARD/ : {
|
||||
*(.note.GNU-stack)
|
||||
*(.gnu_debuglink)
|
||||
*(.gnu.lto_*)
|
||||
*(.note.gnu.build-id)
|
||||
*(.eh_frame_hdr)
|
||||
*(.eh_frame_entry)
|
||||
*(.eh_frame)
|
||||
*(.comment)
|
||||
*(.interp)
|
||||
*(.dynsym)
|
||||
*(.dynstr)
|
||||
*(.hash)
|
||||
*(.gnu.hash)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user