extremely primitive screen impl

This commit is contained in:
2026-03-30 23:25:56 +02:00
parent 6086208879
commit 5c854e5c4a
6 changed files with 309 additions and 5 deletions

View File

@@ -281,6 +281,10 @@ static int luaArch_component_list(lua_State *L) {
luaArch *arch = luaArch_from(L); luaArch *arch = luaArch_from(L);
lua_createtable(L, 64, 0); lua_createtable(L, 64, 0);
size_t len = nn_countComponents(arch->computer); size_t len = nn_countComponents(arch->computer);
if(len == 0) {
lua_createtable(L, 0, 0);
return 1;
}
const char *comps[len]; const char *comps[len];
nn_getComponents(arch->computer, comps); nn_getComponents(arch->computer, comps);
for(size_t i = 0; i < len; i++) { for(size_t i = 0; i < len; i++) {
@@ -377,6 +381,10 @@ static int luaArch_component_methods(lua_State *L) {
return 2; return 2;
} }
size_t methodLen = nn_countComponentMethods(c); size_t methodLen = nn_countComponentMethods(c);
if(methodLen == 0) {
lua_createtable(L, 0, 0);
return 1;
}
const char *methods[methodLen]; const char *methods[methodLen];
nn_getComponentMethods(c, methods, &methodLen); nn_getComponentMethods(c, methods, &methodLen);
lua_createtable(L, 0, methodLen); lua_createtable(L, 0, methodLen);
@@ -402,6 +410,10 @@ static int luaArch_component_fields(lua_State *L) {
return 2; return 2;
} }
size_t methodLen = nn_countComponentMethods(c); size_t methodLen = nn_countComponentMethods(c);
if(methodLen == 0) {
lua_createtable(L, 0, 0);
return 1;
}
const char *methods[methodLen]; const char *methods[methodLen];
nn_getComponentMethods(c, methods, &methodLen); nn_getComponentMethods(c, methods, &methodLen);
lua_createtable(L, 0, methodLen); lua_createtable(L, 0, methodLen);

View File

@@ -412,6 +412,19 @@ int main(int argc, char **argv) {
double nextSecond = 0; double nextSecond = 0;
double wattage = 0; double wattage = 0;
nn_Component *screen = ncl_createScreen(u, NULL, &nn_defaultScreens[3]);
//nn_Component *gpu = ncl_createGPU(u, NULL, &nn_defaultGPUs[3]);
{
// draw test
const char *s = "hello there";
for(size_t i = 0; s[i]; i++) {
unsigned char c = s[i];
ncl_ScreenState *scrstate = nn_getComponentState(screen);
ncl_setScreenPixel(scrstate, i+1, 1, c, 0xFFFFFF, 0x000000, false, false);
}
}
restart:; restart:;
nn_Computer *c = nn_createComputer(u, NULL, "computer0", ramTotal, 256, 256); nn_Computer *c = nn_createComputer(u, NULL, "computer0", ramTotal, 256, 256);
@@ -426,6 +439,7 @@ restart:;
nn_setArchitecture(c, &arch); nn_setArchitecture(c, &arch);
nn_addSupportedArchitecture(c, &arch); nn_addSupportedArchitecture(c, &arch);
nn_mountComponent(c, screen, -1);
nn_mountComponent(c, ocelotCard, -1); nn_mountComponent(c, ocelotCard, -1);
nn_mountComponent(c, eepromCard, 0); nn_mountComponent(c, eepromCard, 0);
nn_mountComponent(c, managedfs, 1); nn_mountComponent(c, managedfs, 1);
@@ -436,6 +450,31 @@ restart:;
BeginDrawing(); BeginDrawing();
ClearBackground(BLACK); ClearBackground(BLACK);
// drawing the screen
{
int offX = 0;
int offY = 0;
int cheight = 20;
int cwidth = MeasureText("A", cheight);
ncl_ScreenState *scrbuf = nn_getComponentState(screen);
ncl_lockScreen(scrbuf);
size_t scrw, scrh;
ncl_getScreenResolution(scrbuf, &scrw, &scrh);
for(int y = 1; y <= scrh; y++) {
for(int x = 1; x <= scrw; x++) {
ncl_Pixel p = ncl_getScreenPixel(scrbuf, x, y);
Vector2 pos = {
offX + (x - 1) * cwidth,
offY + (y - 1) * cheight,
};
DrawRectangle(pos.x, pos.y, cwidth, cheight, ne_processColor(p.bgColor));
DrawTextCodepoint(font, p.codepoint, pos, cheight, ne_processColor(p.fgColor));
}
}
ncl_unlockScreen(scrbuf);
}
int statY = 10; int statY = 10;
if(sand.buf != NULL) { if(sand.buf != NULL) {
DrawText(TextFormat("mem used: %.2f%%", (double)sand.used / sand.cap * 100), 10, statY, 20, YELLOW); DrawText(TextFormat("mem used: %.2f%%", (double)sand.used / sand.cap * 100), 10, statY, 20, YELLOW);
@@ -536,6 +575,8 @@ cleanup:;
nn_destroyComputer(c); nn_destroyComputer(c);
nn_dropComponent(ocelotCard); nn_dropComponent(ocelotCard);
nn_dropComponent(eepromCard); nn_dropComponent(eepromCard);
nn_dropComponent(managedfs);
nn_dropComponent(screen);
// rip the universe // rip the universe
nn_destroyUniverse(u); nn_destroyUniverse(u);
UnloadFont(font); UnloadFont(font);

View File

@@ -274,7 +274,21 @@ bool ncl_remove(ncl_VFS vfs, const char *path) {
return vfs.handler(&req); return vfs.handler(&req);
} }
bool ncl_removeRecursive(ncl_VFS vfs, const char *path); bool ncl_removeRecursive(ncl_VFS vfs, const char *path) {
ncl_Stat s;
if(!ncl_stat(vfs, path, &s)) return false;
if(s.isDirectory) {
void *dir = ncl_opendir(vfs, path);
char name[NN_MAX_PATH];
while(ncl_readdir(vfs, dir, name)) {
char subpath[NN_MAX_PATH];
snprintf(subpath, sizeof(subpath), "%s%c%s", path, vfs.pathsep, name);
ncl_removeRecursive(vfs, subpath);
}
ncl_closedir(vfs, dir);
}
return ncl_remove(vfs, path);
}
bool ncl_mkdir(ncl_VFS vfs, const char *path) { bool ncl_mkdir(ncl_VFS vfs, const char *path) {
ncl_VFSRequest req; ncl_VFSRequest req;
@@ -298,6 +312,7 @@ typedef struct ncl_ScreenPixel {
typedef struct ncl_ScreenState { typedef struct ncl_ScreenState {
nn_Context *ctx; nn_Context *ctx;
nn_Lock *lock;
nn_ScreenConfig conf; nn_ScreenConfig conf;
int width; int width;
int height; int height;
@@ -308,6 +323,8 @@ typedef struct ncl_ScreenState {
int *resolvedPalette; int *resolvedPalette;
ncl_ScreenPixel *pixels; ncl_ScreenPixel *pixels;
ncl_ScreenFlags flags; ncl_ScreenFlags flags;
size_t keyboardCount;
char *keyboards[NCL_MAX_KEYBOARD];
} ncl_ScreenState; } ncl_ScreenState;
typedef struct nn_VRAMBuf { typedef struct nn_VRAMBuf {
@@ -378,7 +395,6 @@ typedef struct ncl_DriveState {
size_t usage; size_t usage;
size_t lastSector; size_t lastSector;
char *path; char *path;
FILE *file;
char label[NN_MAX_LABEL]; char label[NN_MAX_LABEL];
size_t labellen; size_t labellen;
} ncl_DriveState; } ncl_DriveState;
@@ -637,6 +653,23 @@ static nn_Exit ncl_fsHandler(nn_FSRequest *req) {
nn_unlock(ctx, state->lock); nn_unlock(ctx, state->lock);
return NN_OK; return NN_OK;
} }
if(req->action == NN_FS_STAT) {
nn_lock(ctx, state->lock);
char path[NN_MAX_PATH];
ncl_fixPath(state, req->stat.path, path);
ncl_Stat s;
if(!ncl_stat(state->vfs, path, &s)) {
nn_unlock(ctx, state->lock);
nn_setError(C, "no such file or directory");
return NN_EBADCALL;
}
req->stat.isDirectory = s.isDirectory;
req->stat.size = s.size;
req->stat.lastModified = s.lastModified;
nn_unlock(ctx, state->lock);
return NN_OK;
}
// TODO: mkdir, rename
if(C) nn_setError(C, "not implemented yet"); if(C) nn_setError(C, "not implemented yet");
return NN_EBADCALL; return NN_EBADCALL;
@@ -677,12 +710,16 @@ nn_Component *ncl_createFilesystem(nn_Universe *universe, const char *address, c
nn_free(ctx, state, sizeof(*state)); nn_free(ctx, state, sizeof(*state));
return NULL; return NULL;
} }
// TODO: handle OOM case
nn_setComponentTypeID(c, NCL_FS);
return c; return c;
} }
nn_Component *ncl_createDrive(nn_Universe *universe, const char *address, const char *path, const nn_Drive *drive, bool isReadonly); nn_Component *ncl_createDrive(nn_Universe *universe, const char *address, const char *path, const nn_Drive *drive, bool isReadonly);
nn_Component *ncl_createEEPROM(nn_Universe *universe, const char *address, const char *codepath, const char *datapath, bool isReadonly); nn_Component *ncl_createEEPROM(nn_Universe *universe, const char *address, const char *codepath, const char *datapath, bool isReadonly);
ncl_VFS ncl_setVFS(nn_Component *component, ncl_VFS vfs);
static ncl_ScreenPixel ncl_getRealScreenPixel(const ncl_ScreenState *state, int x, int y) { static ncl_ScreenPixel ncl_getRealScreenPixel(const ncl_ScreenState *state, int x, int y) {
if(x < 1 || y < 1 || x >= state->width || y >= state->height) { if(x < 1 || y < 1 || x >= state->width || y >= state->height) {
return (ncl_ScreenPixel) { return (ncl_ScreenPixel) {
@@ -740,9 +777,99 @@ static void ncl_recomputeScreen(const ncl_ScreenState *state) {
} }
} }
nn_Component *ncl_createScreen(nn_Universe *universe, const char *address, const nn_ScreenConfig *config); static nn_Exit ncl_screenHandler(nn_ScreenRequest *req) {
nn_Context *ctx = req->ctx;
nn_Computer *C = req->computer;
ncl_ScreenState *state = req->state;
const nn_ScreenConfig *conf = req->screen;
if(req->action == NN_SCREEN_DROP) {
for(size_t i = 0; i < state->keyboardCount; i++) {
nn_strfree(ctx, state->keyboards[i]);
}
nn_destroyLock(ctx, state->lock);
nn_free(ctx, state->pixels, sizeof(ncl_ScreenPixel) * state->conf.maxWidth * state->conf.maxHeight);
nn_free(ctx, state->palette, sizeof(int) * state->conf.paletteColors);
nn_free(ctx, state->resolvedPalette, sizeof(int) * state->conf.paletteColors);
nn_free(ctx, state, sizeof(*state));
return NN_OK;
}
if(C) nn_setError(C, "ncl-screen: not implemented yet");
return NN_EBADCALL;
}
nn_Component *ncl_createScreen(nn_Universe *universe, const char *address, const nn_ScreenConfig *config) {
nn_Context *ctx = nn_getUniverseContext(universe);
ncl_ScreenState *screen = NULL;
ncl_ScreenPixel *pixels = NULL;
int *palette = NULL;
int *resolvedPalette = NULL;
nn_Component *c = NULL;
nn_Lock *lock = NULL;
screen = nn_alloc(ctx, sizeof(ncl_ScreenState));
if(screen == NULL) goto fail;
lock = nn_createLock(ctx);
if(lock == NULL) goto fail;
pixels = nn_alloc(ctx, sizeof(ncl_ScreenPixel) * config->maxWidth * config->maxHeight);
if(pixels == NULL) goto fail;
palette = nn_alloc(ctx, sizeof(int) * config->paletteColors);
if(palette == NULL) goto fail;
memcpy(palette, config->defaultPalette, sizeof(int) * config->paletteColors);
resolvedPalette = nn_alloc(ctx, sizeof(int) * config->paletteColors);
if(resolvedPalette == NULL) goto fail;
screen->conf = *config;
screen->ctx = ctx;
screen->lock = lock;
screen->width = config->maxWidth;
screen->height = config->maxHeight;
screen->palette = palette;
screen->resolvedPalette = resolvedPalette;
screen->pixels = pixels;
screen->flags = 0;
screen->depth = config->maxDepth;
screen->viewportWidth = screen->width;
screen->viewportHeight = screen->height;
screen->keyboardCount = 0;
ncl_resetScreen(screen);
c = nn_createScreen(universe, address, config, screen, ncl_screenHandler);
if(c == NULL) goto fail;
if(nn_setComponentTypeID(c, NCL_SCREEN)) goto fail;
return c;
fail:;
if(c != NULL) {
nn_dropComponent(c);
return NULL;
}
if(lock != NULL) nn_destroyLock(ctx, lock);
nn_free(ctx, screen, sizeof(*screen));
nn_free(ctx, palette, sizeof(int) * config->paletteColors);
nn_free(ctx, resolvedPalette, sizeof(int) * config->paletteColors);
nn_free(ctx, pixels, sizeof(ncl_ScreenPixel) * config->maxWidth * config->maxHeight);
return NULL;
}
nn_Component *ncl_createGPU(nn_Universe *universe, const char *address, const nn_GPU *gpu); nn_Component *ncl_createGPU(nn_Universe *universe, const char *address, const nn_GPU *gpu);
void ncl_lockScreen(ncl_ScreenState *state) {
nn_lock(state->ctx, state->lock);
}
void ncl_unlockScreen(ncl_ScreenState *state) {
nn_unlock(state->ctx, state->lock);
}
void ncl_resetScreen(ncl_ScreenState *state) { void ncl_resetScreen(ncl_ScreenState *state) {
state->width = state->conf.maxWidth; state->width = state->conf.maxWidth;
state->height = state->conf.maxHeight; state->height = state->conf.maxHeight;
@@ -784,6 +911,18 @@ ncl_Pixel ncl_getScreenPixel(const ncl_ScreenState *state, int x, int y) {
}; };
} }
void ncl_setScreenPixel(ncl_ScreenState *state, int x, int y, nn_codepoint codepoint, int fg, int bg, bool isFgPalette, bool isBgPalette) {
ncl_ScreenPixel p = {
.codepoint = codepoint,
.storedFg = fg,
.storedBg = bg,
.realFg = isFgPalette ? -1 : fg,
.realBg = isBgPalette ? -1 : bg,
};
ncl_setRealScreenPixel(state, x, y, p);
ncl_recomputeScreen(state);
}
ncl_ScreenFlags ncl_getScreenFlags(const ncl_ScreenState *state) { ncl_ScreenFlags ncl_getScreenFlags(const ncl_ScreenState *state) {
return state->flags; return state->flags;
} }
@@ -792,6 +931,19 @@ void ncl_setScreenFlags(ncl_ScreenState *state, ncl_ScreenFlags flags) {
state->flags = flags; state->flags = flags;
} }
char ncl_getScreenDepth(ncl_ScreenState *state) {
return state->depth;
}
void ncl_setScreenDepth(ncl_ScreenState *state, char depth) {
state->depth = depth;
}
nn_Exit ncl_mountKeyboard(ncl_ScreenState *state, const char *keyboardAddress);
void ncl_unmountKeyboard(ncl_ScreenState *state, const char *keyboardAddress);
bool ncl_hasKeyboard(ncl_ScreenState *state, const char *keyboardAddress);
const char *ncl_getKeyboard(ncl_ScreenState *state, size_t idx);
// general stuff // general stuff
void ncl_statComponent(nn_Component *component, ncl_ComponentStat *stat) { void ncl_statComponent(nn_Component *component, ncl_ComponentStat *stat) {
@@ -843,6 +995,19 @@ void ncl_statComponent(nn_Component *component, ncl_ComponentStat *stat) {
nn_unlock(ee->ctx, ee->lock); nn_unlock(ee->ctx, ee->lock);
return; return;
} }
if(strcmp(ty, NCL_SCREEN) == 0) {
ncl_ScreenState *screen = state;
nn_lock(screen->ctx, screen->lock);
stat->screen.conf = &screen->conf;
stat->screen.depth = screen->depth;
stat->screen.flags = screen->flags;
stat->screen.keyboardCount = screen->keyboardCount;
stat->screen.viewportWidth = screen->viewportWidth;
stat->screen.viewportHeight = screen->viewportHeight;
stat->screen.state = screen;
nn_unlock(screen->ctx, screen->lock);
return;
}
} }
// For EEPROMs, filesystems, drives // For EEPROMs, filesystems, drives

View File

@@ -10,6 +10,7 @@
#define NCL_SCREEN "ncl-screen" #define NCL_SCREEN "ncl-screen"
#define NCL_MAX_VRAMBUF 128 #define NCL_MAX_VRAMBUF 128
#define NCL_MAX_KEYBOARD 64
// very low-level actions // very low-level actions
// some environment have VFSes so // some environment have VFSes so
@@ -32,7 +33,7 @@ typedef struct ncl_Stat {
size_t diskSize; size_t diskSize;
// The UNIX timestamp of the last modified date // The UNIX timestamp of the last modified date
// of the entry. // of the entry.
size_t lastModified; intptr_t lastModified;
} ncl_Stat; } ncl_Stat;
typedef enum ncl_VFSAction { typedef enum ncl_VFSAction {
@@ -235,6 +236,8 @@ typedef struct ncl_ComponentStat {
ncl_ScreenFlags flags; ncl_ScreenFlags flags;
int viewportWidth; int viewportWidth;
int viewportHeight; int viewportHeight;
char depth;
size_t keyboardCount;
} screen; } screen;
}; };
} ncl_ComponentStat; } ncl_ComponentStat;
@@ -244,11 +247,20 @@ void ncl_statComponent(nn_Component *component, ncl_ComponentStat *stat);
// Returns whether it was successful or not. // Returns whether it was successful or not.
bool ncl_makeReadonly(nn_Component *component); bool ncl_makeReadonly(nn_Component *component);
void ncl_lockScreen(ncl_ScreenState *state);
void ncl_unlockScreen(ncl_ScreenState *state);
void ncl_resetScreen(ncl_ScreenState *state); void ncl_resetScreen(ncl_ScreenState *state);
void ncl_getScreenResolution(const ncl_ScreenState *state, size_t *width, size_t *height); void ncl_getScreenResolution(const ncl_ScreenState *state, size_t *width, size_t *height);
void ncl_getScreenViewport(const ncl_ScreenState *state, size_t *width, size_t *height); void ncl_getScreenViewport(const ncl_ScreenState *state, size_t *width, size_t *height);
ncl_Pixel ncl_getScreenPixel(const ncl_ScreenState *state, int x, int y); ncl_Pixel ncl_getScreenPixel(const ncl_ScreenState *state, int x, int y);
void ncl_setScreenPixel(ncl_ScreenState *state, int x, int y, nn_codepoint codepoint, int fg, int bg, bool isFgPalette, bool isBgPalette);
ncl_ScreenFlags ncl_getScreenFlags(const ncl_ScreenState *state); ncl_ScreenFlags ncl_getScreenFlags(const ncl_ScreenState *state);
void ncl_setScreenFlags(ncl_ScreenState *state, ncl_ScreenFlags flags); void ncl_setScreenFlags(ncl_ScreenState *state, ncl_ScreenFlags flags);
char ncl_getScreenDepth(ncl_ScreenState *state);
void ncl_setScreenDepth(ncl_ScreenState *state, char depth);
nn_Exit ncl_mountKeyboard(ncl_ScreenState *state, const char *keyboardAddress);
void ncl_unmountKeyboard(ncl_ScreenState *state, const char *keyboardAddress);
bool ncl_hasKeyboard(ncl_ScreenState *state, const char *keyboardAddress);
const char *ncl_getKeyboard(ncl_ScreenState *state, size_t idx);
#endif #endif

