fix syntax

This commit is contained in:
2026-02-17 09:12:48 -06:00
parent 6f6f987649
commit d509f7cbb8
21 changed files with 503 additions and 453 deletions

48
audio.c
View File

@@ -43,22 +43,24 @@ SDL_AudioSpec js2SDL_AudioSpec(JSContext *js, JSValue v) {
}
JSValue SDL_AudioSpec2js(JSContext *js, SDL_AudioSpec spec) {
JSValue obj = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(obj, JS_NewObject(js));
JS_SetPropertyStr(js, obj, "format", SDL_AudioFormat2js(js, spec.format));
JS_SetPropertyStr(js, obj, "channels", JS_NewInt32(js, spec.channels));
JS_SetPropertyStr(js, obj, "freq", JS_NewInt32(js, spec.freq));
return obj;
JS_RETURN(obj);
}
// Enum mappings for audio formats (simplified)
JSValue js_get_audio_drivers(JSContext *js, JSValue self, int argc, JSValue *argv) {
JS_FRAME(js);
int count = SDL_GetNumAudioDrivers();
JSValue arr = JS_NewArray(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < count; i++) {
const char *driver = SDL_GetAudioDriver(i);
JS_SetPropertyUint32(js, arr, i, JS_NewString(js, driver));
JS_SetPropertyNumber(js, arr, i, JS_NewString(js, driver));
}
return arr;
JS_RETURN(arr);
}
JSValue js_get_current_audio_driver(JSContext *js, JSValue self, int argc, JSValue *argv) {
@@ -69,23 +71,25 @@ JSValue js_get_current_audio_driver(JSContext *js, JSValue self, int argc, JSVal
JSValue js_get_audio_playback_devices(JSContext *js, JSValue self, int argc, JSValue *argv) {
SDL_AudioDeviceID *devices = SDL_GetAudioPlaybackDevices(NULL);
if (!devices) return JS_NULL;
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; devices[i]; i++) {
JS_SetPropertyUint32(js, arr, i, SDL_AudioDeviceID2js(js, devices[i]));
JS_SetPropertyNumber(js, arr, i, SDL_AudioDeviceID2js(js, devices[i]));
}
SDL_free(devices);
return arr;
JS_RETURN(arr);
}
JSValue js_get_audio_recording_devices(JSContext *js, JSValue self, int argc, JSValue *argv) {
SDL_AudioDeviceID *devices = SDL_GetAudioRecordingDevices(NULL);
if (!devices) return JS_NULL;
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; devices[i]; i++) {
JS_SetPropertyUint32(js, arr, i, SDL_AudioDeviceID2js(js, devices[i]));
JS_SetPropertyNumber(js, arr, i, SDL_AudioDeviceID2js(js, devices[i]));
}
SDL_free(devices);
return arr;
JS_RETURN(arr);
}
JSValue js_get_audio_device_name(JSContext *js, JSValue self, int argc, JSValue *argv) {
@@ -201,9 +205,11 @@ JSC_CCALL(audio_stream_get_format,
if (!SDL_GetAudioStreamFormat(stream, &src, &dst)) {
ret = JS_NULL;
} else {
JSValue obj = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(obj, JS_NewObject(js));
JS_SetPropertyStr(js, obj, "src", SDL_AudioSpec2js(js, src));
JS_SetPropertyStr(js, obj, "dst", SDL_AudioSpec2js(js, dst));
JS_RestoreFrame(_js_ctx, _js_gc_frame, _js_local_frame);
ret = obj;
}
)
@@ -317,12 +323,13 @@ JSValue js_load_wav(JSContext *js, JSValue self, int argc, JSValue *argv) {
return JS_ThrowInternalError(js, "Failed to load WAV: %s", SDL_GetError());
}
JS_FreeCString(js, path);
JSValue obj = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(obj, JS_NewObject(js));
JS_SetPropertyStr(js, obj, "spec", SDL_AudioSpec2js(js, spec));
JS_SetPropertyStr(js, obj, "data", js_new_blob_stoned_copy(js, data, len));
SDL_free(data);
return obj;
JS_RETURN(obj);
}
JSC_CCALL(convert_audio_samples,
@@ -407,12 +414,13 @@ static const JSCFunctionListEntry js_sdl_audio_funcs[] = {
CELL_USE_INIT(
SDL_Init(SDL_INIT_AUDIO);
JS_NewClassID(&js_SDL_AudioStream_id);
JS_NewClass(JS_GetRuntime(js), js_SDL_AudioStream_id, &js_SDL_AudioStream_class);
JSValue proto = JS_NewObject(js);
JS_NewClass(js, js_SDL_AudioStream_id, &js_SDL_AudioStream_class);
JS_FRAME(js);
JS_LOCAL(proto, JS_NewObject(js));
JS_SetPropertyFunctionList(js, proto, js_SDL_AudioStream_funcs, countof(js_SDL_AudioStream_funcs));
JS_SetClassProto(js, js_SDL_AudioStream_id, proto);
JSValue export = JS_NewObject(js);
JS_SetPropertyFunctionList(js, export, js_sdl_audio_funcs, countof(js_sdl_audio_funcs));
return export;
JS_LOCAL(mod, JS_NewObject(js));
JS_SetPropertyFunctionList(js, mod, js_sdl_audio_funcs, countof(js_sdl_audio_funcs));
JS_RETURN(mod);
)

View File

@@ -42,13 +42,14 @@ JSC_CCALL(camera_get_cameras,
int count = 0;
SDL_CameraID *cameras = SDL_GetCameras(&count);
if (!cameras) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < count; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewUint32(js, cameras[i]));
JS_SetPropertyNumber(js, arr, i, JS_NewUint32(js, cameras[i]));
}
SDL_free(cameras);
return arr;
JS_RETURN(arr);
)
// SDL_GetCameraSupportedFormats(id) -> array of format objects
@@ -60,19 +61,23 @@ JSC_CCALL(camera_get_supported_formats,
SDL_CameraSpec **specs = SDL_GetCameraSupportedFormats(id, &count);
if (!specs) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
JSValue obj = JS_NULL;
JSLocalRef obj__lr = {.ptr = &obj};
JS_PushLocalRef(_js_ctx, &obj__lr);
for (int i = 0; i < count; i++) {
SDL_CameraSpec *spec = specs[i];
JSValue obj = JS_NewObject(js);
obj = JS_NewObject(js);
JS_SetPropertyStr(js, obj, "format", SDL_PixelFormat2js(js, spec->format));
JS_SetPropertyStr(js, obj, "width", JS_NewInt32(js, spec->width));
JS_SetPropertyStr(js, obj, "height", JS_NewInt32(js, spec->height));
JS_SetPropertyStr(js, obj, "framerate_numerator", JS_NewInt32(js, spec->framerate_numerator));
JS_SetPropertyStr(js, obj, "framerate_denominator", JS_NewInt32(js, spec->framerate_denominator));
JS_SetPropertyUint32(js, arr, i, obj);
JS_SetPropertyNumber(js, arr, i, obj);
}
SDL_free(specs);
return arr;
JS_RETURN(arr);
)
// SDL_GetCameraName(id) -> string
@@ -129,14 +134,15 @@ JSC_CCALL(camera_get_format,
SDL_Camera *camera = js2SDL_Camera(js, self);
SDL_CameraSpec spec;
if (!SDL_GetCameraFormat(camera, &spec)) return JS_NULL;
JSValue obj = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(obj, JS_NewObject(js));
JS_SetPropertyStr(js, obj, "format", SDL_PixelFormat2js(js, spec.format));
JS_SetPropertyStr(js, obj, "width", JS_NewInt32(js, spec.width));
JS_SetPropertyStr(js, obj, "height", JS_NewInt32(js, spec.height));
JS_SetPropertyStr(js, obj, "framerate_numerator", JS_NewInt32(js, spec.framerate_numerator));
JS_SetPropertyStr(js, obj, "framerate_denominator", JS_NewInt32(js, spec.framerate_denominator));
return obj;
JS_RETURN(obj);
)
JSC_CCALL(camera_acquire_frame,
@@ -144,11 +150,12 @@ JSC_CCALL(camera_acquire_frame,
Uint64 timestamp;
SDL_Surface *surface = SDL_AcquireCameraFrame(camera, &timestamp);
if (!surface) return JS_NULL;
JSValue obj = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(obj, JS_NewObject(js));
JS_SetPropertyStr(js, obj, "surface", SDL_Surface2js(js, surface));
JS_SetPropertyStr(js, obj, "timestamp", JS_NewInt64(js, timestamp));
return obj;
JS_RETURN(obj);
)
JSC_CCALL(camera_release_frame,
@@ -187,9 +194,9 @@ static const JSCFunctionListEntry js_camera_funcs[] = {
CELL_USE_INIT(
SDL_Init(SDL_INIT_CAMERA);
QJSCLASSPREP_FUNCS(SDL_Camera);
JSValue ret = JS_NewObject(js);
JS_SetPropertyFunctionList(js, ret, js_camera_funcs, countof(js_camera_funcs));
return ret;
JS_FRAME(js);
JS_LOCAL(mod, JS_NewObject(js));
JS_SetPropertyFunctionList(js, mod, js_camera_funcs, countof(js_camera_funcs));
JS_RETURN(mod);
)

View File

@@ -1,2 +1,3 @@
[compilation]
CFLAGS = "-I/opt/homebrew/include"
LDFLAGS = "-lSDL3"

View File

@@ -66,13 +66,14 @@ JSC_CCALL(clipboard_get_mime_types,
size_t count = 0;
char **types = SDL_GetClipboardMimeTypes(&count);
if (!types) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (size_t i = 0; i < count; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewString(js, types[i]));
JS_SetPropertyNumber(js, arr, i, JS_NewString(js, types[i]));
}
SDL_free(types);
return arr;
JS_RETURN(arr);
)
static const JSCFunctionListEntry js_clipboard_funcs[] = {

View File

@@ -150,8 +150,9 @@ static const char *mouse_button_to_string(Uint8 button) {
// Convert SDL_Event to JS object
static JSValue event_to_js(JSContext *js, SDL_Event *event) {
JSValue obj = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(obj, JS_NewObject(js));
JS_SetPropertyStr(js, obj, "type", JS_NewString(js, event_type_to_string(event->type)));
JS_SetPropertyStr(js, obj, "timestamp", JS_NewInt64(js, event->common.timestamp));
@@ -322,8 +323,10 @@ static JSValue event_to_js(JSContext *js, SDL_Event *event) {
JS_SetPropertyStr(js, obj, "sensor", JS_NewInt32(js, event->gsensor.sensor));
{
JSValue data = JS_NewArray(js);
JSLocalRef data__lr = {.ptr = &data};
JS_PushLocalRef(_js_ctx, &data__lr);
for (int i = 0; i < 3; i++) {
JS_SetPropertyUint32(js, data, i, JS_NewFloat64(js, event->gsensor.data[i]));
JS_SetPropertyNumber(js, data, i, JS_NewFloat64(js, event->gsensor.data[i]));
}
JS_SetPropertyStr(js, obj, "data", data);
}
@@ -375,8 +378,10 @@ static JSValue event_to_js(JSContext *js, SDL_Event *event) {
JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->sensor.which));
{
JSValue data = JS_NewArray(js);
JSLocalRef data__lr = {.ptr = &data};
JS_PushLocalRef(_js_ctx, &data__lr);
for (int i = 0; i < 6; i++) {
JS_SetPropertyUint32(js, data, i, JS_NewFloat64(js, event->sensor.data[i]));
JS_SetPropertyNumber(js, data, i, JS_NewFloat64(js, event->sensor.data[i]));
}
JS_SetPropertyStr(js, obj, "data", data);
}
@@ -438,8 +443,8 @@ static JSValue event_to_js(JSContext *js, SDL_Event *event) {
default:
break;
}
return obj;
JS_RETURN(obj);
}
// SDL_PumpEvents()
@@ -480,22 +485,24 @@ JSC_CCALL(events_wait,
JSC_CCALL(events_peep,
int count = 10;
if (argc > 0) JS_ToInt32(js, &count, argv[0]);
SDL_Event *events = malloc(count * sizeof(SDL_Event));
if (!events) return JS_ThrowOutOfMemory(js);
int num = SDL_PeepEvents(events, count, SDL_PEEKEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST);
if (num < 0) {
free(events);
return JS_NewArray(js);
}
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < num; i++) {
JS_SetPropertyUint32(js, arr, i, event_to_js(js, &events[i]));
JS_SetPropertyNumber(js, arr, i, event_to_js(js, &events[i]));
}
free(events);
return arr;
JS_RestoreFrame(_js_ctx, _js_gc_frame, _js_local_frame);
ret = arr;
)
// SDL_HasEvent(type) -> bool
@@ -524,13 +531,15 @@ JSC_CCALL(events_flush_range,
// Get all pending events as array
JSC_CCALL(events_get_all,
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
SDL_Event event;
int i = 0;
while (SDL_PollEvent(&event)) {
JS_SetPropertyUint32(js, arr, i++, event_to_js(js, &event));
JS_SetPropertyNumber(js, arr, i++, event_to_js(js, &event));
}
return arr;
JS_RestoreFrame(_js_ctx, _js_gc_frame, _js_local_frame);
ret = arr;
)
static const JSCFunctionListEntry js_events_funcs[] = {
@@ -544,4 +553,9 @@ static const JSCFunctionListEntry js_events_funcs[] = {
MIST_FUNC_DEF(events, get_all, 0),
};
CELL_USE_FUNCS(js_events_funcs)
CELL_USE_INIT(
JS_FRAME(js);
JS_LOCAL(mod, JS_NewObject(js));
JS_SetPropertyFunctionList(js, mod, js_events_funcs, countof(js_events_funcs));
JS_RETURN(mod);
)

View File

@@ -72,8 +72,11 @@ var keys = {
var running = true
var last_time = time.number()
var ev = null
var key_name = null
var pressed = null
function frame() {
var frame = function() {
if (!running) {
log.console("Exiting...")
$stop()
@@ -86,28 +89,29 @@ function frame() {
last_time = now
// Process events
var ev
while ((ev = events.poll()) != null) {
ev = events.poll()
while (ev != null) {
if (ev.type == "quit" || ev.type == "window_close_requested") {
running = false
return
}
if (ev.type == "key_down" || ev.type == "key_up") {
var key_name = lower(keyboard.get_key_name(ev.key))
var pressed = ev.type == "key_down"
key_name = lower(keyboard.get_key_name(ev.key))
pressed = ev.type == "key_down"
if (key_name == "w") keys.w = pressed
if (key_name == "a") keys.a = pressed
if (key_name == "s") keys.s = pressed
if (key_name == "d") keys.d = pressed
if (key_name == "escape" && pressed) running = false
}
ev = events.poll()
}
// Update position based on keys
if (keys.w) img_y -= speed * dt
if (keys.s) img_y += speed * dt
if (keys.a) img_x -= speed * dt
if (keys.d) img_x += speed * dt
if (keys.w) img_y = img_y - speed * dt
if (keys.s) img_y = img_y + speed * dt
if (keys.a) img_x = img_x - speed * dt
if (keys.d) img_x = img_x + speed * dt
// Clear screen (dark gray)
renderer.draw_color([0.2, 0.2, 0.2, 1])

View File

@@ -142,13 +142,14 @@ JSC_CCALL(gamepad_get_gamepads,
int count = 0;
SDL_JoystickID *gamepads = SDL_GetGamepads(&count);
if (!gamepads) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < count; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewUint32(js, gamepads[i]));
JS_SetPropertyNumber(js, arr, i, JS_NewUint32(js, gamepads[i]));
}
SDL_free(gamepads);
return arr;
JS_RETURN(arr);
)
// SDL_IsGamepad(id) -> bool
@@ -340,13 +341,14 @@ JSC_CCALL(gamepad_get_touchpad_finger,
float x, y, pressure;
if (!SDL_GetGamepadTouchpadFinger(gamepad, touchpad, finger, &down, &x, &y, &pressure))
return JS_NULL;
JSValue result = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(result, JS_NewObject(js));
JS_SetPropertyStr(js, result, "down", JS_NewBool(js, down));
JS_SetPropertyStr(js, result, "x", JS_NewFloat64(js, x));
JS_SetPropertyStr(js, result, "y", JS_NewFloat64(js, y));
JS_SetPropertyStr(js, result, "pressure", JS_NewFloat64(js, pressure));
return result;
JS_RETURN(result);
)
JSC_CCALL(gamepad_has_sensor,
@@ -377,21 +379,22 @@ JSC_CCALL(gamepad_get_sensor_data,
JS_ToInt32(js, &type, argv[0]);
int num_values = 3;
if (argc > 1) JS_ToInt32(js, &num_values, argv[1]);
float *data = malloc(num_values * sizeof(float));
if (!data) return JS_ThrowOutOfMemory(js);
if (!SDL_GetGamepadSensorData(gamepad, (SDL_SensorType)type, data, num_values)) {
free(data);
return JS_NULL;
}
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < num_values; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewFloat64(js, data[i]));
JS_SetPropertyNumber(js, arr, i, JS_NewFloat64(js, data[i]));
}
free(data);
return arr;
JS_RETURN(arr);
)
JSC_CCALL(gamepad_rumble,
@@ -425,8 +428,7 @@ JSC_CCALL(gamepad_get_power_info,
SDL_Gamepad *gamepad = js2SDL_Gamepad(js, self);
int percent;
SDL_PowerState state = SDL_GetGamepadPowerInfo(gamepad, &percent);
JSValue result = JS_NewObject(js);
const char *state_str;
switch (state) {
case SDL_POWERSTATE_ON_BATTERY: state_str = "on_battery"; break;
@@ -435,9 +437,12 @@ JSC_CCALL(gamepad_get_power_info,
case SDL_POWERSTATE_CHARGED: state_str = "charged"; break;
default: state_str = "unknown"; break;
}
JS_FRAME(js);
JS_LOCAL(result, JS_NewObject(js));
JS_SetPropertyStr(js, result, "state", JS_NewString(js, state_str));
JS_SetPropertyStr(js, result, "percent", JS_NewInt32(js, percent));
return result;
JS_RETURN(result);
)
JSC_CCALL(gamepad_close,
@@ -494,9 +499,10 @@ static const JSCFunctionListEntry js_gamepad_funcs[] = {
CELL_USE_INIT(
SDL_Init(SDL_INIT_GAMEPAD);
QJSCLASSPREP_FUNCS(SDL_Gamepad);
JSValue ret = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(ret, JS_NewObject(js));
JS_SetPropertyFunctionList(js, ret, js_gamepad_funcs, countof(js_gamepad_funcs));
return ret;
JS_RETURN(ret);
)

127
gpu.c
View File

@@ -579,7 +579,7 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst
Uint32 vbd_len = JS_ArrayLength(js,vbd_val);
SDL_GPUVertexBufferDescription vbd[vbd_len];
for (Uint32 i = 0; i < vbd_len; i++) {
JSValue elem = JS_GetPropertyUint32(js, vbd_val, i);
JSValue elem = JS_GetPropertyNumber(js, vbd_val, i);
if (JS_IsObject(elem)) {
JSValue slot_val = JS_GetPropertyStr(js, elem, "slot");
JSValue pitch_val = JS_GetPropertyStr(js, elem, "pitch");
@@ -615,7 +615,7 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst
SDL_GPUVertexAttribute vat[vat_len];
for (Uint32 i = 0; i < vat_len; i++) {
JSValue elem = JS_GetPropertyUint32(js, vat_val, i);
JSValue elem = JS_GetPropertyNumber(js, vat_val, i);
if (JS_IsObject(elem)) {
JSValue loc_val = JS_GetPropertyStr(js, elem, "location");
JSValue slot_val = JS_GetPropertyStr(js, elem, "buffer_slot");
@@ -703,7 +703,7 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst
target_info.color_target_descriptions = dsc;
for (int i = 0; i < target_info.num_color_targets; i++) {
JSValue c = JS_GetPropertyUint32(js,color_tars,i);
JSValue c = JS_GetPropertyNumber(js,color_tars,i);
dsc[i] = js2SDL_GPUColorTargetDescription(js,c);
JS_FreeValue(js,c);
}
@@ -825,7 +825,7 @@ JSC_CCALL(gpu_wait_for_fences,
int n = JS_ArrayLength(js,argv[0]);
SDL_GPUFence *fences[n];
for (int i = 0; i < n; i++) {
JSValue a = JS_GetPropertyUint32(js,argv[0],i);
JSValue a = JS_GetPropertyNumber(js,argv[0],i);
fences[i] = js2SDL_GPUFence(js,a);
JS_FreeValue(js,a);
}
@@ -844,16 +844,18 @@ JSC_CCALL(gpu_shader_format,
SDL_GPUDevice *gpu = js2SDL_GPUDevice(js,self);
SDL_GPUShaderFormat fmt = SDL_GetGPUShaderFormats(gpu);
if (!fmt) return JS_ThrowReferenceError(js, "Shader format available invalid.");
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
int i = 0;
if (fmt & SDL_GPU_SHADERFORMAT_PRIVATE) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, ".private"));
if (fmt & SDL_GPU_SHADERFORMAT_SPIRV) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, "spv"));
if (fmt & SDL_GPU_SHADERFORMAT_DXBC) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, "dxbc"));
if (fmt & SDL_GPU_SHADERFORMAT_DXIL) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, "dxil"));
if (fmt & SDL_GPU_SHADERFORMAT_MSL) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, "msl"));
if (fmt & SDL_GPU_SHADERFORMAT_METALLIB) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, "metallib"));
return arr;
if (fmt & SDL_GPU_SHADERFORMAT_PRIVATE) JS_SetPropertyNumber(js, arr, i++, JS_NewString(js, ".private"));
if (fmt & SDL_GPU_SHADERFORMAT_SPIRV) JS_SetPropertyNumber(js, arr, i++, JS_NewString(js, "spv"));
if (fmt & SDL_GPU_SHADERFORMAT_DXBC) JS_SetPropertyNumber(js, arr, i++, JS_NewString(js, "dxbc"));
if (fmt & SDL_GPU_SHADERFORMAT_DXIL) JS_SetPropertyNumber(js, arr, i++, JS_NewString(js, "dxil"));
if (fmt & SDL_GPU_SHADERFORMAT_MSL) JS_SetPropertyNumber(js, arr, i++, JS_NewString(js, "msl"));
if (fmt & SDL_GPU_SHADERFORMAT_METALLIB) JS_SetPropertyNumber(js, arr, i++, JS_NewString(js, "metallib"));
JS_RestoreFrame(_js_ctx, _js_gc_frame, _js_local_frame);
ret = arr;
)
// Standalone compute pipeline constructor: new sdl_gpu.compute_pipeline(device, config)
@@ -988,12 +990,13 @@ static JSValue js_gpu_texture_constructor(JSContext *js, JSValueConst self, int
SDL_GPUTexture *tex = SDL_CreateGPUTexture(gpu, &info);
if (!tex) return JS_ThrowReferenceError(js, "Unable to create texture: %s", SDL_GetError());
JSValue jstex = SDL_GPUTexture2js(js, argv[0], tex);
JS_FRAME(js);
JS_LOCAL(jstex, SDL_GPUTexture2js(js, argv[0], tex));
JS_SetPropertyStr(js, jstex, "width", number2js(js, info.width));
JS_SetPropertyStr(js, jstex, "height", number2js(js, info.height));
JS_SetPropertyStr(js, jstex, "dim", vec22js(js, (vec2){info.width, info.height}));
return jstex;
JS_RETURN(jstex);
}
JSC_CCALL(gpu_swapchain_format,
@@ -1040,7 +1043,7 @@ JSC_CCALL(renderpass_bind_buffers,
int len = JS_ArrayLength(js,buffers);
SDL_GPUBufferBinding bindings[len];
for (int i = 0; i < len; i++) {
JSValue buffer = JS_GetPropertyUint32(js,buffers,i);
JSValue buffer = JS_GetPropertyNumber(js,buffers,i);
bindings[i] = js2SDL_GPUBufferBinding(js, buffer);
JS_FreeValue(js,buffer);
}
@@ -1072,7 +1075,7 @@ JSC_CCALL(renderpass_bind_samplers,
int num = JS_ArrayLength(js,arr);
SDL_GPUTextureSamplerBinding binds[num];
for (int i = 0; i < num; i++) {
JSValue val = JS_GetPropertyUint32(js,arr,i);
JSValue val = JS_GetPropertyNumber(js,arr,i);
binds[i] = js2SDL_GPUTextureSamplerBinding(js, val);
JS_FreeValue(js,val);
}
@@ -1122,7 +1125,7 @@ JSC_CCALL(renderpass_bind_vertex_samplers,
int num = JS_ArrayLength(js,arr);
SDL_GPUTextureSamplerBinding binds[num];
for (int i = 0; i < num; i++) {
JSValue val = JS_GetPropertyUint32(js,arr,i);
JSValue val = JS_GetPropertyNumber(js,arr,i);
binds[i] = js2SDL_GPUTextureSamplerBinding(js,val);
JS_FreeValue(js,val);
}
@@ -1136,7 +1139,7 @@ JSC_CCALL(renderpass_bind_fragment_samplers,
int num = JS_ArrayLength(js,arr);
SDL_GPUTextureSamplerBinding binds[num];
for (int i = 0; i < num; i++) {
JSValue val = JS_GetPropertyUint32(js,arr,i);
JSValue val = JS_GetPropertyNumber(js,arr,i);
binds[i] = js2SDL_GPUTextureSamplerBinding(js,val);
JS_FreeValue(js,val);
}
@@ -1150,7 +1153,7 @@ JSC_CCALL(renderpass_bind_vertex_buffers,
int num = JS_ArrayLength(js,arr);
SDL_GPUBufferBinding binds[num];
for (int i = 0; i < num; i++) {
JSValue val = JS_GetPropertyUint32(js,arr,i);
JSValue val = JS_GetPropertyNumber(js,arr,i);
JS_GETPROP(js, binds[i].buffer, val, buffer, SDL_GPUBuffer)
JS_GETPROP(js, binds[i].offset, val, offset, number)
JS_FreeValue(js,val);
@@ -1189,7 +1192,7 @@ JSC_CCALL(cmd_render_pass,
JSValue passObj = argv[0];
JSValue colorTargetsVal = JS_GetPropertyStr(js, passObj, "color_targets");
if (!JS_IsArray(js, colorTargetsVal))
if (!JS_IsArray(colorTargetsVal))
return JS_ThrowTypeError(js, "render_pass: colorTargets must be an array");
uint32_t colorCount = JS_ArrayLength(js, colorTargetsVal);
@@ -1199,7 +1202,7 @@ JSC_CCALL(cmd_render_pass,
// Fill colorInfos from JS array
for (uint32_t i = 0; i < colorCount; i++) {
JSValue ctargetVal = JS_GetPropertyUint32(js, colorTargetsVal, i);
JSValue ctargetVal = JS_GetPropertyNumber(js, colorTargetsVal, i);
colortars[i] = js2SDL_GPUColorTargetInfo(js,ctargetVal);
JS_FreeValue(js, ctargetVal);
}
@@ -1367,7 +1370,7 @@ JSC_CCALL(cmd_swapchain_pass,
JSValue passObj = argv[1];
JSValue colorTargetsVal = JS_GetPropertyStr(js, passObj, "color_targets");
if (!JS_IsArray(js, colorTargetsVal)) {
if (!JS_IsArray(colorTargetsVal)) {
JS_FreeValue(js, colorTargetsVal);
return JS_ThrowTypeError(js, "swapchain_pass: color_targets must be an array");
}
@@ -1378,7 +1381,7 @@ JSC_CCALL(cmd_swapchain_pass,
return JS_ThrowTypeError(js, "swapchain_pass: only 1 color target is supported");
}
JSValue ctargetVal = JS_GetPropertyUint32(js, colorTargetsVal, 0);
JSValue ctargetVal = JS_GetPropertyNumber(js, colorTargetsVal, 0);
SDL_GPUColorTargetInfo colorTargetInfo = js2SDL_GPUColorTargetInfo(js, ctargetVal);
JS_FreeValue(js, ctargetVal);
JS_FreeValue(js, colorTargetsVal);
@@ -1434,7 +1437,7 @@ JSC_CCALL(cmd_swapchain_pass,
JSC_CCALL(cmd_acquire_swapchain_texture,
SDL_GPUCommandBuffer *cmdbuf = js2SDL_GPUCommandBuffer(js, self);
SDL_Window *window = js2SDL_Window(js, argv[0]);
SDL_GPUTexture* swapchainTexture;
Uint32 w, h;
if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, window, &swapchainTexture, &w, &h)) {
@@ -1449,15 +1452,17 @@ JSC_CCALL(cmd_acquire_swapchain_texture,
wrapper->device = NULL; // We don't need the device pointer as we don't release
wrapper->type = swapchainTexture;
wrapper->owned = 0; // CRITICAL: Do not release this texture
JSValue jstex = JS_NewObjectClass(js, js_SDL_GPUTexture_id);
JS_FRAME(js);
JS_LOCAL(jstex, JS_NewObjectClass(js, js_SDL_GPUTexture_id));
JS_SetOpaque(jstex, wrapper);
JS_SetPropertyStr(js, jstex, "width", number2js(js, w));
JS_SetPropertyStr(js, jstex, "height", number2js(js, h));
JS_SetPropertyStr(js, jstex, "dim", vec22js(js, (vec2){w, h}));
return jstex;
JS_RestoreFrame(_js_ctx, _js_gc_frame, _js_local_frame);
ret = jstex;
)
JSC_CCALL(cmd_compute_pass,
@@ -1468,7 +1473,7 @@ JSC_CCALL(cmd_compute_pass,
int t_n = JS_ArrayLength(js,textures);
SDL_GPUStorageTextureReadWriteBinding t_bind[t_n];
for (int i = 0; i < t_n; i++) {
JSValue T = JS_GetPropertyUint32(js,textures,i);
JSValue T = JS_GetPropertyNumber(js,textures,i);
JS_GETPROP(js, t_bind[i].texture, T, texture, SDL_GPUTexture)
JS_GETPROP(js,t_bind[i].mip_level,T,mip, number)
JS_GETPROP(js,t_bind[i].layer,T,layer, number)
@@ -1478,7 +1483,7 @@ JSC_CCALL(cmd_compute_pass,
int b_n = JS_ArrayLength(js,buffers);
SDL_GPUStorageBufferReadWriteBinding b_bind[b_n];
for (int i = 0; i < b_n; i++) {
JSValue T = JS_GetPropertyUint32(js,buffers,i);
JSValue T = JS_GetPropertyNumber(js,buffers,i);
JS_GETPROP(js,b_bind[i].buffer, T,buffer,SDL_GPUBuffer)
}
@@ -1620,7 +1625,7 @@ JSC_CCALL(transferbuffer_copy_blob,
// Unmap the transfer buffer
SDL_UnmapGPUTransferBuffer(gpu, buffer);
return JS_UNINITIALIZED;
return JS_NULL;
)
static const JSCFunctionListEntry js_SDL_GPUTransferBuffer_funcs[] = {
@@ -1649,7 +1654,7 @@ JSC_CCALL(compute_samplers,
int n = JS_ArrayLength(js,samplers);
SDL_GPUTextureSamplerBinding b[n];
for (int i = 0; i < n; i++) {
JSValue s = JS_GetPropertyUint32(js,samplers,i);
JSValue s = JS_GetPropertyNumber(js,samplers,i);
b[i] = js2SDL_GPUTextureSamplerBinding(js,s);
JS_FreeValue(js,s);
}
@@ -1662,7 +1667,7 @@ JSC_CCALL(compute_storage_textures,
int n = JS_ArrayLength(js,textures);
SDL_GPUTexture *b[n];
for (int i = 0; i < n; i++) {
JSValue s = JS_GetPropertyUint32(js,textures,i);
JSValue s = JS_GetPropertyNumber(js,textures,i);
b[i] = js2SDL_GPUTexture(js,s);
JS_FreeValue(js,s);
}
@@ -1675,7 +1680,7 @@ JSC_CCALL(compute_storage_buffers,
int n = JS_ArrayLength(js,buffers);
SDL_GPUBuffer *b[n];
for (int i = 0; i < n; i++) {
JSValue s = JS_GetPropertyUint32(js,buffers,i);
JSValue s = JS_GetPropertyNumber(js,buffers,i);
b[i] = js2SDL_GPUBuffer(js,s);
JS_FreeValue(js,s);
}
@@ -1765,8 +1770,6 @@ static JSValue js_gpu_constructor(JSContext *js, JSValueConst new_target, int ar
// Function to register module
CELL_USE_INIT(
JSValue ret = JS_NewObject(js);
// Initialize classes
QJSCLASSPREP_FUNCS(SDL_GPUDevice)
QJSCLASSPREP_FUNCS(SDL_GPUBuffer)
@@ -1776,39 +1779,27 @@ CELL_USE_INIT(
QJSCLASSPREP_FUNCS(SDL_GPUComputePass)
QJSCLASSPREP_FUNCS(SDL_GPUCopyPass)
QJSCLASSPREP_FUNCS(SDL_GPURenderPass)
QJSCLASSPREP_NO_FUNCS(SDL_GPUFence)
QJSCLASSPREP_NO_FUNCS(SDL_GPUFence)
QJSCLASSPREP_NO_FUNCS(SDL_GPUComputePipeline)
QJSCLASSPREP_NO_FUNCS(SDL_GPUGraphicsPipeline)
QJSCLASSPREP_NO_FUNCS(SDL_GPUSampler)
QJSCLASSPREP_NO_FUNCS(SDL_GPUShader)
// Create GPU constructor
JSValue gpu_ctor = JS_NewCFunction2(js, js_gpu_constructor, "gpu", 1, JS_CFUNC_generic, 0);
JS_SetPropertyStr(js, ret, "gpu", gpu_ctor);
JS_FRAME(js);
JS_LOCAL(ret, JS_NewObject(js));
// Create GPU constructor
JS_SetPropertyStr(js, ret, "gpu", JS_NewCFunction2(js, js_gpu_constructor, "gpu", 1, JS_CFUNC_generic, 0));
// Add GPU object constructors
JSValue sampler_ctor = JS_NewCFunction2(js, js_gpu_sampler_constructor, "sampler", 2, JS_CFUNC_generic, 0);
JS_SetPropertyStr(js, ret, "sampler", sampler_ctor);
JSValue shader_ctor = JS_NewCFunction2(js, js_gpu_shader_constructor, "shader", 2, JS_CFUNC_generic, 0);
JS_SetPropertyStr(js, ret, "shader", shader_ctor);
JSValue graphics_pipeline_ctor = JS_NewCFunction2(js, js_gpu_graphics_pipeline_constructor, "graphics_pipeline", 2, JS_CFUNC_generic, 0);
JS_SetPropertyStr(js, ret, "graphics_pipeline", graphics_pipeline_ctor);
JSValue compute_pipeline_ctor = JS_NewCFunction2(js, js_gpu_compute_pipeline_constructor, "compute_pipeline", 2, JS_CFUNC_generic, 0);
JS_SetPropertyStr(js, ret, "compute_pipeline", compute_pipeline_ctor);
JSValue buffer_ctor = JS_NewCFunction2(js, js_gpu_buffer_constructor, "buffer", 2, JS_CFUNC_generic, 0);
JS_SetPropertyStr(js, ret, "buffer", buffer_ctor);
JSValue transfer_buffer_ctor = JS_NewCFunction2(js, js_gpu_transfer_buffer_constructor, "transfer_buffer", 2, JS_CFUNC_generic, 0);
JS_SetPropertyStr(js, ret, "transfer_buffer", transfer_buffer_ctor);
JSValue texture_ctor = JS_NewCFunction2(js, js_gpu_texture_constructor, "texture", 2, JS_CFUNC_generic, 0);
JS_SetPropertyStr(js, ret, "texture", texture_ctor);
return ret;
JS_SetPropertyStr(js, ret, "sampler", JS_NewCFunction2(js, js_gpu_sampler_constructor, "sampler", 2, JS_CFUNC_generic, 0));
JS_SetPropertyStr(js, ret, "shader", JS_NewCFunction2(js, js_gpu_shader_constructor, "shader", 2, JS_CFUNC_generic, 0));
JS_SetPropertyStr(js, ret, "graphics_pipeline", JS_NewCFunction2(js, js_gpu_graphics_pipeline_constructor, "graphics_pipeline", 2, JS_CFUNC_generic, 0));
JS_SetPropertyStr(js, ret, "compute_pipeline", JS_NewCFunction2(js, js_gpu_compute_pipeline_constructor, "compute_pipeline", 2, JS_CFUNC_generic, 0));
JS_SetPropertyStr(js, ret, "buffer", JS_NewCFunction2(js, js_gpu_buffer_constructor, "buffer", 2, JS_CFUNC_generic, 0));
JS_SetPropertyStr(js, ret, "transfer_buffer", JS_NewCFunction2(js, js_gpu_transfer_buffer_constructor, "transfer_buffer", 2, JS_CFUNC_generic, 0));
JS_SetPropertyStr(js, ret, "texture", JS_NewCFunction2(js, js_gpu_texture_constructor, "texture", 2, JS_CFUNC_generic, 0));
JS_RETURN(ret);
)

View File

@@ -16,13 +16,14 @@ JSC_CCALL(haptic_get_haptics,
int count = 0;
SDL_HapticID *haptics = SDL_GetHaptics(&count);
if (!haptics) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < count; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewUint32(js, haptics[i]));
JS_SetPropertyNumber(js, arr, i, JS_NewUint32(js, haptics[i]));
}
SDL_free(haptics);
return arr;
JS_RETURN(arr);
)
// SDL_GetHapticNameForID(id) -> string
@@ -184,11 +185,11 @@ static const JSCFunctionListEntry js_haptic_funcs[] = {
CELL_USE_INIT(
SDL_Init(SDL_INIT_HAPTIC);
QJSCLASSPREP_FUNCS(SDL_Haptic);
JSValue ret = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(ret, JS_NewObject(js));
JS_SetPropertyFunctionList(js, ret, js_haptic_funcs, countof(js_haptic_funcs));
// Export feature constants
JS_SetPropertyStr(js, ret, "CONSTANT", JS_NewUint32(js, SDL_HAPTIC_CONSTANT));
JS_SetPropertyStr(js, ret, "SINE", JS_NewUint32(js, SDL_HAPTIC_SINE));
JS_SetPropertyStr(js, ret, "SQUARE", JS_NewUint32(js, SDL_HAPTIC_SQUARE));
@@ -207,6 +208,6 @@ CELL_USE_INIT(
JS_SetPropertyStr(js, ret, "STATUS", JS_NewUint32(js, SDL_HAPTIC_STATUS));
JS_SetPropertyStr(js, ret, "PAUSE", JS_NewUint32(js, SDL_HAPTIC_PAUSE));
JS_SetPropertyStr(js, ret, "INFINITY", JS_NewUint32(js, SDL_HAPTIC_INFINITY));
return ret;
JS_RETURN(ret);
)

View File

@@ -21,8 +21,9 @@ static const char *bus_type_to_string(SDL_hid_bus_type type) {
// Helper to convert device info to JS object
static JSValue device_info_to_js(JSContext *js, SDL_hid_device_info *info) {
JSValue obj = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(obj, JS_NewObject(js));
if (info->path)
JS_SetPropertyStr(js, obj, "path", JS_NewString(js, info->path));
JS_SetPropertyStr(js, obj, "vendor_id", JS_NewUint32(js, info->vendor_id));
@@ -35,8 +36,7 @@ static JSValue device_info_to_js(JSContext *js, SDL_hid_device_info *info) {
JS_SetPropertyStr(js, obj, "interface_subclass", JS_NewInt32(js, info->interface_subclass));
JS_SetPropertyStr(js, obj, "interface_protocol", JS_NewInt32(js, info->interface_protocol));
JS_SetPropertyStr(js, obj, "bus_type", JS_NewString(js, bus_type_to_string(info->bus_type)));
// Convert wide strings to UTF-8
if (info->serial_number) {
char buf[256];
wcstombs(buf, info->serial_number, sizeof(buf) - 1);
@@ -55,8 +55,8 @@ static JSValue device_info_to_js(JSContext *js, SDL_hid_device_info *info) {
buf[sizeof(buf) - 1] = 0;
JS_SetPropertyStr(js, obj, "product", JS_NewString(js, buf));
}
return obj;
JS_RETURN(obj);
}
// SDL_hid_init() -> int
@@ -82,15 +82,16 @@ JSC_CCALL(hidapi_enumerate,
SDL_hid_device_info *devs = SDL_hid_enumerate(vendor_id, product_id);
if (!devs) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
int i = 0;
for (SDL_hid_device_info *cur = devs; cur; cur = cur->next) {
JS_SetPropertyUint32(js, arr, i++, device_info_to_js(js, cur));
JS_SetPropertyNumber(js, arr, i++, device_info_to_js(js, cur));
}
SDL_hid_free_enumeration(devs);
return arr;
JS_RETURN(arr);
)
// SDL_hid_open(vendor_id, product_id) -> device
@@ -265,16 +266,16 @@ static const JSCFunctionListEntry js_hidapi_funcs[] = {
CELL_USE_INIT(
QJSCLASSPREP_FUNCS(SDL_hid_device);
JSValue ret = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(ret, JS_NewObject(js));
JS_SetPropertyFunctionList(js, ret, js_hidapi_funcs, countof(js_hidapi_funcs));
// Export bus type constants
JS_SetPropertyStr(js, ret, "BUS_UNKNOWN", JS_NewInt32(js, SDL_HID_API_BUS_UNKNOWN));
JS_SetPropertyStr(js, ret, "BUS_USB", JS_NewInt32(js, SDL_HID_API_BUS_USB));
JS_SetPropertyStr(js, ret, "BUS_BLUETOOTH", JS_NewInt32(js, SDL_HID_API_BUS_BLUETOOTH));
JS_SetPropertyStr(js, ret, "BUS_I2C", JS_NewInt32(js, SDL_HID_API_BUS_I2C));
JS_SetPropertyStr(js, ret, "BUS_SPI", JS_NewInt32(js, SDL_HID_API_BUS_SPI));
return ret;
JS_RETURN(ret);
)

31
input.c
View File

@@ -15,7 +15,8 @@ QJSCLASS(SDL_Event,)
static JSValue js_keymod(JSContext *js)
{
SDL_Keymod modstate = SDL_GetModState();
JSValue ret = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(ret, JS_NewObject(js));
if (SDL_KMOD_CTRL & modstate)
JS_SetPropertyStr(js,ret,"ctrl", JS_NewBool(js,1));
if (SDL_KMOD_SHIFT & modstate)
@@ -33,7 +34,7 @@ static JSValue js_keymod(JSContext *js)
if (SDL_KMOD_MODE & modstate)
JS_SetPropertyStr(js,ret,"mode", JS_NewBool(js,1));
return ret;
JS_RETURN(ret);
}
// INPUT FUNCTIONS
@@ -57,7 +58,8 @@ JSC_CCALL(input_keymod,
JSC_CCALL(input_mousestate,
float x,y;
SDL_MouseButtonFlags flags = SDL_GetMouseState(&x,&y);
JSValue m = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(m, JS_NewObject(js));
JS_SetPropertyStr(js,m,"x", number2js(js,x));
JS_SetPropertyStr(js,m,"y", number2js(js,y));
@@ -71,8 +73,8 @@ JSC_CCALL(input_mousestate,
JS_SetPropertyStr(js, m, "x1", JS_NewBool(js, 1));
if (flags & SDL_BUTTON_X2MASK)
JS_SetPropertyStr(js, m, "x2", JS_NewBool(js, 1));
return m;
JS_RETURN(m);
)
// Event processing functions (moved from cell.c)
@@ -753,19 +755,19 @@ static WotaBuffer event2wota(const SDL_Event *event) {
// Get all events directly from SDL event queue
JSC_CCALL(input_get_events,
JSValue events_array = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(events_array, JS_NewArray(js));
SDL_Event event;
int event_count = 0;
while (SDL_PollEvent(&event)) {
SDL_Event *e = (SDL_Event *)malloc(sizeof(SDL_Event));
memcpy(e, &event, sizeof(SDL_Event));
JSValue event_obj = SDL_Event2js(js, e);
JS_SetPropertyUint32(js, events_array, event_count, event_obj);
JS_SetPropertyNumber(js, events_array, event_count, SDL_Event2js(js, e));
event_count++;
}
return events_array;
JS_RETURN(events_array);
)
JSC_CCALL(input_objectify,
@@ -795,8 +797,9 @@ static const JSCFunctionListEntry js_input_funcs[] = {
CELL_USE_INIT(
QJSCLASSPREP_NO_FUNCS(SDL_Event);
JSValue mod = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(mod, JS_NewObject(js));
JS_SetPropertyFunctionList(js, mod, js_input_funcs, countof(js_input_funcs));
return mod;
JS_RETURN(mod);
)

View File

@@ -56,13 +56,14 @@ JSC_CCALL(joystick_get_joysticks,
int count = 0;
SDL_JoystickID *joysticks = SDL_GetJoysticks(&count);
if (!joysticks) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < count; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewUint32(js, joysticks[i]));
JS_SetPropertyNumber(js, arr, i, JS_NewUint32(js, joysticks[i]));
}
SDL_free(joysticks);
return arr;
JS_RETURN(arr);
)
// SDL_GetJoystickNameForID(id) -> string
@@ -254,10 +255,11 @@ JSC_CCALL(joystick_get_ball,
JS_ToInt32(js, &ball, argv[0]);
int dx, dy;
if (!SDL_GetJoystickBall(joystick, ball, &dx, &dy)) return JS_NULL;
JSValue result = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(result, JS_NewObject(js));
JS_SetPropertyStr(js, result, "dx", JS_NewInt32(js, dx));
JS_SetPropertyStr(js, result, "dy", JS_NewInt32(js, dy));
return result;
JS_RETURN(result);
)
JSC_CCALL(joystick_get_hat,
@@ -311,8 +313,7 @@ JSC_CCALL(joystick_get_power_info,
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
int percent;
SDL_PowerState state = SDL_GetJoystickPowerInfo(joystick, &percent);
JSValue result = JS_NewObject(js);
const char *state_str;
switch (state) {
case SDL_POWERSTATE_ON_BATTERY: state_str = "on_battery"; break;
@@ -321,9 +322,12 @@ JSC_CCALL(joystick_get_power_info,
case SDL_POWERSTATE_CHARGED: state_str = "charged"; break;
default: state_str = "unknown"; break;
}
JS_FRAME(js);
JS_LOCAL(result, JS_NewObject(js));
JS_SetPropertyStr(js, result, "state", JS_NewString(js, state_str));
JS_SetPropertyStr(js, result, "percent", JS_NewInt32(js, percent));
return result;
JS_RETURN(result);
)
JSC_CCALL(joystick_close,
@@ -381,13 +385,13 @@ static const JSCFunctionListEntry js_joystick_funcs[] = {
CELL_USE_INIT(
SDL_Init(SDL_INIT_JOYSTICK);
QJSCLASSPREP_FUNCS(SDL_Joystick);
JSValue ret = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(ret, JS_NewObject(js));
JS_SetPropertyFunctionList(js, ret, js_joystick_funcs, countof(js_joystick_funcs));
// Export axis constants
JS_SetPropertyStr(js, ret, "AXIS_MAX", JS_NewInt32(js, SDL_JOYSTICK_AXIS_MAX));
JS_SetPropertyStr(js, ret, "AXIS_MIN", JS_NewInt32(js, SDL_JOYSTICK_AXIS_MIN));
return ret;
JS_RETURN(ret);
)

View File

@@ -11,13 +11,14 @@ JSC_CCALL(keyboard_get_keyboards,
int count = 0;
SDL_KeyboardID *keyboards = SDL_GetKeyboards(&count);
if (!keyboards) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < count; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewUint32(js, keyboards[i]));
JS_SetPropertyNumber(js, arr, i, JS_NewUint32(js, keyboards[i]));
}
SDL_free(keyboards);
return arr;
JS_RETURN(arr);
)
// SDL_GetKeyboardNameForID(id) -> string
@@ -33,12 +34,13 @@ JSC_CCALL(keyboard_get_state,
int numkeys = 0;
const bool *state = SDL_GetKeyboardState(&numkeys);
if (!state) return JS_NULL;
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < numkeys; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewBool(js, state[i]));
JS_SetPropertyNumber(js, arr, i, JS_NewBool(js, state[i]));
}
return arr;
JS_RETURN(arr);
)
// SDL_ResetKeyboard()
@@ -77,11 +79,12 @@ JSC_CCALL(keyboard_get_scancode_from_key,
JS_ToUint32(js, &key, argv[0]);
SDL_Keymod modstate;
SDL_Scancode scancode = SDL_GetScancodeFromKey((SDL_Keycode)key, &modstate);
JSValue result = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(result, JS_NewObject(js));
JS_SetPropertyStr(js, result, "scancode", JS_NewInt32(js, scancode));
JS_SetPropertyStr(js, result, "modstate", JS_NewUint32(js, modstate));
return result;
JS_RETURN(result);
)
// SDL_GetScancodeName(scancode) -> string

30
mouse.c
View File

@@ -11,13 +11,14 @@ JSC_CCALL(mouse_get_mice,
int count = 0;
SDL_MouseID *mice = SDL_GetMice(&count);
if (!mice) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < count; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewUint32(js, mice[i]));
JS_SetPropertyNumber(js, arr, i, JS_NewUint32(js, mice[i]));
}
SDL_free(mice);
return arr;
JS_RETURN(arr);
)
// SDL_GetMouseNameForID(id) -> string
@@ -32,36 +33,39 @@ JSC_CCALL(mouse_get_name,
JSC_CCALL(mouse_get_state,
float x, y;
SDL_MouseButtonFlags buttons = SDL_GetMouseState(&x, &y);
JSValue result = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(result, JS_NewObject(js));
JS_SetPropertyStr(js, result, "x", JS_NewFloat64(js, x));
JS_SetPropertyStr(js, result, "y", JS_NewFloat64(js, y));
JS_SetPropertyStr(js, result, "buttons", JS_NewUint32(js, buttons));
return result;
JS_RETURN(result);
)
// SDL_GetGlobalMouseState() -> {x, y, buttons}
JSC_CCALL(mouse_get_global_state,
float x, y;
SDL_MouseButtonFlags buttons = SDL_GetGlobalMouseState(&x, &y);
JSValue result = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(result, JS_NewObject(js));
JS_SetPropertyStr(js, result, "x", JS_NewFloat64(js, x));
JS_SetPropertyStr(js, result, "y", JS_NewFloat64(js, y));
JS_SetPropertyStr(js, result, "buttons", JS_NewUint32(js, buttons));
return result;
JS_RETURN(result);
)
// SDL_GetRelativeMouseState() -> {x, y, buttons}
JSC_CCALL(mouse_get_relative_state,
float x, y;
SDL_MouseButtonFlags buttons = SDL_GetRelativeMouseState(&x, &y);
JSValue result = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(result, JS_NewObject(js));
JS_SetPropertyStr(js, result, "x", JS_NewFloat64(js, x));
JS_SetPropertyStr(js, result, "y", JS_NewFloat64(js, y));
JS_SetPropertyStr(js, result, "buttons", JS_NewUint32(js, buttons));
return result;
JS_RETURN(result);
)
// SDL_WarpMouseGlobal(x, y) -> bool

View File

@@ -41,11 +41,11 @@ JSC_CCALL(SDL_Renderer_rect,
SDL_SetRenderDrawColorFloat(r, color.x, color.y, color.z, color.w);
}
if (JS_IsArray(js,argv[0])) {
if (JS_IsArray(argv[0])) {
int len = JS_ArrayLength(js,argv[0]);
rect rects[len];
for (int i = 0; i < len; i++) {
JSValue val = JS_GetPropertyUint32(js,argv[0],i);
JSValue val = JS_GetPropertyNumber(js,argv[0],i);
rects[i] = js2rect(js,val);
JS_FreeValue(js,val);
}
@@ -63,11 +63,11 @@ JSC_CCALL(SDL_Renderer_fillrect,
SDL_SetRenderDrawColorFloat(r, color.x, color.y, color.z, color.w);
}
if (JS_IsArray(js,argv[0])) {
if (JS_IsArray(argv[0])) {
int len = JS_ArrayLength(js,argv[0]);
rect rects[len];
for (int i = 0; i < len; i++) {
JSValue val = JS_GetPropertyUint32(js,argv[0],i);
JSValue val = JS_GetPropertyNumber(js,argv[0],i);
rects[i] = js2rect(js,val);
JS_FreeValue(js,val);
}
@@ -102,9 +102,12 @@ JSC_CCALL(renderer_load_texture,
SDL_Surface *surf = js2SDL_Surface(js, argv[0]);
SDL_Texture *tex = SDL_CreateTextureFromSurface(renderer, surf);
if (!tex) return JS_ThrowReferenceError(js, "Could not create texture from surface: %s", SDL_GetError());
ret = SDL_Texture2js(js, tex);
JS_SetPropertyStr(js, ret, "width", number2js(js,tex->w));
JS_SetPropertyStr(js,ret,"height", number2js(js,tex->h));
JS_FRAME(js);
JS_LOCAL(result, SDL_Texture2js(js, tex));
JS_SetPropertyStr(js, result, "width", number2js(js,tex->w));
JS_SetPropertyStr(js, result, "height", number2js(js,tex->h));
JS_RestoreFrame(_js_ctx, _js_gc_frame, _js_local_frame);
ret = result;
)
JSC_CCALL(renderer_get_image,
@@ -128,12 +131,12 @@ JSC_CCALL(renderer_line,
SDL_SetRenderDrawColorFloat(r, color.x, color.y, color.z, color.w);
}
if (JS_IsArray(js,argv[0])) {
if (JS_IsArray(argv[0])) {
int len = JS_ArrayLength(js,argv[0]);
vec2 points[len];
assert(sizeof(vec2) == sizeof(SDL_FPoint));
for (int i = 0; i < len; i++) {
JSValue val = JS_GetPropertyUint32(js,argv[0],i);
JSValue val = JS_GetPropertyNumber(js,argv[0],i);
points[i] = js2vec2(js,val);
JS_FreeValue(js,val);
}
@@ -148,12 +151,12 @@ JSC_CCALL(renderer_point,
SDL_SetRenderDrawColorFloat(r, color.x, color.y, color.z, color.w);
}
if (JS_IsArray(js,argv[0])) {
if (JS_IsArray(argv[0])) {
int len = JS_ArrayLength(js,argv[0]);
vec2 points[len];
assert(sizeof(vec2) ==sizeof(SDL_FPoint));
for (int i = 0; i < len; i++) {
JSValue val = JS_GetPropertyUint32(js,argv[0],i);
JSValue val = JS_GetPropertyNumber(js,argv[0],i);
points[i] = js2vec2(js,val);
JS_FreeValue(js,val);
}
@@ -243,8 +246,9 @@ JSC_CCALL(SDL_Renderer_constructor,
CELL_USE_INIT(
SDL_Init(SDL_INIT_VIDEO);
JSValue renderer_ctor = QJSCLASSPREP_FUNCS_CTOR(SDL_Renderer,1);
JS_FRAME(js);
JS_LOCAL(renderer_ctor, QJSCLASSPREP_FUNCS_CTOR(SDL_Renderer,1));
QJSCLASSPREP_NO_FUNCS(SDL_Texture)
return renderer_ctor;
JS_RETURN(renderer_ctor);
)

110
sdl.c
View File

@@ -7,10 +7,10 @@ colorf js2color(JSContext *js,JSValue v) {
colorf color = {1,1,1,1}; // Default to white
if (JS_IsArray(js, v)) {
if (JS_IsArray(v)) {
// Handle array format: [r, g, b, a]
JSValue c[4];
for (int i = 0; i < 4; i++) c[i] = JS_GetPropertyUint32(js,v,i);
for (int i = 0; i < 4; i++) c[i] = JS_GetPropertyNumber(js,v,i);
color.x = js2number(js,c[0]);
color.y = js2number(js,c[1]);
@@ -30,12 +30,13 @@ colorf js2color(JSContext *js,JSValue v) {
JSValue color2js(JSContext *js, colorf color)
{
JSValue arr = JS_NewArray(js);
JS_SetPropertyUint32(js, arr,0,number2js(js,(double)color.x));
JS_SetPropertyUint32(js, arr,1,number2js(js,(double)color.y));
JS_SetPropertyUint32(js, arr,2,number2js(js,(double)color.z));
JS_SetPropertyUint32(js, arr,3,number2js(js,(double)color.w));
return arr;
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
JS_SetPropertyNumber(js, arr,0,number2js(js,(double)color.x));
JS_SetPropertyNumber(js, arr,1,number2js(js,(double)color.y));
JS_SetPropertyNumber(js, arr,2,number2js(js,(double)color.z));
JS_SetPropertyNumber(js, arr,3,number2js(js,(double)color.w));
JS_RETURN(arr);
}
vec2 js2vec2(JSContext *js,JSValue v)
@@ -43,9 +44,9 @@ vec2 js2vec2(JSContext *js,JSValue v)
vec2 v2;
// Check if it's an array
if (JS_IsArray(js, v)) {
{ JSValue val = JS_GetPropertyUint32(js,v,0); v2.x = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyUint32(js,v,1); v2.y = js2number(js, val); JS_FreeValue(js,val); }
if (JS_IsArray(v)) {
{ JSValue val = JS_GetPropertyNumber(js,v,0); v2.x = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js,v,1); v2.y = js2number(js, val); JS_FreeValue(js,val); }
} else {
// Try to get x,y properties from object
JSValue x_val = JS_GetPropertyStr(js, v, "x");
@@ -64,9 +65,9 @@ vec2 js2vec2(JSContext *js,JSValue v)
vec3 js2vec3(JSContext *js,JSValue v)
{
vec3 v3;
{ JSValue val = JS_GetPropertyUint32(js, v,0); v3.x = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyUint32(js, v,1); v3.y = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyUint32(js, v,2); v3.z = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js, v,0); v3.x = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js, v,1); v3.y = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js, v,2); v3.z = js2number(js, val); JS_FreeValue(js,val); }
return v3;
}
@@ -75,7 +76,7 @@ float *js2floats(JSContext *js, JSValue v, size_t *len)
*len = JS_ArrayLength(js,v);
float *arr = malloc(sizeof(float)* *len);
for (int i = 0; i < *len; i++)
{ JSValue val = JS_GetPropertyUint32(js,v,i); arr[i] = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js,v,i); arr[i] = js2number(js, val); JS_FreeValue(js,val); }
return arr;
}
@@ -84,14 +85,14 @@ double *js2doubles(JSContext *js, JSValue v, size_t *len)
*len = JS_ArrayLength(js,v);
double *arr = malloc(sizeof(double)* *len);
for (int i = 0; i < *len; i++)
{ JSValue val = JS_GetPropertyUint32(js,v,i); arr[i] = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js,v,i); arr[i] = js2number(js, val); JS_FreeValue(js,val); }
return arr;
}
vec3 js2vec3f(JSContext *js, JSValue v)
{
vec3 vec;
if (JS_IsArray(js, v))
if (JS_IsArray(v))
return js2vec3(js,v);
else
vec.x = vec.y = vec.z = js2number(js,v);
@@ -100,11 +101,12 @@ vec3 js2vec3f(JSContext *js, JSValue v)
JSValue vec32js(JSContext *js, vec3 v)
{
JSValue array = JS_NewArray(js);
JS_SetPropertyUint32(js, array,0,number2js(js,v.x));
JS_SetPropertyUint32(js, array,1,number2js(js,v.y));
JS_SetPropertyUint32(js, array,2,number2js(js,v.z));
return array;
JS_FRAME(js);
JS_LOCAL(array, JS_NewArray(js));
JS_SetPropertyNumber(js, array,0,number2js(js,v.x));
JS_SetPropertyNumber(js, array,1,number2js(js,v.y));
JS_SetPropertyNumber(js, array,2,number2js(js,v.z));
JS_RETURN(array);
}
JSValue vec3f2js(JSContext *js, vec3 v)
@@ -114,19 +116,20 @@ JSValue vec3f2js(JSContext *js, vec3 v)
JSValue quat2js(JSContext *js, quat q)
{
JSValue arr = JS_NewArray(js);
JS_SetPropertyUint32(js, arr, 0, number2js(js,q.x));
JS_SetPropertyUint32(js, arr,1,number2js(js,q.y));
JS_SetPropertyUint32(js, arr,2,number2js(js,q.z));
JS_SetPropertyUint32(js, arr,3,number2js(js,q.w));
return arr;
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
JS_SetPropertyNumber(js, arr, 0, number2js(js,q.x));
JS_SetPropertyNumber(js, arr,1,number2js(js,q.y));
JS_SetPropertyNumber(js, arr,2,number2js(js,q.z));
JS_SetPropertyNumber(js, arr,3,number2js(js,q.w));
JS_RETURN(arr);
}
vec4 js2vec4(JSContext *js, JSValue v)
{
vec4_union v4;
for (int i = 0; i < 4; i++)
{ JSValue val = JS_GetPropertyUint32(js, v,i); v4.e[i] = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js, v,i); v4.e[i] = js2number(js, val); JS_FreeValue(js,val); }
return (vec4){v4.x, v4.y, v4.z, v4.w};
}
@@ -150,7 +153,7 @@ double arr_vec_length(JSContext *js,JSValue v)
double sum = 0;
for (int i = 0; i < len; i++)
{ JSValue val = JS_GetPropertyUint32(js, v, i); double num = js2number(js, val); JS_FreeValue(js,val); sum += pow(num, 2); }
{ JSValue val = JS_GetPropertyNumber(js, v, i); double num = js2number(js, val); JS_FreeValue(js,val); sum += pow(num, 2); }
return sqrt(sum);
}
@@ -159,18 +162,19 @@ quat js2quat(JSContext *js,JSValue v)
{
vec4_union v4;
for (int i = 0; i < 4; i++)
{ JSValue val = JS_GetPropertyUint32(js, v,i); v4.e[i] = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js, v,i); v4.e[i] = js2number(js, val); JS_FreeValue(js,val); }
return (quat){v4.x, v4.y, v4.z, v4.w};
}
JSValue vec42js(JSContext *js, vec4 v)
{
JSValue array = JS_NewArray(js);
JS_SetPropertyUint32(js, array,0,number2js(js,v.x));
JS_SetPropertyUint32(js, array,1,number2js(js,v.y));
JS_SetPropertyUint32(js, array,2,number2js(js,v.z));
JS_SetPropertyUint32(js, array,3,number2js(js,v.w));
return array;
JS_FRAME(js);
JS_LOCAL(array, JS_NewArray(js));
JS_SetPropertyNumber(js, array,0,number2js(js,v.x));
JS_SetPropertyNumber(js, array,1,number2js(js,v.y));
JS_SetPropertyNumber(js, array,2,number2js(js,v.z));
JS_SetPropertyNumber(js, array,3,number2js(js,v.w));
JS_RETURN(array);
}
vec2 *js2cpvec2arr(JSContext *js,JSValue v) {
@@ -178,7 +182,7 @@ vec2 *js2cpvec2arr(JSContext *js,JSValue v) {
vec2 *arr = malloc(sizeof(vec2) * n);
for (int i = 0; i < n; i++) {
JSValue ii = JS_GetPropertyUint32(js,v,i);
JSValue ii = JS_GetPropertyNumber(js,v,i);
arr[i] = js2vec2(js,ii);
JS_FreeValue(js,ii);
}
@@ -204,11 +208,12 @@ rect js2rect(JSContext *js,JSValue v) {
}
static JSValue floats2array(JSContext *js, float *vals, size_t len) {
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (size_t i = 0; i < len; i++) {
JS_SetPropertyUint32(js, arr, i, number2js(js, vals[i]));
JS_SetPropertyNumber(js, arr, i, number2js(js, vals[i]));
}
return arr;
JS_RETURN(arr);
}
lrtb js2lrtb(JSContext *js, JSValue v)
@@ -223,27 +228,30 @@ lrtb js2lrtb(JSContext *js, JSValue v)
JSValue vec22js(JSContext *js,vec2 v)
{
JSValue array = JS_NewArray(js);
JS_SetPropertyUint32(js, array,0,number2js(js,v.x));
JS_SetPropertyUint32(js, array,1,number2js(js,v.y));
return array;
JS_FRAME(js);
JS_LOCAL(array, JS_NewArray(js));
JS_SetPropertyNumber(js, array,0,number2js(js,v.x));
JS_SetPropertyNumber(js, array,1,number2js(js,v.y));
JS_RETURN(array);
}
JSValue vecarr2js(JSContext *js,vec2 *points, int n) {
JSValue array = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(array, JS_NewArray(js));
for (int i = 0; i < n; i++)
JS_SetPropertyUint32(js, array,i,vec22js(js,points[i]));
return array;
JS_SetPropertyNumber(js, array,i,vec22js(js,points[i]));
JS_RETURN(array);
}
JSValue rect2js(JSContext *js,rect rect) {
JSValue obj = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(obj, JS_NewObject(js));
JS_SetPropertyStr(js, obj, "x", number2js(js, rect.x));
JS_SetPropertyStr(js, obj, "y", number2js(js, rect.y));
JS_SetPropertyStr(js, obj, "width", number2js(js, rect.w));
JS_SetPropertyStr(js, obj, "height", number2js(js, rect.h));
return obj;
JS_RETURN(obj);
}
float *rgba2floats(float *r, struct rgba c)

View File

@@ -27,13 +27,14 @@ JSC_CCALL(sensor_get_sensors,
int count = 0;
SDL_SensorID *sensors = SDL_GetSensors(&count);
if (!sensors) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < count; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewUint32(js, sensors[i]));
JS_SetPropertyNumber(js, arr, i, JS_NewUint32(js, sensors[i]));
}
SDL_free(sensors);
return arr;
JS_RETURN(arr);
)
// SDL_GetSensorNameForID(id) -> string
@@ -95,21 +96,22 @@ JSC_CCALL(sensor_get_data,
SDL_Sensor *sensor = js2SDL_Sensor(js, self);
int num_values = 3;
if (argc > 0) JS_ToInt32(js, &num_values, argv[0]);
float *data = malloc(num_values * sizeof(float));
if (!data) return JS_ThrowOutOfMemory(js);
if (!SDL_GetSensorData(sensor, data, num_values)) {
free(data);
return JS_NULL;
}
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < num_values; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewFloat64(js, data[i]));
JS_SetPropertyNumber(js, arr, i, JS_NewFloat64(js, data[i]));
}
free(data);
return arr;
JS_RETURN(arr);
)
JSC_CCALL(sensor_close,
@@ -145,12 +147,11 @@ static const JSCFunctionListEntry js_sensor_funcs[] = {
CELL_USE_INIT(
SDL_Init(SDL_INIT_SENSOR);
QJSCLASSPREP_FUNCS(SDL_Sensor);
JSValue ret = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(ret, JS_NewObject(js));
JS_SetPropertyFunctionList(js, ret, js_sensor_funcs, countof(js_sensor_funcs));
// Export standard gravity constant
JS_SetPropertyStr(js, ret, "STANDARD_GRAVITY", JS_NewFloat64(js, SDL_STANDARD_GRAVITY));
return ret;
JS_RETURN(ret);
)

126
surface.c
View File

@@ -90,13 +90,14 @@ void SDL_Surface_free(JSRuntime *rt, SDL_Surface *s) {
QJSCLASS(SDL_Surface,)
JSValue make_surface(JSContext *js, SDL_Surface *s){
JSValue ret = SDL_Surface2js(js,s);
JS_FRAME(js);
JS_LOCAL(ret, SDL_Surface2js(js,s));
JS_SetPropertyStr(js, ret, "width", JS_NewInt32(js, s->w));
JS_SetPropertyStr(js, ret, "height", JS_NewInt32(js, s->h));
JS_SetPropertyStr(js, ret, "format", pixelformat2js(js, s->format));
JS_SetPropertyStr(js, ret, "pitch", JS_NewFloat64(js, s->pitch));
return JS_Stone(js, ret);
JS_RETURN(JS_Stone(js, ret));
}
// SDL_Surface methods
@@ -227,40 +228,30 @@ JSValue js_surface_get_pitch(JSContext *js, JSValue self) {
JSC_CCALL(surface_toJSON,
SDL_Surface *surf = js2SDL_Surface(js,self);
// Create the result object
JSValue obj = JS_NewObject(js);
// Add width and height
JS_FRAME(js);
JS_LOCAL(obj, JS_NewObject(js));
JS_SetPropertyStr(js, obj, "width", JS_NewInt32(js, surf->w));
JS_SetPropertyStr(js, obj, "height", JS_NewInt32(js, surf->h));
// Add format
JS_SetPropertyStr(js, obj, "format", pixelformat2js(js, surf->format));
// Add pitch
JS_SetPropertyStr(js, obj, "pitch", JS_NewInt32(js, surf->pitch));
// Lock surface if needed
int locked = 0;
if (SDL_MUSTLOCK(surf)) {
if (SDL_LockSurface(surf) < 0) {
JS_FreeValue(js, obj);
return JS_ThrowInternalError(js, "Lock surface failed: %s", SDL_GetError());
JS_RETURN_EX();
}
locked = 1;
}
// Add pixels as ArrayBuffer
size_t byte_size = surf->pitch * surf->h;
JSValue pixels = js_new_blob_stoned_copy(js, surf->pixels, byte_size);
JS_SetPropertyStr(js, obj, "pixels", pixels);
// Unlock if we locked
JS_SetPropertyStr(js, obj, "pixels", js_new_blob_stoned_copy(js, surf->pixels, byte_size));
if (locked)
SDL_UnlockSurface(surf);
return obj;
JS_RETURN(obj);
)
// Check for integer overflow in size calculations
@@ -420,17 +411,17 @@ static JSValue compress_bc_common(JSContext *js, JSValueConst *argv, int argc, i
free(rgba_data);
// Create result object
JSValue result = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(result, JS_NewObject(js));
JS_SetPropertyStr(js, result, "width", JS_NewInt32(js, width));
JS_SetPropertyStr(js, result, "height", JS_NewInt32(js, height));
JS_SetPropertyStr(js, result, "format", JS_NewString(js, format_name));
JS_SetPropertyStr(js, result, "pitch", JS_NewInt32(js, blocks_x * bytes_per_block));
JSValue compressed_pixels = js_new_blob_stoned_copy(js, output, output_size);
free(output); // Free the output buffer after copying to blob
JS_SetPropertyStr(js, result, "pixels", compressed_pixels);
return result;
JS_SetPropertyStr(js, result, "pixels", js_new_blob_stoned_copy(js, output, output_size));
free(output);
JS_RETURN(result);
}
// BC1/DXT1 compression
@@ -587,19 +578,19 @@ static JSValue compress_bc_channels(JSContext *js, JSValueConst *argv, int argc,
}
free(channel_data);
// Create result object
JSValue result = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(result, JS_NewObject(js));
JS_SetPropertyStr(js, result, "width", JS_NewInt32(js, width));
JS_SetPropertyStr(js, result, "height", JS_NewInt32(js, height));
JS_SetPropertyStr(js, result, "format", JS_NewString(js, format_name));
JS_SetPropertyStr(js, result, "pitch", JS_NewInt32(js, blocks_x * bytes_per_block));
JSValue compressed_pixels = js_new_blob_stoned_copy(js, output, output_size);
free(output); // Free the output buffer after copying to blob
JS_SetPropertyStr(js, result, "pixels", compressed_pixels);
return result;
JS_SetPropertyStr(js, result, "pixels", js_new_blob_stoned_copy(js, output, output_size));
free(output);
JS_RETURN(result);
}
// BC4 compression (single channel)
@@ -775,37 +766,32 @@ static SDL_Surface* image_to_surface(JSContext *js, JSValue img_obj)
// Helper function to convert SDL_Surface back to image object
static JSValue surface_to_image(JSContext *js, SDL_Surface *surf)
{
JSValue obj = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(obj, JS_NewObject(js));
JS_SetPropertyStr(js, obj, "width", JS_NewInt32(js, surf->w));
JS_SetPropertyStr(js, obj, "height", JS_NewInt32(js, surf->h));
JS_SetPropertyStr(js, obj, "format", pixelformat2js(js, surf->format));
JS_SetPropertyStr(js, obj, "pitch", JS_NewInt32(js, surf->pitch));
// Lock surface if needed
int locked = 0;
if (SDL_MUSTLOCK(surf)) {
if (SDL_LockSurface(surf) < 0) {
JS_FreeValue(js, obj);
return JS_NULL;
JS_RETURN_NULL();
}
locked = 1;
}
// Add pixels as stoned blob
size_t byte_size = surf->pitch * surf->h;
JSValue pixels = js_new_blob_stoned_copy(js, surf->pixels, byte_size);
JS_SetPropertyStr(js, obj, "pixels", pixels);
// Unlock if we locked
JS_SetPropertyStr(js, obj, "pixels", js_new_blob_stoned_copy(js, surf->pixels, byte_size));
if (locked)
SDL_UnlockSurface(surf);
// Add depth and hdr properties for completeness
JS_SetPropertyStr(js, obj, "depth", JS_NewInt32(js, SDL_BITSPERPIXEL(surf->format)));
JS_SetPropertyStr(js, obj, "hdr", JS_FALSE);
return obj;
JS_RETURN(obj);
}
// Scale function for image objects
@@ -1068,44 +1054,38 @@ JSC_CCALL(surface_convert_generic,
}
// Create result image object
JSValue result = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(result, JS_NewObject(js));
JS_SetPropertyStr(js, result, "width", JS_NewInt32(js, src_width));
JS_SetPropertyStr(js, result, "height", JS_NewInt32(js, src_height));
JS_SetPropertyStr(js, result, "format", pixelformat2js(js, dst_format));
JS_SetPropertyStr(js, result, "pitch", JS_NewInt32(js, dst_pitch));
JSValue pixels = js_new_blob_stoned_copy(js, dst_pixels, dst_size);
JS_SetPropertyStr(js, result, "pixels", js_new_blob_stoned_copy(js, dst_pixels, dst_size));
free(dst_pixels);
JS_SetPropertyStr(js, result, "pixels", pixels);
// Add depth and hdr for consistency
JS_SetPropertyStr(js, result, "depth", JS_NewInt32(js, SDL_BITSPERPIXEL(dst_format)));
JS_SetPropertyStr(js, result, "hdr", JS_FALSE);
return result;
JS_RETURN(result);
)
CELL_USE_INIT(
QJSCLASSPREP_FUNCS(SDL_Surface)
// Add the surface constructor
JSValue ctor = JS_NewCFunction2(js, js_surface_constructor, "surface", 1, JS_CFUNC_generic, 0);
// Add the generic convert function as a property on the constructor
JS_FRAME(js);
JS_LOCAL(ctor, JS_NewCFunction2(js, js_surface_constructor, "surface", 1, JS_CFUNC_generic, 0));
JS_SetPropertyStr(js, ctor, "convert", JS_NewCFunction(js, js_surface_convert_generic, "convert", 2));
// Add the compression functions as static methods on the constructor
JS_SetPropertyStr(js, ctor, "compress_bc1", JS_NewCFunction(js, js_surface_compress_bc1, "compress_bc1", 2));
JS_SetPropertyStr(js, ctor, "compress_bc3", JS_NewCFunction(js, js_surface_compress_bc3, "compress_bc3", 2));
JS_SetPropertyStr(js, ctor, "compress_bc4", JS_NewCFunction(js, js_surface_compress_bc4, "compress_bc4", 1));
JS_SetPropertyStr(js, ctor, "compress_bc5", JS_NewCFunction(js, js_surface_compress_bc5, "compress_bc5", 1));
// Add standalone image manipulation functions
JS_SetPropertyStr(js, ctor, "scale", JS_NewCFunction(js, js_surface_scale_img, "scale", 2));
JS_SetPropertyStr(js, ctor, "fill", JS_NewCFunction(js, js_surface_fill_img, "fill", 2));
JS_SetPropertyStr(js, ctor, "rect", JS_NewCFunction(js, js_surface_rect_img, "rect", 3));
JS_SetPropertyStr(js, ctor, "blit", JS_NewCFunction(js, js_surface_blit_img, "blit", 5));
JS_SetPropertyStr(js, ctor, "dup", JS_NewCFunction(js, js_surface_dup_img, "dup", 1));
return ctor;
JS_RETURN(ctor);
)

25
touch.c
View File

@@ -6,13 +6,14 @@ JSC_CCALL(touch_get_devices,
int count = 0;
SDL_TouchID *devices = SDL_GetTouchDevices(&count);
if (!devices) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < count; i++) {
JS_SetPropertyUint32(js, arr, i, JS_NewInt64(js, devices[i]));
JS_SetPropertyNumber(js, arr, i, JS_NewInt64(js, devices[i]));
}
SDL_free(devices);
return arr;
JS_RETURN(arr);
)
// SDL_GetTouchDeviceName(touchID) -> string
@@ -44,23 +45,27 @@ JSC_CCALL(touch_get_device_type,
JSC_CCALL(touch_get_fingers,
int64_t touchID;
JS_ToInt64(js, &touchID, argv[0]);
int count = 0;
SDL_Finger **fingers = SDL_GetTouchFingers((SDL_TouchID)touchID, &count);
if (!fingers) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
JSValue finger = JS_NULL;
JSLocalRef finger__lr = {.ptr = &finger};
JS_PushLocalRef(_js_ctx, &finger__lr);
for (int i = 0; i < count; i++) {
SDL_Finger *f = fingers[i];
JSValue finger = JS_NewObject(js);
finger = JS_NewObject(js);
JS_SetPropertyStr(js, finger, "id", JS_NewInt64(js, f->id));
JS_SetPropertyStr(js, finger, "x", JS_NewFloat64(js, f->x));
JS_SetPropertyStr(js, finger, "y", JS_NewFloat64(js, f->y));
JS_SetPropertyStr(js, finger, "pressure", JS_NewFloat64(js, f->pressure));
JS_SetPropertyUint32(js, arr, i, finger);
JS_SetPropertyNumber(js, arr, i, finger);
}
SDL_free(fingers);
return arr;
JS_RETURN(arr);
)
static const JSCFunctionListEntry js_touch_funcs[] = {

21
tray.c
View File

@@ -93,12 +93,13 @@ JSC_CCALL(traymenu_get_entries,
int count = 0;
const SDL_TrayEntry **entries = SDL_GetTrayEntries(menu, &count);
if (!entries) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
for (int i = 0; i < count; i++) {
JS_SetPropertyUint32(js, arr, i, SDL_TrayEntry2js(js, (SDL_TrayEntry*)entries[i]));
JS_SetPropertyNumber(js, arr, i, SDL_TrayEntry2js(js, (SDL_TrayEntry*)entries[i]));
}
return arr;
JS_RETURN(arr);
)
JSC_CCALL(traymenu_insert_entry,
@@ -240,16 +241,16 @@ CELL_USE_INIT(
QJSCLASSPREP_FUNCS(SDL_Tray);
QJSCLASSPREP_FUNCS(SDL_TrayMenu);
QJSCLASSPREP_FUNCS(SDL_TrayEntry);
JSValue ret = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(ret, JS_NewObject(js));
JS_SetPropertyFunctionList(js, ret, js_tray_funcs, countof(js_tray_funcs));
// Export entry flags
JS_SetPropertyStr(js, ret, "BUTTON", JS_NewUint32(js, SDL_TRAYENTRY_BUTTON));
JS_SetPropertyStr(js, ret, "CHECKBOX", JS_NewUint32(js, SDL_TRAYENTRY_CHECKBOX));
JS_SetPropertyStr(js, ret, "SUBMENU", JS_NewUint32(js, SDL_TRAYENTRY_SUBMENU));
JS_SetPropertyStr(js, ret, "DISABLED", JS_NewUint32(js, SDL_TRAYENTRY_DISABLED));
JS_SetPropertyStr(js, ret, "CHECKED", JS_NewUint32(js, SDL_TRAYENTRY_CHECKED));
return ret;
JS_RETURN(ret);
)

91
video.c
View File

@@ -73,7 +73,7 @@ static JSValue js_SDL_Window_constructor(JSContext *js, JSValueConst new_target,
// Handle window position
JSValue x_val = JS_GetPropertyStr(js, opts, "x");
if (!JS_IsNull(x_val)) {
if (JS_IsString(x_val)) {
if (JS_IsText(x_val)) {
const char *pos = JS_ToCString(js, x_val);
if (strcmp(pos, "centered") == 0)
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_CENTERED);
@@ -88,7 +88,7 @@ static JSValue js_SDL_Window_constructor(JSContext *js, JSValueConst new_target,
JSValue y_val = JS_GetPropertyStr(js, opts, "y");
if (!JS_IsNull(y_val)) {
if (JS_IsString(y_val)) {
if (JS_IsText(y_val)) {
const char *pos = JS_ToCString(js, y_val);
if (strcmp(pos, "centered") == 0)
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, SDL_WINDOWPOS_CENTERED);
@@ -170,39 +170,40 @@ static JSValue js_SDL_Window_constructor(JSContext *js, JSValueConst new_target,
}
// Create the window JS object
JSValue window_obj = SDL_Window2js(js, window);
JS_FRAME(js);
JS_LOCAL(window_obj, SDL_Window2js(js, window));
// Set additional properties that can't be set during creation
// These will be applied through the property setters
JSValue opacity_val = JS_GetPropertyStr(js, opts, "opacity");
if (!JS_IsNull(opacity_val)) {
JS_SetPropertyStr(js, window_obj, "opacity", opacity_val);
}
JSValue min_size_val = JS_GetPropertyStr(js, opts, "minimumSize");
if (!JS_IsNull(min_size_val)) {
JS_SetPropertyStr(js, window_obj, "minimumSize", min_size_val);
}
JSValue max_size_val = JS_GetPropertyStr(js, opts, "maximumSize");
if (!JS_IsNull(max_size_val)) {
JS_SetPropertyStr(js, window_obj, "maximumSize", max_size_val);
}
JSValue pos_val = JS_GetPropertyStr(js, opts, "position");
if (!JS_IsNull(pos_val)) {
JS_SetPropertyStr(js, window_obj, "position", pos_val);
}
// Handle text input
JSValue text_input = JS_GetPropertyStr(js, opts, "textInput");
if (JS_ToBool(js, text_input)) {
// SDL_StartTextInput(window);
}
JS_FreeValue(js, text_input);
return window_obj;
JS_RETURN(window_obj);
}
JSC_CCALL(SDL_Window_fullscreen,
@@ -534,7 +535,7 @@ JSValue js_window_flash(JSContext *js, JSValue self, int argc, JSValue *argv)
{
SDL_Window *w = js2SDL_Window(js,self);
SDL_FlashOperation op = SDL_FLASH_BRIEFLY;
if (argc > 0 && JS_IsString(argv[0])) {
if (argc > 0 && JS_IsText(argv[0])) {
const char *operation = JS_ToCString(js,argv[0]);
if (strcmp(operation, "cancel") == 0) op = SDL_FLASH_CANCEL;
else if (strcmp(operation, "briefly") == 0) op = SDL_FLASH_BRIEFLY;
@@ -616,14 +617,14 @@ JSValue js_window_updateSurfaceRects(JSContext *js, JSValue self, int argc, JSVa
{
SDL_Window *w = js2SDL_Window(js,self);
if (!JS_IsArray(js, argv[0]))
if (!JS_IsArray(argv[0]))
return JS_ThrowTypeError(js, "Expected array of rectangles");
int len = JS_ArrayLength(js, argv[0]);
SDL_Rect rects[len];
for (int i = 0; i < len; i++) {
JSValue val = JS_GetPropertyUint32(js, argv[0], i);
JSValue val = JS_GetPropertyNumber(js, argv[0], i);
rect r = js2rect(js, val);
rects[i] = (SDL_Rect){r.x, r.y, r.w, r.h};
JS_FreeValue(js, val);
@@ -638,8 +639,9 @@ JSValue js_window_get_flags(JSContext *js, JSValue self)
{
SDL_Window *w = js2SDL_Window(js,self);
SDL_WindowFlags flags = SDL_GetWindowFlags(w);
JSValue ret = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(ret, JS_NewObject(js));
JS_SetPropertyStr(js, ret, "fullscreen", JS_NewBool(js, flags & SDL_WINDOW_FULLSCREEN));
JS_SetPropertyStr(js, ret, "opengl", JS_NewBool(js, flags & SDL_WINDOW_OPENGL));
JS_SetPropertyStr(js, ret, "occluded", JS_NewBool(js, flags & SDL_WINDOW_OCCLUDED));
@@ -665,8 +667,8 @@ JSValue js_window_get_flags(JSContext *js, JSValue self)
JS_SetPropertyStr(js, ret, "metal", JS_NewBool(js, flags & SDL_WINDOW_METAL));
JS_SetPropertyStr(js, ret, "transparent", JS_NewBool(js, flags & SDL_WINDOW_TRANSPARENT));
JS_SetPropertyStr(js, ret, "notFocusable", JS_NewBool(js, flags & SDL_WINDOW_NOT_FOCUSABLE));
return ret;
JS_RETURN(ret);
}
JSValue js_window_sync(JSContext *js, JSValue self, int argc, JSValue *argv)
@@ -742,52 +744,53 @@ JSValue js_window_set(JSContext *js, JSValue self, int argc, JSValue *argv)
JSValue js_window_state(JSContext *js, JSValue self, int argc, JSValue *argv)
{
SDL_Window *w = js2SDL_Window(js,self);
JSValue ret = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(ret, JS_NewObject(js));
// Title
const char *title = SDL_GetWindowTitle(w);
JS_SetPropertyStr(js, ret, "title", JS_NewString(js, title ? title : ""));
// Size
int width, height;
SDL_GetWindowSize(w, &width, &height);
JSValue sizeObj = JS_NewObject(js);
JS_LOCAL(sizeObj, JS_NewObject(js));
JS_SetPropertyStr(js, sizeObj, "x", JS_NewInt32(js, width));
JS_SetPropertyStr(js, sizeObj, "y", JS_NewInt32(js, height));
JS_SetPropertyStr(js, ret, "size", sizeObj);
// Position
int x, y;
SDL_GetWindowPosition(w, &x, &y);
JSValue posObj = JS_NewObject(js);
JS_LOCAL(posObj, JS_NewObject(js));
JS_SetPropertyStr(js, posObj, "x", JS_NewInt32(js, x));
JS_SetPropertyStr(js, posObj, "y", JS_NewInt32(js, y));
JS_SetPropertyStr(js, ret, "position", posObj);
// Minimum size
int minW, minH;
SDL_GetWindowMinimumSize(w, &minW, &minH);
JSValue minSizeObj = JS_NewObject(js);
JS_LOCAL(minSizeObj, JS_NewObject(js));
JS_SetPropertyStr(js, minSizeObj, "x", JS_NewInt32(js, minW));
JS_SetPropertyStr(js, minSizeObj, "y", JS_NewInt32(js, minH));
JS_SetPropertyStr(js, ret, "minimumSize", minSizeObj);
// Maximum size
int maxW, maxH;
SDL_GetWindowMaximumSize(w, &maxW, &maxH);
JSValue maxSizeObj = JS_NewObject(js);
JS_LOCAL(maxSizeObj, JS_NewObject(js));
JS_SetPropertyStr(js, maxSizeObj, "x", JS_NewInt32(js, maxW));
JS_SetPropertyStr(js, maxSizeObj, "y", JS_NewInt32(js, maxH));
JS_SetPropertyStr(js, ret, "maximumSize", maxSizeObj);
// Opacity
float opacity = SDL_GetWindowOpacity(w);
JS_SetPropertyStr(js, ret, "opacity", JS_NewFloat64(js, opacity));
// Grabs
JS_SetPropertyStr(js, ret, "mouseGrab", JS_NewBool(js, SDL_GetWindowMouseGrab(w)));
JS_SetPropertyStr(js, ret, "keyboardGrab", JS_NewBool(js, SDL_GetWindowKeyboardGrab(w)));
// Flags-based properties
SDL_WindowFlags flags = SDL_GetWindowFlags(w);
JS_SetPropertyStr(js, ret, "fullscreen", JS_NewBool(js, flags & SDL_WINDOW_FULLSCREEN));
@@ -803,28 +806,28 @@ JSValue js_window_state(JSContext *js, JSValue self, int argc, JSValue *argv)
// Display properties
JS_SetPropertyStr(js, ret, "displayScale", JS_NewFloat64(js, SDL_GetWindowDisplayScale(w)));
JS_SetPropertyStr(js, ret, "pixelDensity", JS_NewFloat64(js, SDL_GetWindowPixelDensity(w)));
// Size in pixels
int pixelW, pixelH;
SDL_GetWindowSizeInPixels(w, &pixelW, &pixelH);
JSValue pixelSizeObj = JS_NewObject(js);
JS_LOCAL(pixelSizeObj, JS_NewObject(js));
JS_SetPropertyStr(js, pixelSizeObj, "x", JS_NewInt32(js, pixelW));
JS_SetPropertyStr(js, pixelSizeObj, "y", JS_NewInt32(js, pixelH));
JS_SetPropertyStr(js, ret, "sizeInPixels", pixelSizeObj);
// Flags
JS_SetPropertyStr(js, ret, "flags", JS_NewInt64(js, flags));
JS_SetPropertyStr(js, ret, "id", JS_NewUint32(js, SDL_GetWindowID(w)));
// Parent
SDL_Window *parent = SDL_GetWindowParent(w);
if (parent)
JS_SetPropertyStr(js, ret, "parent", SDL_Window2js(js, parent));
else
JS_SetPropertyStr(js, ret, "parent", JS_NULL);
return ret;
JS_RETURN(ret);
}
@@ -873,17 +876,17 @@ JSC_CCALL(sdl_set_cursor,
CELL_USE_INIT(
if (!SDL_Init(SDL_INIT_VIDEO))
return JS_ThrowInternalError(js, "Unable to initialize video subsystem: %s", SDL_GetError());
JSValue ret = JS_NewObject(js);
JS_FRAME(js);
JS_LOCAL(ret, JS_NewObject(js));
JS_SetPropertyStr(js, ret, "window", QJSCLASSPREP_FUNCS_CTOR(SDL_Window, 1));
QJSCLASSPREP_NO_FUNCS(SDL_Cursor);
// Add cursor functions
JS_SetPropertyStr(js, ret, "createCursor", JS_NewCFunction(js, js_sdl_create_cursor, "createCursor", 2));
JS_SetPropertyStr(js, ret, "setCursor", JS_NewCFunction(js, js_sdl_set_cursor, "setCursor", 1));
return ret;
JS_RETURN(ret);
)