Files
cell/scripts/os_playdate.c
2025-12-07 04:04:11 -06:00

179 lines
4.9 KiB
C

// os_playdate.c - OS module for Playdate
// Provides system information and utilities for Playdate platform
#include "cell.h"
#include "pd_api.h"
#include <stdlib.h>
#include <string.h>
// Global Playdate API pointers - defined in main_playdate.c
extern const struct playdate_sys *pd_sys;
// cell_ns - nanoseconds since some epoch (used by scheduler)
uint64_t cell_ns(void)
{
// Playdate provides milliseconds, convert to nanoseconds
if (pd_sys) {
unsigned int ms = pd_sys->getCurrentTimeMilliseconds();
return (uint64_t)ms * 1000000ULL;
}
return 0;
}
// cell_sleep - sleep for specified seconds
void cell_sleep(double seconds)
{
if (pd_sys) {
pd_sys->delay((uint32_t)(seconds * 1000));
}
}
JSC_CCALL(os_now,
return number2js(js, cell_ns());
)
JSC_CCALL(os_sleep,
double secs = js2number(js, argv[0]);
cell_sleep(secs);
)
static JSValue js_os_totalmem(JSContext *js, JSValue self, int argc, JSValue *argv) {
// Playdate has 16MB RAM, but we don't have direct access to memory stats
return JS_NewInt64(js, 16); // 16 MB
}
static JSValue js_os_platform(JSContext *js, JSValue self, int argc, JSValue *argv) {
return JS_NewString(js, "Playdate");
}
static JSValue js_os_hostname(JSContext *js, JSValue self, int argc, JSValue *argv) {
return JS_NewString(js, "playdate");
}
static JSValue js_os_arch(JSContext *js, JSValue self, int argc, JSValue *argv) {
return JS_NewString(js, "arm");
}
static JSValue js_os_freemem(JSContext *js, JSValue self, int argc, JSValue *argv) {
// No way to get free memory on Playdate
return JS_NewInt64(js, 0);
}
static JSValue js_os_version(JSContext *js, JSValue self, int argc, JSValue *argv) {
#if TARGET_EXTENSION
if (pd_sys) {
const struct PDInfo *info = pd_sys->getSystemInfo();
if (info) {
char buf[32];
snprintf(buf, sizeof(buf), "%u", info->osversion);
return JS_NewString(js, buf);
}
}
#endif
return JS_NewString(js, "unknown");
}
JSC_CCALL(os_mallinfo,
ret = JS_NewObject(js);
)
static JSValue js_os_rusage(JSContext *js, JSValue self, int argc, JSValue *argv) {
// No rusage on Playdate
return JS_NewObject(js);
}
JSC_SCALL(os_system,
// system() not available on Playdate
ret = JS_NewInt32(js, -1);
)
JSC_CCALL(os_exit,
// Can't really exit on Playdate, but we can try
exit(0);
)
// dylib functions - not supported on Playdate
static JSValue js_os_dylib_open(JSContext *js, JSValue self, int argc, JSValue *argv) {
return JS_ThrowInternalError(js, "dylib_open: not supported on Playdate");
}
static JSValue js_os_dylib_symbol(JSContext *js, JSValue self, int argc, JSValue *argv) {
return JS_ThrowInternalError(js, "dylib_symbol: not supported on Playdate");
}
static JSValue js_os_dylib_has_symbol(JSContext *js, JSValue self, int argc, JSValue *argv) {
return JS_NewBool(js, 0);
}
JSC_CCALL(os_print,
size_t len;
const char *str = JS_ToCStringLen(js, &len, argv[0]);
if (pd_sys) {
pd_sys->logToConsole("%.*s", (int)len, str);
}
JS_FreeCString(js, str);
)
static JSValue js_os_load_internal(JSContext *js, JSValue self, int argc, JSValue *argv) {
// No dlsym on Playdate - internal modules are linked statically
return JS_NULL;
}
static JSValue js_os_internal_exists(JSContext *js, JSValue self, int argc, JSValue *argv) {
return JS_NewBool(js, 0);
}
// Random number generation
int randombytes(void *buf, size_t n) {
// Playdate doesn't have a crypto RNG, use a simple PRNG seeded from time
// This is NOT cryptographically secure!
uint8_t *p = (uint8_t *)buf;
static uint32_t seed = 0;
if (seed == 0 && pd_sys) {
seed = pd_sys->getCurrentTimeMilliseconds();
}
for (size_t i = 0; i < n; i++) {
seed = seed * 1103515245 + 12345;
p[i] = (uint8_t)(seed >> 16);
}
return 0;
}
JSC_CCALL(os_random,
return JS_NewFloat64(js, cell_random_fit());
)
JSC_CCALL(os_getenv,
// No environment variables on Playdate
return JS_NULL;
)
static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, platform, 0),
MIST_FUNC_DEF(os, arch, 0),
MIST_FUNC_DEF(os, totalmem, 0),
MIST_FUNC_DEF(os, freemem, 0),
MIST_FUNC_DEF(os, hostname, 0),
MIST_FUNC_DEF(os, version, 0),
MIST_FUNC_DEF(os, now, 0),
MIST_FUNC_DEF(os, rusage, 0),
MIST_FUNC_DEF(os, mallinfo, 0),
MIST_FUNC_DEF(os, system, 1),
MIST_FUNC_DEF(os, exit, 0),
MIST_FUNC_DEF(os, sleep, 1),
MIST_FUNC_DEF(os, dylib_open, 1),
MIST_FUNC_DEF(os, dylib_symbol, 2),
MIST_FUNC_DEF(os, dylib_has_symbol, 2),
MIST_FUNC_DEF(os, load_internal, 1),
MIST_FUNC_DEF(os, internal_exists, 1),
MIST_FUNC_DEF(os, print, 1),
MIST_FUNC_DEF(os, random, 0),
MIST_FUNC_DEF(os, getenv, 1),
};
JSValue js_os_use(JSContext *js) {
JSValue mod = JS_NewObject(js);
JS_SetPropertyFunctionList(js, mod, js_os_funcs, countof(js_os_funcs));
return mod;
}