diff --git a/.gitignore b/.gitignore index fc66526..6157417 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,7 @@ Player/player Player/player.wasm +Player/Cosmo Master/master + +Player/Out/Cosmo/player* diff --git a/Common/Std/any.c b/Common/Std/any.c new file mode 100644 index 0000000..0849891 --- /dev/null +++ b/Common/Std/any.c @@ -0,0 +1,138 @@ +/* + Generic std parts, building on top of platform specifics. +*/ + +#include "../fix.h" +#include "../std.h" +#include "../str.h" +#include +#include + +static uint8_t com_std_any_format_u32(uint32_t v, char buf[10]) { + uint8_t c = 0; + if (v == 0) { + buf[10 - (++c)] = '0'; + } else { + while (v > 0) { + buf[10 - (++c)] = '0' + (v % 10); + v /= 10; + } + } + return c; +} + +static uint8_t com_std_any_format_i32(int32_t v, char buf[11]) { + bool neg = v < 0; + uint8_t c = 0; + if (v == 0) { + buf[11 - (++c)] = '0'; + } else { + while (v > 0) { + buf[11 - (++c)] = '0' + (v % 10); + v /= 10; + } + } + if (neg) + buf[11 - (++c)] = '-'; + return c; +} + +/* Just assume 5 points of precision. */ +static uint8_t com_std_any_format_f64(double v, char buf[11 + 1 + 5]) { + bool neg = v < 0; + uint8_t c = 0; + double frac_part = v - (double)(int32_t)v; + for (int i = 0; i < 5; i++) { + frac_part *= 10.0; + uint8_t digit = (unsigned int)frac_part; + buf[17 - (++c)] = digit + '0'; + frac_part -= digit; + } + buf[17 - (++c)] = '.'; + c += com_std_any_format_i32((int32_t)v, &buf[c]); + return c; +} + +/* We can make it buffered, but who cares, it's only for testing. */ +void com_std_print_(int32_t start, ...) { + va_list args; + va_start(args, start); + + bool afterstring = false; + char type = start; + do { + + /* Put space if not proceeding string. */ + if (!afterstring && type != 'c') + com_std_write(COM_STD_OUTFD, " ", 1); + + afterstring = false; + + switch (type) { + + /* uint32_t case. */ + case 'u': { + uint32_t const v = va_arg(args, uint32_t); + char buf[10]; + uint8_t c = com_std_any_format_u32(v, buf); + com_std_write(COM_STD_OUTFD, &buf[sizeof buf - c], c); + break; + } + + /* null terminated string case. */ + case 'c': { + char const *const v = va_arg(args, char *); + com_std_write(COM_STD_OUTFD, v, com_str_ext_len(v)); + afterstring = true; + break; + } + + /* TODO: FIX THIS */ + /* com_fix case. */ + case 'f': { + com_fix_t const v = va_arg(args, com_fix_t); + char buf[11]; + + int32_t const int_part = com_fix_int(v); + uint8_t c = com_std_any_format_i32(int_part, buf); + com_std_write(COM_STD_OUTFD, &buf[sizeof buf - c], c); + + uint32_t const decimal_val = (com_fix_frac(v) * 10000) >> 16; + uint8_t cd = com_std_any_format_u32(decimal_val, buf); + buf[sizeof buf - (++cd)] = '.'; + com_std_write(COM_STD_OUTFD, &buf[sizeof buf - cd], cd); + + break; + } + + /* double floating point case. */ + case 'd': { + double const v = va_arg(args, double); + char buf[17]; + + uint8_t c = com_std_any_format_f64(v, buf); + com_std_write(COM_STD_OUTFD, &buf[sizeof buf - c], c); + } + + /* End of things. */ + case '.': + break; + + default: + com_std_assert(false && "Unhandled format type"); + } + + type = va_arg(args, int32_t); + + } while (type != '.'); + + com_std_write(COM_STD_OUTFD, "\n", 1); + + va_end(args); +} + +void com_std_print_str(char const *str, uint32_t len, bool newline) { + com_std_write(COM_STD_OUTFD, str, len); + if (newline) + com_std_write(COM_STD_OUTFD, "\n", 1); +} diff --git a/Common/Std/libc.c b/Common/Std/libc.c index f295321..eef4f5e 100644 --- a/Common/Std/libc.c +++ b/Common/Std/libc.c @@ -1,7 +1,9 @@ #include "../std.h" -#include "../str.h" +#include "any.c" #include +#include #include +#include #include #include #include @@ -11,13 +13,7 @@ void *com_std_alloc(void *ptr, size_t size) { return size != 0 ? realloc(ptr, size) : (free(ptr), NULL); } -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); } @@ -43,6 +39,15 @@ int32_t com_std_read(com_std_fd fd, void *data, uint32_t upto) { return fread(data, 1, upto, fd); } +bool com_std_has_data(com_std_fd fd) { + struct pollfd pfd = {.fd = (intptr_t)fd, .events = POLLIN}; + int ret = poll(&pfd, 1, 0); + if (ret > 0) { + return pfd.revents & POLLIN; + } else + return false; +} + bool com_std_sfwd(com_std_fd fd, uint32_t bytes) { com_std_assert(fd != NULL && bytes != 0); return fseek(fd, bytes, SEEK_CUR) == 0; diff --git a/Common/Std/linux-amd64.c b/Common/Std/linux-amd64.c index 9337a7f..2c343e6 100644 --- a/Common/Std/linux-amd64.c +++ b/Common/Std/linux-amd64.c @@ -6,6 +6,7 @@ #include "../std.h" #include +#include #include #include #include @@ -44,6 +45,23 @@ inline int32_t com_std_read(com_std_fd fd, void *data, uint32_t upto) { return ret; } +inline bool com_std_has_data(com_std_fd fd) { + struct pollfd pfd = { + .fd = (intptr_t)fd, + .events = POLLIN, + }; + + long ret; + __asm__ volatile("syscall" + : "=a"(ret) + : "a"(7), "D"(&pfd), "S"(1), "d"(0) + : "rcx", "r11", "memory"); + if (ret > 0) { + return pfd.revents & POLLIN; + } else + return false; +} + inline bool com_std_sfwd(com_std_fd fd, uint32_t bytes) { long ret; __asm__ volatile("syscall" diff --git a/Common/Std/linux-x86.c b/Common/Std/linux-x86.c index 0595a8f..150d066 100644 --- a/Common/Std/linux-x86.c +++ b/Common/Std/linux-x86.c @@ -6,6 +6,7 @@ #include "../std.h" #include +#include #include #include #include @@ -44,6 +45,23 @@ inline int32_t com_std_read(com_std_fd fd, void *data, uint32_t upto) { return ret; } +inline bool com_std_has_data(com_std_fd fd) { + struct pollfd pfd = { + .fd = (intptr_t)fd, + .events = POLLIN, + }; + + long ret; + __asm__ volatile("int $0x80" + : "=a"(ret) + : "a"(168), "b"(&pfd), "c"(1), "d"(0) + : "memory", "cc"); + if (ret > 0) { + return pfd.revents & POLLIN; + } else + return false; +} + inline bool com_std_sfwd(com_std_fd fd, uint32_t bytes) { long ret; __asm__ volatile("int $0x80" diff --git a/Common/Std/linux.c b/Common/Std/linux.c index e49ef29..90576e8 100644 --- a/Common/Std/linux.c +++ b/Common/Std/linux.c @@ -2,41 +2,13 @@ Generic linux std parts. */ -#include "../def.h" +#include "any.c" +#include "nolibc.c" + #include "../std.h" -#include "../str.h" -#include #include void *com_std_alloc(void *ptr, size_t size) { return NULL; } -void com_std_assert(bool holds) { - /* TODO: Write line info to stderr as well. */ - if (!holds) - com_std_exit(-1); -} - -/* TODO: Figure out a way to make it easy to deal with. */ -void com_std_printf(char const *fmt, ...) { - com_std_write((void *)1, fmt, com_str_ext_len(fmt)); -} - -void com_std_print_str(char const *str, uint32_t len, bool newline) { - com_std_write((void *)1, str, len); - if (newline) - com_std_write((void *)1, "\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); -// }; diff --git a/Common/Std/nolibc.c b/Common/Std/nolibc.c new file mode 100644 index 0000000..46429ad --- /dev/null +++ b/Common/Std/nolibc.c @@ -0,0 +1,46 @@ +/* + Generic no libc std parts. +*/ + +#include + +/* Compiler depends on them with low optimization level. */ +void *memcpy(void *__restrict dest, const void *__restrict src, size_t n) { + for (size_t i = 0; i < n; ++i) + ((char *)dest)[i] = ((char *)src)[i]; + return dest; +}; + +void *memset(void *__restrict dest, int s, size_t n) { + for (size_t i = 0; i < n; ++i) + ((char *)dest)[i] = s; + return dest; +}; + +size_t strlen(char const *s) { + char const *p = s; + for (; *p != 0; ++p) { + } + return p - s; +} + +double com_std_sin(double v) { + double result; + __asm__ __volatile__("fldl %1\n\t" + "fsin\n\t" + "fstpl %0" + : "=g"(result) + : "m"(v) + : "st", "st(1)"); + return result; +} + +double com_std_cos(double v) { + double result; + __asm__ __volatile__("fldl %1\n\t" + "fcos\n\t" + "fstpl %0" + : "=g"(result) + : "m"(v)); + return result; +} diff --git a/Common/Std/stub.c b/Common/Std/stub.c index ba844bf..6f5443f 100644 --- a/Common/Std/stub.c +++ b/Common/Std/stub.c @@ -1,11 +1,11 @@ #include "../std.h" +#include "any.c" + #include #include void *com_std_alloc(void *ptr, size_t size) { return NULL; } -void com_std_assert(bool holds) {} -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); } @@ -35,7 +35,3 @@ void com_std_exit(uint32_t status) { __builtin_unreachable(); } void com_std_close(com_std_fd fd) { return; } - -// void memcpy(void *__restrict dest, const void *__restrict src, size_t n) { -// __builtin_memcpy(dest, src, n); -// }; diff --git a/Common/Timer/posix.c b/Common/Timer/posix.c index 09543f3..012342a 100644 --- a/Common/Timer/posix.c +++ b/Common/Timer/posix.c @@ -13,5 +13,6 @@ 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; - com_std_printf("profile \"%s\" took %fms\n", what, (double)diff / 1000000); + com_std_print('c', "Profile ", 'c', what, 'c', " took ", 'd', + (double)diff / 1000000, 'c', "ms"); } diff --git a/Common/cfg.h b/Common/cfg.h index 300b211..6262a24 100644 --- a/Common/cfg.h +++ b/Common/cfg.h @@ -11,4 +11,12 @@ #define COM_CFG_WIDTH 640 #define COM_CFG_HEIGHT 480 +#if COM_DEF_TARGET == COM_DEF_TARGET_WASM +#define COM_CFG_COLORS 4 +#else +#define COM_CFG_COLORS 3 +#endif + +#define COM_CFG_FBSIZE (COM_CFG_WIDTH * COM_CFG_HEIGHT * COM_CFG_COLORS) + #endif diff --git a/Common/def.h b/Common/def.h index 84997e1..e896dbf 100644 --- a/Common/def.h +++ b/Common/def.h @@ -6,6 +6,9 @@ #ifndef COM_DEF_H #define COM_DEF_H +#define COM_DEF_STRLIT_(x) #x +#define COM_DEF_STRLIT(x) COM_DEF_STRLIT_(x) + #define COM_DEF_COMPILER_CLANG 1 #define COM_DEF_COMPILER_GCC 2 @@ -17,6 +20,7 @@ #define COM_DEF_TARGET_LINUX 1 #define COM_DEF_TARGET_WASM 2 +#define COM_DEF_TARGET_COSMO 3 #if defined(__wasm__) #define COM_DEF_TARGET COM_DEF_TARGET_WASM @@ -24,6 +28,9 @@ #elif defined(__linux__) #define COM_DEF_TARGET COM_DEF_TARGET_LINUX #define com_def_export_sym(m_s) __attribute__((visibility("default"))) +#elif defined(__COSMOPOLITAN__) +#define COM_DEF_TARGET COM_DEF_TARGET_COSMO +#define com_def_export_sym(m_s) __attribute__((visibility("default"))) #else #error Unknown target. #endif @@ -31,6 +38,7 @@ #define COM_DEF_CPU_AMD64 1 #define COM_DEF_CPU_X86 2 #define COM_DEF_CPU_WASM32 3 +#define COM_DEF_CPU_AARCH64 4 #if defined(__wasm__) #define COM_DEF_CPU COM_DEF_CPU_WASM32 @@ -44,6 +52,10 @@ #define COM_DEF_CPU COM_DEF_CPU_X86 #define COM_DEF_ALIGNMENT 16 #define COM_DEF_CPU_LITEND 1 +#elif defined(__aarch64__) +#define COM_DEF_CPU COM_DEF_CPU_AARCH64 +#define COM_DEF_ALIGNMENT 16 +#define COM_DEF_CPU_LITEND 1 #else #error Unknown cpu. #endif diff --git a/Common/fix.c b/Common/fix.c index 27cb460..200d706 100644 --- a/Common/fix.c +++ b/Common/fix.c @@ -71,20 +71,6 @@ com_fix_t com_fix_sqrt(com_fix_t a) { : (int32_t)(x >> (-final_shift)); } -void com_fix_print(com_fix_t a) { - if (a < 0) { - com_std_printf("-"); - a = -a; - } - int32_t int_part = a >> 16; - int32_t frac_part = a & 0xFFFF; - - // Convert fractional 16-bit part to a decimal value (up to 4 decimal places) - uint32_t decimal_val = (frac_part * 10000) >> 16; - - com_std_printf("%d.%04u\n", int_part, decimal_val); -} - void com_fix_run_bench(void) { uint64_t start = com_timer_count_ns(); for (int i = 5000000; i--;) { @@ -118,77 +104,3 @@ void com_fix_run_bench(void) { } 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); - } -} diff --git a/Common/fix.h b/Common/fix.h index 4adc57b..f380fe2 100644 --- a/Common/fix.h +++ b/Common/fix.h @@ -23,8 +23,6 @@ typedef int32_t com_fix_t; extern const uint16_t com_fix_sin_lut[128]; -void com_fix_print(com_fix_t a); - void com_fix_run_tests(void); void com_fix_run_bench(void); @@ -32,9 +30,9 @@ static inline com_fix_t com_fix_add(com_fix_t a, com_fix_t b) { return a + b; } static inline com_fix_t com_fix_sub(com_fix_t a, com_fix_t b) { return a - b; } -static inline com_fix_t com_fix_int(com_fix_t a) { - return a >> COM_FIX_FRACBITS; -} +static inline int16_t com_fix_int(com_fix_t a) { return a >> COM_FIX_FRACBITS; } + +static inline uint16_t com_fix_frac(com_fix_t a) { return a & 0xFFFF; } static inline com_fix_t com_fix_mul(com_fix_t a, com_fix_t b) { return (com_fix_t)(((int64_t)a * (int64_t)b) >> COM_FIX_FRACBITS); diff --git a/Common/gem.h b/Common/gem.h index b94d7a0..217cafa 100644 --- a/Common/gem.h +++ b/Common/gem.h @@ -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 * 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; + out[(y * COM_CFG_WIDTH + x) * COM_CFG_COLORS + 0] = 125; + out[(y * COM_CFG_WIDTH + x) * COM_CFG_COLORS + 1] = 125; + out[(y * COM_CFG_WIDTH + x) * COM_CFG_COLORS + 2] = 125; } } } @@ -147,9 +147,9 @@ com_gem_draw_triangle_textured_edge(com_pnt_t v0, com_pnt_t v1, com_pnt_t v2, // uint32_t bidx = com_zord_order(x, y); 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]; + out[bidx * COM_CFG_COLORS + 0] = tex[idx * 3 + 0]; + out[bidx * COM_CFG_COLORS + 1] = tex[idx * 3 + 1]; + out[bidx * COM_CFG_COLORS + 2] = tex[idx * 3 + 2]; } } } @@ -170,9 +170,9 @@ 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 * 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]; + out[bidx * COM_CFG_COLORS + 0] = tex[idx * 3 + 0]; + out[bidx * COM_CFG_COLORS + 1] = tex[idx * 3 + 1]; + out[bidx * COM_CFG_COLORS + 2] = tex[idx * 3 + 2]; } } diff --git a/Common/pnt.h b/Common/pnt.h index e62d9c9..cc0c9ee 100644 --- a/Common/pnt.h +++ b/Common/pnt.h @@ -111,9 +111,4 @@ com_pnt_edge_weight_calc_precomp(com_pnt_t v0, com_pnt_t v1, com_pnt_t v2, precomp[2].a[1] * (p.a[0] - v0.a[0])}}; } -static inline void com_pnt_print(com_pnt_t a) { - com_fix_print(a.a[0]); - com_fix_print(a.a[1]); -} - #endif diff --git a/Common/std.h b/Common/std.h index 1979476..35456bf 100644 --- a/Common/std.h +++ b/Common/std.h @@ -10,6 +10,16 @@ #include #include +#if COM_DEF_TARGET == COM_DEF_TARGET_WASM +#define COM_STD_INFD 0 +#define COM_STD_OUTFD 1 +#else +/* TODO: Make it more graceful, probably with static func. */ +#include +#define COM_STD_INFD (fdopen(STDIN_FILENO, "r")) +#define COM_STD_OUTFD (fdopen(STDOUT_FILENO, "w")) +#endif + /* Generic system interface, linux/bsd derived. */ typedef void *com_std_fd; #define COM_STD_OPEN_READ (1 << 0) @@ -17,6 +27,7 @@ typedef void *com_std_fd; com_std_fd com_std_open(char const *path, uint32_t flags); bool com_std_write(com_std_fd fd, void const *data, uint32_t bytes); int32_t com_std_read(com_std_fd fd, void *data, uint32_t upto); +bool com_std_has_data(com_std_fd); bool com_std_sfwd(com_std_fd fd, uint32_t bytes); com_std_fd com_std_socket(bool isnetwork); bool com_std_connect(com_std_fd sock, bool isnetwork, char const *address); @@ -31,9 +42,44 @@ 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. */ -void com_std_assert(bool holds); -void com_std_printf(char const *fmt, ...); +#define com_std_assert(p_h) \ + do { \ + if (!(p_h)) { \ + const char msg[] = \ + "Assertion failed at "__FILE__ \ + ":" COM_DEF_STRLIT(__LINE__) ": " COM_DEF_STRLIT(p_h); \ + com_std_print_str(msg, sizeof msg, true); \ + com_std_exit(-1); \ + } \ + } while (0) + +/* + Basic printing utility that doesn't utilize format string. + Instead a vector of arguments is passed and concatenated, based on type. + Newline is implied at the end. + + Example: com_std_print("My unit32_t: ", 'u', value, 's', " is here"); + + Format specifiers: + 'u' = uint32_t + 'i' = int32_t + 'd' = float (upcast to double with vargs) + 'c' = null terminated C string + + Our own types: + 'f' = com_fix value + 'p' = com_pnt pointer + 'v' = com_vec pointer + 's' = pointer to com_str structure + 'b' = pointer to com_buf structure + + '.' is placed at the end implicitly with macro, + it is needed to know when to end. +*/ +void com_std_print_(int32_t start, ...); +#define com_std_print(...) com_std_print_(__VA_ARGS__, '.') 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); diff --git a/Common/test.h b/Common/test.h new file mode 100644 index 0000000..0b87c88 --- /dev/null +++ b/Common/test.h @@ -0,0 +1,121 @@ +/* + Centralized test suite. +*/ + +#include "bits.h" +#include "fix.h" +#include "std.h" +#include + +#define TEST(p_e) \ + do { \ + if (!(p_e)) { \ + com_std_print('c', COM_DEF_STRLIT(p_e) " failed!"); \ + anyfail = true; \ + } \ + } while (0) + +static bool com_test_fix(void) { + bool anyfail = false; + { + 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_print('c', "Max sqrt deviation: ", 'd', 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_print('c', "Max sin deviation: ", 'd', 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_print('c', "Max cos deviation: ", 'd', 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_print('c', "Max sincos deviations: ", 'd', max_sin_deviation, 'd', + max_cos_deviation); + } + + return anyfail; +} + +static bool com_test_bits(void) { + bool anyfail = false; + + TEST(com_bits_nalign(0, 4) == 0); + TEST(com_bits_nalign(1, 4) == 4); + TEST(com_bits_nalign(2, 4) == 4); + TEST(com_bits_nalign(3, 4) == 4); + TEST(com_bits_nalign(4, 4) == 4); + TEST(com_bits_nalign(5, 4) == 8); + + return anyfail; +} + +static bool com_test_run(void) { + bool anyfail = false; + if (com_test_fix()) { + com_std_print('c', "com_fix tests failed!"); + anyfail = true; + } + if (com_test_bits()) { + com_std_print('c', "com_bits tests failed!"); + anyfail = true; + } + return !anyfail; +} + +#undef TEST diff --git a/Common/vec.h b/Common/vec.h index 789d0db..165ce0c 100644 --- a/Common/vec.h +++ b/Common/vec.h @@ -93,10 +93,4 @@ static inline com_fix_t com_vec_max(com_vec_t a) { return com_fix_max(com_fix_max(a.a[0], a.a[1]), a.a[2]); } -static inline void com_vec_print(com_vec_t a) { - com_fix_print(a.a[0]); - com_fix_print(a.a[1]); - com_fix_print(a.a[2]); -} - #endif diff --git a/Player/Display/display.h b/Player/Display/display.h index a199239..79e697f 100644 --- a/Player/Display/display.h +++ b/Player/Display/display.h @@ -1,7 +1,8 @@ #ifndef PLR_DISPLAY_H #define PLR_DISPLAY_H -__attribute__((used)) extern int plr_display_x11_main(int argc, char *argv[]); +__attribute__((used)) extern int plr_display_x11_main(int argc, + char const *const *argv); __attribute__((used)) extern int plr_display_dos_main(void); #endif diff --git a/Player/Display/x11.c b/Player/Display/x11.c index 3bd332d..fa0e373 100644 --- a/Player/Display/x11.c +++ b/Player/Display/x11.c @@ -1,6 +1,3 @@ -#include -#include -#include #include #include #include @@ -11,16 +8,26 @@ #include "../../Common/bits.h" #include "../../Common/buf.h" #include "../../Common/cfg.h" +#include "../../Common/def.h" #include "../../Common/lzw.h" #include "../../Common/mat.h" #include "../../Common/std.h" #include "../../Common/str.h" +#include "../../Common/test.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 - */ +#if COM_DEF_TARGET == COM_DEF_TARGET_COSMO +#include +#else +#include +#endif + +/* + https://hereket.com/posts/from-scratch-x11-windowing/ + https://gaultier.github.io/blog/write_a_video_game_from_scratch_like_1987.html + https://xorg.freedesktop.org/archive/X11R7.7-RC1/doc/xproto/x11protocol.html +*/ static struct { uint32_t id; @@ -94,7 +101,7 @@ static struct plr_x11_auth_entry { result.success = true; return result; BREAK: - com_std_printf("Failure to initialize X11\n"); + com_std_print('c', "Failure to initialize X11"); return result; } @@ -108,8 +115,8 @@ static bool plr_x11_handshake(com_std_fd xfd, uint16_t auth_len; uint16_t auth_data_len; uint16_t pad1; - } request = { - .endianness = 'l', + } __attribute__((packed)) request = { + .endianness = COM_DEF_CPU_LITEND ? 'l' : 'B', .major_version = 11, .auth_len = sizeof(AUTH_ENTRY_MAGIC_COOKIE) - 1, // IS -1 NEEDED? .auth_data_len = auth_entry.auth_data->len, @@ -131,7 +138,7 @@ static bool plr_x11_handshake(com_std_fd xfd, uint16_t major_version; uint16_t minor_version; uint16_t length; - } response; + } __attribute__((packed)) response; if (!com_std_read(xfd, &response, sizeof response)) return false; @@ -154,7 +161,7 @@ static bool plr_x11_handshake(com_std_fd xfd, uint8_t min_keycode; uint8_t max_keycode; uint32_t pad2; - } dyn_response; + } __attribute__((packed)) dyn_response; if (!com_std_read(xfd, &dyn_response, sizeof dyn_response)) return false; @@ -177,6 +184,54 @@ static bool plr_x11_handshake(com_std_fd xfd, return true; } +/* TODO: Instead have a poll_events function instead. */ +static inline bool plr_x11_poll_errors(com_std_fd xfd) { + union { + struct { + uint8_t type; + uint8_t errcode; + uint16_t sequenceid; + uint32_t badval; + uint16_t minorop; + uint32_t majorop; + char pad[18]; + } __attribute__((packed)) error; + struct { + uint8_t type; + uint8_t data; + uint16_t sequenceid; + uint32_t length; + char pad[24]; + } __attribute__((packed)) reply; + } response; + + while (com_std_has_data(xfd)) { + if (!com_std_read(xfd, &response, sizeof response)) + return false; + + /* Exhaust variable length data of reply. */ + if (response.reply.type == 1) { + char buf[1024]; + com_std_assert(response.reply.length * 4 <= sizeof buf); + if (!com_std_read(xfd, &buf, response.reply.length * 4)) + return false; + } + + if (response.reply.type == 0 && response.error.errcode != 0) { + com_std_print('c', "X11 error code=", 'u', response.error.errcode, 'c', + " for seqid=", 'u', response.error.sequenceid); + + /* This means X11 closed the connection. */ + // if (response.error.errcode == 0) + // return false; + } + + /* TODO: Save polled events, as they might be used later. */ + }; + + return true; +} + static inline uint32_t plr_x11_next_id(void) { static uint32_t cur_id = 0; cur_id = 1 + ((plr_x11_connection.resource_id_mask & (cur_id)) | @@ -184,29 +239,35 @@ static inline uint32_t plr_x11_next_id(void) { return cur_id; } +/* Used to number requests. */ +static inline uint32_t plr_x11_next_seqid(void) { + static uint32_t cur_id = 1; + return cur_id++; +} + static uint32_t plr_x11_create_graphical_context(com_std_fd xfd) { uint32_t const gc_id = plr_x11_next_id(); + uint32_t const seq = plr_x11_next_seqid(); struct { uint8_t opcode; uint8_t pad1; - uint16_t length; + uint16_t request_length; uint32_t id; uint32_t drawable; uint32_t bitmask; uint32_t value1; - } request = { + } __attribute__((packed)) request = { .opcode = 55, - .length = 5, + .request_length = sizeof request / 4, .id = gc_id, .drawable = plr_x11_root_screen.id, .bitmask = 8, /* TODO: Figure out. */ - .value1 = 0x0000ff00, + .value1 = 0x00000000, }; - if (com_std_write(xfd, &request, sizeof request)) - return gc_id; - else + if (!com_std_write(xfd, &request, sizeof request)) return 0; + return gc_id; } static uint32_t plr_x11_create_window(com_std_fd xfd) { @@ -220,6 +281,7 @@ static uint32_t plr_x11_create_window(com_std_fd xfd) { #define EVENT_FLAG_BUTTON_RELEASE 0x8 uint32_t const window_id = plr_x11_next_id(); + uint32_t const seq = plr_x11_next_seqid(); struct { uint8_t opcode; uint8_t depth; @@ -236,10 +298,10 @@ static uint32_t plr_x11_create_window(com_std_fd xfd) { uint32_t bitmask; uint32_t value1; uint32_t value2; - } request = { + } __attribute__((packed)) request = { .opcode = 1, - .depth = 32, - .request_length = 8 + 2, + .depth = COM_CFG_COLORS * 8, + .request_length = sizeof request / 4, .window_id = window_id, .parent_id = plr_x11_root_screen.id, .width = COM_CFG_WIDTH, @@ -248,16 +310,15 @@ static uint32_t plr_x11_create_window(com_std_fd xfd) { .class = 1, .root_visual_id = plr_x11_root_screen.root_visual_id, .bitmask = FLAG_WIN_BG_PIXEL | FLAG_WIN_EVENT, - .value1 = 0x00ffff00, + .value1 = 0x00000000, .value2 = EVENT_FLAG_EXPOSURE | EVENT_FLAG_BUTTON_RELEASE | EVENT_FLAG_BUTTON_PRESS | EVENT_FLAG_KEY_PRESS | EVENT_FLAG_KEY_RELEASE, }; - if (com_std_write(xfd, &request, sizeof request)) - return window_id; - else + if (!com_std_write(xfd, &request, sizeof request)) return 0; + return window_id; } static bool plr_x11_show_window(com_std_fd xfd, uint32_t window_id) { @@ -266,9 +327,9 @@ static bool plr_x11_show_window(com_std_fd xfd, uint32_t window_id) { uint8_t pad1; uint16_t request_length; uint32_t window_id; - } request = { + } __attribute__((packed)) request = { .opcode = 8, - .request_length = 2, + .request_length = sizeof request / 4, .window_id = window_id, }; return com_std_write(xfd, &request, sizeof request); @@ -276,36 +337,35 @@ static bool plr_x11_show_window(com_std_fd xfd, uint32_t window_id) { static uint32_t plr_x11_create_pixmap(com_std_fd xfd, uint32_t window_id) { uint32_t const pixmap_id = plr_x11_next_id(); + uint32_t const seq = plr_x11_next_seqid(); struct { uint8_t opcode; uint8_t depth; - uint16_t length; + uint16_t request_length; uint32_t pixmap_id; uint32_t drawable; uint16_t width; uint16_t height; - } request = { + } __attribute__((packed)) request = { .opcode = 53, - .depth = 32, - .length = 4, + .depth = COM_CFG_COLORS * 8, + .request_length = sizeof request / 4, .pixmap_id = pixmap_id, .drawable = window_id, .width = COM_CFG_WIDTH, .height = COM_CFG_HEIGHT, }; - if (com_std_write(xfd, &request, sizeof request)) - return pixmap_id; - else + if (!com_std_write(xfd, &request, sizeof request)) return 0; + return pixmap_id; } -static bool -plr_x11_put_framebuffer(com_std_fd xfd, uint32_t gc_id, uint32_t window_id, - uint32_t pixmap_id, - uint32_t pixels[COM_CFG_WIDTH * COM_CFG_HEIGHT]) { - uint32_t const padded = - com_bits_nalign(4 * COM_CFG_WIDTH * COM_CFG_HEIGHT, 4); +static bool plr_x11_put_framebuffer(com_std_fd xfd, uint32_t gc_id, + uint32_t pixmap_id, + uint8_t pixels[COM_CFG_FBSIZE]) { + uint32_t const seq = plr_x11_next_seqid(); + uint32_t const padded = com_bits_nalign(COM_CFG_FBSIZE, 4); struct { uint8_t opcode; @@ -320,35 +380,84 @@ plr_x11_put_framebuffer(com_std_fd xfd, uint32_t gc_id, uint32_t window_id, uint8_t left_pad; uint8_t depth; uint16_t pad1; - } request = { + } __attribute__((packed)) request = { .opcode = 72, .format = 2, // ZPixmap - .request_length = 6 + padded / 4, + .request_length = sizeof request / 4 + padded / 4, .drawable_id = pixmap_id, .gc_id = gc_id, .width = COM_CFG_WIDTH, .height = COM_CFG_HEIGHT, .dst_x = 0, .dst_y = 0, - .depth = 32, + .depth = COM_CFG_COLORS * 8, }; if (!com_std_write(xfd, &request, sizeof request)) return false; - if (!com_std_write(xfd, pixels, 4 * COM_CFG_WIDTH * COM_CFG_HEIGHT)) + if (!com_std_write(xfd, pixels, COM_CFG_FBSIZE)) return false; /* Use request memory for pad, it doesn't matter what we write. */ - uint32_t const padfinal = padded - (4 * COM_CFG_WIDTH * COM_CFG_HEIGHT); - if (padfinal && !com_std_write(xfd, &request, padfinal)) + uint32_t const padfinal = padded - COM_CFG_FBSIZE; + if (padfinal && !com_std_write(xfd, &pixels, padfinal)) return false; + return true; +} + +static bool plr_x11_establish_connection(com_std_fd xfd, int argc, + char const *const *argv) { + com_buf_make_on_stack(char, xauthbuf, 1024, 0); + + /* First we need to authenticate X11 connection, which requires some funk. + */ + /* We assume that $XAUTHORITY is set and I hope it is true. */ + char const *xauthpath = NULL; + for (char const *const *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. */ + com_std_fd const xauthfd = com_std_open(xauthpath, COM_STD_OPEN_READ); + if (xauthfd < 0) { + com_std_print('c', "Failure to initialize X11"); + return false; + } + + struct com_bin xauthbin = { + .ctx = (void *)(int64_t)xauthfd, + .flags = COM_BIN_BIG_ENDIAN, + .interface = {.readn = fileread, .skipn = fileskip}}; + + /* Loop over auth entries until we find magic cookie one. */ + struct plr_x11_auth_entry auth_entry; + do { + com_buf_clear(xauthbuf); + auth_entry = plr_x11_read_auth_entry(&xauthbin, xauthbuf); + } while (auth_entry.success && auth_entry.family != 256); + if (!auth_entry.success) { + com_std_print('c', "Failure to initialize X11"); + return false; + } + + com_std_close(xauthfd); + + /* TODO: Check for auth_entry.name == MAGIC ? */ + if (!plr_x11_handshake(xfd, auth_entry)) { + com_std_print('c', "Failure to initialize X11"); + return false; + } + + com_buf_free(xauthbuf); return true; } -static uint32_t pixel_buffer[COM_CFG_WIDTH * COM_CFG_HEIGHT]; - // TODO: correct error handling. -extern int plr_display_x11_main(int argc, char *argv[]) { +extern int plr_display_x11_main(int argc, char const *const *argv) { char test_string[] = "what is this?"; char *compressed_string = NULL; uint32_t compressed_string_sz = 0; @@ -366,12 +475,16 @@ extern int plr_display_x11_main(int argc, char *argv[]) { com_mat_t t0 = com_mat_mul(m1, m0); com_mat_t t1 = com_mat_mul_reodered(com_mat_reoder(m1), m0); - com_fix_print(t0.a[4]); - com_fix_print(t1.a[4]); + com_std_print('f', t0.a[4]); + com_std_print('f', t1.a[4]); // com_vec_t v0 = com_mat_vec_project(com_mat_reoder(m0), com_vec_identity()); // com_fix_print(v0.a[0]); +#ifndef NDEBUG + com_test_run(); +#endif + // com_fix_run_tests(); // com_fix_run_bench(); // com_mat_run_bench(); @@ -380,87 +493,47 @@ extern int plr_display_x11_main(int argc, char *argv[]) { /* Open X11 socket for communication. */ com_std_fd const xfd = com_std_socket(false); if (!xfd) { - com_std_printf("Failure to initialize X11\n"); + com_std_print('c', "Failure to initialize X11"); return -1; } if (!com_std_connect(xfd, false, "/tmp/.X11-unix/X0")) { - com_std_printf("Failure to initialize X11\n"); + com_std_print('c', "Failure to initialize X11"); 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 const *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. */ - com_std_fd const xauthfd = com_std_open(xauthpath, COM_STD_OPEN_READ); - if (xauthfd < 0) { - com_std_printf("Failure to initialize X11\n"); + if (!plr_x11_establish_connection(xfd, argc, argv)) { + com_std_print('c', "Failure to initialize X11"); 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}}; - - /* Loop over auth entries until we find magic cookie one. */ - struct plr_x11_auth_entry auth_entry; - do { - com_buf_clear(xauthbuf); - auth_entry = plr_x11_read_auth_entry(&xauthbin, xauthbuf); - } while (auth_entry.success && auth_entry.family != 256); - if (!auth_entry.success) { - com_std_printf("Failure to initialize X11\n"); - return -1; - } - - com_std_close(xauthfd); - - /* TODO: Check for auth_entry.name == MAGIC ? */ - if (!plr_x11_handshake(xfd, auth_entry)) { - com_std_printf("Failure to initialize X11\n"); - return -1; - } - - com_buf_free(xauthbuf); - uint32_t const gc = plr_x11_create_graphical_context(xfd); if (!gc) { - com_std_printf("Failure to initialize X11\n"); + com_std_print('c', "Failure to initialize X11"); return -1; } uint32_t const win = plr_x11_create_window(xfd); if (!win) { - com_std_printf("Failure to initialize X11\n"); + com_std_print('c', "Failure to initialize X11"); return -1; } uint32_t const fb = plr_x11_create_pixmap(xfd, win); if (!fb) { - com_std_printf("Failure to initialize X11\n"); + com_std_print('c', "Failure to initialize X11"); return -1; } // Display *display = XOpenDisplay(NULL); // if (NULL == display) { - // com_std_printf("Failed to initialize display"); + // com_std_print('c', "Failed to initialize display"); // return -1; // } // Window root = DefaultRootWindow(display); // if (None == root) { - // com_std_printf("No root window found"); + // com_std_print('c', "No root window found"); // XCloseDisplay(display); // return -1; // } @@ -473,7 +546,7 @@ extern int plr_display_x11_main(int argc, char *argv[]) { // XCreateSimpleWindow(display, root, 0, 0, WIDTH, HEIGHT, 0, 0, // 0xffffffff); // if (None == window) { - // com_std_printf("Failed to create window"); + // com_std_print('c', "Failed to create window"); // XCloseDisplay(display); // return -1; // } @@ -507,7 +580,7 @@ extern int plr_display_x11_main(int argc, char *argv[]) { // pixel_buffer, WIDTH, HEIGHT, 32, 0); // if (!ximage) { - // com_std_printf("Failed to create XImage\n"); + // com_std_print('c', "Failed to create XImage"); // // com_std_alloc(pixel_buffer, 0); // XCloseDisplay(display); // return -1; @@ -547,16 +620,22 @@ extern int plr_display_x11_main(int argc, char *argv[]) { // XCloseDisplay(display); + uint8_t *fbm = plr_draw_get_pixel_buffer(); + plr_draw_screen(fbm); + + // if (!plr_x11_put_framebuffer(xfd, gc, fb, fbm)) { + // com_std_print('c', "Failure to drive X11"); + // return -1; + // } + + if (!plr_x11_show_window(xfd, win)) { + com_std_print('c', "Failure to drive X11"); + return -1; + } + while (1) { - plr_draw_screen((uint8_t *)pixel_buffer); - - if (!plr_x11_put_framebuffer(xfd, gc, win, fb, pixel_buffer)) { - com_std_printf("Failure to drive X11\n"); - return -1; - } - - if (!plr_x11_show_window(xfd, win)) { - com_std_printf("Failure to drive X11\n"); + if (!plr_x11_poll_errors(xfd)) { + com_std_print('c', "X11 closed connection"); return -1; } } diff --git a/Player/Main/cosmo.c b/Player/Main/cosmo.c new file mode 100644 index 0000000..41b0547 --- /dev/null +++ b/Player/Main/cosmo.c @@ -0,0 +1,7 @@ +#include "../../Common/std.h" +#include "../Display/display.h" +#include +extern int main(int argc, char const *const *argv) { + com_std_write(COM_STD_OUTFD, "TEST?", sizeof "TEST?" - 1); + return plr_display_x11_main(argc, argv); +} diff --git a/Player/Main/libc.c b/Player/Main/libc.c deleted file mode 100644 index 9669a80..0000000 --- a/Player/Main/libc.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "../Display/display.h" - -extern int main(int argc, char **argv) { plr_display_x11_main(argc, argv); } diff --git a/Player/Makefile b/Player/Makefile index a82125b..19b2eae 100644 --- a/Player/Makefile +++ b/Player/Makefile @@ -4,7 +4,15 @@ DEBUG ?= 1 # Emit debug info. SQUEEZE ?= 0 # Nuclear option to save space. BITS ?= 64 RUN ?= 0 -CFLAGS = -Wall -std=gnu99 -flto=thin -ffast-math -fno-ident -fvisibility=hidden -fuse-ld=lld + +ISCLANG = 1 +ifeq ($(MAKECMDGOALS),cosmo) + ISCLANG = 0 +endif +CFLAGS = -Wall -std=gnu99 -ffast-math -fno-ident -fvisibility=hidden +ifeq ($(ISCLANG), 1) + CFLAGS = -flto=thin -fuse-ld=lld +endif ifeq ($(MAKECMDGOALS),linux) CFLAGS += -fno-pic -fno-pie ifeq ($(RELEASE), 1) @@ -12,7 +20,10 @@ ifeq ($(MAKECMDGOALS),linux) -Wl,--optimize-bb-jumps endif ifeq ($(SQUEEZE), 1) - CFLAGS += -Wl,-T,tiny.ld -Wl,--icf=all -Wl,--bp-compression-sort=both \ + ifeq ($(DEBUG), 0) + CFLAGS += -Wl,-T,tiny.ld + endif + CFLAGS += -Wl,--icf=all -Wl,--bp-compression-sort=both \ -Wl,--nmagic endif ifeq ($(BITS), 64) @@ -37,32 +48,27 @@ ifeq ($(RELEASE), 1) -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 \ - ./Display/display.h \ - ./draw.h -SRC = ../Common/lzw.c ../Common/fix.c ../Common/mat.c ./draw.c -LINUX = ./amalgam.c -WASM = ./amalgam.c -DOS = maindos.c Display/dos.c -%.o: %.c $(DEPS) - $(CC) -c -o $@ $< $(CFLAGS) - -%.o: %.s $(DEPS) - $(CC) -c -o $@ $< $(CFLAGS) - -# TODO: Make it work with no stdlib. linux: CFLAGS += -static -mbmi2 -nostdlib -linux: $(LINUX) | $(SRC) +linux: ./amalgam.c $(CC) -o player $^ $(CFLAGS) # Note: lld package might need to be downloaded. wasm: CFLAGS += --target=wasm32 -nostdlib -Wl,--no-entry -msimd128 -mbulk-memory wasm: - $(CC) -o player.wasm $(WASM) $(CFLAGS) + $(CC) -o player.wasm ./amalgam.c $(CFLAGS) + +# todo: Add -mtiny for release without debug +cosmo: CC = ./Cosmo/bin/cosmocc -I /usr/include/X11 -mdbg +cosmo: ./amalgam.c + $(CC) -o ./Out/Cosmo/player $^ +ifeq ($(RUN), 1) +ifeq ($(DEBUG), 1) + gdb ./Out/Cosmo/player.com.dbg +else + ./Out/Cosmo/player +endif +endif # https://tippach.hier-im-netz.de/wdosx dos: CFLAGS += -ffreestanding -m32 -fno-PIC -fno-PIE -nostdlib -nodefaultlibs @@ -79,5 +85,6 @@ else dosbox -c "mount c $(PWD)" -c "c:" -c "DOS.EXE" endif endif + clean: rm -r *.o ../*.o diff --git a/Player/Out/Cosmo/ape b/Player/Out/Cosmo/ape new file mode 100755 index 0000000..f56c3ef Binary files /dev/null and b/Player/Out/Cosmo/ape differ diff --git a/Player/Out/Cosmo/run.cmd b/Player/Out/Cosmo/run.cmd new file mode 100755 index 0000000..73407af --- /dev/null +++ b/Player/Out/Cosmo/run.cmd @@ -0,0 +1,8 @@ +:;# amalgam of batch and shell scripts as a entry single point + +:; SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +:; $SCRIPT_DIR/ape $SCRIPT_DIR/player +:; exit + +@echo off +player diff --git a/Player/amalgam.c b/Player/amalgam.c index afc5097..6d78ba7 100644 --- a/Player/amalgam.c +++ b/Player/amalgam.c @@ -21,8 +21,12 @@ #endif #include "../Common/Timer/stub.c" #include "./Display/x11.c" -// #include "./Main/libc.c" #elif COM_DEF_TARGET == COM_DEF_TARGET_WASM #include "../Common/Std/stub.c" #include "../Common/Timer/stub.c" +#elif COM_DEF_TARGET == COM_DEF_TARGET_COSMO +#include "../Common/Std/libc.c" +#include "../Common/Timer/posix.c" +#include "./Display/x11.c" +#include "./Main/cosmo.c" #endif diff --git a/Player/draw.c b/Player/draw.c index 0ff81bf..a79590c 100644 --- a/Player/draw.c +++ b/Player/draw.c @@ -2,30 +2,30 @@ #include "../Common/cfg.h" #include "../Common/def.h" #include "../Common/gem.h" -#include "../Common/std.h" #include "../Common/time.h" #include -#if COM_DEF_TARGET == COM_DEF_TARGET_WASM -uint8_t plr_draw_buffer[COM_CFG_WIDTH * COM_CFG_HEIGHT * 4]; +static _Alignas(16) uint8_t plr_draw_buffer[COM_CFG_FBSIZE]; com_def_export_sym( "plr_draw_get_pixel_buffer") uint8_t *plr_draw_get_pixel_buffer(void) { return plr_draw_buffer; } -#endif com_def_export_sym("plr_draw_screen") void plr_draw_screen( uint8_t *pixel_buffer) { + uint8_t *pixel_buffer_aligned = __builtin_assume_aligned(pixel_buffer, 16); 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; + int pixel_index = (y * COM_CFG_WIDTH + x) * COM_CFG_COLORS; // Assuming standard Little-Endian 32-bit BGRA format - pixel_buffer[pixel_index + 0] = (x) % 256; // Blue - pixel_buffer[pixel_index + 1] = (y) % 256; // Green - pixel_buffer[pixel_index + 2] = (x + y) % 256; // Red - pixel_buffer[pixel_index + 3] = 255; // Alpha/Padding + pixel_buffer_aligned[pixel_index + 0] = (x) % 256; // Blue + pixel_buffer_aligned[pixel_index + 1] = (y) % 256; // Green + pixel_buffer_aligned[pixel_index + 2] = (x + y) % 256; // Red +#if COM_CFG_COLORS == 4 + pixel_buffer_aligned[pixel_index + 3] = 255; // Alpha/Padding +#endif } } @@ -65,7 +65,7 @@ com_def_export_sym("plr_draw_screen") void plr_draw_screen( // com_std_printf("%i, %i\n", p2.a[0], p2.a[1]); // com_std_printf("%i, %i\n", p3.a[0], p3.a[1]); - uint8_t tex[32 * 32 * 3] = {0}; + uint8_t _Alignas(16) tex[32 * 32 * 3] = {0}; for (int y = 0; y < 32; ++y) { for (int x = 0; x < 32; ++x) { // uint32_t idx = com_zord_order(x, y); diff --git a/Player/draw.h b/Player/draw.h index c7bb5f0..3daf498 100644 --- a/Player/draw.h +++ b/Player/draw.h @@ -4,5 +4,6 @@ #include extern void plr_draw_screen(uint8_t *pixel_buffer); +extern uint8_t *plr_draw_get_pixel_buffer(void); #endif diff --git a/Player/tiny.ld b/Player/tiny.ld index fc5bac2..bd95b72 100644 --- a/Player/tiny.ld +++ b/Player/tiny.ld @@ -14,19 +14,19 @@ SECTIONS *(.text*) } - .rodata : { + .rodata ALIGN(16) : { *(.rodata*) } - .data : { + .data ALIGN(16) : { *(.data*) } - .shstrtab : { + .shstrtab ALIGN(16) : { *(.shstrtab*) } - .bss : { + .bss ALIGN(16) : { *(.bss*) *(COMMON) }