computers can be turned on/off now
This commit is contained in:
@@ -116,6 +116,27 @@ static void luaArch_nnToLua(luaArch *arch, lua_State *L, size_t nnIdx) {
|
||||
luaL_error(L, "bad NN value: %s", nn_typenameof(C, nnIdx));
|
||||
}
|
||||
|
||||
static int luaArch_computer_beep(lua_State *L) {
|
||||
nn_Beep beep = {.frequency = 1000, .duration = 1, .volume = 1};
|
||||
if(lua_isnumber(L, 1)) {
|
||||
beep.frequency = lua_tonumber(L, 1);
|
||||
}
|
||||
if(lua_isnumber(L, 2)) {
|
||||
beep.duration = lua_tonumber(L, 2);
|
||||
}
|
||||
if(lua_isnumber(L, 3)) {
|
||||
beep.volume = lua_tonumber(L, 3);
|
||||
}
|
||||
if(beep.frequency < 20) beep.frequency = 20;
|
||||
if(beep.duration < 0) beep.duration = 0;
|
||||
if(beep.volume < 0) beep.volume = 0;
|
||||
if(beep.frequency > 20000) beep.frequency = 20000;
|
||||
if(beep.duration > 5) beep.duration = 5;
|
||||
if(beep.volume > 1) beep.volume = 1;
|
||||
nn_setComputerBeep(luaArch_from(L)->computer, beep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int luaArch_computer_freeMemory(lua_State *L) {
|
||||
lua_pushinteger(L, nn_getFreeMemory(luaArch_from(L)->computer));
|
||||
return 1;
|
||||
@@ -531,6 +552,8 @@ static int luaArch_unicode_wtrunc(lua_State *L) {
|
||||
static void luaArch_loadEnv(lua_State *L) {
|
||||
lua_createtable(L, 0, 10);
|
||||
int computer = lua_gettop(L);
|
||||
lua_pushcfunction(L, luaArch_computer_beep);
|
||||
lua_setfield(L, computer, "beep");
|
||||
lua_pushcfunction(L, luaArch_computer_freeMemory);
|
||||
lua_setfield(L, computer, "freeMemory");
|
||||
lua_pushcfunction(L, luaArch_computer_totalMemory);
|
||||
|
||||
24
src/main.c
24
src/main.c
@@ -457,7 +457,6 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
restart:;
|
||||
nn_Computer *c = nn_createComputer(u, NULL, "computer0", ramTotal, 256, 256);
|
||||
if(showStats) {
|
||||
// collects stats
|
||||
@@ -549,6 +548,11 @@ restart:;
|
||||
if(t != NULL) nn_pushClipboard(c, "mainKB", t, player);
|
||||
}
|
||||
|
||||
if(IsKeyPressed(KEY_TAB)) {
|
||||
printf("force crashing\n");
|
||||
nn_forceCrashComputer(c, "get crashed lol");
|
||||
}
|
||||
|
||||
while(1) {
|
||||
int keycode = GetKeyPressed();
|
||||
nn_codepoint unicode = GetCharPressed();
|
||||
@@ -574,6 +578,11 @@ restart:;
|
||||
keybuf[i].key = 0;
|
||||
nn_pushKeyUp(c, "mainKB", keybuf[i].unicode, key, player);
|
||||
}
|
||||
// unicode keys handled by raylib
|
||||
if(IsKeyPressedRepeat(keybuf[i].key) && keybuf[i].unicode == 0) {
|
||||
int key = keycode_to_oc(keybuf[i].key);
|
||||
nn_pushKeyDown(c, "mainKB", keybuf[i].unicode, key, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,7 +603,6 @@ restart:;
|
||||
if(getenv("NN_NOIDLE") != NULL) nn_resetIdleTime(c);
|
||||
nn_Exit e = nn_tick(c);
|
||||
if(e != NN_OK) {
|
||||
nn_setErrorFromExit(c, e);
|
||||
printf("error: %s\n", nn_getError(c));
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -616,10 +624,18 @@ restart:;
|
||||
}
|
||||
if(state == NN_RESTART) {
|
||||
printf("restart requested\n");
|
||||
nn_destroyComputer(c);
|
||||
goto restart;
|
||||
nn_stopComputer(c);
|
||||
ncl_resetScreen(nn_getComponentState(screen));
|
||||
nn_addIdleTime(c, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
nn_Beep beep;
|
||||
if(nn_getComputerBeep(c, &beep)) {
|
||||
nn_clearComputerBeep(c);
|
||||
printf("beep: %f Hz, %fs, %f%% volume\n", beep.frequency, beep.duration, beep.volume * 100);
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:;
|
||||
|
||||
106
src/neonucleus.c
106
src/neonucleus.c
@@ -784,6 +784,15 @@ void nn_hashDeinit(nn_HashMap *map) {
|
||||
nn_free(map->ctx, map->buf, map->hash->entSize * map->bufsize);
|
||||
}
|
||||
|
||||
void nn_hashClear(nn_HashMap *map) {
|
||||
for(size_t i = 0; i < map->bufsize; i++) {
|
||||
void *ent = NN_PTROFF(map->buf, i, map->hash->entSize);
|
||||
if(map->hash->handler(NN_HASH_CMP, ent, NULL) == NN_HASH_DIFFERENT) {
|
||||
map->hash->handler(NN_HASH_REMOVE, ent, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t nn_hashGetHash(nn_HashMap *map, void *entry) {
|
||||
return map->hash->handler(NN_HASH_HASH, entry, NULL);
|
||||
}
|
||||
@@ -1044,6 +1053,7 @@ typedef struct nn_Computer {
|
||||
size_t userCount;
|
||||
double idleTimestamp;
|
||||
double memoryScale;
|
||||
nn_Beep beep;
|
||||
nn_Value callstack[NN_MAX_STACK];
|
||||
char errorBuffer[NN_MAX_ERROR_SIZE];
|
||||
nn_Architecture archs[NN_MAX_ARCHITECTURES];
|
||||
@@ -1169,6 +1179,7 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char
|
||||
c->memoryScale = 1;
|
||||
// set to empty string
|
||||
c->errorBuffer[0] = '\0';
|
||||
nn_clearComputerBeep(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -1196,34 +1207,86 @@ static const nn_MethodEntry *nn_getInternalMethod(nn_Component *c, const char *m
|
||||
return nn_hashGet(&c->methodsMap, &lookingFor);
|
||||
}
|
||||
|
||||
void nn_destroyComputer(nn_Computer *computer) {
|
||||
nn_Context *ctx = &computer->universe->ctx;
|
||||
nn_Exit nn_startComputer(nn_Computer *computer) {
|
||||
if(nn_isComputerOn(computer)) {
|
||||
nn_stopComputer(computer);
|
||||
}
|
||||
nn_ArchitectureRequest req;
|
||||
req.computer = computer;
|
||||
req.globalState = computer->arch.state;
|
||||
req.localState = NULL;
|
||||
req.action = NN_ARCH_INIT;
|
||||
nn_Exit err = computer->arch.handler(&req);
|
||||
if(err) {
|
||||
computer->state = NN_CRASHED;
|
||||
nn_setErrorFromExit(computer, err);
|
||||
return err;
|
||||
}
|
||||
computer->archState = req.localState;
|
||||
return NN_OK;
|
||||
}
|
||||
|
||||
if(computer->arch.name != NULL && computer->archState != NULL) {
|
||||
void nn_stopComputer(nn_Computer *computer) {
|
||||
nn_Context *ctx = &computer->universe->ctx;
|
||||
if(nn_isComputerOn(computer)) {
|
||||
nn_ArchitectureRequest req;
|
||||
req.computer = computer;
|
||||
req.globalState = computer->arch.state;
|
||||
req.localState = computer->archState;
|
||||
req.action = NN_ARCH_DEINIT;
|
||||
computer->arch.handler(&req);
|
||||
computer->archState = NULL;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < computer->stackSize; i++) {
|
||||
nn_dropValue(computer->callstack[i]);
|
||||
}
|
||||
for(nn_ComponentEntry *c = nn_hashIterate(&computer->components, NULL); c != NULL; c = nn_hashIterate(&computer->components, c)) {
|
||||
nn_signalComponent(c->comp, computer, NN_CSIGUNMOUNTED);
|
||||
nn_dropComponent(c->comp);
|
||||
}
|
||||
computer->state = NN_BOOTUP;
|
||||
for(size_t i = 0; i < computer->signalCount; i++) {
|
||||
nn_Signal s = computer->signals[i];
|
||||
for(size_t j = 0; j < s.len; j++) nn_dropValue(s.values[j]);
|
||||
nn_free(ctx, s.values, sizeof(nn_Value) * s.len);
|
||||
}
|
||||
computer->signalCount = 0;
|
||||
}
|
||||
|
||||
void nn_forceCrashComputer(nn_Computer *computer, const char *s) {
|
||||
nn_stopComputer(computer);
|
||||
computer->state = NN_CRASHED;
|
||||
nn_setError(computer, s);
|
||||
}
|
||||
|
||||
bool nn_isComputerOn(nn_Computer *computer) {
|
||||
return computer->archState != NULL;
|
||||
}
|
||||
|
||||
void nn_setComputerBeep(nn_Computer *computer, nn_Beep beep) {
|
||||
if(beep.duration < 0) beep.duration = 0;
|
||||
computer->beep = beep;
|
||||
nn_addIdleTime(computer, beep.duration);
|
||||
}
|
||||
|
||||
bool nn_getComputerBeep(nn_Computer *computer, nn_Beep *beep) {
|
||||
*beep = computer->beep;
|
||||
return computer->beep.volume > 0;
|
||||
}
|
||||
|
||||
void nn_clearComputerBeep(nn_Computer *computer) {
|
||||
computer->beep.volume = 0;
|
||||
}
|
||||
|
||||
void nn_destroyComputer(nn_Computer *computer) {
|
||||
nn_Context *ctx = &computer->universe->ctx;
|
||||
nn_stopComputer(computer);
|
||||
|
||||
for(size_t i = 0; i < computer->stackSize; i++) {
|
||||
nn_dropValue(computer->callstack[i]);
|
||||
}
|
||||
for(size_t i = 0; i < computer->userCount; i++) {
|
||||
nn_strfree(ctx, computer->users[i]);
|
||||
}
|
||||
|
||||
for(nn_ComponentEntry *c = nn_hashIterate(&computer->components, NULL); c != NULL; c = nn_hashIterate(&computer->components, c)) {
|
||||
nn_signalComponent(c->comp, computer, NN_CSIGUNMOUNTED);
|
||||
nn_dropComponent(c->comp);
|
||||
}
|
||||
nn_destroyLock(ctx, computer->lock);
|
||||
nn_hashDeinit(&computer->components);
|
||||
if(computer->tmpaddress != NULL) nn_strfree(ctx, computer->tmpaddress);
|
||||
nn_strfree(ctx, computer->address);
|
||||
@@ -1522,6 +1585,9 @@ void nn_resetIdleTime(nn_Computer *computer) {
|
||||
}
|
||||
|
||||
nn_Exit nn_tick(nn_Computer *computer) {
|
||||
if(computer->state == NN_CRASHED) {
|
||||
return NN_EBADSTATE;
|
||||
}
|
||||
nn_resetCallBudget(computer);
|
||||
nn_resetComponentBudgets(computer);
|
||||
nn_clearstack(computer);
|
||||
@@ -1531,20 +1597,10 @@ nn_Exit nn_tick(nn_Computer *computer) {
|
||||
computer->idleTimestamp = nn_getUptime(computer);
|
||||
if(computer->state == NN_BOOTUP) {
|
||||
// init state
|
||||
nn_ArchitectureRequest req;
|
||||
req.computer = computer;
|
||||
req.globalState = computer->arch.state;
|
||||
req.localState = NULL;
|
||||
req.action = NN_ARCH_INIT;
|
||||
err = computer->arch.handler(&req);
|
||||
if(err) {
|
||||
computer->state = NN_CRASHED;
|
||||
nn_setErrorFromExit(computer, err);
|
||||
return err;
|
||||
}
|
||||
computer->archState = req.localState;
|
||||
err = nn_startComputer(computer);
|
||||
if(err) return err;
|
||||
} else if(computer->state != NN_RUNNING) {
|
||||
nn_setErrorFromExit(computer, NN_EBADSTATE);
|
||||
if(computer->state != NN_CRASHED) nn_setErrorFromExit(computer, NN_EBADSTATE);
|
||||
return NN_EBADSTATE;
|
||||
}
|
||||
computer->state = NN_RUNNING;
|
||||
@@ -1562,8 +1618,6 @@ nn_Exit nn_tick(nn_Computer *computer) {
|
||||
return NN_OK;
|
||||
}
|
||||
|
||||
// TODO: every component method src/neonucleus.h:530
|
||||
|
||||
static nn_Exit nn_defaultComponent(nn_ComponentRequest *request) {
|
||||
return NN_OK;
|
||||
}
|
||||
|
||||
@@ -410,6 +410,26 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char
|
||||
void nn_destroyComputer(nn_Computer *computer);
|
||||
void nn_lockComputer(nn_Computer *computer);
|
||||
void nn_unlockComputer(nn_Computer *computer);
|
||||
// stops the computer if an architecture state is already present,
|
||||
// will also clear the signal buffer and set the state to NN_BOOTUP.
|
||||
nn_Exit nn_startComputer(nn_Computer *computer);
|
||||
// destroys the architecture state if present.
|
||||
// Will also do other shutdown routines, such as unmounting every
|
||||
void nn_stopComputer(nn_Computer *computer);
|
||||
void nn_forceCrashComputer(nn_Computer *computer, const char *s);
|
||||
// returns whether an architecture state is present
|
||||
bool nn_isComputerOn(nn_Computer *computer);
|
||||
|
||||
typedef struct nn_Beep {
|
||||
double frequency;
|
||||
double duration;
|
||||
double volume;
|
||||
} nn_Beep;
|
||||
|
||||
void nn_setComputerBeep(nn_Computer *computer, nn_Beep beep);
|
||||
bool nn_getComputerBeep(nn_Computer *computer, nn_Beep *beep);
|
||||
void nn_clearComputerBeep(nn_Computer *computer);
|
||||
|
||||
// get the userdata pointer
|
||||
void *nn_getComputerUserdata(nn_Computer *computer);
|
||||
const char *nn_getComputerAddress(nn_Computer *computer);
|
||||
|
||||
Reference in New Issue
Block a user