Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions examples/hello.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) Wasym A. Alonso. All Rights Reserved.

#include <carbon.h>

int main(void) {
carbon_println("Hello, World!");
return 0;
}
128 changes: 128 additions & 0 deletions src/carbon.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) Wasym A. Alonso. All Rights Reserved.

function make_env(...envs) {
return new Proxy(envs, {
get(target, prop, receiver) {
for (let env of envs) {
if (env.hasOwnProperty(prop)) return env[prop];
}
return (...args) => { throw new Error(`NOT IMPLEMENTED: ${prop} (${args})`); };
}
});
}

function cstr_len(buffer, ptr) {
const bytes = new Uint8Array(buffer);
let len = 0;
while (bytes[ptr]) {
++len;
++ptr;
}
return len;
}

function ptr_as_cstr(buffer, ptr) {
const bytes = new Uint8Array(buffer, ptr, cstr_len(buffer, ptr));
return new TextDecoder().decode(bytes);
}

function ptr_as_drawcanvas(buffer, ptr) {
/*
u32 *pixels; -> +0
usz width; -> +4
usz height; -> +8
usz stride; -> +12
*/
const view = new DataView(buffer);
const pixels_ptr = view.getUint32(ptr + 0, true);
const width = view.getUint32(ptr + 4, true);
const height = view.getUint32(ptr + 8, true);
const stride = view.getUint32(ptr + 12, true);
const pixels = new Uint32Array(buffer, pixels_ptr, width * height);
return { pixels, width, height, stride };
}

function todo() { throw new Error("NOT IMPLEMENTED"); }

export let wasm = null;
let max_fps = 60;

export async function load(wasm_file) {
let max_fps = null;
wasm = await WebAssembly.instantiateStreaming(fetch(wasm_file), {
env: make_env({
// char *carbon_string_fmt(const char *s, ...);
carbon_string_fmt: (s, ...args) => {
console.debug(s); // This is ptr in WASM memory where the string is located
const buffer = wasm.instance.exports.memory.buffer;
console.debug(ptr_as_cstr(buffer, s)); // This is the string itself
for (const arg of args) {
console.debug(arg);
console.debug(ptr_as_cstr(buffer, arg));
}
todo();
},

// void carbon_log_print(FILE *stream, const char *fmt, ...);
carbon_log_print: (stream, fmt, ...args) => {
console.log(fmt);
todo();
},

// void carbon_assert_abort(const char *expr, const char *file, u32 line, const char *func);
carbon_assert_abort: (expr, file, line, func) => {
todo();
},

carbon_win_open: carbon_win_open,
carbon_win_close: carbon_win_close,
carbon_win_shouldclose: carbon_win_shouldclose,
carbon_win_set_max_fps: carbon_win_set_max_fps,
carbon_win_get_deltatime: carbon_win_get_deltatime,
carbon_win_update: carbon_win_update
})
});
}

// void carbon_win_open(u16 width, u16 height, const char *title);
function carbon_win_open(width, height, title) {
const ctx = document.getElementById("app").getContext("2d");
const buffer = wasm.instance.exports.memory.buffer;
ctx.canvas.width = width;
ctx.canvas.height = height;
document.title = ptr_as_cstr(buffer, title);
}

// void carbon_win_close(void);
function carbon_win_close() {}

// u8 carbon_win_shouldclose(void);
function carbon_win_shouldclose() { return false; }

// void carbon_win_set_max_fps(u32 fps);
function carbon_win_set_max_fps(fps) { max_fps = fps; }

// f64 carbon_win_get_deltatime(void);
function carbon_win_get_deltatime() { return 1.0 / max_fps; }

// void carbon_win_update(CBN_DrawCanvas dc);
function carbon_win_update(dc) {
const ctx = document.getElementById("app").getContext("2d");
const buffer = wasm.instance.exports.memory.buffer;
const dc_obj = ptr_as_drawcanvas(buffer, dc);
const data = new Uint8ClampedArray(dc_obj.width * dc_obj.height * 4);
for (let i = 0; i < dc_obj.pixels.length; ++i) {
const color = dc_obj.pixels[i];
const r = (color >> 24) & 0xff;
const g = (color >> 16) & 0xff;
const b = (color >> 8) & 0xff;
const a = (color >> 0) & 0xff;
data[i * 4 + 0] = r;
data[i * 4 + 1] = g;
data[i * 4 + 2] = b;
data[i * 4 + 3] = a;
}
ctx.putImageData(new ImageData(data, dc_obj.stride), 0, 0);
todo(); // TODO: if remove this, it doesn't loop properly and crashes the whole thing...
}
17 changes: 17 additions & 0 deletions src/carbon_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@
#define CARBON_CPU_ARCH "amd64"
#elif defined(__aarch64__)
#define CARBON_CPU_ARCH "aarch64"
#elif defined(__wasm32__)
#define CARBON_CPU_ARCH "wasm32"
#else
#error CPU architecture is not supported
#endif
Expand All @@ -102,10 +104,13 @@
#define CARBON_TARGET_OS "windows-msvc"
#elif defined(_WIN32) && defined(__MINGW64__)
#define CARBON_TARGET_OS "windows-mingw"
#elif defined(__wasm__)
#define CARBON_TARGET_OS "web"
#else
#error Target OS is not supported
#endif

