Files
cell/playdate/sys_playdate.c
2025-12-11 14:42:30 -06:00

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(&current, &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;
}