268 lines
9.4 KiB
C
268 lines
9.4 KiB
C
// 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 <string.h>
|
|
|
|
// --- 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;
|
|
}
|