This commit is contained in:
2025-11-26 18:22:22 -06:00
parent 2110688fa5
commit e28e241485
25 changed files with 150 additions and 4290 deletions

View File

@@ -255,7 +255,6 @@ src += 'qjs_http.c'
src += [ # engine
'qjs_soloud.c',
'HandmadeMath.c',
]
src += ['quickjs.c', 'libregexp.c', 'libunicode.c', 'cutils.c', 'dtoa.c']

491
qopconv.c
View File

@@ -1,491 +0,0 @@
/*
Copyright (c) 2024, Dominic Szablewski - https://phoboslab.org
SPDX-License-Identifier: MIT
Command line tool to create and unpack qop archives
*/
#define _DEFAULT_SOURCE
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#define QOP_IMPLEMENTATION
#include "qop.h"
#define MAX_PATH_LEN 1024
#define BUFFER_SIZE 4096
#define UNUSED(x) (void)(x)
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define die(...) \
printf("Abort at " TOSTRING(__FILE__) " line " TOSTRING(__LINE__) ": " __VA_ARGS__); \
printf("\n"); \
exit(1)
#define error_if(TEST, ...) \
if (TEST) { \
die(__VA_ARGS__); \
}
// -----------------------------------------------------------------------------
// Platform specific file/dir handling
typedef struct {
char *name;
unsigned char is_dir;
unsigned char is_file;
} pi_dirent;
#if defined(_WIN32)
#include <windows.h>
typedef struct {
WIN32_FIND_DATA data;
pi_dirent current;
HANDLE dir;
unsigned char is_first;
} pi_dir;
pi_dir *pi_dir_open(const char *path) {
char find_str[MAX_PATH_LEN];
snprintf(find_str, MAX_PATH_LEN, "%s/*", path);
pi_dir *d = malloc(sizeof(pi_dir));
d->is_first = 1;
d->dir = FindFirstFile(find_str, &d->data);
if (d->dir == INVALID_HANDLE_VALUE) {
free(d);
return NULL;
}
return d;
}
pi_dirent *pi_dir_next(pi_dir *d) {
if (!d->is_first) {
if (FindNextFile(d->dir, &d->data) == 0) {
return NULL;
}
}
d->is_first = 0;
d->current.name = d->data.cFileName;
d->current.is_dir = d->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
d->current.is_file = !d->current.is_dir;
return &d->current;
}
void pi_dir_close(pi_dir *d) {
FindClose(d->dir);
free(d);
}
int pi_mkdir(char *path, int mode) {
UNUSED(mode);
return CreateDirectory(path, NULL) ? 0 : -1;
}
#else
#include <dirent.h>
typedef struct {
DIR *dir;
struct dirent *data;
pi_dirent current;
} pi_dir;
pi_dir *pi_dir_open(const char *path) {
DIR *dir = opendir(path);
if (!dir) {
return NULL;
}
pi_dir *d = malloc(sizeof(pi_dir));
d->dir = dir;
return d;
}
pi_dirent *pi_dir_next(pi_dir *d) {
d->data = readdir(d->dir);
if (!d->data) {
return NULL;
}
d->current.name = d->data->d_name;
d->current.is_dir = d->data->d_type & DT_DIR;
d->current.is_file = d->data->d_type == DT_REG;
return &d->current;
}
void pi_dir_close(pi_dir *d) {
closedir(d->dir);
free(d);
}
int pi_mkdir(char *path, int mode) {
return mkdir(path, mode);
}
#endif
// -----------------------------------------------------------------------------
// Unpack
int create_path(const char *path, const mode_t mode) {
char tmp[MAX_PATH_LEN];
char *p = NULL;
struct stat sb;
size_t len;
// copy path
len = strnlen(path, MAX_PATH_LEN);
if (len == 0 || len == MAX_PATH_LEN) {
return -1;
}
memcpy(tmp, path, len);
tmp[len] = '\0';
// remove file part
char *last_slash = strrchr(tmp, '/');
if (last_slash == NULL) {
return 0;
}
*last_slash = '\0';
// check if path exists and is a directory
if (stat(tmp, &sb) == 0) {
if (S_ISDIR(sb.st_mode)) {
return 0;
}
}
// recursive mkdir
for (p = tmp + 1; *p; p++) {
if (*p == '/') {
*p = 0;
if (stat(tmp, &sb) != 0) {
if (pi_mkdir(tmp, mode) < 0) {
return -1;
}
}
else if (!S_ISDIR(sb.st_mode)) {
return -1;
}
*p = '/';
}
}
if (stat(tmp, &sb) != 0) {
if (pi_mkdir(tmp, mode) < 0) {
return -1;
}
}
else if (!S_ISDIR(sb.st_mode)) {
return -1;
}
return 0;
}
unsigned int copy_out(FILE *src, unsigned int offset, unsigned int size, const char *dest_path) {
FILE *dest = fopen(dest_path, "wb");
error_if(!dest, "Could not open file %s for writing", dest_path);
char buffer[BUFFER_SIZE];
size_t bytes_read, bytes_written;
unsigned int bytes_total = 0;
unsigned int read_size = size < BUFFER_SIZE ? size : BUFFER_SIZE;
fseek(src, offset, SEEK_SET);
while (read_size > 0 && (bytes_read = fread(buffer, 1, read_size, src)) > 0) {
bytes_written = fwrite(buffer, 1, bytes_read, dest);
error_if(bytes_written != bytes_read, "Write error");
bytes_total += bytes_written;
if (bytes_total >= size) {
break;
}
if (size - bytes_total < read_size) {
read_size = size - bytes_total;
}
}
error_if(ferror(src), "read error for file %s", dest_path);
fclose(dest);
return bytes_total;
}
void unpack(const char *archive_path, int list_only) {
qop_desc qop;
int archive_size = qop_open(archive_path, &qop);
error_if(archive_size == 0, "Could not open archive %s", archive_path);
// Read the archive index
int index_len = qop_read_index(&qop, malloc(qop.hashmap_size));
error_if(index_len == 0, "Could not read index from archive %s", archive_path);
// Extract all files
for (unsigned int i = 0; i < qop.hashmap_len; i++) {
qop_file *file = &qop.hashmap[i];
if (file->size == 0) {
continue;
}
error_if(file->path_len >= MAX_PATH_LEN, "Path for file %016llx exceeds %d", file->hash, MAX_PATH_LEN);
char path[MAX_PATH_LEN];
qop_read_path(&qop, file, path);
// Integrity check
// error_if(!qop_find(&qop, path), "could not find %s", path);
printf("%6d %016llx %10d %s\n", i, file->hash, file->size, path);
if (!list_only) {
error_if(create_path(path, 0755) != 0, "Could not create path %s", path);
copy_out(qop.fh, qop.files_offset + file->offset + file->path_len, file->size, path);
}
}
free(qop.hashmap);
qop_close(&qop);
}
// -----------------------------------------------------------------------------
// Pack
typedef struct {
qop_file *files;
int len;
int capacity;
int size;
char dest_path[MAX_PATH_LEN];
} pack_state;
int canonicalize_path(const char *path, char *buffer, size_t buffer_len) {
#if defined(_WIN32)
return _fullpath(buffer, path, buffer_len) != NULL;
#else
UNUSED(buffer_len);
return realpath(path, buffer) != NULL;
#endif
}
void write_16(unsigned int v, FILE *fh) {
unsigned char b[sizeof(unsigned short)];
b[0] = 0xff & (v );
b[1] = 0xff & (v >> 8);
int written = fwrite(b, sizeof(unsigned short), 1, fh);
error_if(!written, "Write error");
}
void write_32(unsigned int v, FILE *fh) {
unsigned char b[sizeof(unsigned int)];
b[0] = 0xff & (v );
b[1] = 0xff & (v >> 8);
b[2] = 0xff & (v >> 16);
b[3] = 0xff & (v >> 24);
int written = fwrite(b, sizeof(unsigned int), 1, fh);
error_if(!written, "Write error");
}
void write_64(qop_uint64_t v, FILE *fh) {
unsigned char b[sizeof(qop_uint64_t)];
b[0] = 0xff & (v );
b[1] = 0xff & (v >> 8);
b[2] = 0xff & (v >> 16);
b[3] = 0xff & (v >> 24);
b[4] = 0xff & (v >> 32);
b[5] = 0xff & (v >> 40);
b[6] = 0xff & (v >> 48);
b[7] = 0xff & (v >> 56);
int written = fwrite(b, sizeof(qop_uint64_t), 1, fh);
error_if(!written, "Write error");
}
unsigned int copy_into(const char *src_path, FILE *dest) {
FILE *src = fopen(src_path, "rb");
error_if(!src, "Could not open file %s for reading", src_path);
char buffer[BUFFER_SIZE];
size_t bytes_read, bytes_written;
unsigned int bytes_total = 0;
while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, src)) > 0) {
bytes_written = fwrite(buffer, 1, bytes_read, dest);
error_if(bytes_written != bytes_read, "Write error");
bytes_total += bytes_written;
}
error_if(ferror(src), "read error for file %s", src_path);
fclose(src);
return bytes_total;
}
void add_file(const char *path, FILE *dest, pack_state *state) {
if (state->dest_path[0]) {
char absolute[MAX_PATH_LEN];
if (canonicalize_path(path, absolute, MAX_PATH_LEN) && strcmp(absolute, state->dest_path) == 0) {
return;
}
}
if (state->len >= state->capacity) {
state->capacity *= 2;
state->files = realloc(state->files, state->capacity * sizeof(qop_file));
}
// Strip leading "./" from path for archive
const char *archive_path = path;
if (path[0] == '.' && path[1] == '/') {
archive_path = path + 2;
}
qop_uint64_t hash = qop_hash(archive_path);
// Write the path into the archive
int path_len = strlen(archive_path) + 1;
int path_written = fwrite(archive_path, sizeof(char), path_len, dest);
error_if(path_written != path_len, "Write error");
// Copy the file into the archive
unsigned int size = copy_into(path, dest);
printf("%6d %016llx %10d %s\n", state->len, hash, size, archive_path);
// Collect file info for the index
state->files[state->len] = (qop_file){
.hash = hash,
.offset = state->size,
.size = size,
.path_len = path_len,
.flags = QOP_FLAG_NONE
};
state->size += size + path_len;
state->len++;
}
void add_dir(const char *path, FILE *dest, pack_state *state) {
pi_dir *dir = pi_dir_open(path);
error_if(!dir, "Could not open directory %s for reading", path);
pi_dirent *entry;
while ((entry = pi_dir_next(dir))) {
if (
entry->is_dir &&
strcmp(entry->name, ".") != 0 &&
strcmp(entry->name, "..") != 0
) {
char subpath[MAX_PATH_LEN];
snprintf(subpath, MAX_PATH_LEN, "%s/%s", path, entry->name);
add_dir(subpath, dest, state);
}
else if (entry->is_file) {
char subpath[MAX_PATH_LEN];
snprintf(subpath, MAX_PATH_LEN, "%s/%s", path, entry->name);
add_file(subpath, dest, state);
}
}
pi_dir_close(dir);
}
void pack(const char *read_dir, char **sources, int sources_len, const char *archive_path) {
FILE *dest = fopen(archive_path, "wb");
error_if(!dest, "Could not open file %s for writing", archive_path);
pack_state state;
state.files = malloc(sizeof(qop_file) * 1024);
state.len = 0;
state.capacity = 1024;
state.size = 0;
state.dest_path[0] = '\0';
if (!canonicalize_path(archive_path, state.dest_path, MAX_PATH_LEN)) {
state.dest_path[0] = '\0';
}
if (read_dir) {
error_if(chdir(read_dir) != 0, "Could not change to directory %s", read_dir);
}
// Add files/directories
for (int i = 0; i < sources_len; i++) {
struct stat s;
error_if(stat(sources[i], &s) != 0, "Could not stat file %s", sources[i]);
if (S_ISDIR(s.st_mode)) {
add_dir(sources[i], dest, &state);
}
else if (S_ISREG(s.st_mode)) {
add_file(sources[i], dest, &state);
}
else {
die("Path %s is neither a directory nor a regular file", sources[i]);
}
}
// Write index and header
unsigned int total_size = state.size + QOP_HEADER_SIZE;
for (int i = 0; i < state.len; i++) {
write_64(state.files[i].hash, dest);
write_32(state.files[i].offset, dest);
write_32(state.files[i].size, dest);
write_16(state.files[i].path_len, dest);
write_16(state.files[i].flags, dest);
total_size += 20;
}
write_32(state.len, dest);
write_32(total_size, dest);
write_32(QOP_MAGIC, dest);
free(state.files);
fclose(dest);
printf("files: %d, size: %d bytes\n", state.len, total_size);
}
void exit_usage(void) {
puts(
"Usage: qopconv [OPTION...] FILE...\n"
"\n"
"Examples:\n"
" qopconv dir1 archive.qop # Create archive.qop from dir1/\n"
" qopconv foo bar archive.qop # Create archive.qop from files foo and bar\n"
" qoponvv -u archive.qop # Unpack archive.qop in current directory\n"
" qopconv -l archive.qop # List files in archive.qop\n"
" qopconv -d dir1 dir2 archive.qop # Use dir1 prefix for reading, create\n"
" archive.qop from files in dir1/dir2/\n"
"\n"
"Options (mutually exclusive):\n"
" -u <archive> ... unpack archive\n"
" -l <archive> ... list contents of archive\n"
" -d <dir> ....... change read dir when creating archives\n"
);
exit(1);
}
int main(int argc, char **argv) {
if (argc < 3) {
exit_usage();
}
// Unpack
if (strcmp(argv[1], "-u") == 0) {
unpack(argv[2], 0);
}
else if (strcmp(argv[1], "-l") == 0) {
unpack(argv[2], 1);
}
else {
int files_start = 1;
char *read_dir = NULL;
if (strcmp(argv[1], "-d") == 0) {
read_dir = argv[2];
files_start = 3;
}
if (argc < 2 + files_start) {
exit_usage();
}
pack(read_dir, argv + files_start, argc - 1 - files_start, argv[argc-1]);
}
return 0;
}

