diff --git a/src/computer.h b/src/computer.h index 7d842bf..e556991 100644 --- a/src/computer.h +++ b/src/computer.h @@ -4,6 +4,7 @@ #include "neonucleus.h" typedef struct nn_computer { + char state; nn_component *components; size_t componentLen; size_t componentCap; @@ -15,6 +16,8 @@ typedef struct nn_computer { nn_architecture *nextArch; nn_architecture supportedArch[NN_MAX_ARCHITECTURES]; size_t supportedArchCount; + double timeOffset; + nn_universe *universe; } nn_computer; #endif diff --git a/src/neonucleus.h b/src/neonucleus.h index 80d8af3..b24e757 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -5,6 +5,43 @@ #include #include +// Based off https://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) + //define something for Windows (32-bit and 64-bit, this part is common) + #ifdef _WIN64 + #define NN_WINDOWS + #else + #error "Windows 32-bit is not supported" + #endif +#elif __APPLE__ + #include + #if TARGET_IPHONE_SIMULATOR + #error "iPhone Emulators are not supported" + #elif TARGET_OS_MACCATALYST + // I guess? + #define NN_MACOS + #elif TARGET_OS_IPHONE + #error "iPhone are not supported" + #elif TARGET_OS_MAC + #define NN_MACOS + #else + #error "Unknown Apple platform" + #endif +#elif __ANDROID__ + #error "Android is not supported" +#elif __linux__ + #define NN_LINUX +#endif + +#if __unix__ // all unices not caught above + // Unix + #define NN_UNIX + #define NN_POSIX +#elif defined(_POSIX_VERSION) + // POSIX + #define NN_POSIX +#endif + // The entire C API, in one header // Magic limits @@ -98,14 +135,19 @@ void nn_lock(nn_guard *guard); void nn_unlock(nn_guard *guard); void nn_deleteGuard(nn_guard *guard); +double nn_realTime(); +double nn_realTimeClock(void *_); + +typedef double nn_clock_t(void *_); + nn_universe *nn_newUniverse(); void nn_unsafeDeleteUniverse(nn_universe *universe); void *nn_queryUserdata(nn_universe *universe, const char *name); void nn_storeUserdata(nn_universe *universe, const char *name, void *data); +void nn_setClock(nn_universe *universe, nn_clock_t *clock, void *userdata); nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_architecture *arch, void *userdata, size_t memoryLimit, size_t componentLimit); void nn_tickComputer(nn_computer *computer); -void nn_setUptime(nn_computer *computer, double uptime); double nn_getUptime(nn_computer *computer); size_t nn_getComputerMemoryUsed(nn_computer *computer); size_t nn_getComputerMemoryTotal(nn_computer *computer); @@ -121,6 +163,7 @@ void nn_popSignal(nn_computer *computer); void nn_addUser(nn_computer *computer, const char *name); void nn_deleteUser(nn_computer *computer, const char *name); const char *nn_indexUser(nn_computer *computer, size_t idx); +bool nn_isUser(nn_computer *computer, const char *name); /// This means the computer has not yet started. /// This is used to determine whether newComponent and removeComponent should emit signals. @@ -158,12 +201,6 @@ const char *nn_indexUser(nn_computer *computer, size_t idx); int nn_getState(nn_computer *computer); void nn_setState(nn_computer *computer, int state); -size_t nn_countUsers(nn_computer *computer); -bool nn_isUser(nn_computer *computer, const char *user); -void nn_addUser(nn_computer *computer, const char *user); -void nn_removeUser(nn_computer *computer, const char *user); -const char *nn_getUser(nn_computer *computer, size_t idx); - void nn_setEnergyInfo(nn_computer *computer, size_t energy, size_t capacity); size_t nn_getEnergy(nn_computer *computer); void nn_removeEnergy(nn_computer *computer, size_t energy); diff --git a/src/universe.c b/src/universe.c index fd8ac8f..512f852 100644 --- a/src/universe.c +++ b/src/universe.c @@ -1,16 +1,7 @@ #include "neonucleus.h" +#include "universe.h" #include -typedef struct nn_universe_udata { - char *name; - void *userdata; -} nn_universe_udata; - -typedef struct nn_universe { - nn_universe_udata udata[NN_MAX_USERDATA]; - size_t udataLen; -} nn_universe; - nn_universe *nn_newUniverse() { nn_universe *u = nn_malloc(sizeof(nn_universe)); if(u == NULL) return u; diff --git a/src/universe.h b/src/universe.h index 9f3eed3..7e5aee4 100644 --- a/src/universe.h +++ b/src/universe.h @@ -3,6 +3,16 @@ #include "neonucleus.h" -typedef struct nn_universe nn_universe; +typedef struct nn_universe_udata { + char *name; + void *userdata; +} nn_universe_udata; + +typedef struct nn_universe { + nn_universe_udata udata[NN_MAX_USERDATA]; + size_t udataLen; + nn_clock_t *currentClock; + void *clockUserdata; +} nn_universe; #endif diff --git a/src/utils.c b/src/utils.c index a348467..1fbf7a8 100644 --- a/src/utils.c +++ b/src/utils.c @@ -2,6 +2,12 @@ #include #include +#ifdef NN_POSIX +#include +#else +#include +#endif + void *nn_malloc(size_t size) { return malloc(size); } @@ -27,3 +33,30 @@ void *nn_memdup(const void *buf, size_t len) { if(m == NULL) return m; return memcpy(m, buf, len); } + +#ifdef NN_POSIX + +double nn_realTime() { + struct timespec time; + if(clock_gettime(CLOCK_MONOTONIC, &time) < 0) return 0; // oh no + return time.tv_sec + ((double)time.tv_nsec) / 1e9; +} + +#else + + +double nn_realTime() { + LARGE_INTEGER frequency = {0}; + if(!QueryPerformanceFrequency(&frequency)) return 0; + + LARGE_INTEGER now = {0}; + if(!QueryPerformanceCounter(&now)) return 0; + + return (double)now.QuadPart / frequency.QuadPart; +} + +#endif + +double nn_realTimeClock(void *_) { + return nn_realTime(); +}