179 lines
4.9 KiB
C
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;
|
|
}
|