85
scripts/compile.ce Normal file
View File

@@ -0,0 +1,85 @@
// cell compile
var os = use('os')
var io = use('cellfs')
log.console(json.encode(cell.config))
var project_name = cell.config.project.name
if (!project_name) {
log.console("Error: project.name not found in cell.toml")
$_.stop()
}
log.console("Building project: " + project_name)
// 2. Prepare output directory
if (!io.exists('.cell')) {
io.mkdir('.cell')
}
// 3. Find source files
var files = io.enumerate('.', true)
var objects = []
for (var i = 0; i < files.length; i++) {
var file = files[i]
if (file.endsWith('.c')) {
var path_no_ext = file.substring(0, file.length - 2)
var safe_path = path_no_ext.replace(/\//g, '_').replace(/\\/g, '_')
if (safe_path.startsWith('._')) safe_path = safe_path.substring(2)
var use_name = 'js_' + project_name + '_' + safe_path + '_use'
var obj_file = '.cell/build/' + file + '.o'
var obj_dir = io.realdir(obj_file)
var last_slash = file.lastIndexOf('/')
if (last_slash != -1) {
var dir = '.cell/build/' + file.substring(0, last_slash)
if (!io.exists(dir)) {
obj_file = '.cell/build/' + safe_path + '.o'
}
} else {
obj_file = '.cell/build/' + file + '.o'
}
objects.push(obj_file)
log.console("Compiling " + file + " -> " + obj_file)
log.console(`export name is ${use_name}`)
// Compile command
// cc -fPIC -c <file> -O3 -DCELL_USE_NAME=<name> -o <obj_file>
var cmd = 'cc -fPIC -c ' + file + ' -O3 -DCELL_USE_NAME=' + use_name + ' -o ' + obj_file
var ret = os.system(cmd)
if (ret != 0) {
log.console("Compilation failed for " + file)
$_.stop()
}
}
}
// 4. Link shared library
var lib_ext = '.so'
var link_flags = '-shared'
if (os.platform() == 'macOS') {
lib_ext = '.dylib'
link_flags = '-shared'
} else if (os.platform() == 'Windows') {
lib_ext = '.dll'
}
var lib_name = project_name + lib_ext
log.console("Linking " + lib_name)
var link_cmd = 'cc ' + link_flags + ' ' + objects.join(' ') + ' -lcell -o ' + lib_name
var ret = os.system(link_cmd)
if (ret != 0) {
log.console("Linking failed")
$_.stop()
}
log.console("Build complete: " + lib_name)
$_.stop()

View File

@@ -1,4 +1,3 @@
// doc.js
function docOf(obj, prop) {
var block = obj[cell.DOC];
if (!block) return '';

View File

@@ -497,6 +497,8 @@ config ??= {}
config.system ??= {}
config.system.__proto__ = default_config
cell.config = config
ENETSERVICE = config.system.net_service
REPLYTIMEOUT = config.system.reply_timeout

File diff suppressed because it is too large Load Diff

View File

@@ -1,673 +0,0 @@
/*
HandmadeMath.h v2.0.0
This is a single header file with a bunch of useful types and functions for
games and graphics. Consider it a lightweight alternative to GLM that works
both C and C++.
=============================================================================
CONFIG
=============================================================================
By default, all angles in Handmade Math are specified in radians. However, it
can be configured to use degrees or turns instead. Use one of the following
defines to specify the default unit for angles:
#define HANDMADE_MATH_USE_RADIANS
#define HANDMADE_MATH_USE_DEGREES
#define HANDMADE_MATH_USE_TURNS
Regardless of the default angle, you can use the following functions to
specify an angle in a particular unit:
HMM_AngleRad(radians)
HMM_AngleDeg(degrees)
HMM_AngleTurn(turns)
The definitions of these functions change depending on the default unit.
-----------------------------------------------------------------------------
Handmade Math ships with SSE (SIMD) implementations of several common
operations. To disable the use of SSE intrinsics, you must define
HANDMADE_MATH_NO_SSE before including this file:
#define HANDMADE_MATH_NO_SSE
#include "HandmadeMath.h"
-----------------------------------------------------------------------------
To use Handmade Math without the C runtime library, you must provide your own
implementations of basic math functions. Otherwise, HandmadeMath.h will use
the runtime library implementation of these functions.
Define HANDMADE_MATH_PROVIDE_MATH_FUNCTIONS and provide your own
implementations of HMM_SINF, HMM_COSF, HMM_TANF, HMM_ACOSF, and HMM_SQRTF
before including HandmadeMath.h, like so:
#define HANDMADE_MATH_PROVIDE_MATH_FUNCTIONS
#define HMM_SINF MySinF
#define HMM_COSF MyCosF
#define HMM_TANF MyTanF
#define HMM_ACOSF MyACosF
#define HMM_SQRTF MySqrtF
#include "HandmadeMath.h"
By default, it is assumed that your math functions take radians. To use
different units, you must define HMM_ANGLE_USER_TO_INTERNAL and
HMM_ANGLE_INTERNAL_TO_USER. For example, if you want to use degrees in your
code but your math functions use turns:
#define HMM_ANGLE_USER_TO_INTERNAL(a) ((a)*HMM_DegToTurn)
#define HMM_ANGLE_INTERNAL_TO_USER(a) ((a)*HMM_TurnToDeg)
=============================================================================
LICENSE
This software is in the public domain. Where that dedictaion is not
recognized, you are granted a perpetual, irrevocable license to copy,
distribute, and modify this file as you see fit.
=============================================================================
CREDITS
Originally written by Zakary Strange.
Functionality:
Zakary Strange (strangezak@protonmail.com && @strangezak)
Matt Mascarenhas (@miblo_)
Aleph
FieryDrake (@fierydrake)
Gingerbill (@TheGingerBill)
Ben Visness (@bvisness)
Trinton Bullard (@Peliex_Dev)
@AntonDan
Logan Forman (@dev_dwarf)
Fixes:
Jeroen van Rijn (@J_vanRijn)
Kiljacken (@Kiljacken)
Insofaras (@insofaras)
Daniel Gibson (@DanielGibson)
*/
#ifndef HANDMADE_MATH_H
#define HANDMADE_MATH_H
#if !defined(HANDMADE_MATH_NO_SIMD)
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
#define HANDMADE_MATH__USE_NEON 1
#include <arm_neon.h>
#elif defined(_MSC_VER)
#if defined(_M_AMD64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1)
#define HANDMADE_MATH__USE_SSE 1
#include <xmmintrin.h>
#endif
#elif defined(__SSE__)
#define HANDMADE_MATH__USE_SSE 1
#include <xmmintrin.h>
#endif
#endif
#ifdef _MSC_VER
#pragma warning(disable : 4201)
#endif
#if defined(__GNUC__) || defined(__clang__)
#define HMM_DEPRECATED(msg) __attribute__((deprecated(msg)))
#elif defined(_MSC_VER)
#define HMM_DEPRECATED(msg) __declspec(deprecated(msg))
#else
#define HMM_DEPRECATED(msg)
#endif
#if !defined(HANDMADE_MATH_USE_DEGREES) && !defined(HANDMADE_MATH_USE_TURNS) && !defined(HANDMADE_MATH_USE_RADIANS)
#define HANDMADE_MATH_USE_RADIANS
#endif
#define HMM_PI 3.14159265358979323846
#define HMM_PI32 3.14159265359f
#define HMM_DEG180 180.0
#define HMM_DEG18032 180.0f
#define HMM_TURNHALF 0.5
#define HMM_TURNHALF32 0.5f
#define HMM_RadToDeg ((float)(HMM_DEG180 / HMM_PI))
#define HMM_RadToTurn ((float)(HMM_TURNHALF / HMM_PI))
#define HMM_DegToRad ((float)(HMM_PI / HMM_DEG180))
#define HMM_DegToTurn ((float)(HMM_TURNHALF / HMM_DEG180))
#define HMM_TurnToRad ((float)(HMM_PI / HMM_TURNHALF))
#define HMM_TurnToDeg ((float)(HMM_DEG180 / HMM_TURNHALF))
#if defined(HANDMADE_MATH_USE_RADIANS)
#define HMM_AngleRad(a) (a)
#define HMM_AngleDeg(a) ((a)*HMM_DegToRad)
#define HMM_AngleTurn(a) ((a)*HMM_TurnToRad)
#elif defined(HANDMADE_MATH_USE_DEGREES)
#define HMM_AngleRad(a) ((a)*HMM_RadToDeg)
#define HMM_AngleDeg(a) (a)
#define HMM_AngleTurn(a) ((a)*HMM_TurnToDeg)
#elif defined(HANDMADE_MATH_USE_TURNS)
#define HMM_AngleRad(a) ((a)*HMM_RadToTurn)
#define HMM_AngleDeg(a) ((a)*HMM_DegToTurn)
#define HMM_AngleTurn(a) (a)
#endif
#if !defined(HANDMADE_MATH_PROVIDE_MATH_FUNCTIONS)
#include <math.h>
#define HMM_SINF sinf
#define HMM_COSF cosf
#define HMM_TANF tanf
#define HMM_SQRTF sqrtf
#define HMM_ACOSF acosf
#endif
#if !defined(HMM_ANGLE_USER_TO_INTERNAL)
#define HMM_ANGLE_USER_TO_INTERNAL(a) (HMM_ToRad(a))
#endif
#if !defined(HMM_ANGLE_INTERNAL_TO_USER)
#if defined(HANDMADE_MATH_USE_RADIANS)
#define HMM_ANGLE_INTERNAL_TO_USER(a) (a)
#elif defined(HANDMADE_MATH_USE_DEGREES)
#define HMM_ANGLE_INTERNAL_TO_USER(a) ((a)*HMM_RadToDeg)
#elif defined(HANDMADE_MATH_USE_TURNS)
#define HMM_ANGLE_INTERNAL_TO_USER(a) ((a)*HMM_RadToTurn)
#endif
#endif
#define HMM_MIN(a, b) ((a) > (b) ? (b) : (a))
#define HMM_MAX(a, b) ((a) < (b) ? (b) : (a))
#define HMM_ABS(a) ((a) > 0 ? (a) : -(a))
#define HMM_MOD(a, m) (((a) % (m)) >= 0 ? ((a) % (m)) : (((a) % (m)) + (m)))
#define HMM_SQUARE(x) ((x) * (x))
#define HMMFMT_VEC3 "[%g,%g,%g]"
#define HMMPRINT_VEC3(vec) vec.x, vec.y, vec.z
#define FMT_VEC4 "[%g,%g,%g,%g]"
#define PRINT_VEC4(vec) vec.x, vec.y, vec.z, vec.w
#define FMT_M4 "[%g,%g,%g,%g\n%g,%g,%g,%g\n%g,%g,%g,%g\n%g,%g,%g,%g]"
#define PRINT_M4(m) m.e[0][0], m.e[0][1], m.e[0][2], m.e[0][3], m.e[1][0], m.e[1][1], m.e[1][2], m.e[1][3], m.e[2][0], m.e[2][1], m.e[2][2], m.e[2][3], m.e[3][0], m.e[3][1], m.e[3][2], m.e[3][3]
typedef union HMM_Vec2 {
struct
{
float X, Y;
};
struct {
float x, y;
};
struct
{
float U, V;
};
struct
{
float Left, Right;
};
struct
{
float Width, Height;
};
float Elements[2];
float e[2];
} HMM_Vec2;
typedef union HMM_Vec3 {
struct
{
float X, Y, Z;
};
struct { float x, y, z; };
struct
{
float U, V, W;
};
struct
{
float R, G, B;
};
struct
{
HMM_Vec2 XY;
float _Ignored0;
};
struct
{
HMM_Vec2 xy;
float _Ignored4;
};
struct
{
float _Ignored1;
HMM_Vec2 YZ;
};
struct
{
HMM_Vec2 UV;
float _Ignored2;
};
struct
{
float _Ignored3;
HMM_Vec2 VW;
};
struct
{
HMM_Vec2 cp;
float _Ignored5;
};
float Elements[3];
float e[3];
} HMM_Vec3;
typedef union HMM_Quat {
struct
{
union {
HMM_Vec3 XYZ;
struct
{
float X, Y, Z;
};
};
float W;
};
struct {float x, y, z, w;};
float Elements[4];
float e[4];
#ifdef HANDMADE_MATH__USE_SSE
__m128 SSE;
#endif
} HMM_Quat;
typedef union HMM_Vec4 {
struct
{
union {
HMM_Vec3 XYZ;
struct
{
float X, Y, Z;
};
HMM_Vec3 xyz;
};
float W;
};
struct
{
union {
HMM_Vec3 RGB;
struct
{
float R, G, B;
};
};
float A;
};
struct
{
HMM_Vec2 XY;
float _Ignored0;
float _Ignored1;
};
struct {
HMM_Vec2 xy;
float _ig0;
float _ig1;
};
struct {
HMM_Vec2 _2;
float _ig2;
float _ig3;
};
struct {
HMM_Vec3 _3;
float _ig4;
};
struct
{
float _Ignored2;
HMM_Vec2 YZ;
float _Ignored3;
};
struct
{
float _Ignored4;
float _Ignored5;
HMM_Vec2 ZW;
};
struct
{
HMM_Vec2 cp;
HMM_Vec2 wh;
};
HMM_Quat quat;
struct {float x, y, z, w; };
struct {float r, g, b, a; };
struct {float u0, u1, v0, v1;};
float Elements[4];
float e[4];
#ifdef HANDMADE_MATH__USE_SSE
__m128 SSE;
#endif
#ifdef HANDMADE_MATH__USE_NEON
float32x4_t NEON;
#endif
} HMM_Vec4;
typedef union HMM_Mat2 {
float Elements[2][2];
HMM_Vec2 Columns[2];
} HMM_Mat2;
typedef union HMM_Mat3 {
float Elements[3][3];
HMM_Vec3 Columns[3];
} HMM_Mat3;
typedef union HMM_Mat4 {
float Elements[4][4];
HMM_Vec4 Columns[4];
HMM_Vec4 col[4];
float e[4][4];
float em[16];
} HMM_Mat4;
extern const HMM_Vec2 v2zero;
extern const HMM_Vec2 v2one;
extern const HMM_Vec3 v3zero;
extern const HMM_Vec3 v3one;
extern const HMM_Vec4 v4zero;
typedef signed int HMM_Bool;
extern const HMM_Vec3 vX;
extern const HMM_Vec3 vY;
extern const HMM_Vec3 vZ;
extern const HMM_Vec3 vUP;
extern const HMM_Vec3 vDOWN;
extern const HMM_Vec3 vFWD;
extern const HMM_Vec3 vBKWD;
extern const HMM_Vec3 vLEFT;
extern const HMM_Vec3 vRIGHT;
extern const HMM_Mat4 MAT1;
extern const HMM_Quat QUAT1;
/*
* Angle unit conversion functions
*/
float HMM_ToRad(float Angle);
float HMM_ToDeg(float Angle);
float HMM_ToTurn(float Angle);
/*
* Floating-point math functions
*/
float HMM_SinF(float Angle);
float HMM_CosF(float Angle);
float HMM_TanF(float Angle);
float HMM_ACosF(float Arg);
float HMM_SqrtF(float Float);
float HMM_InvSqrtF(float Float);
/*
* Utility functions
*/
float HMM_Lerp(float A, float Time, float B);
float HMM_Clamp(float Min, float Value, float Max);
float frand(float max);
/*
* Vector initialization
*/
HMM_Vec2 HMM_V2(float X, float Y);
HMM_Vec3 HMM_V3(float X, float Y, float Z);
HMM_Vec3 HMM_V3i(float i);
HMM_Vec4 HMM_V4(float X, float Y, float Z, float W);
HMM_Vec4 HMM_V4V(HMM_Vec3 Vector, float W);
/*
* Binary vector operations
*/
HMM_Vec2 HMM_AddV2(HMM_Vec2 Left, HMM_Vec2 Right);
HMM_Vec3 HMM_AddV3(HMM_Vec3 Left, HMM_Vec3 Right);
HMM_Vec4 HMM_AddV4(HMM_Vec4 Left, HMM_Vec4 Right);
HMM_Vec2 HMM_SubV2(HMM_Vec2 Left, HMM_Vec2 Right);
HMM_Vec3 HMM_SubV3(HMM_Vec3 Left, HMM_Vec3 Right);
HMM_Vec4 HMM_SubV4(HMM_Vec4 Left, HMM_Vec4 Right);
HMM_Vec2 HMM_MulV2(HMM_Vec2 Left, HMM_Vec2 Right);
HMM_Vec2 HMM_MulV2F(HMM_Vec2 Left, float Right);
HMM_Vec3 HMM_MulV3(HMM_Vec3 Left, HMM_Vec3 Right);
HMM_Vec3 HMM_MulV3F(HMM_Vec3 Left, float Right);
HMM_Vec4 HMM_MulV4(HMM_Vec4 Left, HMM_Vec4 Right);
HMM_Vec4 HMM_MulV4F(HMM_Vec4 Left, float Right);
HMM_Vec2 HMM_DivV2(HMM_Vec2 Left, HMM_Vec2 Right);
HMM_Vec2 HMM_DivV2F(HMM_Vec2 Left, float Right);
HMM_Vec3 HMM_DivV3(HMM_Vec3 Left, HMM_Vec3 Right);
HMM_Vec3 HMM_DivV3F(HMM_Vec3 Left, float Right);
HMM_Vec4 HMM_DivV4(HMM_Vec4 Left, HMM_Vec4 Right);
HMM_Vec4 HMM_DivV4F(HMM_Vec4 Left, float Right);
HMM_Bool HMM_EqV2(HMM_Vec2 Left, HMM_Vec2 Right);
HMM_Bool HMM_EqV3(HMM_Vec3 Left, HMM_Vec3 Right);
HMM_Bool HMM_EqV4(HMM_Vec4 Left, HMM_Vec4 Right);
float HMM_DotV2(HMM_Vec2 Left, HMM_Vec2 Right);
HMM_Vec2 HMM_ProjV2(HMM_Vec2 a, HMM_Vec2 b);
float HMM_DotV3(HMM_Vec3 Left, HMM_Vec3 Right);
float HMM_DotV4(HMM_Vec4 Left, HMM_Vec4 Right);
HMM_Vec3 HMM_Cross(HMM_Vec3 Left, HMM_Vec3 Right);
/*
* Unary vector operations
*/
float HMM_LenSqrV2(HMM_Vec2 A);
float HMM_LenSqrV3(HMM_Vec3 A);
float HMM_LenSqrV4(HMM_Vec4 A);
float HMM_LenV2(HMM_Vec2 A);
float HMM_AngleV2(HMM_Vec2 a, HMM_Vec2 b);
float HMM_DistV2(HMM_Vec2 a, HMM_Vec2 b);
HMM_Vec2 HMM_V2Rotate(HMM_Vec2 v, float angle);
float HMM_LenV3(HMM_Vec3 A);
float HMM_DistV3(HMM_Vec3 a, HMM_Vec3 b);
float HMM_AngleV3(HMM_Vec3 a, HMM_Vec3 b);
float HMM_LenV4(HMM_Vec4 A);
float HMM_AngleV4(HMM_Vec4 a, HMM_Vec4 b);
HMM_Vec2 HMM_NormV2(HMM_Vec2 A);
HMM_Vec3 HMM_NormV3(HMM_Vec3 A);
HMM_Vec4 HMM_NormV4(HMM_Vec4 A);
/*
* Utility vector functions
*/
HMM_Vec2 HMM_LerpV2(HMM_Vec2 A, float Time, HMM_Vec2 B);
HMM_Vec3 HMM_LerpV3(HMM_Vec3 A, float Time, HMM_Vec3 B);
HMM_Vec4 HMM_LerpV4(HMM_Vec4 A, float Time, HMM_Vec4 B);
/*
* SSE stuff
*/
HMM_Vec4 HMM_LinearCombineV4M4(HMM_Vec4 Left, HMM_Mat4 Right);
/*
* 2x2 Matrices
*/
HMM_Mat2 HMM_M2(void);
HMM_Mat2 HMM_M2D(float Diagonal);
HMM_Mat2 HMM_TransposeM2(HMM_Mat2 Matrix);
HMM_Mat2 HMM_RotateM2(float angle);
HMM_Mat2 HMM_AddM2(HMM_Mat2 Left, HMM_Mat2 Right);
HMM_Mat2 HMM_SubM2(HMM_Mat2 Left, HMM_Mat2 Right);
HMM_Vec2 HMM_MulM2V2(HMM_Mat2 Matrix, HMM_Vec2 Vector);
HMM_Mat2 HMM_MulM2(HMM_Mat2 Left, HMM_Mat2 Right);
HMM_Mat2 HMM_MulM2F(HMM_Mat2 Matrix, float Scalar);
HMM_Mat2 HMM_DivM2F(HMM_Mat2 Matrix, float Scalar);
float HMM_DeterminantM2(HMM_Mat2 Matrix);
HMM_Mat2 HMM_InvGeneralM2(HMM_Mat2 Matrix);
/*
* 3x3 Matrices
*/
HMM_Mat3 HMM_M3(void);
HMM_Mat3 HMM_M3D(float Diagonal);
HMM_Mat3 HMM_Translate2D(HMM_Vec2 p);
HMM_Mat3 HMM_RotateM3(float angle);
HMM_Mat3 HMM_ScaleM3(HMM_Vec2 s);
HMM_Mat3 HMM_TransposeM3(HMM_Mat3 Matrix);
HMM_Mat3 HMM_AddM3(HMM_Mat3 Left, HMM_Mat3 Right);
HMM_Mat3 HMM_SubM3(HMM_Mat3 Left, HMM_Mat3 Right);
HMM_Vec3 HMM_MulM3V3(HMM_Mat3 Matrix, HMM_Vec3 Vector);
HMM_Mat3 HMM_MulM3(HMM_Mat3 Left, HMM_Mat3 Right);
HMM_Mat3 HMM_MulM3F(HMM_Mat3 Matrix, float Scalar);
HMM_Mat3 HMM_DivM3F(HMM_Mat3 Matrix, float Scalar);
HMM_Mat2 HMM_ScaleM2(HMM_Vec2 Scale);
float HMM_DeterminantM3(HMM_Mat3 Matrix);
HMM_Mat3 HMM_M2Basis(HMM_Mat2 basis);
HMM_Mat3 HMM_InvGeneralM3(HMM_Mat3 Matrix);
/*
* 4x4 Matrices
*/
HMM_Mat4 HMM_M4(void);
HMM_Mat4 HMM_M4D(float Diagonal);
HMM_Mat4 HMM_TransposeM4(HMM_Mat4 Matrix);
HMM_Mat4 HMM_AddM4(HMM_Mat4 Left, HMM_Mat4 Right);
HMM_Mat4 HMM_SubM4(HMM_Mat4 Left, HMM_Mat4 Right);
HMM_Mat4 HMM_MulM4(HMM_Mat4 Left, HMM_Mat4 Right);
HMM_Mat4 HMM_MulM4_P(HMM_Mat4 *Left, HMM_Mat4 *Right);
HMM_Mat4 HMM_MulM4F(HMM_Mat4 Matrix, float Scalar);
HMM_Vec4 HMM_MulM4V4(HMM_Mat4 Matrix, HMM_Vec4 Vector);
HMM_Vec4 HMM_MulM4V4_P(HMM_Mat4 *Matrix, HMM_Vec4 *Vector);
HMM_Mat4 HMM_DivM4F(HMM_Mat4 Matrix, float Scalar);
float HMM_DeterminantM4(HMM_Mat4 Matrix);
// Returns a general-purpose inverse of an HMM_Mat4. Note that special-purpose inverses of many transformations
// are available and will be more efficient.
HMM_Mat4 HMM_InvGeneralM4(HMM_Mat4 Matrix);
/*
* Common graphics transformations
*/
// Produces a right-handed orthographic projection matrix with Z ranging from -1 to 1 (the GL convention).
// Left, Right, Bottom, and Top specify the coordinates of their respective clipping planes.
// Near and Far specify the distances to the near and far clipping planes.
HMM_Mat4 HMM_Orthographic_RH_NO(float Left, float Right, float Bottom, float Top, float Near, float Far);
// Produces a right-handed orthographic projection matrix with Z ranging from 0 to 1 (the DirectX convention).
// Left, Right, Bottom, and Top specify the coordinates of their respective clipping planes.
// Near and Far specify the distances to the near and far clipping planes.
HMM_Mat4 HMM_Orthographic_RH_ZO(float Left, float Right, float Bottom, float Top, float Near, float Far);
// Produces a left-handed orthographic projection matrix with Z ranging from -1 to 1 (the GL convention).
// Left, Right, Bottom, and Top specify the coordinates of their respective clipping planes.
// Near and Far specify the distances to the near and far clipping planes.
HMM_Mat4 HMM_Orthographic_LH_NO(float Left, float Right, float Bottom, float Top, float Near, float Far);
// Produces a left-handed orthographic projection matrix with Z ranging from 0 to 1 (the DirectX convention).
// Left, Right, Bottom, and Top specify the coordinates of their respective clipping planes.
// Near and Far specify the distances to the near and far clipping planes.
HMM_Mat4 HMM_Orthographic_LH_ZO(float Left, float Right, float Bottom, float Top, float Near, float Far);
// Returns an inverse for the given orthographic projection matrix. Works for all orthographic
// projection matrices, regardless of handedness or NDC convention.
HMM_Mat4 HMM_InvOrthographic(HMM_Mat4 OrthoMatrix);
HMM_Mat4 HMM_Perspective_RH_NO(float FOV, float AspectRatio, float Near, float Far);
HMM_Mat4 HMM_Perspective_RH_ZO(float FOV, float AspectRatio, float Near, float Far);
HMM_Mat4 HMM_Perspective_LH_NO(float FOV, float AspectRatio, float Near, float Far);
HMM_Mat4 HMM_Perspective_LH_ZO(float FOV, float AspectRatio, float Near, float Far);
HMM_Mat4 HMM_Perspective_Metal(float FOV, float AspectRation, float Near, float Far);
HMM_Mat4 HMM_Orthographic_Metal(float l, float r, float b, float t, float near, float far);
HMM_Mat4 HMM_Orthographic_DX(float l, float r, float b, float t, float near, float far);
HMM_Mat4 HMM_Orthographic_GL(float l, float r, float b, float t, float near, float far);
HMM_Mat4 HMM_InvPerspective_RH(HMM_Mat4 PerspectiveMatrix);
HMM_Mat4 HMM_InvPerspective_LH(HMM_Mat4 PerspectiveMatrix);
HMM_Mat4 HMM_Translate(HMM_Vec3 Translation);
HMM_Mat4 HMM_InvTranslate(HMM_Mat4 TranslationMatrix);
HMM_Mat4 HMM_Rotate_RH(float Angle, HMM_Vec3 Axis);
HMM_Mat4 HMM_Rotate_LH(float Angle, HMM_Vec3 Axis);
HMM_Mat4 HMM_InvRotate(HMM_Mat4 RotationMatrix);
HMM_Mat4 HMM_Scale(HMM_Vec3 Scale);
HMM_Mat4 HMM_InvScale(HMM_Mat4 ScaleMatrix);
HMM_Mat4 _HMM_LookAt(HMM_Vec3 F, HMM_Vec3 S, HMM_Vec3 U, HMM_Vec3 Eye);
HMM_Mat4 HMM_LookAt_RH(HMM_Vec3 Eye, HMM_Vec3 Center, HMM_Vec3 Up);
HMM_Mat4 HMM_LookAt_LH(HMM_Vec3 Eye, HMM_Vec3 Center, HMM_Vec3 Up);
HMM_Mat4 HMM_InvLookAt(HMM_Mat4 Matrix);
/*
* Quaternion operations
*/
HMM_Vec3 HMM_QVRot(HMM_Vec3 v, HMM_Quat q)
;
HMM_Quat HMM_Q(float X, float Y, float Z, float W);
HMM_Quat HMM_QV4(HMM_Vec4 Vector);
HMM_Quat HMM_AddQ(HMM_Quat Left, HMM_Quat Right);
HMM_Quat HMM_SubQ(HMM_Quat Left, HMM_Quat Right);
HMM_Quat HMM_MulQ(HMM_Quat Left, HMM_Quat Right);
HMM_Quat HMM_MulQF(HMM_Quat Left, float Multiplicative);
HMM_Quat HMM_DivQF(HMM_Quat Left, float Divnd);
float HMM_DotQ(HMM_Quat Left, HMM_Quat Right);
HMM_Quat HMM_InvQ(HMM_Quat Left);
HMM_Quat HMM_NormQ(HMM_Quat Quat);
HMM_Quat _HMM_MixQ(HMM_Quat Left, float MixLeft, HMM_Quat Right, float MixRight);
HMM_Quat HMM_NLerp(HMM_Quat Left, float Time, HMM_Quat Right);
HMM_Quat HMM_SLerp(HMM_Quat Left, float Time, HMM_Quat Right);
HMM_Mat4 HMM_QToM4(HMM_Quat Left);
HMM_Mat4 HMM_M4TRS(HMM_Vec3 t, HMM_Quat q, HMM_Vec3 s);
HMM_Mat3 HMM_M3TRS(HMM_Vec2 t, float angle, HMM_Vec2 s);
HMM_Mat3 HMM_Mat4ToMat3(HMM_Mat4 m);
HMM_Quat HMM_M4ToQ_RH(HMM_Mat4 M);
HMM_Quat HMM_M4ToQ_LH(HMM_Mat4 M);
HMM_Quat HMM_QFromAxisAngle_RH(HMM_Vec3 Axis, float AngleOfRotation);
HMM_Quat HMM_QFromAxisAngle_LH(HMM_Vec3 Axis, float AngleOfRotation);
float HMM_Q_Roll(HMM_Quat q);
float HMM_Q_Yaw(HMM_Quat q);
float HMM_Q_Pitch(HMM_Quat q);
#endif /* HANDMADE_MATH_H */

View File

@@ -1,5 +1,5 @@
#ifndef PROSPERON_H
#define PROSPERON_H
#ifndef CELL_H
#define CELL_H
#include <SDL3/SDL.h>
#include "quickjs.h"
@@ -113,6 +113,11 @@ void actor_clock(cell_rt *actor, JSValue fn);
int JS_ArrayLength(JSContext *js, JSValue a);
int js2bool(JSContext *js, JSValue v);
JSValue bool2js(JSContext *js, int b);
double js2number(JSContext *js, JSValue v);
JSValue number2js(JSContext *js, double g);
#ifdef __cplusplus
}
#endif

View File

@@ -81,18 +81,13 @@ double rand_range(JSContext *js, double min, double max)
return genRand(mrand) * (max-min)+min;
}
typedef struct texture_vertex {
float x, y, z;
float u, v;
uint8_t r, g, b,a;
} texture_vertex;
#define JS_GETNUM(JS,VAL,I,TO,TYPE) { \
JSValue val = JS_GetPropertyUint32(JS,VAL,I); \
TO = js2##TYPE(JS, val); \
JS_FreeValue(JS, val); } \
int js2bool(JSContext *js, JSValue v) { return JS_ToBool(js,v); }
JSValue bool2js(JSContext *js, int b) { return JS_NewBool(js,b); }
JSValue number2js(JSContext *js, double g) { return JS_NewFloat64(js,g); }
double js2number(JSContext *js, JSValue v) {
@@ -102,47 +97,6 @@ double js2number(JSContext *js, JSValue v) {
return g;
}
JSValue js_getpropertyuint32(JSContext *js, JSValue v, unsigned int i)
{
JSValue ret = JS_GetPropertyUint32(js,v,i);
JS_FreeValue(js,ret);
return ret;
}
double js_getnum_uint32(JSContext *js, JSValue v, unsigned int i)
{
JSValue val = JS_GetPropertyUint32(js,v,i);
double ret = js2number(js, val);
JS_FreeValue(js,val);
return ret;
}
double js_getnum_str(JSContext *js, JSValue v, const char *str)
{
JSValue val = JS_GetPropertyStr(js,v,str);
double ret = js2number(js,val);
JS_FreeValue(js,val);
return ret;
}
#define JS_GETPROP(JS, TARGET, VALUE, PROP, TYPE) {\
JSValue __##PROP##__v = JS_GetPropertyStr(JS,VALUE,#PROP); \
TARGET = js2##TYPE(JS, __##PROP##__v); \
JS_FreeValue(JS,__##PROP##__v); }\
#define JS_GETATOM(JS, TARGET, VALUE, ATOM, TYPE) {\
JSValue __##PROP##__v = JS_GetPropertyStr(JS,VALUE,#ATOM); \
TARGET = js2##TYPE(JS, __##PROP##__v); \
JS_FreeValue(JS,__##PROP##__v); }\
int JS_GETBOOL(JSContext *js, JSValue v, const char *prop)
{
JSValue __v = JS_GetPropertyStr(js,v,prop);
int r = JS_ToBool(js,__v);
JS_FreeValue(js,__v);
return r;
}
JSValue js_getproperty(JSContext *js, JSValue v, const char *prop)
{
JSValue ret = JS_GetPropertyStr(js, v, prop);
@@ -176,28 +130,6 @@ JSValue make_quad_indices_buffer(JSContext *js, int quads)
return JS_DupValue(js,rt->idx_buffer);
}
typedef struct lrtb lrtb;
lrtb js2lrtb(JSContext *js, JSValue v)
{
lrtb ret = {0};
JS_GETATOM(js,ret.l,v,l,number)
JS_GETATOM(js,ret.r,v,r,number)
JS_GETATOM(js,ret.b,v,b,number)
JS_GETATOM(js,ret.t,v,t,number)
return ret;
}
JSValue vec22js(JSContext *js,HMM_Vec2 v)
{
JSValue array = JS_NewArray(js);
JS_SetPropertyUint32(js, array,0,number2js(js,v.x));
JS_SetPropertyUint32(js, array,1,number2js(js,v.y));
return array;
}
char *js2strdup(JSContext *js, JSValue v) {
const char *str = JS_ToCString(js, v);
char *ret = strdup(str);
@@ -216,340 +148,6 @@ double js2angle(JSContext *js,JSValue v) {
return n * HMM_TurnToRad;
}
typedef HMM_Vec4 colorf;
colorf js2color(JSContext *js,JSValue v) {
if (JS_IsNull(v)) return (colorf){1,1,1,1};
colorf color = {1,1,1,1}; // Default to white
if (JS_IsArray(js, v)) {
// Handle array format: [r, g, b, a]
JSValue c[4];
for (int i = 0; i < 4; i++) c[i] = JS_GetPropertyUint32(js,v,i);
color.r = js2number(js,c[0]);
color.g = js2number(js,c[1]);
color.b = js2number(js,c[2]);
color.a = JS_IsNull(c[3]) ? 1.0 : js2number(js,c[3]);
for (int i = 0; i < 4; i++) JS_FreeValue(js,c[i]);
} else if (JS_IsObject(v)) {
JS_GETPROP(js, color.r, v, r, number)
JS_GETPROP(js, color.g, v, g, number)
JS_GETPROP(js, color.b, v, b, number)
JS_GETPROP(js, color.a, v, a, number)
}
return color;
}
JSValue color2js(JSContext *js, colorf color)
{
JSValue arr = JS_NewArray(js);
JS_SetPropertyUint32(js, arr,0,number2js(js,(double)color.r));
JS_SetPropertyUint32(js, arr,1,number2js(js,(double)color.g));
JS_SetPropertyUint32(js, arr,2,number2js(js,(double)color.b));
JS_SetPropertyUint32(js, arr,3,number2js(js,(double)color.a));
return arr;
}
HMM_Vec2 js2vec2(JSContext *js,JSValue v)
{
HMM_Vec2 v2;
// Check if it's an array
if (JS_IsArray(js, v)) {
v2.X = js_getnum_uint32(js,v,0);
v2.Y = js_getnum_uint32(js,v,1);
} else {
// Try to get x,y properties from object
JSValue x_val = JS_GetPropertyStr(js, v, "x");
JSValue y_val = JS_GetPropertyStr(js, v, "y");
v2.X = js2number(js, x_val);
v2.Y = js2number(js, y_val);
JS_FreeValue(js, x_val);
JS_FreeValue(js, y_val);
}
return v2;
}
HMM_Vec3 js2vec3(JSContext *js,JSValue v)
{
HMM_Vec3 v3;
v3.x = js_getnum_uint32(js, v,0);
v3.y = js_getnum_uint32(js, v,1);
v3.z = js_getnum_uint32(js, v,2);
return v3;
}
float *js2floats(JSContext *js, JSValue v, size_t *len)
{
*len = JS_ArrayLength(js,v);
float *arr = malloc(sizeof(float)* *len);
for (int i = 0; i < *len; i++)
arr[i] = js_getnum_uint32(js,v,i);
return arr;
}
double *js2doubles(JSContext *js, JSValue v, size_t *len)
{
*len = JS_ArrayLength(js,v);
double *arr = malloc(sizeof(double)* *len);
for (int i = 0; i < *len; i++)
arr[i] = js_getnum_uint32(js,v,i);
return arr;
}
HMM_Vec3 js2vec3f(JSContext *js, JSValue v)
{
HMM_Vec3 vec;
if (JS_IsArray(js, v))
return js2vec3(js,v);
else
vec.x = vec.y = vec.z = js2number(js,v);
return vec;
}
JSValue vec32js(JSContext *js, HMM_Vec3 v)
{
JSValue array = JS_NewArray(js);
JS_SetPropertyUint32(js, array,0,number2js(js,v.x));
JS_SetPropertyUint32(js, array,1,number2js(js,v.y));
JS_SetPropertyUint32(js, array,2,number2js(js,v.z));
return array;
}
JSValue vec3f2js(JSContext *js, HMM_Vec3 v)
{
return vec32js(js,v);
}
JSValue quat2js(JSContext *js, HMM_Quat q)
{
JSValue arr = JS_NewArray(js);
JS_SetPropertyUint32(js, arr, 0, number2js(js,q.x));
JS_SetPropertyUint32(js, arr,1,number2js(js,q.y));
JS_SetPropertyUint32(js, arr,2,number2js(js,q.z));
JS_SetPropertyUint32(js, arr,3,number2js(js,q.w));
return arr;
}
HMM_Vec4 js2vec4(JSContext *js, JSValue v)
{
HMM_Vec4 v4;
for (int i = 0; i < 4; i++)
v4.e[i] = js_getnum_uint32(js, v,i);
return v4;
}
double arr_vec_length(JSContext *js,JSValue v)
{
int len = JS_ArrayLength(js,v);
switch(len) {
case 2: return HMM_LenV2(js2vec2(js,v));
case 3: return HMM_LenV3(js2vec3(js,v));
case 4: return HMM_LenV4(js2vec4(js,v));
}
double sum = 0;
for (int i = 0; i < len; i++)
sum += pow(js_getnum_uint32(js, v, i), 2);
return sqrt(sum);
}
HMM_Quat js2quat(JSContext *js,JSValue v)
{
return js2vec4(js,v).quat;
}
JSValue vec42js(JSContext *js, HMM_Vec4 v)
{
JSValue array = JS_NewArray(js);
for (int i = 0; i < 4; i++)
JS_SetPropertyUint32(js, array,i,number2js(js,v.e[i]));
return array;
}
HMM_Vec2 *js2cpvec2arr(JSContext *js,JSValue v) {
HMM_Vec2 *arr = NULL;
int n = JS_ArrayLength(js,v);
arrsetlen(arr,n);
for (int i = 0; i < n; i++)
arr[i] = js2vec2(js,js_getpropertyuint32(js, v, i));
return arr;
}
JSValue vecarr2js(JSContext *js,HMM_Vec2 *points, int n) {
JSValue array = JS_NewArray(js);
for (int i = 0; i < n; i++)
JS_SetPropertyUint32(js, array,i,vec22js(js,points[i]));
return array;
}
rect js2rect(JSContext *js,JSValue v) {
if (JS_IsNull(v)) return (rect){0,0,1,1};
rect rect;
JS_GETATOM(js,rect.x,v,x,number)
JS_GETATOM(js,rect.y,v,y,number)
JS_GETATOM(js,rect.w,v,width,number)
JS_GETATOM(js,rect.h,v,height,number)
float anchor_x, anchor_y;
JS_GETATOM(js, anchor_x, v, anchor_x, number)
JS_GETATOM(js, anchor_y, v, anchor_y, number)
rect.y -= anchor_y*rect.h;
rect.x -= anchor_x*rect.w;
return rect;
}
irect js2irect(JSContext *js, JSValue v)
{
if (JS_IsNull(v)) return (irect){0,0,1,1};
irect rect;
JS_GETATOM(js,rect.x,v,x,number)
JS_GETATOM(js,rect.y,v,y,number)
JS_GETATOM(js,rect.w,v,width,number)
JS_GETATOM(js,rect.h,v,height,number)
float anchor_x, anchor_y;
JS_GETATOM(js, anchor_x, v, anchor_x, number)
JS_GETATOM(js, anchor_y, v, anchor_y, number)
rect.y -= anchor_y*rect.h;
rect.x -= anchor_x*rect.w;
return rect;
}
JSValue rect2js(JSContext *js,rect rect) {
JSValue obj = JS_NewObject(js);
JS_SetPropertyStr(js, obj, "x", number2js(js, rect.x));
JS_SetPropertyStr(js, obj, "y", number2js(js, rect.y));
JS_SetPropertyStr(js, obj, "width", number2js(js, rect.w));
JS_SetPropertyStr(js, obj, "height", number2js(js, rect.h));
return obj;
}
static JSValue floats2array(JSContext *js, float *vals, size_t len) {
JSValue arr = JS_NewArray(js);
for (size_t i = 0; i < len; i++) {
JS_SetPropertyUint32(js, arr, i, number2js(js, vals[i]));
}
return arr;
}
#define JS_HMM_FN(OP, HMM, SIGN) \
JSC_CCALL(array_##OP, \
int len = JS_ArrayLength(js,self); \
if (!JS_IsArray(js, argv[0])) { \
double n = js2number(js,argv[0]); \
JSValue arr = JS_NewArray(js); \
for (int i = 0; i < len; i++) \
JS_SetPropertyUint32(js, arr, i, number2js(js,js_getnum_uint32(js, self,i) SIGN n)); \
return arr; \
} \
switch(len) { \
case 2: \
return vec22js(js,HMM_##HMM##V2(js2vec2(js,self), js2vec2(js,argv[0]))); \
case 3: \
return vec32js(js, HMM_##HMM##V3(js2vec3(js,self), js2vec3(js,argv[0]))); \
case 4: \
return vec42js(js,HMM_##HMM##V4(js2vec4(js,self), js2vec4(js,argv[0]))); \
} \
\
JSValue arr = JS_NewArray(js); \
for (int i = 0; i < len; i++) { \
double a = js_getnum_uint32(js, self,i); \
double b = js_getnum_uint32(js, argv[0],i); \
JS_SetPropertyUint32(js, arr, i, number2js(js,a SIGN b)); \
} \
return arr; \
) \
JS_HMM_FN(add, Add, +)
JS_HMM_FN(sub, Sub, -)
JS_HMM_FN(div, Div, /)
JS_HMM_FN(scale, Mul, *)
JSC_CCALL(array_lerp,
double t = js2number(js,argv[1]);
int len = JS_ArrayLength(js,self);
JSValue arr = JS_NewArray(js);
for (int i = 0; i < len; i++) {
double from = js_getnum_uint32(js, self, i);
double to = js_getnum_uint32(js, argv[0], i);
JS_SetPropertyUint32(js, arr, i, number2js(js,(to - from) * t + from));
}
return arr;
)
JSValue js_array_get_x(JSContext *js, JSValue self) { return JS_GetPropertyUint32(js,self,0); }
JSValue js_array_set_x(JSContext *js, JSValue self, JSValue val) { JS_SetPropertyUint32(js,self,0,val); return JS_NULL; }
JSValue js_array_get_y(JSContext *js, JSValue self) { return JS_GetPropertyUint32(js,self,1); }
JSValue js_array_set_y(JSContext *js, JSValue self, JSValue val) { JS_SetPropertyUint32(js,self,1,val); return JS_NULL; }
// Single-value accessors
JSValue js_array_get_r(JSContext *js, JSValue self)
{ return JS_GetPropertyUint32(js, self, 0); }
JSValue js_array_set_r(JSContext *js, JSValue self, JSValue val)
{ JS_SetPropertyUint32(js, self, 0, val); return JS_NULL; }
JSValue js_array_get_g(JSContext *js, JSValue self)
{ return JS_GetPropertyUint32(js, self, 1); }
JSValue js_array_set_g(JSContext *js, JSValue self, JSValue val)
{ JS_SetPropertyUint32(js, self, 1, val); return JS_NULL; }
JSValue js_array_get_b(JSContext *js, JSValue self)
{ return JS_GetPropertyUint32(js, self, 2); }
JSValue js_array_set_b(JSContext *js, JSValue self, JSValue val)
{ JS_SetPropertyUint32(js, self, 2, val); return JS_NULL; }
JSValue js_array_get_a(JSContext *js, JSValue self)
{ return JS_GetPropertyUint32(js, self, 3); }
JSValue js_array_set_a(JSContext *js, JSValue self, JSValue val)
{ JS_SetPropertyUint32(js, self, 3, val); return JS_NULL; }
// Multi-value accessors
static const JSCFunctionListEntry js_array_funcs[] = {
PROTO_FUNC_DEF(array, add, 1),
PROTO_FUNC_DEF(array, sub, 1),
PROTO_FUNC_DEF(array, div,1),
PROTO_FUNC_DEF(array, scale, 1),
PROTO_FUNC_DEF(array, lerp, 2),
JS_CGETSET_DEF("x", js_array_get_x,js_array_set_x),
JS_CGETSET_DEF("y", js_array_get_y, js_array_set_y),
JS_CGETSET_DEF("r", js_array_get_r, js_array_set_r),
JS_CGETSET_DEF("g", js_array_get_g, js_array_set_g),
JS_CGETSET_DEF("b", js_array_get_b, js_array_set_b),
JS_CGETSET_DEF("a", js_array_get_a, js_array_set_a),
};
JSC_CCALL(number_lerp,
double a = js2number(js,self);
double b = js2number(js,argv[0]);
double t = js2number(js,argv[1]);
return number2js(js, (b-a)*t+a);
)
static const JSCFunctionListEntry js_number_funcs[] = {
PROTO_FUNC_DEF(number, lerp, 2),
};
static uint32_t rng_state = 123456789;
static uint32_t xorshift32(){
uint32_t x = rng_state;
@@ -601,73 +199,10 @@ JSC_CCALL(os_srand,
m_seedRand(mrand, js2number(js,argv[0]));
)
JSC_CCALL(os_make_line_prim,
return JS_NULL;
/*
JSValue prim = JS_NewObject(js);
HMM_Vec2 *v = js2cpvec2arr(js,argv[0]);
parsl_context *par_ctx = parsl_create_context((parsl_config){
.thickness = js2number(js,argv[1]),
.flags= PARSL_FLAG_ANNOTATIONS,
.u_mode = js2number(js,argv[2])
});
uint16_t spine_lens[] = {arrlen(v)};
parsl_mesh *m = parsl_mesh_from_lines(par_ctx, (parsl_spine_list){
.num_vertices = arrlen(v),
.num_spines = 1,
.vertices = v,
.spine_lengths = spine_lens,
.closed = JS_ToBool(js,argv[3])
});
JS_SetPropertyStr(js, prim, "pos", make_gpu_buffer(js,m->positions,sizeof(*m->positions)*m->num_vertices, 0, 2,1,0));
JS_SetPropertyStr(js, prim, "indices", make_gpu_buffer(js,m->triangle_indices,sizeof(*m->triangle_indices)*m->num_triangles*3, JS_TYPED_ARRAY_UINT32, 1,1,1));
float uv[m->num_vertices*2];
for (int i = 0; i < m->num_vertices; i++) {
uv[i*2] = m->annotations[i].u_along_curve;
uv[i*2+1] = m->annotations[i].v_across_curve;
}
JS_SetPropertyStr(js, prim, "uv", make_gpu_buffer(js, uv, sizeof(uv), 0,2,1,0));
JS_SetPropertyStr(js,prim,"vertices", number2js(js,m->num_vertices));
JS_SetPropertyStr(js,prim,"num_indices", number2js(js,m->num_triangles*3));
JS_SetPropertyStr(js,prim,"first_index", number2js(js,0));
parsl_destroy_context(par_ctx);
return prim;
*/
)
static const JSCFunctionListEntry js_util_funcs[] = {
MIST_FUNC_DEF(os, guid, 0),
};
JSC_CCALL(graphics_hsl_to_rgb,
float h, s, l;
JS_ToFloat64(js, &h, argv[0]);
JS_ToFloat64(js, &s, argv[1]);
JS_ToFloat64(js, &l, argv[2]);
float c = (1 - abs(2 * l - 1)) * s;
float x = c * (1 - abs(fmod((h/60),2) - 1));
float m = l - c / 2;
float r = 0, g = 0, b = 0;
if (h < 60) { r = c; g = x; }
else if (h < 120) { r = x; g = c; }
else if (h < 180) { g = c; b = x; }
else if (h < 240) { g = x; b = c; }
else if (h < 300) { r = x; b = c; }
else { r = c; b = x; }
return color2js(js, (colorf){r+m, g+m, b+m, 1});
)
static void *get_main_module_handle() {
#if defined(_WIN32)
return GetModuleHandle(NULL);
@@ -803,18 +338,6 @@ void ffi_load(JSContext *js)
JSValue prosp = JS_NewObject(js);
JS_SetPropertyStr(js,globalThis,"prosperon", prosp);
JSValue jsarray = JS_GetPropertyStr(js,globalThis, "Array");
JSValue array_proto = JS_GetPropertyStr(js,jsarray, "prototype");
JS_SetPropertyFunctionList(js, array_proto, js_array_funcs, countof(js_array_funcs));
JS_FreeValue(js,jsarray);
JS_FreeValue(js,array_proto);
JSValue jsnumber = JS_GetPropertyStr(js,globalThis, "Number");
JSValue number_proto = JS_GetPropertyStr(js,jsnumber, "prototype");
JS_SetPropertyFunctionList(js, number_proto, js_number_funcs, countof(js_number_funcs));
JS_FreeValue(js,jsnumber);
JS_FreeValue(js,number_proto);
JSValue hidden_fn = JS_NewObject(js);
// Add functions that should only be accessible to engine.js

View File

@@ -2,102 +2,7 @@
#define FFI_H
#include "cell.h"
#include "HandmadeMath.h"
#include "render.h"
#define JS_SetProperty(js, tar, str, val) JS_SetPropertyStr(js, tar, #str, val)
#define JS_GetProperty(js, tar, atom) JS_GetPropertyStr(js, tar, #atom)
// Core FFI functions
void ffi_load(JSContext *js);
int js_print_exception(JSContext *js, JSValue v);
// Global trace flag
extern int trace;
// Common type definitions - rect and colorf are defined in render.h
// Common conversion functions used across modules
JSValue rect2js(JSContext *js, rect r);
JSValue vec22js(JSContext *js, HMM_Vec2 v);
JSValue vec32js(JSContext *js, HMM_Vec3 v);
JSValue vec42js(JSContext *js, HMM_Vec4 v);
JSValue quat2js(JSContext *js, HMM_Quat q);
JSValue color2js(JSContext *js, colorf c);
JSValue number2js(JSContext *js, double d);
JSValue angle2js(JSContext *js, double a);
rect js2rect(JSContext *js, JSValue v);
HMM_Vec2 js2vec2(JSContext *js, JSValue v);
HMM_Vec3 js2vec3(JSContext *js, JSValue v);
HMM_Vec4 js2vec4(JSContext *js, JSValue v);
HMM_Quat js2quat(JSContext *js, JSValue v);
colorf js2color(JSContext *js, JSValue v);
double js2number(JSContext *js, JSValue v);
double js2angle(JSContext *js, JSValue v);
// Forward declaration for MTRand from prosperon.h
typedef struct tagMTRand MTRand;
// Random number generation functions
double genRand(MTRand *mrand);
int64_t genRandLong(MTRand *mrand);
void m_seedRand(MTRand *mrand, uint64_t seed);
double rand_range(JSContext *js, double min, double max);
// Common data structures
struct lrtb {
float l;
float r;
float t;
float b;
};
typedef struct lrtb lrtb;
typedef struct text_vert text_vert;
// Common macros for property access
#define JS_GETPROP(JS, TARGET, VALUE, PROP, TYPE) {\
JSValue __##PROP##__v = JS_GetPropertyStr(JS,VALUE,#PROP); \
TARGET = js2##TYPE(JS, __##PROP##__v); \
JS_FreeValue(JS,__##PROP##__v); }\
#define JS_GETATOM(JS, TARGET, VALUE, ATOM, TYPE) {\
JSValue __##PROP##__v = JS_GetPropertyStr(JS,VALUE,#ATOM); \
TARGET = js2##TYPE(JS, __##PROP##__v); \
JS_FreeValue(JS,__##PROP##__v); }\
// Common conversion functions
lrtb js2lrtb(JSContext *js, JSValue v);
int js2bool(JSContext *js, JSValue v);
JSValue make_gpu_buffer(JSContext *js, void *data, size_t size, int type, int elements, int copy, int index);
JSValue make_quad_indices_buffer(JSContext *js, int quads);
// SDL type conversion functions
SDL_Window *js2SDL_Window(JSContext *js, JSValue v);
JSValue SDL_Window2js(JSContext *js, SDL_Window *w);
// X-macro enum definition system for string<->enum conversion
#define ENUM_MAPPING_TABLE(ENUM) \
static const struct { int value; const char *name; } ENUM##_mapping[]
#define JS2ENUM(NAME) \
int js2##NAME(JSContext *js, JSValue v) { \
if (JS_IsNull(v)) return 0; \
const char *str = JS_ToCString(js, v); \
if (!str) return 0; \
for(int i = 0; i < sizeof(NAME##_mapping)/sizeof(NAME##_mapping[0]); i++) \
if(!strcmp(NAME##_mapping[i].name, str)) { \
JS_FreeCString(js, str); \
return NAME##_mapping[i].value; \
} \
JS_FreeCString(js, str); \
return 0; \
} \
JSValue NAME##2js(JSContext *js, int enumval) { \
for(int i = 0; i < sizeof(NAME##_mapping)/sizeof(NAME##_mapping[0]); i++) \
if(NAME##_mapping[i].value == enumval) \
return JS_NewString(js, NAME##_mapping[i].name); \
return JS_NULL; \
}
#endif

View File

@@ -1,5 +1,4 @@
#include "qjs_actor.h"
#include "jsffi.h"
#include "qjs_macros.h"
#include "qjs_wota.h"
#include "cell.h"

View File

@@ -1,5 +1,5 @@
#include "cell.h"
#include "qjs_macros.h"
#include "jsffi.h"
JSC_CCALL(debug_stack_depth, return number2js(js,js_debugger_stack_depth(js)))
JSC_CCALL(debug_build_backtrace, return js_debugger_build_backtrace(js,NULL))

View File

@@ -1,5 +1,4 @@
#include "cell.h"
#include "jsffi.h"
#include <fcntl.h>
#include <sys/stat.h>

View File

@@ -1,4 +1,4 @@
#include "jsffi.h"
#include "cell.h"
#include <stdint.h>
#include <limits.h>

View File

@@ -1,4 +1,3 @@
#include "jsffi.h"
#include "cell.h"
JSC_CCALL(os_gc, JS_RunGC(JS_GetRuntime(js)) )

View File

@@ -1,5 +1,4 @@
#include "cell.h"
#include "jsffi.h"
#include <string.h>
#include <stdlib.h>

View File

@@ -158,3 +158,43 @@ JS_SetClassProto(js, js_##TYPE##_id, TYPE##_proto); \
#define countof(x) (sizeof(x)/sizeof((x)[0]))
// Common macros for property access
#define JS_GETPROP(JS, TARGET, VALUE, PROP, TYPE) {\
JSValue __##PROP##__v = JS_GetPropertyStr(JS,VALUE,#PROP); \
TARGET = js2##TYPE(JS, __##PROP##__v); \
JS_FreeValue(JS,__##PROP##__v); }\
#define JS_GETATOM(JS, TARGET, VALUE, ATOM, TYPE) {\
JSValue __##PROP##__v = JS_GetPropertyStr(JS,VALUE,#ATOM); \
TARGET = js2##TYPE(JS, __##PROP##__v); \
JS_FreeValue(JS,__##PROP##__v); }\
// X-macro enum definition system for string<->enum conversion
#define ENUM_MAPPING_TABLE(ENUM) \
static const struct { int value; const char *name; } ENUM##_mapping[]
#define JS2ENUM(NAME) \
int js2##NAME(JSContext *js, JSValue v) { \
if (JS_IsNull(v)) return 0; \
const char *str = JS_ToCString(js, v); \
if (!str) return 0; \
for(int i = 0; i < sizeof(NAME##_mapping)/sizeof(NAME##_mapping[0]); i++) \
if(!strcmp(NAME##_mapping[i].name, str)) { \
JS_FreeCString(js, str); \
return NAME##_mapping[i].value; \
} \
JS_FreeCString(js, str); \
return 0; \
} \
JSValue NAME##2js(JSContext *js, int enumval) { \
for(int i = 0; i < sizeof(NAME##_mapping)/sizeof(NAME##_mapping[0]); i++) \
if(NAME##_mapping[i].value == enumval) \
return JS_NewString(js, NAME##_mapping[i].name); \
return JS_NULL; \
}
#define CELL_USE_FUNCS(FUNCS) \
JSValue CELL_USE_NAME(JSContext *js) { \
JSValue mod = JS_NewObject(js); \
JS_SetPropertyFunctionList(js, mod, FUNCS, countof(FUNCS)); \
return mod; }

View File

@@ -1,491 +0,0 @@
#include "jsffi.h"
#include "qjs_macros.h"
#include <math.h>
#include <stdlib.h>
#include "HandmadeMath.h"
#include "cell.h"
// Utility function to get number from array index
static double js_getnum_uint32(JSContext *js, JSValue v, unsigned int i)
{
JSValue val = JS_GetPropertyUint32(js,v,i);
double ret = js2number(js, val);
JS_FreeValue(js,val);
return ret;
}
// Convert JS array to float array
static float *js2floats(JSContext *js, JSValue v, size_t *len)
{
*len = JS_ArrayLength(js,v);
float *arr = malloc(sizeof(float)* *len);
for (int i = 0; i < *len; i++)
arr[i] = js_getnum_uint32(js,v,i);
return arr;
}
// Convert float array to JS array
static JSValue floats2array(JSContext *js, float *vals, size_t len) {
JSValue arr = JS_NewArray(js);
for (size_t i = 0; i < len; i++) {
JS_SetPropertyUint32(js, arr, i, number2js(js, vals[i]));
}
return arr;
}
// Calculate vector length
static double arr_vec_length(JSContext *js,JSValue v)
{
int len = JS_ArrayLength(js,v);
switch(len) {
case 2: return HMM_LenV2(js2vec2(js,v));
case 3: return HMM_LenV3(js2vec3(js,v));
case 4: return HMM_LenV4(js2vec4(js,v));
}
double sum = 0;
for (int i = 0; i < len; i++)
sum += pow(js_getnum_uint32(js, v, i), 2);
return sqrt(sum);
}
// GCD helper function
static int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
// MATH FUNCTIONS
JSC_CCALL(math_rotate,
HMM_Vec2 vec = js2vec2(js,argv[0]);
double angle = js2angle(js, argv[1]);
HMM_Vec2 pivot = JS_IsNull(argv[2]) ? v2zero : js2vec2(js,argv[2]);
vec = HMM_SubV2(vec,pivot);
float r = HMM_LenV2(vec);
angle += atan2f(vec.y, vec.x);
vec.x = r * cosf(angle);
vec.y = r * sinf(angle);
vec = HMM_AddV2(vec,pivot);
return vec22js(js, vec);
)
JSC_CCALL(math_norm,
int len = JS_ArrayLength(js,argv[0]);
switch(len) {
case 2: return vec22js(js,HMM_NormV2(js2vec2(js,argv[0])));
case 3: return vec32js(js, HMM_NormV3(js2vec3(js,argv[0])));
case 4: return vec42js(js,HMM_NormV4(js2vec4(js,argv[0])));
}
double length = arr_vec_length(js,argv[0]);
JSValue newarr = JS_NewArray(js);
for (int i = 0; i < len; i++)
JS_SetPropertyUint32(js, newarr, i, number2js(js,js_getnum_uint32(js, argv[0],i)/length));
ret = newarr;
)
JSC_CCALL(math_angle_between,
int len = JS_ArrayLength(js,argv[0]);
switch(len) {
case 2: return angle2js(js,HMM_AngleV2(js2vec2(js,argv[0]), js2vec2(js,argv[1])));
case 3: return angle2js(js,HMM_AngleV3(js2vec3(js,argv[0]), js2vec3(js,argv[1])));
case 4: return angle2js(js,HMM_AngleV4(js2vec4(js,argv[0]), js2vec4(js,argv[1])));
}
return JS_ThrowReferenceError(js, "Input array must have a length between 2 and 4.");
)
JSC_CCALL(math_lerp,
double s = js2number(js,argv[0]);
double f = js2number(js,argv[1]);
double t = js2number(js,argv[2]);
ret = number2js(js,(f-s)*t+s);
)
JSC_CCALL(math_gcd, ret = number2js(js,gcd(js2number(js,argv[0]), js2number(js,argv[1]))); )
JSC_CCALL(math_lcm,
double a = js2number(js,argv[0]);
double b = js2number(js,argv[1]);
ret = number2js(js,(a*b)/gcd(a,b));
)
JSC_CCALL(math_clamp,
double x = js2number(js,argv[0]);
double l = js2number(js,argv[1]);
double h = js2number(js,argv[2]);
return number2js(js,x > h ? h : x < l ? l : x);
)
JSC_CCALL(math_angledist,
double a1 = js2number(js,argv[0]);
double a2 = js2number(js,argv[1]);
a1 = fmod(a1,1);
a2 = fmod(a2,1);
double dist = a2-a1;
if (dist == 0) return number2js(js,dist);
if (dist > 0) {
if (dist > 0.5) return number2js(js,dist-1);
return number2js(js,dist);
}
if (dist < -0.5) return number2js(js,dist+1);
return number2js(js,dist);
)
JSC_CCALL(math_jitter,
double n = js2number(js,argv[0]);
double pct = js2number(js,argv[1]);
return number2js(js,n + (rand_range(js,-pct,pct)*n));
)
JSC_CCALL(math_mean,
double len = JS_ArrayLength(js,argv[0]);
double sum = 0;
for (int i = 0; i < len; i++)
sum += js_getnum_uint32(js, argv[0], i);
return number2js(js,sum/len);
)
JSC_CCALL(math_sum,
double sum = 0.0;
int len = JS_ArrayLength(js,argv[0]);
for (int i = 0; i < len; i++)
sum += js_getnum_uint32(js, argv[0], i);
return number2js(js,sum);
)
JSC_CCALL(math_sigma,
int len = JS_ArrayLength(js,argv[0]);
double sum = 0;
for (int i = 0; i < len; i++)
sum += js_getnum_uint32(js, argv[0], i);
double mean = sum/(double)len;
sum = 0;
for (int i = 0; i < len; i++)
sum += pow(js_getnum_uint32(js, argv[0], i) - mean, 2);
return number2js(js,sqrt(sum/len));
)
JSC_CCALL(math_median,
int len = JS_ArrayLength(js,argv[0]);
double vals[len];
for (int i = 0; i < len; i++)
vals[i] = js_getnum_uint32(js, argv[0], i);
// Simple bubble sort for median calculation
for (int i = 0; i < len-1; i++) {
for (int j = 0; j < len-i-1; j++) {
if (vals[j] > vals[j+1]) {
double temp = vals[j];
vals[j] = vals[j+1];
vals[j+1] = temp;
}
}
}
if (len % 2 == 0)
return number2js(js,(vals[len/2-1] + vals[len/2]) / 2.0);
else
return number2js(js,vals[len/2]);
)
JSC_CCALL(math_length, return number2js(js,arr_vec_length(js,argv[0])); )
JSC_CCALL(math_from_to,
double start = js2number(js,argv[0]);
double end = js2number(js,argv[1]);
double step = js2number(js,argv[2]);
int inclusive = JS_ToBool(js,argv[3]);
int arr = JS_ToBool(js,argv[4]);
JSValue jsarr = JS_NewArray(js);
int i = 0;
for (double val = start; val <= end; val += step) {
if (val == end && !inclusive) break;
JS_SetPropertyUint32(js, jsarr, i++, number2js(js, val));
}
return jsarr;
)
JSC_CCALL(math_dot,
size_t alen, blen;
float *a = js2floats(js,argv[0], &alen);
float *b = js2floats(js,argv[1], &blen);
float dot = 0;
size_t len = alen < blen? alen : blen;
for (size_t i = 0; i < len; i++)
dot += a[i] * b[i];
free(a);
free(b);
return number2js(js,dot);
)
JSC_CCALL(math_project,
size_t alen, blen;
float *a = js2floats(js, argv[0], &alen);
float *b = js2floats(js, argv[1], &blen);
if (!a || !b) {
free(a);
free(b);
return JS_NULL;
}
// We'll work up to the smaller length
size_t len = (alen < blen) ? alen : blen;
if (len == 0) {
free(a);
free(b);
return JS_NULL;
}
// Compute dot products: a·b and b·b
float ab = 0, bb = 0;
for (size_t i = 0; i < len; i++) {
ab += a[i] * b[i];
bb += b[i] * b[i];
}
// Build the result array
float *proj = (float*)malloc(sizeof(float) * len);
if (!proj) {
free(a);
free(b);
return JS_EXCEPTION; // or some error
}
float scale = (bb != 0.0f) ? (ab / bb) : 0.0f;
for (size_t i = 0; i < len; i++)
proj[i] = scale * b[i];
ret = floats2array(js, proj, len);
free(a);
free(b);
free(proj);
)
JSC_CCALL(math_midpoint,
size_t alen, blen;
float *a = js2floats(js, argv[0], &alen);
float *b = js2floats(js, argv[1], &blen);
if (!a || !b) {
free(a);
free(b);
return JS_NULL;
}
size_t len = (alen < blen) ? alen : blen;
if (len == 0) {
free(a);
free(b);
return JS_NULL;
}
float *m = (float*)malloc(sizeof(float) * len);
if (!m) {
free(a);
free(b);
return JS_EXCEPTION;
}
for (size_t i = 0; i < len; i++)
m[i] = (a[i] + b[i]) * 0.5f;
ret = floats2array(js, m, len);
free(a);
free(b);
free(m);
)
JSC_CCALL(math_reflect,
size_t alen, blen;
float *a = js2floats(js, argv[0], &alen);
float *b = js2floats(js, argv[1], &blen);
if (!a || !b) {
free(a);
free(b);
return JS_NULL;
}
size_t len = (alen < blen) ? alen : blen;
if (len == 0) {
free(a);
free(b);
return JS_NULL;
}
// Reflect vector a across normal b
// reflection = a - 2 * (a·b) * b
float ab = 0, bb = 0;
for (size_t i = 0; i < len; i++) {
ab += a[i] * b[i];
bb += b[i] * b[i];
}
float *result = (float*)malloc(sizeof(float) * len);
if (!result) {
free(a);
free(b);
return JS_EXCEPTION;
}
float scale = (bb != 0.0f) ? (2.0f * ab / bb) : 0.0f;
for (size_t i = 0; i < len; i++)
result[i] = a[i] - scale * b[i];
ret = floats2array(js, result, len);
free(a);
free(b);
free(result);
)
JSC_CCALL(math_direction,
size_t alen, blen;
float *a = js2floats(js, argv[0], &alen);
float *b = js2floats(js, argv[1], &blen);
if (!a || !b) {
free(a);
free(b);
return JS_NULL;
}
size_t len = (alen < blen) ? alen : blen;
if (len == 0) {
free(a);
free(b);
return JS_NULL;
}
// Direction vector from a to b (normalized)
float *dir = (float*)malloc(sizeof(float) * len);
if (!dir) {
free(a);
free(b);
return JS_EXCEPTION;
}
float mag = 0;
for (size_t i = 0; i < len; i++) {
dir[i] = b[i] - a[i];
mag += dir[i] * dir[i];
}
mag = sqrtf(mag);
if (mag > 0.0f) {
for (size_t i = 0; i < len; i++)
dir[i] /= mag;
}
ret = floats2array(js, dir, len);
free(a);
free(b);
free(dir);
)
JSC_CCALL(math_angle,
size_t len;
float *v = js2floats(js, argv[0], &len);
if (!v || len < 2) {
free(v);
return JS_NULL;
}
// Return angle in radians for 2D vector
ret = number2js(js, atan2f(v[1], v[0]));
free(v);
)
JSC_CCALL(math_distance,
size_t alen, blen;
float *a = js2floats(js, argv[0], &alen);
float *b = js2floats(js, argv[1], &blen);
if (!a || !b) {
free(a);
free(b);
return JS_NULL;
}
size_t len = (alen < blen) ? alen : blen;
if (len == 0) {
free(a);
free(b);
return JS_NULL;
}
float distSq = 0.0f;
for (size_t i = 0; i < len; i++) {
float diff = b[i] - a[i];
distSq += diff * diff;
}
float dist = sqrtf(distSq);
free(a);
free(b);
return number2js(js, dist);
)
static const JSCFunctionListEntry js_math_funcs[] = {
MIST_FUNC_DEF(math, dot,2),
MIST_FUNC_DEF(math, project,2),
MIST_FUNC_DEF(math, rotate, 3),
MIST_FUNC_DEF(math, midpoint, 2),
MIST_FUNC_DEF(math, reflect, 2),
MIST_FUNC_DEF(math, distance, 2),
MIST_FUNC_DEF(math, direction, 2),
MIST_FUNC_DEF(math, angle, 1),
MIST_FUNC_DEF(math, norm, 1),
MIST_FUNC_DEF(math, angle_between, 2),
MIST_FUNC_DEF(math, lerp, 3),
MIST_FUNC_DEF(math, gcd, 2),
MIST_FUNC_DEF(math, lcm, 2),
MIST_FUNC_DEF(math, clamp, 3),
MIST_FUNC_DEF(math, angledist, 2),
MIST_FUNC_DEF(math, jitter, 2),
MIST_FUNC_DEF(math, mean, 1),
MIST_FUNC_DEF(math, sum, 1),
MIST_FUNC_DEF(math, sigma, 1),
MIST_FUNC_DEF(math, median, 1),
MIST_FUNC_DEF(math, length, 1),
MIST_FUNC_DEF(math, from_to, 5),
};
JSValue js_math_use(JSContext *js) {
JSValue mod = JS_NewObject(js);
JS_SetPropertyFunctionList(js,mod,js_math_funcs,countof(js_math_funcs));
return mod;
}

View File

@@ -1,6 +1,4 @@
#include "cell.h"
#include "jsffi.h"
#include "qjs_common.h"
#include <SDL3/SDL.h>
#include <sys/time.h>
@@ -271,6 +269,16 @@ JSC_CCALL(os_trace_message,
)
#endif
JSC_SCALL(os_system,
int err = system(str);
ret = number2js(js,err);
)
JSC_SCALL(os_exit,
printf("exit\n");
exit(0);
)
static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, platform, 0),
MIST_FUNC_DEF(os, arch, 0),
@@ -284,6 +292,8 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, mallinfo, 0),
MIST_FUNC_DEF(os, buffer2string, 1),
MIST_FUNC_DEF(os, frame, 0),
MIST_FUNC_DEF(os, system, 1),
MIST_FUNC_DEF(os, exit, 0),
};
JSValue js_os_use(JSContext *js) {

View File

@@ -1,6 +1,5 @@
#include "qop.h"
#include "cell.h"
#include "jsffi.h"
static JSClassID js_qop_archive_class_id;

View File

@@ -1,5 +1,4 @@
#include "cell.h"
#include "jsffi.h"
#ifdef _WIN32
#include <winsock2.h>

View File

@@ -35,30 +35,6 @@ static JSClassDef js_##TYPE##_class = { \
JS_FreeValue(js, tmp); \
} \
static double js2number(JSContext *js, JSValue v)
{
double ret;
JS_ToFloat64(js, &ret, v);
return ret;
}
static JSValue number2js(JSContext *js, double num)
{
return JS_NewFloat64(js, num);
}
static int js2bool(JSContext *js, JSValue v)
{
int b;
JS_ToInt32(js, &b, v);
return b;
}
static JSValue bool2js(JSContext *js, int b)
{
return JS_NewBool(js,b);
}
typedef unsigned int voice;
static Soloud *soloud;

View File

@@ -1,5 +1,4 @@
#include "cell.h"
#include "jsffi.h"
#include <string.h>
#include <stdlib.h>

View File

@@ -1,5 +1,5 @@
#include "cell.h"
#include "wildmatch.h"
#include "jsffi.h"
#include "qjs_macros.h"
JSC_CCALL(wildstar_match,

View File

@@ -1,3 +0,0 @@
@echo off
"%~dp0cell.exe" accio
pause