View File

@@ -1469,6 +1469,7 @@ void nn_dropComponentN(nn_Component *c, size_t n) {
nn_strfree(ctx, c->type); nn_strfree(ctx, c->type);
nn_strfree(ctx, c->internalID); nn_strfree(ctx, c->internalID);
nn_hashDeinit(&c->methodsMap); nn_hashDeinit(&c->methodsMap);
nn_free(ctx, c, sizeof(*c));
} }
void nn_setComponentHandler(nn_Component *c, nn_ComponentHandler *handler) { void nn_setComponentHandler(nn_Component *c, nn_ComponentHandler *handler) {
@@ -3315,6 +3316,7 @@ static nn_Exit nn_veepromHandler(nn_EEPROMRequest *request) {
if(request->action == NN_EEPROM_DROP) { if(request->action == NN_EEPROM_DROP) {
nn_free(ctx, state->code, eeprom->size); nn_free(ctx, state->code, eeprom->size);
nn_free(ctx, state->data, eeprom->dataSize); nn_free(ctx, state->data, eeprom->dataSize);
nn_free(ctx, state, sizeof(*state));
return NN_OK; return NN_OK;
} }
if(request->action == NN_EEPROM_GET) { if(request->action == NN_EEPROM_GET) {
@@ -3384,6 +3386,12 @@ nn_Component *nn_createVEEPROM(nn_Universe *universe, const char *address, const
state->datalen = veeprom->datalen; state->datalen = veeprom->datalen;
nn_memcpy(state->label, veeprom->label, veeprom->labellen); nn_memcpy(state->label, veeprom->label, veeprom->labellen);
state->labellen = veeprom->labellen; state->labellen = veeprom->labellen;
if(veeprom->arch == NULL) {
state->archlen = 0;
} else {
state->archlen = nn_strlen(veeprom->arch);
}
nn_memcpy(state->arch, veeprom->arch, state->archlen);
nn_Component *c = nn_createEEPROM(universe, address, eeprom, state, nn_veepromHandler); nn_Component *c = nn_createEEPROM(universe, address, eeprom, state, nn_veepromHandler);
if(c == NULL) goto fail; if(c == NULL) goto fail;
@@ -3767,3 +3775,53 @@ nn_Component *nn_createFilesystem(nn_Universe *universe, const char *address, co
nn_setComponentHandler(c, nn_fsHandler); nn_setComponentHandler(c, nn_fsHandler);
return c; return c;
} }
nn_Component *nn_createVFilesystem(nn_Universe *universe, const char *address, const nn_VFilesystem *vfs, const nn_Filesystem *fs);
typedef struct nn_ScreenState {
nn_Context *ctx;
nn_ScreenConfig scrconf;
nn_ScreenHandler *handler;
} nn_ScreenState;
static nn_Exit nn_screenHandler(nn_ComponentRequest *req) {
if(req->action == NN_COMP_CHECKMETHOD) return NN_OK;
if(req->action == NN_COMP_SIGNAL) return NN_OK;
nn_Context *ctx = req->ctx;
nn_ScreenState *state = req->classState;
nn_Computer *C = req->computer;
nn_ScreenRequest sreq;
sreq.ctx = ctx;
sreq.state = req->state;
sreq.computer = C;
sreq.screen = &state->scrconf;
if(req->action == NN_COMP_DROP) {
sreq.action = NN_SCREEN_DROP;
state->handler(&sreq);
nn_free(ctx, state, sizeof(*state));
return NN_OK;
}
nn_setError(C, "screen: not yet implemented");
return NN_EBADCALL;
}
nn_Component *nn_createScreen(nn_Universe *universe, const char *address, const nn_ScreenConfig *scrconf, void *state, nn_ScreenHandler *handler) {
nn_Component *c = nn_createComponent(universe, address, "screen");
if(c == NULL) return NULL;
// TODO: methods
nn_Context *ctx = &universe->ctx;
nn_ScreenState *scrstate = nn_alloc(ctx, sizeof(*scrstate));
if(scrstate == NULL) {
nn_dropComponent(c);
return NULL;
}
scrstate->ctx = ctx;
scrstate->scrconf = *scrconf;
scrstate->handler = handler;
nn_setComponentState(c, state);
nn_setComponentClassState(c, scrstate);
nn_setComponentHandler(c, nn_screenHandler);
return c;
}

View File

@@ -1003,7 +1003,7 @@ typedef struct nn_FSRequest {
bool isDirectory; bool isDirectory;
// in seconds. Result will be multiplied by 1000. // in seconds. Result will be multiplied by 1000.
// This is because OpenOS code is garbage. // This is because OpenOS code is garbage.
size_t lastModified; intptr_t lastModified;
// size. 0 for directories. // size. 0 for directories.
size_t size; size_t size;
} stat; } stat;
@@ -1175,6 +1175,22 @@ typedef struct nn_ScreenConfig {
// OC has 3 tiers, NN adds a 4th one as well. // OC has 3 tiers, NN adds a 4th one as well.
extern const nn_ScreenConfig nn_defaultScreens[4]; extern const nn_ScreenConfig nn_defaultScreens[4];
typedef enum nn_ScreenAction {
NN_SCREEN_DROP,
} nn_ScreenAction;
typedef struct nn_ScreenRequest {
nn_Context *ctx;
nn_Computer *computer;
void *state;
const nn_ScreenConfig *screen;
nn_ScreenAction action;
} nn_ScreenRequest;
typedef nn_Exit (nn_ScreenHandler)(nn_ScreenRequest *req);
nn_Component *nn_createScreen(nn_Universe *universe, const char *address, const nn_ScreenConfig *scrconf, void *state, nn_ScreenHandler *handler);
// GPU class // GPU class
typedef struct nn_GPU { typedef struct nn_GPU {