diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f106f2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +build/ +runtime/ +shaderc +hello-bgfx +include/generated/ +.DS_Store \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..38c2313 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "files.associations": { + "sdl.h": "c", + "vs.sc.mtl.bin.h": "c", + "embedded_shader.h": "c" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..77635b5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,80 @@ +cmake_minimum_required(VERSION 3.1) +project(hello-bgfx) + +# set(BGFX_AMALGAMATED OFF CACHE INTERNAL "" FORCE) +# set(BGFX_BUILD_EXAMPLES OFF CACHE INTERNAL "" FORCE) +set(BGFX_CONFIG_DEBUG OFF CACHE INTERNAL "" FORCE) +set(BX_CONFIG_DEBUG OFF CACHE INTERNAL "" FORCE) +# set(BGFX_CUSTOM_TARGETS OFF CACHE INTERNAL "" FORCE) +# set(BGFX_INSTALL OFF CACHE INTERNAL "" FORCE) +# set(BGFX_INSTALL_EXAMPLES OFF CACHE INTERNAL "" FORCE) +# set(BGFX_USE_DEBUG_SUFFIX OFF CACHE INTERNAL "" FORCE) +# set(BGFX_USE_OVR OFF CACHE INTERNAL "" FORCE) +# set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "" FORCE) +# set(BX_AMALGAMATED OFF CACHE INTERNAL "" FORCE) +# if (HELLO_BGFX_BUILD_SHADERS) +# set(BGFX_BUILD_TOOLS ON CACHE INTERNAL "" FORCE) +# else() +# set(BGFX_BUILD_TOOLS OFF CACHE INTERNAL "" FORCE) +# endif() +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/bgfx.cmake) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/SDL) + +# add quickjs +set(quickjs_version 2021-03-27) +set(quickjs_sources_root ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/quickjs) +set(quickjs_sources + ${quickjs_sources_root}/quickjs.h + ${quickjs_sources_root}/quickjs-libc.h + ${quickjs_sources_root}/quickjs.c + ${quickjs_sources_root}/libregexp.c + ${quickjs_sources_root}/libunicode.c + ${quickjs_sources_root}/libbf.c + ${quickjs_sources_root}/cutils.c + ${quickjs_sources_root}/quickjs-libc.c +) +add_library(quickjs STATIC + ${quickjs_sources} +) +target_compile_definitions(quickjs + PRIVATE + CONFIG_VERSION="${quickjs_version}" +) +target_include_directories(quickjs + PRIVATE + ${quickjs_sources_root} +) + + +# Note: This was necessary to avoid a run-time error on macOS/OpenGL. Without +# this option, the NSOpenGLViewContext's setView method was called from a +# wrong (?) thread during bgfx::init and then the app crashes. This needs to be +# investigated further. +#target_compile_definitions(bgfx PUBLIC BGFX_CONFIG_MULTITHREADED=0) + +# workaraound to resolve shaderc +if (NOT TARGET bgfx::shaderc AND TARGET shaderc) + add_executable(bgfx::shaderc ALIAS shaderc) +endif() + +bgfx_compile_shader_to_header( + TYPE VERTEX + SHADERS ${CMAKE_CURRENT_SOURCE_DIR}/shaders/vs.sc + VARYING_DEF ${CMAKE_CURRENT_SOURCE_DIR}/shaders/varying.def.sc + OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include/generated/shaders +) +bgfx_compile_shader_to_header( + TYPE FRAGMENT + SHADERS ${CMAKE_CURRENT_SOURCE_DIR}/shaders/fs.sc + VARYING_DEF ${CMAKE_CURRENT_SOURCE_DIR}/shaders/varying.def.sc + OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include/generated/shaders +) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +file(GLOB files src/*.cpp) +add_executable(hello-bgfx ${files} shaders/vs.sc shaders/fs.sc shaders/varying.def.sc) + +#target_include_directories(hello-bgfx PRIVATE ${quickjs_sources_root}) +target_include_directories(hello-bgfx PRIVATE include) +target_include_directories(hello-bgfx PRIVATE src) +target_link_libraries(hello-bgfx bgfx bx SDL2-static quickjs) \ No newline at end of file diff --git a/include/quickjs-libc.h b/include/quickjs-libc.h new file mode 100644 index 0000000..fbbe5b0 --- /dev/null +++ b/include/quickjs-libc.h @@ -0,0 +1,59 @@ +/* + * QuickJS C library + * + * Copyright (c) 2017-2018 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef QUICKJS_LIBC_H +#define QUICKJS_LIBC_H + +#include +#include + +#include "quickjs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name); +JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name); +void js_std_add_helpers(JSContext *ctx, int argc, char **argv); +void js_std_loop(JSContext *ctx); +void js_std_init_handlers(JSRuntime *rt); +void js_std_free_handlers(JSRuntime *rt); +void js_std_dump_error(JSContext *ctx); +uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename); +int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, + JS_BOOL use_realpath, JS_BOOL is_main); +JSModuleDef *js_module_loader(JSContext *ctx, + const char *module_name, void *opaque); +void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, + int flags); +void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, + JSValueConst reason, + JS_BOOL is_handled, void *opaque); +void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)); + +#ifdef __cplusplus +} /* extern "C" { */ +#endif + +#endif /* QUICKJS_LIBC_H */ diff --git a/include/quickjs.h b/include/quickjs.h new file mode 100644 index 0000000..d4a5cd3 --- /dev/null +++ b/include/quickjs.h @@ -0,0 +1,1049 @@ +/* + * QuickJS Javascript Engine + * + * Copyright (c) 2017-2021 Fabrice Bellard + * Copyright (c) 2017-2021 Charlie Gordon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef QUICKJS_H +#define QUICKJS_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define js_likely(x) __builtin_expect(!!(x), 1) +#define js_unlikely(x) __builtin_expect(!!(x), 0) +#define js_force_inline inline __attribute__((always_inline)) +#define __js_printf_like(f, a) __attribute__((format(printf, f, a))) +#else +#define js_likely(x) (x) +#define js_unlikely(x) (x) +#define js_force_inline inline +#define __js_printf_like(a, b) +#endif + +#define JS_BOOL int + +typedef struct JSRuntime JSRuntime; +typedef struct JSContext JSContext; +typedef struct JSObject JSObject; +typedef struct JSClass JSClass; +typedef uint32_t JSClassID; +typedef uint32_t JSAtom; + +#if INTPTR_MAX >= INT64_MAX +#define JS_PTR64 +#define JS_PTR64_DEF(a) a +#else +#define JS_PTR64_DEF(a) +#endif + +#ifndef JS_PTR64 +#define JS_NAN_BOXING +#endif + +enum { + /* all tags with a reference count are negative */ + JS_TAG_FIRST = -11, /* first negative tag */ + JS_TAG_BIG_DECIMAL = -11, + JS_TAG_BIG_INT = -10, + JS_TAG_BIG_FLOAT = -9, + JS_TAG_SYMBOL = -8, + JS_TAG_STRING = -7, + JS_TAG_MODULE = -3, /* used internally */ + JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */ + JS_TAG_OBJECT = -1, + + JS_TAG_INT = 0, + JS_TAG_BOOL = 1, + JS_TAG_NULL = 2, + JS_TAG_UNDEFINED = 3, + JS_TAG_UNINITIALIZED = 4, + JS_TAG_CATCH_OFFSET = 5, + JS_TAG_EXCEPTION = 6, + JS_TAG_FLOAT64 = 7, + /* any larger tag is FLOAT64 if JS_NAN_BOXING */ +}; + +typedef struct JSRefCountHeader { + int ref_count; +} JSRefCountHeader; + +#define JS_FLOAT64_NAN NAN + +#ifdef CONFIG_CHECK_JSVALUE +/* JSValue consistency : it is not possible to run the code in this + mode, but it is useful to detect simple reference counting + errors. It would be interesting to modify a static C analyzer to + handle specific annotations (clang has such annotations but only + for objective C) */ +typedef struct __JSValue *JSValue; +typedef const struct __JSValue *JSValueConst; + +#define JS_VALUE_GET_TAG(v) (int)((uintptr_t)(v) & 0xf) +/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ +#define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v) +#define JS_VALUE_GET_INT(v) (int)((intptr_t)(v) >> 4) +#define JS_VALUE_GET_BOOL(v) JS_VALUE_GET_INT(v) +#define JS_VALUE_GET_FLOAT64(v) (double)JS_VALUE_GET_INT(v) +#define JS_VALUE_GET_PTR(v) (void *)((intptr_t)(v) & ~0xf) + +#define JS_MKVAL(tag, val) (JSValue)(intptr_t)(((val) << 4) | (tag)) +#define JS_MKPTR(tag, p) (JSValue)((intptr_t)(p) | (tag)) + +#define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) + +#define JS_NAN JS_MKVAL(JS_TAG_FLOAT64, 1) + +static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) +{ + return JS_MKVAL(JS_TAG_FLOAT64, (int)d); +} + +static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) +{ + return 0; +} + +#elif defined(JS_NAN_BOXING) + +typedef uint64_t JSValue; + +#define JSValueConst JSValue + +#define JS_VALUE_GET_TAG(v) (int)((v) >> 32) +#define JS_VALUE_GET_INT(v) (int)(v) +#define JS_VALUE_GET_BOOL(v) (int)(v) +#define JS_VALUE_GET_PTR(v) (void *)(intptr_t)(v) + +#define JS_MKVAL(tag, val) (((uint64_t)(tag) << 32) | (uint32_t)(val)) +#define JS_MKPTR(tag, ptr) (((uint64_t)(tag) << 32) | (uintptr_t)(ptr)) + +#define JS_FLOAT64_TAG_ADDEND (0x7ff80000 - JS_TAG_FIRST + 1) /* quiet NaN encoding */ + +static inline double JS_VALUE_GET_FLOAT64(JSValue v) +{ + union { + JSValue v; + double d; + } u; + u.v = v; + u.v += (uint64_t)JS_FLOAT64_TAG_ADDEND << 32; + return u.d; +} + +#define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32)) + +static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) +{ + union { + double d; + uint64_t u64; + } u; + JSValue v; + u.d = d; + /* normalize NaN */ + if (js_unlikely((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000)) + v = JS_NAN; + else + v = u.u64 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32); + return v; +} + +#define JS_TAG_IS_FLOAT64(tag) ((unsigned)((tag) - JS_TAG_FIRST) >= (JS_TAG_FLOAT64 - JS_TAG_FIRST)) + +/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ +static inline int JS_VALUE_GET_NORM_TAG(JSValue v) +{ + uint32_t tag; + tag = JS_VALUE_GET_TAG(v); + if (JS_TAG_IS_FLOAT64(tag)) + return JS_TAG_FLOAT64; + else + return tag; +} + +static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) +{ + uint32_t tag; + tag = JS_VALUE_GET_TAG(v); + return tag == (JS_NAN >> 32); +} + +#else /* !JS_NAN_BOXING */ + +typedef union JSValueUnion { + int32_t int32; + double float64; + void *ptr; +} JSValueUnion; + +typedef struct JSValue { + JSValueUnion u; + int64_t tag; +} JSValue; + +#define JSValueConst JSValue + +#define JS_VALUE_GET_TAG(v) ((int32_t)(v).tag) +/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ +#define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v) +#define JS_VALUE_GET_INT(v) ((v).u.int32) +#define JS_VALUE_GET_BOOL(v) ((v).u.int32) +#define JS_VALUE_GET_FLOAT64(v) ((v).u.float64) +#define JS_VALUE_GET_PTR(v) ((v).u.ptr) + +#define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag } +#define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag } + +#define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) + +#define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 } + +static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) +{ + JSValue v; + v.tag = JS_TAG_FLOAT64; + v.u.float64 = d; + return v; +} + +static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) +{ + union { + double d; + uint64_t u64; + } u; + if (v.tag != JS_TAG_FLOAT64) + return 0; + u.d = v.u.float64; + return (u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000; +} + +#endif /* !JS_NAN_BOXING */ + +#define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0) +#define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2))) + +#define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v)) +#define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v)) +#define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST) + +/* special values */ +#define JS_NULL JS_MKVAL(JS_TAG_NULL, 0) +#define JS_UNDEFINED JS_MKVAL(JS_TAG_UNDEFINED, 0) +#define JS_FALSE JS_MKVAL(JS_TAG_BOOL, 0) +#define JS_TRUE JS_MKVAL(JS_TAG_BOOL, 1) +#define JS_EXCEPTION JS_MKVAL(JS_TAG_EXCEPTION, 0) +#define JS_UNINITIALIZED JS_MKVAL(JS_TAG_UNINITIALIZED, 0) + +/* flags for object properties */ +#define JS_PROP_CONFIGURABLE (1 << 0) +#define JS_PROP_WRITABLE (1 << 1) +#define JS_PROP_ENUMERABLE (1 << 2) +#define JS_PROP_C_W_E (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_ENUMERABLE) +#define JS_PROP_LENGTH (1 << 3) /* used internally in Arrays */ +#define JS_PROP_TMASK (3 << 4) /* mask for NORMAL, GETSET, VARREF, AUTOINIT */ +#define JS_PROP_NORMAL (0 << 4) +#define JS_PROP_GETSET (1 << 4) +#define JS_PROP_VARREF (2 << 4) /* used internally */ +#define JS_PROP_AUTOINIT (3 << 4) /* used internally */ + +/* flags for JS_DefineProperty */ +#define JS_PROP_HAS_SHIFT 8 +#define JS_PROP_HAS_CONFIGURABLE (1 << 8) +#define JS_PROP_HAS_WRITABLE (1 << 9) +#define JS_PROP_HAS_ENUMERABLE (1 << 10) +#define JS_PROP_HAS_GET (1 << 11) +#define JS_PROP_HAS_SET (1 << 12) +#define JS_PROP_HAS_VALUE (1 << 13) + +/* throw an exception if false would be returned + (JS_DefineProperty/JS_SetProperty) */ +#define JS_PROP_THROW (1 << 14) +/* throw an exception if false would be returned in strict mode + (JS_SetProperty) */ +#define JS_PROP_THROW_STRICT (1 << 15) + +#define JS_PROP_NO_ADD (1 << 16) /* internal use */ +#define JS_PROP_NO_EXOTIC (1 << 17) /* internal use */ + +#define JS_DEFAULT_STACK_SIZE (256 * 1024) + +/* JS_Eval() flags */ +#define JS_EVAL_TYPE_GLOBAL (0 << 0) /* global code (default) */ +#define JS_EVAL_TYPE_MODULE (1 << 0) /* module code */ +#define JS_EVAL_TYPE_DIRECT (2 << 0) /* direct call (internal use) */ +#define JS_EVAL_TYPE_INDIRECT (3 << 0) /* indirect call (internal use) */ +#define JS_EVAL_TYPE_MASK (3 << 0) + +#define JS_EVAL_FLAG_STRICT (1 << 3) /* force 'strict' mode */ +#define JS_EVAL_FLAG_STRIP (1 << 4) /* force 'strip' mode */ +/* compile but do not run. The result is an object with a + JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed + with JS_EvalFunction(). */ +#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5) +/* don't include the stack frames before this eval in the Error() backtraces */ +#define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6) + +typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); +typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); +typedef JSValue JSCFunctionData(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValue *func_data); + +typedef struct JSMallocState { + size_t malloc_count; + size_t malloc_size; + size_t malloc_limit; + void *opaque; /* user opaque */ +} JSMallocState; + +typedef struct JSMallocFunctions { + void *(*js_malloc)(JSMallocState *s, size_t size); + void (*js_free)(JSMallocState *s, void *ptr); + void *(*js_realloc)(JSMallocState *s, void *ptr, size_t size); + size_t (*js_malloc_usable_size)(const void *ptr); +} JSMallocFunctions; + +typedef struct JSGCObjectHeader JSGCObjectHeader; + +JSRuntime *JS_NewRuntime(void); +/* info lifetime must exceed that of rt */ +void JS_SetRuntimeInfo(JSRuntime *rt, const char *info); +void JS_SetMemoryLimit(JSRuntime *rt, size_t limit); +void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold); +/* use 0 to disable maximum stack size check */ +void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size); +/* should be called when changing thread to update the stack top value + used to check stack overflow. */ +void JS_UpdateStackTop(JSRuntime *rt); +JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque); +void JS_FreeRuntime(JSRuntime *rt); +void *JS_GetRuntimeOpaque(JSRuntime *rt); +void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque); +typedef void JS_MarkFunc(JSRuntime *rt, JSGCObjectHeader *gp); +void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); +void JS_RunGC(JSRuntime *rt); +JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj); + +JSContext *JS_NewContext(JSRuntime *rt); +void JS_FreeContext(JSContext *s); +JSContext *JS_DupContext(JSContext *ctx); +void *JS_GetContextOpaque(JSContext *ctx); +void JS_SetContextOpaque(JSContext *ctx, void *opaque); +JSRuntime *JS_GetRuntime(JSContext *ctx); +void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj); +JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id); + +/* the following functions are used to select the intrinsic object to + save memory */ +JSContext *JS_NewContextRaw(JSRuntime *rt); +void JS_AddIntrinsicBaseObjects(JSContext *ctx); +void JS_AddIntrinsicDate(JSContext *ctx); +void JS_AddIntrinsicEval(JSContext *ctx); +void JS_AddIntrinsicStringNormalize(JSContext *ctx); +void JS_AddIntrinsicRegExpCompiler(JSContext *ctx); +void JS_AddIntrinsicRegExp(JSContext *ctx); +void JS_AddIntrinsicJSON(JSContext *ctx); +void JS_AddIntrinsicProxy(JSContext *ctx); +void JS_AddIntrinsicMapSet(JSContext *ctx); +void JS_AddIntrinsicTypedArrays(JSContext *ctx); +void JS_AddIntrinsicPromise(JSContext *ctx); +void JS_AddIntrinsicBigInt(JSContext *ctx); +void JS_AddIntrinsicBigFloat(JSContext *ctx); +void JS_AddIntrinsicBigDecimal(JSContext *ctx); +/* enable operator overloading */ +void JS_AddIntrinsicOperators(JSContext *ctx); +/* enable "use math" */ +void JS_EnableBignumExt(JSContext *ctx, JS_BOOL enable); + +JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv); + +void *js_malloc_rt(JSRuntime *rt, size_t size); +void js_free_rt(JSRuntime *rt, void *ptr); +void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size); +size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr); +void *js_mallocz_rt(JSRuntime *rt, size_t size); + +void *js_malloc(JSContext *ctx, size_t size); +void js_free(JSContext *ctx, void *ptr); +void *js_realloc(JSContext *ctx, void *ptr, size_t size); +size_t js_malloc_usable_size(JSContext *ctx, const void *ptr); +void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack); +void *js_mallocz(JSContext *ctx, size_t size); +char *js_strdup(JSContext *ctx, const char *str); +char *js_strndup(JSContext *ctx, const char *s, size_t n); + +typedef struct JSMemoryUsage { + int64_t malloc_size, malloc_limit, memory_used_size; + int64_t malloc_count; + int64_t memory_used_count; + int64_t atom_count, atom_size; + int64_t str_count, str_size; + int64_t obj_count, obj_size; + int64_t prop_count, prop_size; + int64_t shape_count, shape_size; + int64_t js_func_count, js_func_size, js_func_code_size; + int64_t js_func_pc2line_count, js_func_pc2line_size; + int64_t c_func_count, array_count; + int64_t fast_array_count, fast_array_elements; + int64_t binary_object_count, binary_object_size; +} JSMemoryUsage; + +void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s); +void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt); + +/* atom support */ +#define JS_ATOM_NULL 0 + +JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len); +JSAtom JS_NewAtom(JSContext *ctx, const char *str); +JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n); +JSAtom JS_DupAtom(JSContext *ctx, JSAtom v); +void JS_FreeAtom(JSContext *ctx, JSAtom v); +void JS_FreeAtomRT(JSRuntime *rt, JSAtom v); +JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom); +JSValue JS_AtomToString(JSContext *ctx, JSAtom atom); +const char *JS_AtomToCString(JSContext *ctx, JSAtom atom); +JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val); + +/* object class support */ + +typedef struct JSPropertyEnum { + JS_BOOL is_enumerable; + JSAtom atom; +} JSPropertyEnum; + +typedef struct JSPropertyDescriptor { + int flags; + JSValue value; + JSValue getter; + JSValue setter; +} JSPropertyDescriptor; + +typedef struct JSClassExoticMethods { + /* Return -1 if exception (can only happen in case of Proxy object), + FALSE if the property does not exists, TRUE if it exists. If 1 is + returned, the property descriptor 'desc' is filled if != NULL. */ + int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc, + JSValueConst obj, JSAtom prop); + /* '*ptab' should hold the '*plen' property keys. Return 0 if OK, + -1 if exception. The 'is_enumerable' field is ignored. + */ + int (*get_own_property_names)(JSContext *ctx, JSPropertyEnum **ptab, + uint32_t *plen, + JSValueConst obj); + /* return < 0 if exception, or TRUE/FALSE */ + int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop); + /* return < 0 if exception or TRUE/FALSE */ + int (*define_own_property)(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValueConst val, + JSValueConst getter, JSValueConst setter, + int flags); + /* The following methods can be emulated with the previous ones, + so they are usually not needed */ + /* return < 0 if exception or TRUE/FALSE */ + int (*has_property)(JSContext *ctx, JSValueConst obj, JSAtom atom); + JSValue (*get_property)(JSContext *ctx, JSValueConst obj, JSAtom atom, + JSValueConst receiver); + /* return < 0 if exception or TRUE/FALSE */ + int (*set_property)(JSContext *ctx, JSValueConst obj, JSAtom atom, + JSValueConst value, JSValueConst receiver, int flags); +} JSClassExoticMethods; + +typedef void JSClassFinalizer(JSRuntime *rt, JSValue val); +typedef void JSClassGCMark(JSRuntime *rt, JSValueConst val, + JS_MarkFunc *mark_func); +#define JS_CALL_FLAG_CONSTRUCTOR (1 << 0) +typedef JSValue JSClassCall(JSContext *ctx, JSValueConst func_obj, + JSValueConst this_val, int argc, JSValueConst *argv, + int flags); + +typedef struct JSClassDef { + const char *class_name; + JSClassFinalizer *finalizer; + JSClassGCMark *gc_mark; + /* if call != NULL, the object is a function. If (flags & + JS_CALL_FLAG_CONSTRUCTOR) != 0, the function is called as a + constructor. In this case, 'this_val' is new.target. A + constructor call only happens if the object constructor bit is + set (see JS_SetConstructorBit()). */ + JSClassCall *call; + /* XXX: suppress this indirection ? It is here only to save memory + because only a few classes need these methods */ + JSClassExoticMethods *exotic; +} JSClassDef; + +JSClassID JS_NewClassID(JSClassID *pclass_id); +int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def); +int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id); + +/* value handling */ + +static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_BOOL val) +{ + return JS_MKVAL(JS_TAG_BOOL, (val != 0)); +} + +static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val) +{ + return JS_MKVAL(JS_TAG_INT, val); +} + +static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val) +{ + return JS_MKVAL(JS_TAG_CATCH_OFFSET, val); +} + +static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val) +{ + JSValue v; + if (val == (int32_t)val) { + v = JS_NewInt32(ctx, val); + } else { + v = __JS_NewFloat64(ctx, val); + } + return v; +} + +static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val) +{ + JSValue v; + if (val <= 0x7fffffff) { + v = JS_NewInt32(ctx, val); + } else { + v = __JS_NewFloat64(ctx, val); + } + return v; +} + +JSValue JS_NewBigInt64(JSContext *ctx, int64_t v); +JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v); + +static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double d) +{ + JSValue v; + int32_t val; + union { + double d; + uint64_t u; + } u, t; + u.d = d; + val = (int32_t)d; + t.d = val; + /* -0 cannot be represented as integer, so we compare the bit + representation */ + if (u.u == t.u) { + v = JS_MKVAL(JS_TAG_INT, val); + } else { + v = __JS_NewFloat64(ctx, d); + } + return v; +} + +static inline JS_BOOL JS_IsNumber(JSValueConst v) +{ + int tag = JS_VALUE_GET_TAG(v); + return tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag); +} + +static inline JS_BOOL JS_IsBigInt(JSContext *ctx, JSValueConst v) +{ + int tag = JS_VALUE_GET_TAG(v); + return tag == JS_TAG_BIG_INT; +} + +static inline JS_BOOL JS_IsBigFloat(JSValueConst v) +{ + int tag = JS_VALUE_GET_TAG(v); + return tag == JS_TAG_BIG_FLOAT; +} + +static inline JS_BOOL JS_IsBigDecimal(JSValueConst v) +{ + int tag = JS_VALUE_GET_TAG(v); + return tag == JS_TAG_BIG_DECIMAL; +} + +static inline JS_BOOL JS_IsBool(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL; +} + +static inline JS_BOOL JS_IsNull(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_NULL; +} + +static inline JS_BOOL JS_IsUndefined(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_UNDEFINED; +} + +static inline JS_BOOL JS_IsException(JSValueConst v) +{ + return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION); +} + +static inline JS_BOOL JS_IsUninitialized(JSValueConst v) +{ + return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED); +} + +static inline JS_BOOL JS_IsString(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_STRING; +} + +static inline JS_BOOL JS_IsSymbol(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL; +} + +static inline JS_BOOL JS_IsObject(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT; +} + +JSValue JS_Throw(JSContext *ctx, JSValue obj); +JSValue JS_GetException(JSContext *ctx); +JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val); +void JS_ResetUncatchableError(JSContext *ctx); +JSValue JS_NewError(JSContext *ctx); +JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...); +JSValue __js_printf_like(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...); +JSValue __js_printf_like(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...); +JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...); +JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...); +JSValue JS_ThrowOutOfMemory(JSContext *ctx); + +void __JS_FreeValue(JSContext *ctx, JSValue v); +static inline void JS_FreeValue(JSContext *ctx, JSValue v) +{ + if (JS_VALUE_HAS_REF_COUNT(v)) { + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + if (--p->ref_count <= 0) { + __JS_FreeValue(ctx, v); + } + } +} +void __JS_FreeValueRT(JSRuntime *rt, JSValue v); +static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v) +{ + if (JS_VALUE_HAS_REF_COUNT(v)) { + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + if (--p->ref_count <= 0) { + __JS_FreeValueRT(rt, v); + } + } +} + +static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v) +{ + if (JS_VALUE_HAS_REF_COUNT(v)) { + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + p->ref_count++; + } + return (JSValue)v; +} + +static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v) +{ + if (JS_VALUE_HAS_REF_COUNT(v)) { + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + p->ref_count++; + } + return (JSValue)v; +} + +int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */ +int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val); +static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val) +{ + return JS_ToInt32(ctx, (int32_t*)pres, val); +} +int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val); +int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val); +int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val); +/* return an exception if 'val' is a Number */ +int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val); +/* same as JS_ToInt64() but allow BigInt */ +int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val); + +JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1); +JSValue JS_NewString(JSContext *ctx, const char *str); +JSValue JS_NewAtomString(JSContext *ctx, const char *str); +JSValue JS_ToString(JSContext *ctx, JSValueConst val); +JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val); +const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, JS_BOOL cesu8); +static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValueConst val1) +{ + return JS_ToCStringLen2(ctx, plen, val1, 0); +} +static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1) +{ + return JS_ToCStringLen2(ctx, NULL, val1, 0); +} +void JS_FreeCString(JSContext *ctx, const char *ptr); + +JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto, JSClassID class_id); +JSValue JS_NewObjectClass(JSContext *ctx, int class_id); +JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto); +JSValue JS_NewObject(JSContext *ctx); + +JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val); +JS_BOOL JS_IsConstructor(JSContext* ctx, JSValueConst val); +JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val); + +JSValue JS_NewArray(JSContext *ctx); +int JS_IsArray(JSContext *ctx, JSValueConst val); + +JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, + JSAtom prop, JSValueConst receiver, + JS_BOOL throw_ref_error); +static js_force_inline JSValue JS_GetProperty(JSContext *ctx, JSValueConst this_obj, + JSAtom prop) +{ + return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, 0); +} +JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj, + const char *prop); +JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj, + uint32_t idx); + +int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValue val, + int flags); +static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValue val) +{ + return JS_SetPropertyInternal(ctx, this_obj, prop, val, JS_PROP_THROW); +} +int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj, + uint32_t idx, JSValue val); +int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, + int64_t idx, JSValue val); +int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, + const char *prop, JSValue val); +int JS_HasProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop); +int JS_IsExtensible(JSContext *ctx, JSValueConst obj); +int JS_PreventExtensions(JSContext *ctx, JSValueConst obj); +int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags); +int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val); +JSValue JS_GetPrototype(JSContext *ctx, JSValueConst val); + +#define JS_GPN_STRING_MASK (1 << 0) +#define JS_GPN_SYMBOL_MASK (1 << 1) +#define JS_GPN_PRIVATE_MASK (1 << 2) +/* only include the enumerable properties */ +#define JS_GPN_ENUM_ONLY (1 << 4) +/* set theJSPropertyEnum.is_enumerable field */ +#define JS_GPN_SET_ENUM (1 << 5) + +int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, + uint32_t *plen, JSValueConst obj, int flags); +int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, + JSValueConst obj, JSAtom prop); + +JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, + int argc, JSValueConst *argv); +JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom, + int argc, JSValueConst *argv); +JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj, + int argc, JSValueConst *argv); +JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj, + JSValueConst new_target, + int argc, JSValueConst *argv); +JS_BOOL JS_DetectModule(const char *input, size_t input_len); +/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */ +JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len, + const char *filename, int eval_flags); +/* same as JS_Eval() but with an explicit 'this_obj' parameter */ +JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj, + const char *input, size_t input_len, + const char *filename, int eval_flags); +JSValue JS_GetGlobalObject(JSContext *ctx); +int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj); +int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValueConst val, + JSValueConst getter, JSValueConst setter, int flags); +int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValue val, int flags); +int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj, + uint32_t idx, JSValue val, int flags); +int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj, + const char *prop, JSValue val, int flags); +int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValue getter, JSValue setter, + int flags); +void JS_SetOpaque(JSValue obj, void *opaque); +void *JS_GetOpaque(JSValueConst obj, JSClassID class_id); +void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id); + +/* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */ +JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, + const char *filename); +#define JS_PARSE_JSON_EXT (1 << 0) /* allow extended JSON */ +JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len, + const char *filename, int flags); +JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, + JSValueConst replacer, JSValueConst space0); + +typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr); +JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, + JSFreeArrayBufferDataFunc *free_func, void *opaque, + JS_BOOL is_shared); +JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len); +void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj); +uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj); +JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, + size_t *pbyte_offset, + size_t *pbyte_length, + size_t *pbytes_per_element); +typedef struct { + void *(*sab_alloc)(void *opaque, size_t size); + void (*sab_free)(void *opaque, void *ptr); + void (*sab_dup)(void *opaque, void *ptr); + void *sab_opaque; +} JSSharedArrayBufferFunctions; +void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, + const JSSharedArrayBufferFunctions *sf); + +JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs); + +/* is_handled = TRUE means that the rejection is handled */ +typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValueConst promise, + JSValueConst reason, + JS_BOOL is_handled, void *opaque); +void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque); + +/* return != 0 if the JS code needs to be interrupted */ +typedef int JSInterruptHandler(JSRuntime *rt, void *opaque); +void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque); +/* if can_block is TRUE, Atomics.wait() can be used */ +void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block); +/* set the [IsHTMLDDA] internal slot */ +void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj); + +typedef struct JSModuleDef JSModuleDef; + +/* return the module specifier (allocated with js_malloc()) or NULL if + exception */ +typedef char *JSModuleNormalizeFunc(JSContext *ctx, + const char *module_base_name, + const char *module_name, void *opaque); +typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx, + const char *module_name, void *opaque); + +/* module_normalize = NULL is allowed and invokes the default module + filename normalizer */ +void JS_SetModuleLoaderFunc(JSRuntime *rt, + JSModuleNormalizeFunc *module_normalize, + JSModuleLoaderFunc *module_loader, void *opaque); +/* return the import.meta object of a module */ +JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m); +JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m); + +/* JS Job support */ + +typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValueConst *argv); +int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValueConst *argv); + +JS_BOOL JS_IsJobPending(JSRuntime *rt); +int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx); + +/* Object Writer/Reader (currently only used to handle precompiled code) */ +#define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */ +#define JS_WRITE_OBJ_BSWAP (1 << 1) /* byte swapped output */ +#define JS_WRITE_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */ +#define JS_WRITE_OBJ_REFERENCE (1 << 3) /* allow object references to + encode arbitrary object + graph */ +uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj, + int flags); +uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, + int flags, uint8_t ***psab_tab, size_t *psab_tab_len); + +#define JS_READ_OBJ_BYTECODE (1 << 0) /* allow function/module */ +#define JS_READ_OBJ_ROM_DATA (1 << 1) /* avoid duplicating 'buf' data */ +#define JS_READ_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */ +#define JS_READ_OBJ_REFERENCE (1 << 3) /* allow object references */ +JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, + int flags); +/* instantiate and evaluate a bytecode function. Only used when + reading a script or module with JS_ReadObject() */ +JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj); +/* load the dependencies of the module 'obj'. Useful when JS_ReadObject() + returns a module. */ +int JS_ResolveModule(JSContext *ctx, JSValueConst obj); + +/* only exported for os.Worker() */ +JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels); +/* only exported for os.Worker() */ +JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename, + const char *filename); + +/* C function definition */ +typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */ + JS_CFUNC_generic, + JS_CFUNC_generic_magic, + JS_CFUNC_constructor, + JS_CFUNC_constructor_magic, + JS_CFUNC_constructor_or_func, + JS_CFUNC_constructor_or_func_magic, + JS_CFUNC_f_f, + JS_CFUNC_f_f_f, + JS_CFUNC_getter, + JS_CFUNC_setter, + JS_CFUNC_getter_magic, + JS_CFUNC_setter_magic, + JS_CFUNC_iterator_next, +} JSCFunctionEnum; + +typedef union JSCFunctionType { + JSCFunction *generic; + JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); + JSCFunction *constructor; + JSValue (*constructor_magic)(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic); + JSCFunction *constructor_or_func; + double (*f_f)(double); + double (*f_f_f)(double, double); + JSValue (*getter)(JSContext *ctx, JSValueConst this_val); + JSValue (*setter)(JSContext *ctx, JSValueConst this_val, JSValueConst val); + JSValue (*getter_magic)(JSContext *ctx, JSValueConst this_val, int magic); + JSValue (*setter_magic)(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic); + JSValue (*iterator_next)(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int *pdone, int magic); +} JSCFunctionType; + +JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, + const char *name, + int length, JSCFunctionEnum cproto, int magic); +JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, + int length, int magic, int data_len, + JSValueConst *data); + +static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name, + int length) +{ + return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0); +} + +static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func, + const char *name, + int length, JSCFunctionEnum cproto, int magic) +{ + return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic); +} +void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, + JSValueConst proto); + +/* C property definition */ + +typedef struct JSCFunctionListEntry { + const char *name; + uint8_t prop_flags; + uint8_t def_type; + int16_t magic; + union { + struct { + uint8_t length; /* XXX: should move outside union */ + uint8_t cproto; /* XXX: should move outside union */ + JSCFunctionType cfunc; + } func; + struct { + JSCFunctionType get; + JSCFunctionType set; + } getset; + struct { + const char *name; + int base; + } alias; + struct { + const struct JSCFunctionListEntry *tab; + int len; + } prop_list; + const char *str; + int32_t i32; + int64_t i64; + double f64; + } u; +} JSCFunctionListEntry; + +#define JS_DEF_CFUNC 0 +#define JS_DEF_CGETSET 1 +#define JS_DEF_CGETSET_MAGIC 2 +#define JS_DEF_PROP_STRING 3 +#define JS_DEF_PROP_INT32 4 +#define JS_DEF_PROP_INT64 5 +#define JS_DEF_PROP_DOUBLE 6 +#define JS_DEF_PROP_UNDEFINED 7 +#define JS_DEF_OBJECT 8 +#define JS_DEF_ALIAS 9 + +/* Note: c++ does not like nested designators */ +#define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } +#define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } } +#define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } } +#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } } +#define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, .u = { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } } +#define JS_CGETSET_MAGIC_DEF(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET_MAGIC, magic, .u = { .getset = { .get = { .getter_magic = fgetter }, .set = { .setter_magic = fsetter } } } } +#define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, .u = { .str = cstr } } +#define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, .u = { .i32 = val } } +#define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, .u = { .i64 = val } } +#define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, .u = { .f64 = val } } +#define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, .u = { .i32 = 0 } } +#define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, .u = { .prop_list = { tab, len } } } +#define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, -1 } } } +#define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, base } } } + +void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj, + const JSCFunctionListEntry *tab, + int len); + +/* C module definition */ + +typedef int JSModuleInitFunc(JSContext *ctx, JSModuleDef *m); + +JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str, + JSModuleInitFunc *func); +/* can only be called before the module is instantiated */ +int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str); +int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m, + const JSCFunctionListEntry *tab, int len); +/* can only be called after the module is instantiated */ +int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name, + JSValue val); +int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, + const JSCFunctionListEntry *tab, int len); + +#undef js_unlikely +#undef js_force_inline + +#ifdef __cplusplus +} /* extern "C" { */ +#endif + +#endif /* QUICKJS_H */ diff --git a/main.js b/main.js new file mode 100644 index 0000000..64f2d4a --- /dev/null +++ b/main.js @@ -0,0 +1,9 @@ +import { test } from "./my-module.js"; + +console.log(test()) + +async function main(){ + await Promise.resolve() + console.log("Test") +} + diff --git a/my-module.js b/my-module.js new file mode 100644 index 0000000..ce08bba --- /dev/null +++ b/my-module.js @@ -0,0 +1,3 @@ +export function test() { + return 42 +} \ No newline at end of file diff --git a/shaders/bgfx_shader.sh b/shaders/bgfx_shader.sh new file mode 100644 index 0000000..48dbfd0 --- /dev/null +++ b/shaders/bgfx_shader.sh @@ -0,0 +1,730 @@ +/* + * Copyright 2011-2023 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE + */ + +#ifndef BGFX_SHADER_H_HEADER_GUARD +#define BGFX_SHADER_H_HEADER_GUARD + +#if !defined(BGFX_CONFIG_MAX_BONES) +# define BGFX_CONFIG_MAX_BONES 32 +#endif // !defined(BGFX_CONFIG_MAX_BONES) + +#ifndef __cplusplus + +#if BGFX_SHADER_LANGUAGE_HLSL > 300 +# define BRANCH [branch] +# define LOOP [loop] +# define UNROLL [unroll] +#else +# define BRANCH +# define LOOP +# define UNROLL +#endif // BGFX_SHADER_LANGUAGE_HLSL > 300 + +#if (BGFX_SHADER_LANGUAGE_HLSL > 300 || BGFX_SHADER_LANGUAGE_METAL || BGFX_SHADER_LANGUAGE_SPIRV) && BGFX_SHADER_TYPE_FRAGMENT +# define EARLY_DEPTH_STENCIL [earlydepthstencil] +#else +# define EARLY_DEPTH_STENCIL +#endif // BGFX_SHADER_LANGUAGE_HLSL > 300 && BGFX_SHADER_TYPE_FRAGMENT + +#if BGFX_SHADER_LANGUAGE_GLSL +# define ARRAY_BEGIN(_type, _name, _count) _type _name[_count] = _type[]( +# define ARRAY_END() ) +#else +# define ARRAY_BEGIN(_type, _name, _count) _type _name[_count] = { +# define ARRAY_END() } +#endif // BGFX_SHADER_LANGUAGE_GLSL + +#if BGFX_SHADER_LANGUAGE_HLSL \ + || BGFX_SHADER_LANGUAGE_PSSL \ + || BGFX_SHADER_LANGUAGE_SPIRV \ + || BGFX_SHADER_LANGUAGE_METAL +# define CONST(_x) static const _x +# define dFdx(_x) ddx(_x) +# define dFdy(_y) ddy(-(_y)) +# define inversesqrt(_x) rsqrt(_x) +# define fract(_x) frac(_x) + +# define bvec2 bool2 +# define bvec3 bool3 +# define bvec4 bool4 + +// To be able to patch the uav registers on the DXBC SPDB Chunk (D3D11 renderer) the whitespaces around +// '_type[_reg]' are necessary. This only affects shaders with debug info (i.e., those that have the SPDB Chunk). +# if BGFX_SHADER_LANGUAGE_HLSL > 400 || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_SPIRV || BGFX_SHADER_LANGUAGE_METAL +# define REGISTER(_type, _reg) register( _type[_reg] ) +# else +# define REGISTER(_type, _reg) register(_type ## _reg) +# endif // BGFX_SHADER_LANGUAGE_HLSL + +# if BGFX_SHADER_LANGUAGE_HLSL > 300 || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_SPIRV || BGFX_SHADER_LANGUAGE_METAL +# if BGFX_SHADER_LANGUAGE_HLSL > 400 || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_SPIRV || BGFX_SHADER_LANGUAGE_METAL +# define dFdxCoarse(_x) ddx_coarse(_x) +# define dFdxFine(_x) ddx_fine(_x) +# define dFdyCoarse(_y) ddy_coarse(-(_y)) +# define dFdyFine(_y) ddy_fine(-(_y)) +# endif // BGFX_SHADER_LANGUAGE_HLSL > 400 + +# if BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_SPIRV || BGFX_SHADER_LANGUAGE_METAL +float intBitsToFloat(int _x) { return asfloat(_x); } +vec2 intBitsToFloat(uint2 _x) { return asfloat(_x); } +vec3 intBitsToFloat(uint3 _x) { return asfloat(_x); } +vec4 intBitsToFloat(uint4 _x) { return asfloat(_x); } +# endif // BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_SPIRV || BGFX_SHADER_LANGUAGE_METAL + +float uintBitsToFloat(uint _x) { return asfloat(_x); } +vec2 uintBitsToFloat(uint2 _x) { return asfloat(_x); } +vec3 uintBitsToFloat(uint3 _x) { return asfloat(_x); } +vec4 uintBitsToFloat(uint4 _x) { return asfloat(_x); } + +uint floatBitsToUint(float _x) { return asuint(_x); } +uvec2 floatBitsToUint(vec2 _x) { return asuint(_x); } +uvec3 floatBitsToUint(vec3 _x) { return asuint(_x); } +uvec4 floatBitsToUint(vec4 _x) { return asuint(_x); } + +int floatBitsToInt(float _x) { return asint(_x); } +ivec2 floatBitsToInt(vec2 _x) { return asint(_x); } +ivec3 floatBitsToInt(vec3 _x) { return asint(_x); } +ivec4 floatBitsToInt(vec4 _x) { return asint(_x); } + +uint bitfieldReverse(uint _x) { return reversebits(_x); } +uint2 bitfieldReverse(uint2 _x) { return reversebits(_x); } +uint3 bitfieldReverse(uint3 _x) { return reversebits(_x); } +uint4 bitfieldReverse(uint4 _x) { return reversebits(_x); } + +# if !BGFX_SHADER_LANGUAGE_SPIRV +uint packHalf2x16(vec2 _x) +{ + return (f32tof16(_x.y)<<16) | f32tof16(_x.x); +} + +vec2 unpackHalf2x16(uint _x) +{ + return vec2(f16tof32(_x & 0xffff), f16tof32(_x >> 16) ); +} +# endif // !BGFX_SHADER_LANGUAGE_SPIRV + +struct BgfxSampler2D +{ + SamplerState m_sampler; + Texture2D m_texture; +}; + +struct BgfxISampler2D +{ + Texture2D m_texture; +}; + +struct BgfxUSampler2D +{ + Texture2D m_texture; +}; + +struct BgfxSampler2DArray +{ + SamplerState m_sampler; + Texture2DArray m_texture; +}; + +struct BgfxSampler2DShadow +{ + SamplerComparisonState m_sampler; + Texture2D m_texture; +}; + +struct BgfxSampler2DArrayShadow +{ + SamplerComparisonState m_sampler; + Texture2DArray m_texture; +}; + +struct BgfxSampler3D +{ + SamplerState m_sampler; + Texture3D m_texture; +}; + +struct BgfxISampler3D +{ + Texture3D m_texture; +}; + +struct BgfxUSampler3D +{ + Texture3D m_texture; +}; + +struct BgfxSamplerCube +{ + SamplerState m_sampler; + TextureCube m_texture; +}; + +struct BgfxSamplerCubeShadow +{ + SamplerComparisonState m_sampler; + TextureCube m_texture; +}; + +struct BgfxSampler2DMS +{ + Texture2DMS m_texture; +}; + +vec4 bgfxTexture2D(BgfxSampler2D _sampler, vec2 _coord) +{ + return _sampler.m_texture.Sample(_sampler.m_sampler, _coord); +} + +vec4 bgfxTexture2DBias(BgfxSampler2D _sampler, vec2 _coord, float _bias) +{ + return _sampler.m_texture.SampleBias(_sampler.m_sampler, _coord, _bias); +} + +vec4 bgfxTexture2DLod(BgfxSampler2D _sampler, vec2 _coord, float _level) +{ + return _sampler.m_texture.SampleLevel(_sampler.m_sampler, _coord, _level); +} + +vec4 bgfxTexture2DLodOffset(BgfxSampler2D _sampler, vec2 _coord, float _level, ivec2 _offset) +{ + return _sampler.m_texture.SampleLevel(_sampler.m_sampler, _coord, _level, _offset); +} + +vec4 bgfxTexture2DProj(BgfxSampler2D _sampler, vec3 _coord) +{ + vec2 coord = _coord.xy * rcp(_coord.z); + return _sampler.m_texture.Sample(_sampler.m_sampler, coord); +} + +vec4 bgfxTexture2DProj(BgfxSampler2D _sampler, vec4 _coord) +{ + vec2 coord = _coord.xy * rcp(_coord.w); + return _sampler.m_texture.Sample(_sampler.m_sampler, coord); +} + +vec4 bgfxTexture2DGrad(BgfxSampler2D _sampler, vec2 _coord, vec2 _dPdx, vec2 _dPdy) +{ + return _sampler.m_texture.SampleGrad(_sampler.m_sampler, _coord, _dPdx, _dPdy); +} + +vec4 bgfxTexture2DArray(BgfxSampler2DArray _sampler, vec3 _coord) +{ + return _sampler.m_texture.Sample(_sampler.m_sampler, _coord); +} + +vec4 bgfxTexture2DArrayLod(BgfxSampler2DArray _sampler, vec3 _coord, float _lod) +{ + return _sampler.m_texture.SampleLevel(_sampler.m_sampler, _coord, _lod); +} + +vec4 bgfxTexture2DArrayLodOffset(BgfxSampler2DArray _sampler, vec3 _coord, float _level, ivec2 _offset) +{ + return _sampler.m_texture.SampleLevel(_sampler.m_sampler, _coord, _level, _offset); +} + +float bgfxShadow2D(BgfxSampler2DShadow _sampler, vec3 _coord) +{ + return _sampler.m_texture.SampleCmpLevelZero(_sampler.m_sampler, _coord.xy, _coord.z); +} + +float bgfxShadow2DProj(BgfxSampler2DShadow _sampler, vec4 _coord) +{ + vec3 coord = _coord.xyz * rcp(_coord.w); + return _sampler.m_texture.SampleCmpLevelZero(_sampler.m_sampler, coord.xy, coord.z); +} + +vec2 bgfxTextureSize(BgfxSampler2DShadow _sampler, int _lod) +{ + vec2 result; + float numberOfMipMapLevels; + _sampler.m_texture.GetDimensions(_lod, result.x, result.y, numberOfMipMapLevels); + return result; +} + +vec4 bgfxShadow2DArray(BgfxSampler2DArrayShadow _sampler, vec4 _coord) +{ + return _sampler.m_texture.SampleCmpLevelZero(_sampler.m_sampler, _coord.xyz, _coord.w); +} + +vec2 bgfxTextureSize(BgfxSampler2DArrayShadow _sampler, int _lod) +{ + vec2 result; + float numberOfMipMapLevels; + float numberOfElements; + _sampler.m_texture.GetDimensions(_lod, result.x, result.y, numberOfElements, numberOfMipMapLevels); + return result; +} + +vec4 bgfxTexture3D(BgfxSampler3D _sampler, vec3 _coord) +{ + return _sampler.m_texture.Sample(_sampler.m_sampler, _coord); +} + +vec4 bgfxTexture3DLod(BgfxSampler3D _sampler, vec3 _coord, float _level) +{ + return _sampler.m_texture.SampleLevel(_sampler.m_sampler, _coord, _level); +} + +ivec4 bgfxTexture3D(BgfxISampler3D _sampler, vec3 _coord) +{ + uvec3 size; + _sampler.m_texture.GetDimensions(size.x, size.y, size.z); + return _sampler.m_texture.Load(ivec4(_coord * size, 0) ); +} + +uvec4 bgfxTexture3D(BgfxUSampler3D _sampler, vec3 _coord) +{ + uvec3 size; + _sampler.m_texture.GetDimensions(size.x, size.y, size.z); + return _sampler.m_texture.Load(ivec4(_coord * size, 0) ); +} + +vec4 bgfxTextureCube(BgfxSamplerCube _sampler, vec3 _coord) +{ + return _sampler.m_texture.Sample(_sampler.m_sampler, _coord); +} + +vec4 bgfxTextureCubeBias(BgfxSamplerCube _sampler, vec3 _coord, float _bias) +{ + return _sampler.m_texture.SampleBias(_sampler.m_sampler, _coord, _bias); +} + +vec4 bgfxTextureCubeLod(BgfxSamplerCube _sampler, vec3 _coord, float _level) +{ + return _sampler.m_texture.SampleLevel(_sampler.m_sampler, _coord, _level); +} + +float bgfxShadowCube(BgfxSamplerCubeShadow _sampler, vec4 _coord) +{ + return _sampler.m_texture.SampleCmpLevelZero(_sampler.m_sampler, _coord.xyz, _coord.w); +} + +vec4 bgfxTexelFetch(BgfxSampler2D _sampler, ivec2 _coord, int _lod) +{ + return _sampler.m_texture.Load(ivec3(_coord, _lod) ); +} + +vec4 bgfxTexelFetchOffset(BgfxSampler2D _sampler, ivec2 _coord, int _lod, ivec2 _offset) +{ + return _sampler.m_texture.Load(ivec3(_coord, _lod), _offset ); +} + +vec2 bgfxTextureSize(BgfxSampler2D _sampler, int _lod) +{ + vec2 result; + float numberOfMipMapLevels; + _sampler.m_texture.GetDimensions(_lod, result.x, result.y, numberOfMipMapLevels); + return result; +} + +vec2 bgfxTextureSize(BgfxISampler2D _sampler, int _lod) +{ + vec2 result; + float numberOfMipMapLevels; + _sampler.m_texture.GetDimensions(_lod, result.x, result.y, numberOfMipMapLevels); + return result; +} + +vec2 bgfxTextureSize(BgfxUSampler2D _sampler, int _lod) +{ + vec2 result; + float numberOfMipMapLevels; + _sampler.m_texture.GetDimensions(_lod, result.x, result.y, numberOfMipMapLevels); + return result; +} + +vec4 bgfxTextureGather0(BgfxSampler2D _sampler, vec2 _coord) +{ + return _sampler.m_texture.GatherRed(_sampler.m_sampler, _coord); +} + +vec4 bgfxTextureGather1(BgfxSampler2D _sampler, vec2 _coord) +{ + return _sampler.m_texture.GatherGreen(_sampler.m_sampler, _coord); +} + +vec4 bgfxTextureGather2(BgfxSampler2D _sampler, vec2 _coord) +{ + return _sampler.m_texture.GatherBlue(_sampler.m_sampler, _coord); +} + +vec4 bgfxTextureGather3(BgfxSampler2D _sampler, vec2 _coord) +{ + return _sampler.m_texture.GatherAlpha(_sampler.m_sampler, _coord); +} + +vec4 bgfxTextureGatherOffset0(BgfxSampler2D _sampler, vec2 _coord, ivec2 _offset) +{ + return _sampler.m_texture.GatherRed(_sampler.m_sampler, _coord, _offset); +} + +vec4 bgfxTextureGatherOffset1(BgfxSampler2D _sampler, vec2 _coord, ivec2 _offset) +{ + return _sampler.m_texture.GatherGreen(_sampler.m_sampler, _coord, _offset); +} + +vec4 bgfxTextureGatherOffset2(BgfxSampler2D _sampler, vec2 _coord, ivec2 _offset) +{ + return _sampler.m_texture.GatherBlue(_sampler.m_sampler, _coord, _offset); +} + +vec4 bgfxTextureGatherOffset3(BgfxSampler2D _sampler, vec2 _coord, ivec2 _offset) +{ + return _sampler.m_texture.GatherAlpha(_sampler.m_sampler, _coord, _offset); +} + +vec4 bgfxTextureGather0(BgfxSampler2DArray _sampler, vec3 _coord) +{ + return _sampler.m_texture.GatherRed(_sampler.m_sampler, _coord); +} + +vec4 bgfxTextureGather1(BgfxSampler2DArray _sampler, vec3 _coord) +{ + return _sampler.m_texture.GatherGreen(_sampler.m_sampler, _coord); +} + +vec4 bgfxTextureGather2(BgfxSampler2DArray _sampler, vec3 _coord) +{ + return _sampler.m_texture.GatherBlue(_sampler.m_sampler, _coord); +} + +vec4 bgfxTextureGather3(BgfxSampler2DArray _sampler, vec3 _coord) +{ + return _sampler.m_texture.GatherAlpha(_sampler.m_sampler, _coord); +} + +ivec4 bgfxTexelFetch(BgfxISampler2D _sampler, ivec2 _coord, int _lod) +{ + return _sampler.m_texture.Load(ivec3(_coord, _lod) ); +} + +uvec4 bgfxTexelFetch(BgfxUSampler2D _sampler, ivec2 _coord, int _lod) +{ + return _sampler.m_texture.Load(ivec3(_coord, _lod) ); +} + +vec4 bgfxTexelFetch(BgfxSampler2DMS _sampler, ivec2 _coord, int _sampleIdx) +{ + return _sampler.m_texture.Load(_coord, _sampleIdx); +} + +vec4 bgfxTexelFetch(BgfxSampler2DArray _sampler, ivec3 _coord, int _lod) +{ + return _sampler.m_texture.Load(ivec4(_coord, _lod) ); +} + +vec4 bgfxTexelFetch(BgfxSampler3D _sampler, ivec3 _coord, int _lod) +{ + return _sampler.m_texture.Load(ivec4(_coord, _lod) ); +} + +vec3 bgfxTextureSize(BgfxSampler3D _sampler, int _lod) +{ + vec3 result; + float numberOfMipMapLevels; + _sampler.m_texture.GetDimensions(_lod, result.x, result.y, result.z, numberOfMipMapLevels); + return result; +} + +# define SAMPLER2D(_name, _reg) \ + uniform SamplerState _name ## Sampler : REGISTER(s, _reg); \ + uniform Texture2D _name ## Texture : REGISTER(t, _reg); \ + static BgfxSampler2D _name = { _name ## Sampler, _name ## Texture } +# define ISAMPLER2D(_name, _reg) \ + uniform Texture2D _name ## Texture : REGISTER(t, _reg); \ + static BgfxISampler2D _name = { _name ## Texture } +# define USAMPLER2D(_name, _reg) \ + uniform Texture2D _name ## Texture : REGISTER(t, _reg); \ + static BgfxUSampler2D _name = { _name ## Texture } +# define sampler2D BgfxSampler2D +# define texture2D(_sampler, _coord) bgfxTexture2D(_sampler, _coord) +# define texture2DBias(_sampler, _coord, _bias) bgfxTexture2DBias(_sampler, _coord, _bias) +# define texture2DLod(_sampler, _coord, _level) bgfxTexture2DLod(_sampler, _coord, _level) +# define texture2DLodOffset(_sampler, _coord, _level, _offset) bgfxTexture2DLodOffset(_sampler, _coord, _level, _offset) +# define texture2DProj(_sampler, _coord) bgfxTexture2DProj(_sampler, _coord) +# define texture2DGrad(_sampler, _coord, _dPdx, _dPdy) bgfxTexture2DGrad(_sampler, _coord, _dPdx, _dPdy) + +# define SAMPLER2DARRAY(_name, _reg) \ + uniform SamplerState _name ## Sampler : REGISTER(s, _reg); \ + uniform Texture2DArray _name ## Texture : REGISTER(t, _reg); \ + static BgfxSampler2DArray _name = { _name ## Sampler, _name ## Texture } +# define sampler2DArray BgfxSampler2DArray +# define texture2DArray(_sampler, _coord) bgfxTexture2DArray(_sampler, _coord) +# define texture2DArrayLod(_sampler, _coord, _lod) bgfxTexture2DArrayLod(_sampler, _coord, _lod) +# define texture2DArrayLodOffset(_sampler, _coord, _level, _offset) bgfxTexture2DArrayLodOffset(_sampler, _coord, _level, _offset) + +# define SAMPLER2DMS(_name, _reg) \ + uniform Texture2DMS _name ## Texture : REGISTER(t, _reg); \ + static BgfxSampler2DMS _name = { _name ## Texture } +# define sampler2DMS BgfxSampler2DMS + +# define SAMPLER2DSHADOW(_name, _reg) \ + uniform SamplerComparisonState _name ## SamplerComparison : REGISTER(s, _reg); \ + uniform Texture2D _name ## Texture : REGISTER(t, _reg); \ + static BgfxSampler2DShadow _name = { _name ## SamplerComparison, _name ## Texture } +# define sampler2DShadow BgfxSampler2DShadow +# define shadow2D(_sampler, _coord) bgfxShadow2D(_sampler, _coord) +# define shadow2DProj(_sampler, _coord) bgfxShadow2DProj(_sampler, _coord) + +# define SAMPLER2DARRAYSHADOW(_name, _reg) \ + uniform SamplerComparisonState _name ## SamplerComparison : REGISTER(s, _reg); \ + uniform Texture2DArray _name ## Texture : REGISTER(t, _reg); \ + static BgfxSampler2DArrayShadow _name = { _name ## SamplerComparison, _name ## Texture } +# define sampler2DArrayShadow BgfxSampler2DArrayShadow +# define shadow2DArray(_sampler, _coord) bgfxShadow2DArray(_sampler, _coord) + +# define SAMPLER3D(_name, _reg) \ + uniform SamplerState _name ## Sampler : REGISTER(s, _reg); \ + uniform Texture3D _name ## Texture : REGISTER(t, _reg); \ + static BgfxSampler3D _name = { _name ## Sampler, _name ## Texture } +# define ISAMPLER3D(_name, _reg) \ + uniform Texture3D _name ## Texture : REGISTER(t, _reg); \ + static BgfxISampler3D _name = { _name ## Texture } +# define USAMPLER3D(_name, _reg) \ + uniform Texture3D _name ## Texture : REGISTER(t, _reg); \ + static BgfxUSampler3D _name = { _name ## Texture } +# define sampler3D BgfxSampler3D +# define texture3D(_sampler, _coord) bgfxTexture3D(_sampler, _coord) +# define texture3DLod(_sampler, _coord, _level) bgfxTexture3DLod(_sampler, _coord, _level) + +# define SAMPLERCUBE(_name, _reg) \ + uniform SamplerState _name ## Sampler : REGISTER(s, _reg); \ + uniform TextureCube _name ## Texture : REGISTER(t, _reg); \ + static BgfxSamplerCube _name = { _name ## Sampler, _name ## Texture } +# define samplerCube BgfxSamplerCube +# define textureCube(_sampler, _coord) bgfxTextureCube(_sampler, _coord) +# define textureCubeBias(_sampler, _coord, _bias) bgfxTextureCubeBias(_sampler, _coord, _bias) +# define textureCubeLod(_sampler, _coord, _level) bgfxTextureCubeLod(_sampler, _coord, _level) + +# define SAMPLERCUBESHADOW(_name, _reg) \ + uniform SamplerComparisonState _name ## SamplerComparison : REGISTER(s, _reg); \ + uniform TextureCube _name ## Texture : REGISTER(t, _reg); \ + static BgfxSamplerCubeShadow _name = { _name ## SamplerComparison, _name ## Texture } +# define samplerCubeShadow BgfxSamplerCubeShadow +# define shadowCube(_sampler, _coord) bgfxShadowCube(_sampler, _coord) + +# define texelFetch(_sampler, _coord, _lod) bgfxTexelFetch(_sampler, _coord, _lod) +# define texelFetchOffset(_sampler, _coord, _lod, _offset) bgfxTexelFetchOffset(_sampler, _coord, _lod, _offset) +# define textureSize(_sampler, _lod) bgfxTextureSize(_sampler, _lod) +# define textureGather(_sampler, _coord, _comp) bgfxTextureGather ## _comp(_sampler, _coord) +# define textureGatherOffset(_sampler, _coord, _offset, _comp) bgfxTextureGatherOffset ## _comp(_sampler, _coord, _offset) +# else + +# define sampler2DShadow sampler2D + +vec4 bgfxTexture2DProj(sampler2D _sampler, vec3 _coord) +{ + return tex2Dproj(_sampler, vec4(_coord.xy, 0.0, _coord.z) ); +} + +vec4 bgfxTexture2DProj(sampler2D _sampler, vec4 _coord) +{ + return tex2Dproj(_sampler, _coord); +} + +float bgfxShadow2D(sampler2DShadow _sampler, vec3 _coord) +{ +#if 0 + float occluder = tex2D(_sampler, _coord.xy).x; + return step(_coord.z, occluder); +#else + return tex2Dproj(_sampler, vec4(_coord.xy, _coord.z, 1.0) ).x; +#endif // 0 +} + +float bgfxShadow2DProj(sampler2DShadow _sampler, vec4 _coord) +{ +#if 0 + vec3 coord = _coord.xyz * rcp(_coord.w); + float occluder = tex2D(_sampler, coord.xy).x; + return step(coord.z, occluder); +#else + return tex2Dproj(_sampler, _coord).x; +#endif // 0 +} + +# define SAMPLER2D(_name, _reg) uniform sampler2D _name : REGISTER(s, _reg) +# define SAMPLER2DMS(_name, _reg) uniform sampler2DMS _name : REGISTER(s, _reg) +# define texture2D(_sampler, _coord) tex2D(_sampler, _coord) +# define texture2DProj(_sampler, _coord) bgfxTexture2DProj(_sampler, _coord) + +# define SAMPLER2DARRAY(_name, _reg) SAMPLER2D(_name, _reg) +# define texture2DArray(_sampler, _coord) texture2D(_sampler, (_coord).xy) +# define texture2DArrayLod(_sampler, _coord, _lod) texture2DLod(_sampler, _coord, _lod) + +# define SAMPLER2DSHADOW(_name, _reg) uniform sampler2DShadow _name : REGISTER(s, _reg) +# define shadow2D(_sampler, _coord) bgfxShadow2D(_sampler, _coord) +# define shadow2DProj(_sampler, _coord) bgfxShadow2DProj(_sampler, _coord) + +# define SAMPLER3D(_name, _reg) uniform sampler3D _name : REGISTER(s, _reg) +# define texture3D(_sampler, _coord) tex3D(_sampler, _coord) + +# define SAMPLERCUBE(_name, _reg) uniform samplerCUBE _name : REGISTER(s, _reg) +# define textureCube(_sampler, _coord) texCUBE(_sampler, _coord) + +# define texture2DLod(_sampler, _coord, _level) tex2Dlod(_sampler, vec4( (_coord).xy, 0.0, _level) ) +# define texture2DGrad(_sampler, _coord, _dPdx, _dPdy) tex2Dgrad(_sampler, _coord, _dPdx, _dPdy) +# define texture3DLod(_sampler, _coord, _level) tex3Dlod(_sampler, vec4( (_coord).xyz, _level) ) +# define textureCubeLod(_sampler, _coord, _level) texCUBElod(_sampler, vec4( (_coord).xyz, _level) ) + +# endif // BGFX_SHADER_LANGUAGE_HLSL > 300 + +vec3 instMul(vec3 _vec, mat3 _mtx) { return mul(_mtx, _vec); } +vec3 instMul(mat3 _mtx, vec3 _vec) { return mul(_vec, _mtx); } +vec4 instMul(vec4 _vec, mat4 _mtx) { return mul(_mtx, _vec); } +vec4 instMul(mat4 _mtx, vec4 _vec) { return mul(_vec, _mtx); } + +bvec2 lessThan(vec2 _a, vec2 _b) { return _a < _b; } +bvec3 lessThan(vec3 _a, vec3 _b) { return _a < _b; } +bvec4 lessThan(vec4 _a, vec4 _b) { return _a < _b; } + +bvec2 lessThanEqual(vec2 _a, vec2 _b) { return _a <= _b; } +bvec3 lessThanEqual(vec3 _a, vec3 _b) { return _a <= _b; } +bvec4 lessThanEqual(vec4 _a, vec4 _b) { return _a <= _b; } + +bvec2 greaterThan(vec2 _a, vec2 _b) { return _a > _b; } +bvec3 greaterThan(vec3 _a, vec3 _b) { return _a > _b; } +bvec4 greaterThan(vec4 _a, vec4 _b) { return _a > _b; } + +bvec2 greaterThanEqual(vec2 _a, vec2 _b) { return _a >= _b; } +bvec3 greaterThanEqual(vec3 _a, vec3 _b) { return _a >= _b; } +bvec4 greaterThanEqual(vec4 _a, vec4 _b) { return _a >= _b; } + +bvec2 notEqual(vec2 _a, vec2 _b) { return _a != _b; } +bvec3 notEqual(vec3 _a, vec3 _b) { return _a != _b; } +bvec4 notEqual(vec4 _a, vec4 _b) { return _a != _b; } + +bvec2 equal(vec2 _a, vec2 _b) { return _a == _b; } +bvec3 equal(vec3 _a, vec3 _b) { return _a == _b; } +bvec4 equal(vec4 _a, vec4 _b) { return _a == _b; } + +float mix(float _a, float _b, float _t) { return lerp(_a, _b, _t); } +vec2 mix(vec2 _a, vec2 _b, vec2 _t) { return lerp(_a, _b, _t); } +vec3 mix(vec3 _a, vec3 _b, vec3 _t) { return lerp(_a, _b, _t); } +vec4 mix(vec4 _a, vec4 _b, vec4 _t) { return lerp(_a, _b, _t); } + +float mod(float _a, float _b) { return _a - _b * floor(_a / _b); } +vec2 mod(vec2 _a, vec2 _b) { return _a - _b * floor(_a / _b); } +vec3 mod(vec3 _a, vec3 _b) { return _a - _b * floor(_a / _b); } +vec4 mod(vec4 _a, vec4 _b) { return _a - _b * floor(_a / _b); } + +#else +# define CONST(_x) const _x +# define atan2(_x, _y) atan(_x, _y) +# define mul(_a, _b) ( (_a) * (_b) ) +# define saturate(_x) clamp(_x, 0.0, 1.0) +# define SAMPLER2D(_name, _reg) uniform sampler2D _name +# define SAMPLER2DMS(_name, _reg) uniform sampler2DMS _name +# define SAMPLER3D(_name, _reg) uniform sampler3D _name +# define SAMPLERCUBE(_name, _reg) uniform samplerCube _name +# define SAMPLER2DSHADOW(_name, _reg) uniform sampler2DShadow _name + +# define SAMPLER2DARRAY(_name, _reg) uniform sampler2DArray _name +# define SAMPLER2DMSARRAY(_name, _reg) uniform sampler2DMSArray _name +# define SAMPLERCUBEARRAY(_name, _reg) uniform samplerCubeArray _name +# define SAMPLER2DARRAYSHADOW(_name, _reg) uniform sampler2DArrayShadow _name + +# define ISAMPLER2D(_name, _reg) uniform isampler2D _name +# define USAMPLER2D(_name, _reg) uniform usampler2D _name +# define ISAMPLER3D(_name, _reg) uniform isampler3D _name +# define USAMPLER3D(_name, _reg) uniform usampler3D _name + +# if BGFX_SHADER_LANGUAGE_GLSL >= 130 +# define texture2D(_sampler, _coord) texture(_sampler, _coord) +# define texture2DArray(_sampler, _coord) texture(_sampler, _coord) +# define texture3D(_sampler, _coord) texture(_sampler, _coord) +# define textureCube(_sampler, _coord) texture(_sampler, _coord) +# define texture2DLod(_sampler, _coord, _lod) textureLod(_sampler, _coord, _lod) +# define texture2DLodOffset(_sampler, _coord, _lod, _offset) textureLodOffset(_sampler, _coord, _lod, _offset) +# define texture2DBias(_sampler, _coord, _bias) texture(_sampler, _coord, _bias) +# define textureCubeBias(_sampler, _coord, _bias) texture(_sampler, _coord, _bias) +# else +# define texture2DBias(_sampler, _coord, _bias) texture2D(_sampler, _coord, _bias) +# define textureCubeBias(_sampler, _coord, _bias) textureCube(_sampler, _coord, _bias) +# endif // BGFX_SHADER_LANGUAGE_GLSL >= 130 + +vec3 instMul(vec3 _vec, mat3 _mtx) { return mul(_vec, _mtx); } +vec3 instMul(mat3 _mtx, vec3 _vec) { return mul(_mtx, _vec); } +vec4 instMul(vec4 _vec, mat4 _mtx) { return mul(_vec, _mtx); } +vec4 instMul(mat4 _mtx, vec4 _vec) { return mul(_mtx, _vec); } + +float rcp(float _a) { return 1.0/_a; } +vec2 rcp(vec2 _a) { return vec2(1.0)/_a; } +vec3 rcp(vec3 _a) { return vec3(1.0)/_a; } +vec4 rcp(vec4 _a) { return vec4(1.0)/_a; } +#endif // BGFX_SHADER_LANGUAGE_* + +vec2 vec2_splat(float _x) { return vec2(_x, _x); } +vec3 vec3_splat(float _x) { return vec3(_x, _x, _x); } +vec4 vec4_splat(float _x) { return vec4(_x, _x, _x, _x); } + +#if BGFX_SHADER_LANGUAGE_GLSL >= 130 || BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_SPIRV || BGFX_SHADER_LANGUAGE_METAL +uvec2 uvec2_splat(uint _x) { return uvec2(_x, _x); } +uvec3 uvec3_splat(uint _x) { return uvec3(_x, _x, _x); } +uvec4 uvec4_splat(uint _x) { return uvec4(_x, _x, _x, _x); } +#endif // BGFX_SHADER_LANGUAGE_GLSL >= 130 || BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_SPIRV || BGFX_SHADER_LANGUAGE_METAL + +mat4 mtxFromRows(vec4 _0, vec4 _1, vec4 _2, vec4 _3) +{ +#if BGFX_SHADER_LANGUAGE_GLSL + return transpose(mat4(_0, _1, _2, _3) ); +#else + return mat4(_0, _1, _2, _3); +#endif // BGFX_SHADER_LANGUAGE_GLSL +} +mat4 mtxFromCols(vec4 _0, vec4 _1, vec4 _2, vec4 _3) +{ +#if BGFX_SHADER_LANGUAGE_GLSL + return mat4(_0, _1, _2, _3); +#else + return transpose(mat4(_0, _1, _2, _3) ); +#endif // BGFX_SHADER_LANGUAGE_GLSL +} +mat3 mtxFromRows(vec3 _0, vec3 _1, vec3 _2) +{ +#if BGFX_SHADER_LANGUAGE_GLSL + return transpose(mat3(_0, _1, _2) ); +#else + return mat3(_0, _1, _2); +#endif // BGFX_SHADER_LANGUAGE_GLSL +} +mat3 mtxFromCols(vec3 _0, vec3 _1, vec3 _2) +{ +#if BGFX_SHADER_LANGUAGE_GLSL + return mat3(_0, _1, _2); +#else + return transpose(mat3(_0, _1, _2) ); +#endif // BGFX_SHADER_LANGUAGE_GLSL +} + +#if BGFX_SHADER_LANGUAGE_GLSL +#define mtxFromRows3(_0, _1, _2) transpose(mat3(_0, _1, _2) ) +#define mtxFromRows4(_0, _1, _2, _3) transpose(mat4(_0, _1, _2, _3) ) +#define mtxFromCols3(_0, _1, _2) mat3(_0, _1, _2) +#define mtxFromCols4(_0, _1, _2, _3) mat4(_0, _1, _2, _3) +#else +#define mtxFromRows3(_0, _1, _2) mat3(_0, _1, _2) +#define mtxFromRows4(_0, _1, _2, _3) mat4(_0, _1, _2, _3) +#define mtxFromCols3(_0, _1, _2) transpose(mat3(_0, _1, _2) ) +#define mtxFromCols4(_0, _1, _2, _3) transpose(mat4(_0, _1, _2, _3) ) +#endif // BGFX_SHADER_LANGUAGE_GLSL + +uniform vec4 u_viewRect; +uniform vec4 u_viewTexel; +uniform mat4 u_view; +uniform mat4 u_invView; +uniform mat4 u_proj; +uniform mat4 u_invProj; +uniform mat4 u_viewProj; +uniform mat4 u_invViewProj; +uniform mat4 u_model[BGFX_CONFIG_MAX_BONES]; +uniform mat4 u_modelView; +uniform mat4 u_modelViewProj; +uniform vec4 u_alphaRef4; +#define u_alphaRef u_alphaRef4.x + +#endif // __cplusplus + +#endif // BGFX_SHADER_H_HEADER_GUARD diff --git a/shaders/common.sh b/shaders/common.sh new file mode 100644 index 0000000..6c649fe --- /dev/null +++ b/shaders/common.sh @@ -0,0 +1,7 @@ +/* + * Copyright 2011-2023 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE + */ + +#include +#include "shaderlib.sh" diff --git a/shaders/fs.sc b/shaders/fs.sc new file mode 100644 index 0000000..82f874b --- /dev/null +++ b/shaders/fs.sc @@ -0,0 +1,13 @@ +$input v_color0 + +/* + * Copyright 2011-2023 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE + */ + +#include "common.sh" + +void main() +{ + gl_FragColor = v_color0; +} diff --git a/shaders/shaderlib.sh b/shaders/shaderlib.sh new file mode 100644 index 0000000..389a1ec --- /dev/null +++ b/shaders/shaderlib.sh @@ -0,0 +1,431 @@ +/* + * Copyright 2011-2023 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE + */ + +#ifndef __SHADERLIB_SH__ +#define __SHADERLIB_SH__ + +vec4 encodeRE8(float _r) +{ + float exponent = ceil(log2(_r) ); + return vec4(_r / exp2(exponent) + , 0.0 + , 0.0 + , (exponent + 128.0) / 255.0 + ); +} + +float decodeRE8(vec4 _re8) +{ + float exponent = _re8.w * 255.0 - 128.0; + return _re8.x * exp2(exponent); +} + +vec4 encodeRGBE8(vec3 _rgb) +{ + vec4 rgbe8; + float maxComponent = max(max(_rgb.x, _rgb.y), _rgb.z); + float exponent = ceil(log2(maxComponent) ); + rgbe8.xyz = _rgb / exp2(exponent); + rgbe8.w = (exponent + 128.0) / 255.0; + return rgbe8; +} + +vec3 decodeRGBE8(vec4 _rgbe8) +{ + float exponent = _rgbe8.w * 255.0 - 128.0; + vec3 rgb = _rgbe8.xyz * exp2(exponent); + return rgb; +} + +vec3 encodeNormalUint(vec3 _normal) +{ + return _normal * 0.5 + 0.5; +} + +vec3 decodeNormalUint(vec3 _encodedNormal) +{ + return _encodedNormal * 2.0 - 1.0; +} + +vec2 encodeNormalSphereMap(vec3 _normal) +{ + return normalize(_normal.xy) * sqrt(_normal.z * 0.5 + 0.5); +} + +vec3 decodeNormalSphereMap(vec2 _encodedNormal) +{ + float zz = dot(_encodedNormal, _encodedNormal) * 2.0 - 1.0; + return vec3(normalize(_encodedNormal.xy) * sqrt(1.0 - zz*zz), zz); +} + +vec2 octahedronWrap(vec2 _val) +{ + // Reference(s): + // - Octahedron normal vector encoding + // https://web.archive.org/web/20191027010600/https://knarkowicz.wordpress.com/2014/04/16/octahedron-normal-vector-encoding/comment-page-1/ + return (1.0 - abs(_val.yx) ) + * mix(vec2_splat(-1.0), vec2_splat(1.0), vec2(greaterThanEqual(_val.xy, vec2_splat(0.0) ) ) ); +} + +vec2 encodeNormalOctahedron(vec3 _normal) +{ + _normal /= abs(_normal.x) + abs(_normal.y) + abs(_normal.z); + _normal.xy = _normal.z >= 0.0 ? _normal.xy : octahedronWrap(_normal.xy); + _normal.xy = _normal.xy * 0.5 + 0.5; + return _normal.xy; +} + +vec3 decodeNormalOctahedron(vec2 _encodedNormal) +{ + _encodedNormal = _encodedNormal * 2.0 - 1.0; + + vec3 normal; + normal.z = 1.0 - abs(_encodedNormal.x) - abs(_encodedNormal.y); + normal.xy = normal.z >= 0.0 ? _encodedNormal.xy : octahedronWrap(_encodedNormal.xy); + return normalize(normal); +} + +vec3 convertRGB2XYZ(vec3 _rgb) +{ + // Reference(s): + // - RGB/XYZ Matrices + // https://web.archive.org/web/20191027010220/http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html + vec3 xyz; + xyz.x = dot(vec3(0.4124564, 0.3575761, 0.1804375), _rgb); + xyz.y = dot(vec3(0.2126729, 0.7151522, 0.0721750), _rgb); + xyz.z = dot(vec3(0.0193339, 0.1191920, 0.9503041), _rgb); + return xyz; +} + +vec3 convertXYZ2RGB(vec3 _xyz) +{ + vec3 rgb; + rgb.x = dot(vec3( 3.2404542, -1.5371385, -0.4985314), _xyz); + rgb.y = dot(vec3(-0.9692660, 1.8760108, 0.0415560), _xyz); + rgb.z = dot(vec3( 0.0556434, -0.2040259, 1.0572252), _xyz); + return rgb; +} + +vec3 convertXYZ2Yxy(vec3 _xyz) +{ + // Reference(s): + // - XYZ to xyY + // https://web.archive.org/web/20191027010144/http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_xyY.html + float inv = 1.0/dot(_xyz, vec3(1.0, 1.0, 1.0) ); + return vec3(_xyz.y, _xyz.x*inv, _xyz.y*inv); +} + +vec3 convertYxy2XYZ(vec3 _Yxy) +{ + // Reference(s): + // - xyY to XYZ + // https://web.archive.org/web/20191027010036/http://www.brucelindbloom.com/index.html?Eqn_xyY_to_XYZ.html + vec3 xyz; + xyz.x = _Yxy.x*_Yxy.y/_Yxy.z; + xyz.y = _Yxy.x; + xyz.z = _Yxy.x*(1.0 - _Yxy.y - _Yxy.z)/_Yxy.z; + return xyz; +} + +vec3 convertRGB2Yxy(vec3 _rgb) +{ + return convertXYZ2Yxy(convertRGB2XYZ(_rgb) ); +} + +vec3 convertYxy2RGB(vec3 _Yxy) +{ + return convertXYZ2RGB(convertYxy2XYZ(_Yxy) ); +} + +vec3 convertRGB2Yuv(vec3 _rgb) +{ + vec3 yuv; + yuv.x = dot(_rgb, vec3(0.299, 0.587, 0.114) ); + yuv.y = (_rgb.x - yuv.x)*0.713 + 0.5; + yuv.z = (_rgb.z - yuv.x)*0.564 + 0.5; + return yuv; +} + +vec3 convertYuv2RGB(vec3 _yuv) +{ + vec3 rgb; + rgb.x = _yuv.x + 1.403*(_yuv.y-0.5); + rgb.y = _yuv.x - 0.344*(_yuv.y-0.5) - 0.714*(_yuv.z-0.5); + rgb.z = _yuv.x + 1.773*(_yuv.z-0.5); + return rgb; +} + +vec3 convertRGB2YIQ(vec3 _rgb) +{ + vec3 yiq; + yiq.x = dot(vec3(0.299, 0.587, 0.114 ), _rgb); + yiq.y = dot(vec3(0.595716, -0.274453, -0.321263), _rgb); + yiq.z = dot(vec3(0.211456, -0.522591, 0.311135), _rgb); + return yiq; +} + +vec3 convertYIQ2RGB(vec3 _yiq) +{ + vec3 rgb; + rgb.x = dot(vec3(1.0, 0.9563, 0.6210), _yiq); + rgb.y = dot(vec3(1.0, -0.2721, -0.6474), _yiq); + rgb.z = dot(vec3(1.0, -1.1070, 1.7046), _yiq); + return rgb; +} + +vec3 toLinear(vec3 _rgb) +{ + return pow(abs(_rgb), vec3_splat(2.2) ); +} + +vec4 toLinear(vec4 _rgba) +{ + return vec4(toLinear(_rgba.xyz), _rgba.w); +} + +vec3 toLinearAccurate(vec3 _rgb) +{ + vec3 lo = _rgb / 12.92; + vec3 hi = pow( (_rgb + 0.055) / 1.055, vec3_splat(2.4) ); + vec3 rgb = mix(hi, lo, vec3(lessThanEqual(_rgb, vec3_splat(0.04045) ) ) ); + return rgb; +} + +vec4 toLinearAccurate(vec4 _rgba) +{ + return vec4(toLinearAccurate(_rgba.xyz), _rgba.w); +} + +float toGamma(float _r) +{ + return pow(abs(_r), 1.0/2.2); +} + +vec3 toGamma(vec3 _rgb) +{ + return pow(abs(_rgb), vec3_splat(1.0/2.2) ); +} + +vec4 toGamma(vec4 _rgba) +{ + return vec4(toGamma(_rgba.xyz), _rgba.w); +} + +vec3 toGammaAccurate(vec3 _rgb) +{ + vec3 lo = _rgb * 12.92; + vec3 hi = pow(abs(_rgb), vec3_splat(1.0/2.4) ) * 1.055 - 0.055; + vec3 rgb = mix(hi, lo, vec3(lessThanEqual(_rgb, vec3_splat(0.0031308) ) ) ); + return rgb; +} + +vec4 toGammaAccurate(vec4 _rgba) +{ + return vec4(toGammaAccurate(_rgba.xyz), _rgba.w); +} + +vec3 toReinhard(vec3 _rgb) +{ + return toGamma(_rgb/(_rgb+vec3_splat(1.0) ) ); +} + +vec4 toReinhard(vec4 _rgba) +{ + return vec4(toReinhard(_rgba.xyz), _rgba.w); +} + +vec3 toFilmic(vec3 _rgb) +{ + _rgb = max(vec3_splat(0.0), _rgb - 0.004); + _rgb = (_rgb*(6.2*_rgb + 0.5) ) / (_rgb*(6.2*_rgb + 1.7) + 0.06); + return _rgb; +} + +vec4 toFilmic(vec4 _rgba) +{ + return vec4(toFilmic(_rgba.xyz), _rgba.w); +} + +vec3 toAcesFilmic(vec3 _rgb) +{ + // Reference(s): + // - ACES Filmic Tone Mapping Curve + // https://web.archive.org/web/20191027010704/https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ + float aa = 2.51f; + float bb = 0.03f; + float cc = 2.43f; + float dd = 0.59f; + float ee = 0.14f; + return saturate( (_rgb*(aa*_rgb + bb) )/(_rgb*(cc*_rgb + dd) + ee) ); +} + +vec4 toAcesFilmic(vec4 _rgba) +{ + return vec4(toAcesFilmic(_rgba.xyz), _rgba.w); +} + +vec3 luma(vec3 _rgb) +{ + float yy = dot(vec3(0.2126729, 0.7151522, 0.0721750), _rgb); + return vec3_splat(yy); +} + +vec4 luma(vec4 _rgba) +{ + return vec4(luma(_rgba.xyz), _rgba.w); +} + +vec3 conSatBri(vec3 _rgb, vec3 _csb) +{ + vec3 rgb = _rgb * _csb.z; + rgb = mix(luma(rgb), rgb, _csb.y); + rgb = mix(vec3_splat(0.5), rgb, _csb.x); + return rgb; +} + +vec4 conSatBri(vec4 _rgba, vec3 _csb) +{ + return vec4(conSatBri(_rgba.xyz, _csb), _rgba.w); +} + +vec3 posterize(vec3 _rgb, float _numColors) +{ + return floor(_rgb*_numColors) / _numColors; +} + +vec4 posterize(vec4 _rgba, float _numColors) +{ + return vec4(posterize(_rgba.xyz, _numColors), _rgba.w); +} + +vec3 sepia(vec3 _rgb) +{ + vec3 color; + color.x = dot(_rgb, vec3(0.393, 0.769, 0.189) ); + color.y = dot(_rgb, vec3(0.349, 0.686, 0.168) ); + color.z = dot(_rgb, vec3(0.272, 0.534, 0.131) ); + return color; +} + +vec4 sepia(vec4 _rgba) +{ + return vec4(sepia(_rgba.xyz), _rgba.w); +} + +vec3 blendOverlay(vec3 _base, vec3 _blend) +{ + vec3 lt = 2.0 * _base * _blend; + vec3 gte = 1.0 - 2.0 * (1.0 - _base) * (1.0 - _blend); + return mix(lt, gte, step(vec3_splat(0.5), _base) ); +} + +vec4 blendOverlay(vec4 _base, vec4 _blend) +{ + return vec4(blendOverlay(_base.xyz, _blend.xyz), _base.w); +} + +vec3 adjustHue(vec3 _rgb, float _hue) +{ + vec3 yiq = convertRGB2YIQ(_rgb); + float angle = _hue + atan2(yiq.z, yiq.y); + float len = length(yiq.yz); + return convertYIQ2RGB(vec3(yiq.x, len*cos(angle), len*sin(angle) ) ); +} + +vec4 packFloatToRgba(float _value) +{ + const vec4 shift = vec4(256 * 256 * 256, 256 * 256, 256, 1.0); + const vec4 mask = vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); + vec4 comp = fract(_value * shift); + comp -= comp.xxyz * mask; + return comp; +} + +float unpackRgbaToFloat(vec4 _rgba) +{ + const vec4 shift = vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0); + return dot(_rgba, shift); +} + +vec2 packHalfFloat(float _value) +{ + const vec2 shift = vec2(256, 1.0); + const vec2 mask = vec2(0, 1.0 / 256.0); + vec2 comp = fract(_value * shift); + comp -= comp.xx * mask; + return comp; +} + +float unpackHalfFloat(vec2 _rg) +{ + const vec2 shift = vec2(1.0 / 256.0, 1.0); + return dot(_rg, shift); +} + +float random(vec2 _uv) +{ + return fract(sin(dot(_uv.xy, vec2(12.9898, 78.233) ) ) * 43758.5453); +} + +vec3 fixCubeLookup(vec3 _v, float _lod, float _topLevelCubeSize) +{ + // Reference(s): + // - Seamless cube-map filtering + // https://web.archive.org/web/20190411181934/http://the-witness.net/news/2012/02/seamless-cube-map-filtering/ + float ax = abs(_v.x); + float ay = abs(_v.y); + float az = abs(_v.z); + float vmax = max(max(ax, ay), az); + float scale = 1.0 - exp2(_lod) / _topLevelCubeSize; + if (ax != vmax) { _v.x *= scale; } + if (ay != vmax) { _v.y *= scale; } + if (az != vmax) { _v.z *= scale; } + return _v; +} + +vec2 texture2DBc5(sampler2D _sampler, vec2 _uv) +{ +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + return texture2D(_sampler, _uv).yx; +#else + return texture2D(_sampler, _uv).xy; +#endif +} + +mat3 cofactor(mat4 _m) +{ + // Reference: + // Cofactor of matrix. Use to transform normals. The code assumes the last column of _m is [0,0,0,1]. + // https://www.shadertoy.com/view/3s33zj + // https://github.com/graphitemaster/normals_revisited + return mat3( + _m[1][1]*_m[2][2]-_m[1][2]*_m[2][1], + _m[1][2]*_m[2][0]-_m[1][0]*_m[2][2], + _m[1][0]*_m[2][1]-_m[1][1]*_m[2][0], + _m[0][2]*_m[2][1]-_m[0][1]*_m[2][2], + _m[0][0]*_m[2][2]-_m[0][2]*_m[2][0], + _m[0][1]*_m[2][0]-_m[0][0]*_m[2][1], + _m[0][1]*_m[1][2]-_m[0][2]*_m[1][1], + _m[0][2]*_m[1][0]-_m[0][0]*_m[1][2], + _m[0][0]*_m[1][1]-_m[0][1]*_m[1][0] + ); +} + +float toClipSpaceDepth(float _depthTextureZ) +{ +#if BGFX_SHADER_LANGUAGE_GLSL + return _depthTextureZ * 2.0 - 1.0; +#else + return _depthTextureZ; +#endif // BGFX_SHADER_LANGUAGE_GLSL +} + +vec3 clipToWorld(mat4 _invViewProj, vec3 _clipPos) +{ + vec4 wpos = mul(_invViewProj, vec4(_clipPos, 1.0) ); + return wpos.xyz / wpos.w; +} + +#endif // __SHADERLIB_SH__ diff --git a/shaders/varying.def.sc b/shaders/varying.def.sc new file mode 100644 index 0000000..9d9d83e --- /dev/null +++ b/shaders/varying.def.sc @@ -0,0 +1,4 @@ +vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0); + +vec3 a_position : POSITION; +vec4 a_color0 : COLOR0; diff --git a/shaders/vs.sc b/shaders/vs.sc new file mode 100644 index 0000000..83201d4 --- /dev/null +++ b/shaders/vs.sc @@ -0,0 +1,15 @@ +$input a_position, a_color0 +$output v_color0 + +/* + * Copyright 2011-2023 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE + */ + +#include "common.sh" + +void main() +{ + gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) ); + v_color0 = a_color0; +} diff --git a/src/bgfx.cpp b/src/bgfx.cpp new file mode 100644 index 0000000..505aae2 --- /dev/null +++ b/src/bgfx.cpp @@ -0,0 +1,99 @@ +#include +#include + +#include "common.h" +#include "logo.h" + +static bgfx_platform_data_t get_platform_data(SDL_Window* win); +uint16_t uint16_max(uint16_t _a, uint16_t _b) +{ + return _a < _b ? _b : _a; +} + +int app_init_bgfx(){ + bgfx_init_t init; + bgfx_init_ctor(&init); + + init.platformData = get_platform_data(app_state.window); + init.resolution.width = app_config.width; + init.resolution.height = app_config.height; + init.resolution.reset = BGFX_RESET_VSYNC; + + // calling render_frame on the same thread before init to force single-threaded mode + bgfx_render_frame(16); + bgfx_init(&init); + //bgfx_reset(WIDTH, HEIGHT, BGFX_RESET_VSYNC, init.resolution.format); + + bgfx_set_debug(BGFX_DEBUG_TEXT); + + bgfx_set_view_clear(0 + , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH + , 0x303030ff + , 1.0f + , 0 + ); + + return 0; +} + +int app_update_bgfx(){ + // Set view 0 default viewport. + bgfx_set_view_rect(0, 0, 0, (uint16_t)app_config.width, (uint16_t)app_config.height); + + // This dummy draw call is here to make sure that view 0 is cleared + // if no other draw calls are submitted to view 0. + bgfx_encoder_t* encoder = bgfx_encoder_begin(true); + bgfx_encoder_touch(encoder, 0); + bgfx_encoder_end(encoder); + + // Use debug font to print information about this example. + bgfx_dbg_text_clear(0, false); + bgfx_dbg_text_image( + uint16_max( (uint16_t)app_config.width/2/8, 20)-20 + , uint16_max( (uint16_t)app_config.height/2/16, 6)-6 + , 40 + , 12 + , s_logo + , 160 + ); + + bgfx_dbg_text_printf(0, 1, 0x0f, "Color can be changed with ANSI \x1b[9;me\x1b[10;ms\x1b[11;mc\x1b[12;ma\x1b[13;mp\x1b[14;me\x1b[0m code too."); + + bgfx_dbg_text_printf(80, 1, 0x0f, "\x1b[;0m \x1b[;1m \x1b[; 2m \x1b[; 3m \x1b[; 4m \x1b[; 5m \x1b[; 6m \x1b[; 7m \x1b[0m"); + bgfx_dbg_text_printf(80, 2, 0x0f, "\x1b[;8m \x1b[;9m \x1b[;10m \x1b[;11m \x1b[;12m \x1b[;13m \x1b[;14m \x1b[;15m \x1b[0m"); + + bgfx_dbg_text_printf(0, 3, 0x1f, "hello-bgfx"); + bgfx_dbg_text_printf(0, 4, 0x3f, "Description: Initialization and debug text with C99 API."); + + // Advance to next frame. Rendering thread will be kicked to + // process submitted rendering primitives. + bgfx_frame(false); +} + +int app_dispose_bgfx(){ + bgfx_shutdown(); +} + +static bgfx_platform_data_t get_platform_data(SDL_Window* win){ + bgfx_platform_data_t pd = {0}; +#if !BX_PLATFORM_EMSCRIPTEN + SDL_SysWMinfo wmi; + SDL_VERSION(&wmi.version); + if (!SDL_GetWindowWMInfo(win, &wmi)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_SysWMinfo could not be retrieved: %s", SDL_GetError()); + return pd; + } +#endif + +#if BX_PLATFORM_WINDOWS + pd.nwh = wmi.info.win.window; +#elif BX_PLATFORM_OSX + pd.nwh = wmi.info.cocoa.window; +#elif BX_PLATFORM_LINUX + pd.ndt = wmi.info.x11.display; + pd.nwh = (void*)(uintptr_t)wmi.info.x11.window; +#elif BX_PLATFORM_EMSCRIPTEN + pd.nwh = (void*)"#canvas"; +#endif + return pd; +} diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..b7b50c4 --- /dev/null +++ b/src/common.h @@ -0,0 +1,40 @@ +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include + +#include + + +typedef struct { + uint width; + uint height; +} App_Config; + +typedef struct { + SDL_Window* window; + bool quit; +} App_State; + +extern App_Config app_config; +extern App_State app_state;; + +int app_init_sdl(); +int app_update_sdl(); +int app_dispose_sdl(); + +int app_init_quickjs(int argc, char** argv); +int app_update_quickjs(); +int app_dispose_quickjs(); + +int app_init_bgfx(); +int app_update_bgfx(); +int app_dispose_bgfx(); + +// utiles +char* app_read_file(const char* filename, size_t* out_size); + +#endif \ No newline at end of file diff --git a/src/logo.h b/src/logo.h new file mode 100644 index 0000000..87e00b1 --- /dev/null +++ b/src/logo.h @@ -0,0 +1,253 @@ +static const uint8_t s_logo[4000] = +{ + 0xdc, 0x03, 0xdc, 0x03, 0xdc, 0x03, 0xdc, 0x03, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // ........ . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0xdc, 0x08, // . . . . . . ... + 0xdc, 0x03, 0xdc, 0x07, 0xdc, 0x07, 0xdc, 0x08, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // ........ . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0xde, 0x03, 0xb0, 0x3b, 0xb1, 0x3b, 0xb2, 0x3b, 0xdb, 0x3b, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // ...;.;.;.; . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0xdc, 0x03, 0xb1, 0x3b, 0xb2, 0x3b, // . . . . ....;.; + 0xdb, 0x3b, 0xdf, 0x03, 0xdf, 0x3b, 0xb2, 0x3f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // .;...;.? . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0xb1, 0x3b, 0xb1, 0x3b, 0xb2, 0x3b, 0xb2, 0x3f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // ..;.;.;.? . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0xb1, 0x3b, 0xb1, 0x3b, 0xb2, 0x3b, // . . . . ..;.;.; + 0xb2, 0x3f, 0x20, 0x0f, 0x20, 0x0f, 0xdf, 0x03, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // .? . ... . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0xb1, 0x3b, 0xb1, 0x3b, 0xb1, 0x3b, 0xb1, 0x3f, 0xdc, 0x0b, 0xdc, 0x03, 0xdc, 0x03, // ..;.;.;.?...... + 0xdc, 0x03, 0xdc, 0x03, 0x20, 0x0f, 0x20, 0x0f, 0xdc, 0x08, 0xdc, 0x03, 0xdc, 0x03, 0xdc, 0x03, // .... . ......... + 0xdc, 0x03, 0xdc, 0x03, 0xdc, 0x03, 0xdc, 0x08, 0x20, 0x0f, 0xb1, 0x3b, 0xb1, 0x3b, 0xb1, 0x3b, // ........ ..;.;.; + 0xb1, 0x3f, 0xb1, 0x3f, 0xb2, 0x0b, 0x20, 0x0f, 0x20, 0x0f, 0xdc, 0x03, 0xdc, 0x03, 0xdc, 0x03, // .?.?.. . ....... + 0x20, 0x0f, 0x20, 0x0f, 0xdc, 0x03, 0xdc, 0x03, 0xdc, 0x03, 0x20, 0x0f, 0x20, 0x01, 0x20, 0x0f, // . ....... . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0xb2, 0x3b, 0xb1, 0x3b, 0xb0, 0x3b, 0xb0, 0x3f, 0x20, 0x0f, 0xde, 0x03, 0xb0, 0x3f, // ..;.;.;.? ....? + 0xb1, 0x3f, 0xb2, 0x3f, 0xdd, 0x03, 0xde, 0x03, 0xdb, 0x03, 0xdb, 0x03, 0xb2, 0x3f, 0x20, 0x0f, // .?.?.........? . + 0x20, 0x0f, 0xb0, 0x3f, 0xb1, 0x3f, 0xb2, 0x3f, 0xde, 0x38, 0xb2, 0x3b, 0xb1, 0x3b, 0xb0, 0x3b, // ..?.?.?.8.;.;.; + 0xb0, 0x3f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0xb0, 0x3b, 0xb1, 0x3b, 0xb2, 0x3b, 0xb2, 0x3f, // .? . . ..;.;.;.? + 0xdd, 0x03, 0xde, 0x03, 0xb0, 0x3f, 0xb1, 0x3f, 0xb2, 0x3f, 0xdd, 0x03, 0x20, 0x01, 0x20, 0x0f, // .....?.?.?.. . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0xb2, 0x3b, 0xb1, 0x3b, 0xb0, 0x3b, 0xb0, 0x3f, 0x20, 0x0f, 0x20, 0x0f, 0xdb, 0x03, // ..;.;.;.? . ... + 0xb0, 0x3f, 0xb1, 0x3f, 0xdd, 0x03, 0xb1, 0x3b, 0xb0, 0x3b, 0xdb, 0x03, 0xb1, 0x3f, 0x20, 0x0f, // .?.?...;.;...? . + 0x20, 0x0f, 0x20, 0x3f, 0xb0, 0x3f, 0xb1, 0x3f, 0xb0, 0x3b, 0xb2, 0x3b, 0xb1, 0x3b, 0xb0, 0x3b, // . ?.?.?.;.;.;.; + 0xb0, 0x3f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0xdc, 0x08, 0xdc, 0x3b, 0xb1, 0x3b, 0xb1, 0x3f, // .? . . ....;.;.? + 0xb1, 0x3b, 0xb0, 0x3b, 0xb2, 0x3b, 0xb0, 0x3f, 0xdc, 0x03, 0x20, 0x0f, 0x20, 0x01, 0x20, 0x0f, // .;.;.;.?.. . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0xb2, 0x3b, 0xb1, 0x3b, 0xb0, 0x3b, 0xb0, 0x3f, 0xdc, 0x0b, 0xdc, 0x07, 0xdb, 0x03, // ..;.;.;.?...... + 0xdb, 0x03, 0xdc, 0x38, 0x20, 0x0f, 0xdf, 0x03, 0xb1, 0x3b, 0xb0, 0x3b, 0xb0, 0x3f, 0xdc, 0x03, // ...8 ....;.;.?.. + 0xdc, 0x07, 0xb0, 0x3f, 0xb1, 0x3f, 0xb2, 0x3f, 0xdd, 0x3b, 0xb2, 0x3b, 0xb1, 0x3b, 0xdc, 0x78, // ...?.?.?.;.;.;.x + 0xdf, 0x08, 0x20, 0x0f, 0x20, 0x0f, 0xde, 0x08, 0xb2, 0x3b, 0xb1, 0x3b, 0xb0, 0x3b, 0xb0, 0x3f, // .. . ....;.;.;.? + 0x20, 0x0f, 0xdf, 0x03, 0xb1, 0x3b, 0xb2, 0x3b, 0xdb, 0x03, 0xdd, 0x03, 0x20, 0x01, 0x20, 0x0f, // ....;.;.... . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0xdc, 0x08, 0xdc, 0x08, 0xdc, 0x08, 0x20, 0x0f, // . . . ....... . + 0x20, 0x0f, 0xb0, 0x3f, 0xb0, 0x3f, 0xb1, 0x3f, 0xdd, 0x3b, 0xdb, 0x0b, 0xdf, 0x03, 0x20, 0x0f, // ..?.?.?.;.... . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0xdf, 0x08, 0xdf, 0x03, 0xdf, 0x03, 0xdf, 0x08, // . . . ......... + 0x20, 0x0f, 0x20, 0x0f, 0xdf, 0x08, 0xdf, 0x03, 0xdf, 0x03, 0x20, 0x0f, 0x20, 0x01, 0x20, 0x0f, // . ....... . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0xdb, 0x08, 0xb2, 0x38, 0xb1, 0x38, 0xdc, 0x03, // . . . ....8.8.. + 0xdc, 0x07, 0xb0, 0x3b, 0xb1, 0x3b, 0xdf, 0x3b, 0xdf, 0x08, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // ...;.;.;.. . . . + 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, // . . . . . . . . + 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, // . . . . . . . . + 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, // . . . . . . . . + 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, // . . . . . . . . + 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, // . . . . . . . . + 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, // . . . . . . . . + 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, // . . . . . . . . + 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0b, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x2d, 0x08, 0x3d, 0x08, 0x20, 0x0a, 0x43, 0x0b, 0x72, 0x0b, 0x6f, 0x0b, 0x73, 0x0b, 0x73, 0x0b, // -.=. .C.r.o.s.s. + 0x2d, 0x0b, 0x70, 0x0b, 0x6c, 0x0b, 0x61, 0x0b, 0x74, 0x0b, 0x66, 0x0b, 0x6f, 0x0b, 0x72, 0x0b, // -.p.l.a.t.f.o.r. + 0x6d, 0x0b, 0x20, 0x0b, 0x72, 0x0b, 0x65, 0x0b, 0x6e, 0x0b, 0x64, 0x0b, 0x65, 0x0b, 0x72, 0x0b, // m. .r.e.n.d.e.r. + 0x69, 0x0b, 0x6e, 0x0b, 0x67, 0x0b, 0x20, 0x0b, 0x6c, 0x0b, 0x69, 0x0b, 0x62, 0x0b, 0x72, 0x0b, // i.n.g. .l.i.b.r. + 0x61, 0x0b, 0x72, 0x0b, 0x79, 0x0b, 0x20, 0x0f, 0x3d, 0x08, 0x2d, 0x08, 0x20, 0x01, 0x20, 0x0f, // a.r.y. .=.-. . . + 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, // . . . . . . . . + 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, // . . . . . . . . + 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, // . . . . . . . . + 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, // . . . . . . . . + 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, 0x20, 0x0a, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . + 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, 0x20, 0x0f, // . . . . . . . . +}; diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..8144d39 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,27 @@ +#include + +#include "common.h" +#include "shaders.h" + +App_Config app_config = { 640, 480 }; +App_State app_state = { NULL, 0 }; + +int main(int argc, char *argv[]) { + + app_init_quickjs(argc, argv); + app_init_sdl(); + app_init_bgfx(); + + // Main loop + while (!app_state.quit) { + app_update_sdl(); + app_update_quickjs(); + app_update_bgfx(); + } + + app_dispose_bgfx(); + app_dispose_sdl(); + app_dispose_quickjs(); + return 0; +} + diff --git a/src/quickjs.cpp b/src/quickjs.cpp new file mode 100644 index 0000000..0e7cd47 --- /dev/null +++ b/src/quickjs.cpp @@ -0,0 +1,113 @@ +#include +#include "common.h" +#include + +static JSContext *JS_NewCustomContext(JSRuntime *rt); +static int eval_buf(JSContext *ctx, const void *buf, int buf_len, + const char *filename, int eval_flags); + +static JSRuntime* rt; +static JSContext* ctx; + +int app_init_quickjs(int argc, char** argv){ + rt = JS_NewRuntime(); + if (!rt) + { + fprintf(stderr, "qjs: cannot allocate JS runtime\n"); + return -1; + } + js_std_set_worker_new_context_func(JS_NewCustomContext); + js_std_init_handlers(rt); + ctx = JS_NewCustomContext(rt); + if (!ctx) { + fprintf(stderr, "qjs: cannot allocate JS context\n"); + return -1; + } + + JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); + js_std_add_helpers(ctx, argc, argv); + + const char *str = "import * as std from 'std';\n" + "import * as os from 'os';\n" + "globalThis.std = std;\n" + "globalThis.os = os;\n"; + eval_buf(ctx, str, strlen(str), "", JS_EVAL_TYPE_MODULE); + + const char* filename = "main.js"; + size_t len; + const char* buf = app_read_file(filename, &len); + if (!buf) { + JS_ThrowReferenceError(ctx, "could not load module filename '%s'", + filename); + return -1; + } + int res = eval_buf(ctx, buf, len, "main", JS_EVAL_TYPE_MODULE); + if(res){ + return res; + } + return 0; +} + +int app_update_quickjs(){ + JSContext *ctx1; + int err; + + /* execute the pending jobs */ + for(;;) { + err = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); + if (err <= 0) { + if (err < 0) { + js_std_dump_error(ctx1); + } + break; + } + } +} + +int app_dispose_quickjs(){ + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + +/* also used to initialize the worker context */ +static JSContext *JS_NewCustomContext(JSRuntime *rt) +{ + JSContext *ctx; + ctx = JS_NewContext(rt); + if (!ctx) + return NULL; + + /* system modules */ + js_init_module_std(ctx, "std"); + js_init_module_os(ctx, "os"); + return ctx; +} + +static int eval_buf(JSContext *ctx, const void *buf, int buf_len, + const char *filename, int eval_flags) +{ + JSValue val; + int ret; + + if ((eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_MODULE) { + /* for the modules, we compile then run to be able to set + import.meta */ + val = JS_Eval(ctx, (const char*)buf, buf_len, filename, + eval_flags | JS_EVAL_FLAG_COMPILE_ONLY); + if (!JS_IsException(val)) { + js_module_set_import_meta(ctx, val, 1, 1); + val = JS_EvalFunction(ctx, val); + } + } else { + val = JS_Eval(ctx, (const char*)buf, buf_len, filename, eval_flags); + } + if (JS_IsException(val)) { + js_std_dump_error(ctx); + ret = -1; + } else { + ret = 0; + } + JS_FreeValue(ctx, val); + return ret; +} \ No newline at end of file diff --git a/src/sdl.cpp b/src/sdl.cpp new file mode 100644 index 0000000..bb35e1f --- /dev/null +++ b/src/sdl.cpp @@ -0,0 +1,52 @@ +#include "common.h" + +static SDL_Event event; +static bool is_initialized = false; +static bool is_window_created = false; +static Uint32 init_flags = SDL_INIT_VIDEO; + +int app_init_sdl(){ + // Initialize SDL + if (SDL_Init(init_flags) < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize SDL: %s", SDL_GetError()); + return -1; + } + is_initialized = true; + // Create a window and renderer + app_state.window = SDL_CreateWindow("hello bgfx", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + app_config.width, + app_config.height, + SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + if (!app_state.window) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create window: %s", SDL_GetError()); + return -1; + } + is_window_created = true; + + return 0; +} + +int app_update_sdl(){ + // Handle events + while (SDL_PollEvent(&event)) { + SDL_KeyCode keycode; + switch (event.type) { + case SDL_QUIT: + app_state.quit = true; + break; + default: + break; + } + } + return 0; +} + +int app_dispose_sdl(){ + if(is_window_created) + SDL_DestroyWindow(app_state.window); + + if(is_initialized) + SDL_Quit(); +} \ No newline at end of file diff --git a/src/shaders.h b/src/shaders.h new file mode 100644 index 0000000..a132514 --- /dev/null +++ b/src/shaders.h @@ -0,0 +1,19 @@ +#ifndef SHADERS_H +#define SHADERS_H + +#include + +#if BX_PLATFORM_WINDOWS +#include +#include +#include +#include +#elif BX_PLATFORM_OSX +#include +#include +#elif (BX_PLATFORM_LINUX || BX_PLATFORM_EMSCRIPTEN) +#include +#include +#endif + +#endif \ No newline at end of file diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000..6d6c0e1 --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,33 @@ +#include "common.h" + +// Function to read a file into a string +char* app_read_file(const char* filename, size_t* out_size) { + FILE* file = fopen(filename, "rb"); + if (!file) { + fprintf(stderr, "Failed to open file: %s\n", filename); + return NULL; + } + + // Get the file size + fseek(file, 0, SEEK_END); + long size = ftell(file); + if(out_size) *out_size = (size_t)size; + rewind(file); + + // Allocate a buffer to hold the file contents + char* buffer = (char*) malloc(size + 1); + if (!buffer) { + fprintf(stderr, "Failed to allocate memory for file contents\n"); + fclose(file); + return NULL; + } + + // Read the file contents into the buffer + size_t bytesRead = fread(buffer, 1, size, file); + buffer[bytesRead] = '\0'; + + // Clean up + fclose(file); + + return buffer; +} \ No newline at end of file diff --git a/thirdparty/SDL b/thirdparty/SDL index f7df966..ac13ca9 160000 --- a/thirdparty/SDL +++ b/thirdparty/SDL @@ -1 +1 @@ -Subproject commit f7df966b417d351301cf4a3ded5a54d4a29804e8 +Subproject commit ac13ca9ab691e13e8eebe9684740ddcb0d716203