// sys_playdate.c - Cell integration for Playdate System API // Wraps pd_api_sys.h functions for JavaScript access #include "cell.h" #include "common.h" #include // --- System Functions --- JSC_CCALL(sys_logToConsole, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); const char *str = JS_ToCString(js, argv[0]); if (str) { pd_sys->logToConsole("%s", str); JS_FreeCString(js, str); } return JS_NULL; ) JSC_CCALL(sys_error, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); const char *str = JS_ToCString(js, argv[0]); if (str) { pd_sys->error("%s", str); JS_FreeCString(js, str); } return JS_NULL; ) JSC_CCALL(sys_getLanguage, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); PDLanguage lang = pd_sys->getLanguage(); return JS_NewInt32(js, lang); ) JSC_CCALL(sys_getCurrentTimeMilliseconds, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); return JS_NewInt64(js, pd_sys->getCurrentTimeMilliseconds()); ) JSC_CCALL(sys_getSecondsSinceEpoch, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); unsigned int ms = 0; unsigned int secs = pd_sys->getSecondsSinceEpoch(&ms); JSValue obj = JS_NewObject(js); JS_SetPropertyStr(js, obj, "seconds", JS_NewInt64(js, secs)); JS_SetPropertyStr(js, obj, "milliseconds", JS_NewInt32(js, ms)); return obj; ) JSC_CCALL(sys_drawFPS, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); int x = (int)js2number(js, argv[0]); int y = (int)js2number(js, argv[1]); pd_sys->drawFPS(x, y); return JS_NULL; ) JSC_CCALL(sys_getButtonState, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); PDButtons current, pushed, released; pd_sys->getButtonState(¤t, &pushed, &released); JSValue obj = JS_NewObject(js); JS_SetPropertyStr(js, obj, "current", JS_NewInt32(js, current)); JS_SetPropertyStr(js, obj, "pushed", JS_NewInt32(js, pushed)); JS_SetPropertyStr(js, obj, "released", JS_NewInt32(js, released)); return obj; ) JSC_CCALL(sys_setPeripheralsEnabled, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); PDPeripherals mask = (PDPeripherals)(int)js2number(js, argv[0]); pd_sys->setPeripheralsEnabled(mask); return JS_NULL; ) JSC_CCALL(sys_getAccelerometer, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); float x, y, z; pd_sys->getAccelerometer(&x, &y, &z); JSValue obj = JS_NewObject(js); JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, x)); JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, y)); JS_SetPropertyStr(js, obj, "z", JS_NewFloat64(js, z)); return obj; ) JSC_CCALL(sys_getCrankChange, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); return JS_NewFloat64(js, pd_sys->getCrankChange()); ) JSC_CCALL(sys_getCrankAngle, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); return JS_NewFloat64(js, pd_sys->getCrankAngle()); ) JSC_CCALL(sys_isCrankDocked, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); return JS_NewBool(js, pd_sys->isCrankDocked()); ) JSC_CCALL(sys_setCrankSoundsDisabled, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); int flag = JS_ToBool(js, argv[0]); int prev = pd_sys->setCrankSoundsDisabled(flag); return JS_NewBool(js, prev); ) JSC_CCALL(sys_getFlipped, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); return JS_NewBool(js, pd_sys->getFlipped()); ) JSC_CCALL(sys_setAutoLockDisabled, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); pd_sys->setAutoLockDisabled(JS_ToBool(js, argv[0])); return JS_NULL; ) JSC_CCALL(sys_getReduceFlashing, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); return JS_NewBool(js, pd_sys->getReduceFlashing()); ) JSC_CCALL(sys_getElapsedTime, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); return JS_NewFloat64(js, pd_sys->getElapsedTime()); ) JSC_CCALL(sys_resetElapsedTime, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); pd_sys->resetElapsedTime(); return JS_NULL; ) JSC_CCALL(sys_getBatteryPercentage, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); return JS_NewFloat64(js, pd_sys->getBatteryPercentage()); ) JSC_CCALL(sys_getBatteryVoltage, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); return JS_NewFloat64(js, pd_sys->getBatteryVoltage()); ) JSC_CCALL(sys_getTimezoneOffset, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); return JS_NewInt32(js, pd_sys->getTimezoneOffset()); ) JSC_CCALL(sys_shouldDisplay24HourTime, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); return JS_NewBool(js, pd_sys->shouldDisplay24HourTime()); ) JSC_CCALL(sys_convertEpochToDateTime, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); uint32_t epoch = (uint32_t)js2number(js, argv[0]); struct PDDateTime dt; pd_sys->convertEpochToDateTime(epoch, &dt); JSValue obj = JS_NewObject(js); JS_SetPropertyStr(js, obj, "year", JS_NewInt32(js, dt.year)); JS_SetPropertyStr(js, obj, "month", JS_NewInt32(js, dt.month)); JS_SetPropertyStr(js, obj, "day", JS_NewInt32(js, dt.day)); JS_SetPropertyStr(js, obj, "weekday", JS_NewInt32(js, dt.weekday)); JS_SetPropertyStr(js, obj, "hour", JS_NewInt32(js, dt.hour)); JS_SetPropertyStr(js, obj, "minute", JS_NewInt32(js, dt.minute)); JS_SetPropertyStr(js, obj, "second", JS_NewInt32(js, dt.second)); return obj; ) JSC_CCALL(sys_convertDateTimeToEpoch, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); struct PDDateTime dt = {0}; dt.year = (uint16_t)js2number(js, JS_GetPropertyStr(js, argv[0], "year")); dt.month = (uint8_t)js2number(js, JS_GetPropertyStr(js, argv[0], "month")); dt.day = (uint8_t)js2number(js, JS_GetPropertyStr(js, argv[0], "day")); dt.hour = (uint8_t)js2number(js, JS_GetPropertyStr(js, argv[0], "hour")); dt.minute = (uint8_t)js2number(js, JS_GetPropertyStr(js, argv[0], "minute")); dt.second = (uint8_t)js2number(js, JS_GetPropertyStr(js, argv[0], "second")); return JS_NewInt64(js, pd_sys->convertDateTimeToEpoch(&dt)); ) JSC_CCALL(sys_clearICache, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); pd_sys->clearICache(); return JS_NULL; ) JSC_CCALL(sys_delay, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); pd_sys->delay((uint32_t)js2number(js, argv[0])); return JS_NULL; ) JSC_SCALL(sys_restartGame, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); pd_sys->restartGame(str); ) JSC_CCALL(sys_getLaunchArgs, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); const char *path = NULL; const char *args = pd_sys->getLaunchArgs(&path); JSValue obj = JS_NewObject(js); JS_SetPropertyStr(js, obj, "args", args ? JS_NewString(js, args) : JS_NULL); JS_SetPropertyStr(js, obj, "path", path ? JS_NewString(js, path) : JS_NULL); return obj; ) JSC_CCALL(sys_getSystemInfo, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); const struct PDInfo *info = pd_sys->getSystemInfo(); if (!info) return JS_NULL; JSValue obj = JS_NewObject(js); JS_SetPropertyStr(js, obj, "osversion", JS_NewInt64(js, info->osversion)); JS_SetPropertyStr(js, obj, "language", JS_NewInt32(js, info->language)); return obj; ) // --- Menu Functions --- JSC_CCALL(sys_removeAllMenuItems, if (!pd_sys) return JS_ThrowInternalError(js, "system not initialized"); pd_sys->removeAllMenuItems(); return JS_NULL; ) static const JSCFunctionListEntry js_sys_funcs[] = { MIST_FUNC_DEF(sys, logToConsole, 1), MIST_FUNC_DEF(sys, error, 1), MIST_FUNC_DEF(sys, getLanguage, 0), MIST_FUNC_DEF(sys, getCurrentTimeMilliseconds, 0), MIST_FUNC_DEF(sys, getSecondsSinceEpoch, 0), MIST_FUNC_DEF(sys, drawFPS, 2), MIST_FUNC_DEF(sys, getButtonState, 0), MIST_FUNC_DEF(sys, setPeripheralsEnabled, 1), MIST_FUNC_DEF(sys, getAccelerometer, 0), MIST_FUNC_DEF(sys, getCrankChange, 0), MIST_FUNC_DEF(sys, getCrankAngle, 0), MIST_FUNC_DEF(sys, isCrankDocked, 0), MIST_FUNC_DEF(sys, setCrankSoundsDisabled, 1), MIST_FUNC_DEF(sys, getFlipped, 0), MIST_FUNC_DEF(sys, setAutoLockDisabled, 1), MIST_FUNC_DEF(sys, getReduceFlashing, 0), MIST_FUNC_DEF(sys, getElapsedTime, 0), MIST_FUNC_DEF(sys, resetElapsedTime, 0), MIST_FUNC_DEF(sys, getBatteryPercentage, 0), MIST_FUNC_DEF(sys, getBatteryVoltage, 0), MIST_FUNC_DEF(sys, getTimezoneOffset, 0), MIST_FUNC_DEF(sys, shouldDisplay24HourTime, 0), MIST_FUNC_DEF(sys, convertEpochToDateTime, 1), MIST_FUNC_DEF(sys, convertDateTimeToEpoch, 1), MIST_FUNC_DEF(sys, clearICache, 0), MIST_FUNC_DEF(sys, delay, 1), MIST_FUNC_DEF(sys, restartGame, 1), MIST_FUNC_DEF(sys, getLaunchArgs, 0), MIST_FUNC_DEF(sys, getSystemInfo, 0), MIST_FUNC_DEF(sys, removeAllMenuItems, 0), }; JSValue js_sys_use(JSContext *js) { JSValue mod = JS_NewObject(js); JS_SetPropertyFunctionList(js, mod, js_sys_funcs, countof(js_sys_funcs)); return mod; }