#if !defined(CARBON_C_COMPILER) || !defined(CARBON_CXX_COMPILER)
#if defined(__clang__)
#define CARBON_C_COMPILER "clang"
#define CARBON_CXX_COMPILER "clang++"
Expand All @@ -128,12 +133,24 @@
#define CARBON_CXX_COMPILER "c++"
#define CARBON_COMPILER_VERSION __VERSION__
#endif
#else
#define CARBON_COMPILER_VERSION __VERSION__
#endif

#ifdef __cplusplus
#define CARBON_COMPILER CARBON_CXX_COMPILER
#else
#define CARBON_COMPILER CARBON_C_COMPILER
#endif

#ifndef CARBON_AR_TOOL
#if defined(_WIN32) && defined(__MINGW64__)
#define CARBON_AR_TOOL "x86_64-w64-mingw32-ar"
#else
#define CARBON_AR_TOOL "ar"
#endif
#endif

#ifdef __cplusplus
namespace std {
template <typename T>
Expand Down
2 changes: 2 additions & 0 deletions src/carbon_deps.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef __wasm__
// Common
#include <time.h>
#include <ctype.h>
Expand Down Expand Up @@ -53,3 +54,4 @@
#include <optional>
#include <type_traits>
#endif
#endif // __wasm__
20 changes: 20 additions & 0 deletions src/carbon_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,26 @@ u8 carbon_fs_create_directories(const char *path) {
return true;
}

char *carbon_fs_get_curr_directory(void) {
static char dir[CARBON_FS_PATH_MAX_LEN];
carbon_memory_set(dir, 0, CARBON_FS_PATH_MAX_LEN);
#ifdef _WIN32
char *path = _getcwd(dir, CARBON_FS_PATH_MAX_LEN - 1);
#else
char *path = getcwd(dir, CARBON_FS_PATH_MAX_LEN - 1);
#endif
if (!path) {
carbon_log_error("unable to get the current directory");
return 0;
}
usz len = carbon_string_len(path);
if (len && len < CARBON_FS_PATH_MAX_LEN - 1 && path[len - 1] != '/') {
path[len] = '/';
path[len + 1] = 0;
}
return path;
}

char *carbon_fs_get_bin_directory(void) {
static char dir[CARBON_FS_PATH_MAX_LEN];
carbon_memory_set(dir, 0, CARBON_FS_PATH_MAX_LEN);
Expand Down
1 change: 1 addition & 0 deletions src/carbon_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ CARBON_API u8 carbon_fs_remove_all(const char *file);
CARBON_API u8 carbon_fs_change_directory(const char *path);
CARBON_API u8 carbon_fs_create_directory(const char *path);
CARBON_API u8 carbon_fs_create_directories(const char *path);
CARBON_API char *carbon_fs_get_curr_directory(void);
CARBON_API char *carbon_fs_get_bin_directory(void);
CARBON_API CBN_PatternMatchedFiles carbon_fs_pattern_match(const char *pattern);
CARBON_API u32 carbon_fs_get_file_size(const char *file);
Expand Down
4 changes: 4 additions & 0 deletions src/carbon_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

#include "carbon.inc"

#ifdef __wasm__
#include "../vendor/walloc/walloc.c"
#endif

void *carbon_memory_copy(void *dst, const void *src, usz n) {
u8 *d = (u8 *) dst;
const u8 *s = (const u8 *) src;
Expand Down
7 changes: 7 additions & 0 deletions src/carbon_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
#define CARBON_CALLOC(n, sz) calloc(n, sz)
#define CARBON_FREE(p) free(p)

#ifdef __wasm__
void *malloc(usz);
void *realloc(void *, usz);
void *calloc(usz, usz);
void free(void *);
#endif

/**
* @brief Copies a set of bytes from a memory area to another one.
* @param dst The destination memory area address.
Expand Down
11 changes: 10 additions & 1 deletion src/carbon_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ typedef signed short i16;
CARBON_STATIC_ASSERT(sizeof(u16) == 2 && sizeof(i16) == 2, "Expected u16/i16 to be 2 bytes");
typedef unsigned int u32;
typedef signed int i32;
typedef u32 uint;
CARBON_STATIC_ASSERT(sizeof(u32) == 4 && sizeof(i32) == 4, "Expected u32/i32 to be 4 bytes");
typedef unsigned long long u64;
typedef signed long long i64;
Expand All @@ -26,10 +27,18 @@ CARBON_STATIC_ASSERT(sizeof(f32) == 4, "Expected f32 to be 4 bytes");
typedef double f64;
CARBON_STATIC_ASSERT(sizeof(f64) == 8, "Expected f64 to be 8 bytes");

typedef u32 uint;
#ifdef __wasm32__
typedef __SIZE_TYPE__ usz;
typedef signed long isz;
typedef __UINTPTR_TYPE__ uptr;
typedef struct {} FILE;
extern FILE *stdout;
extern FILE *stderr;
#else
typedef size_t usz;
typedef ssize_t isz;
typedef uintptr_t uptr;
#endif

#ifdef __cplusplus
template <typename T>
Expand Down
Loading