the gpu like kinda functions idfk

This commit is contained in:
IonutParau 2025-06-26 23:27:56 +02:00
parent e2bc6bd469
commit 6a21b83d5a
11 changed files with 295 additions and 32 deletions

View File

@ -18,6 +18,7 @@ fn addEngineSources(c: *std.Build.Step.Compile) void {
"src/components/filesystem.c", "src/components/filesystem.c",
"src/components/screen.c", "src/components/screen.c",
"src/components/gpu.c", "src/components/gpu.c",
"src/components/keyboard.c",
}, },
}); });
} }

View File

@ -1,6 +1,7 @@
#include "../neonucleus.h" #include "../neonucleus.h"
#include "screen.h" #include "screen.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
typedef struct nni_gpu { typedef struct nni_gpu {
nn_screen *currentScreen; nn_screen *currentScreen;
@ -23,6 +24,16 @@ bool nni_samePixel(nn_scrchr_t a, nn_scrchr_t b) {
; ;
} }
bool nni_inBounds(nni_gpu *gpu, int x, int y) {
if(gpu->currentScreen == NULL) return false;
return
x >= 0 &&
y >= 0 &&
x < gpu->currentScreen->width &&
y < gpu->currentScreen->height &&
true;
}
nni_gpu *nni_newGPU(nn_gpuControl *ctrl) { nni_gpu *nni_newGPU(nn_gpuControl *ctrl) {
nni_gpu *gpu = nn_malloc(sizeof(nni_gpu)); nni_gpu *gpu = nn_malloc(sizeof(nni_gpu));
gpu->currentScreen = NULL; gpu->currentScreen = NULL;
@ -113,13 +124,13 @@ void nni_gpu_bind(nni_gpu *gpu, void *_, nn_component *component, nn_computer *c
void nni_gpu_set(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) { void nni_gpu_set(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
if(gpu->currentScreen == NULL) return; if(gpu->currentScreen == NULL) return;
int x = nn_toInt(nn_getArgument(computer, 0)); int x = nn_toInt(nn_getArgument(computer, 0)) - 1;
int y = nn_toInt(nn_getArgument(computer, 1)); int y = nn_toInt(nn_getArgument(computer, 1)) - 1;
const char *s = nn_toCString(nn_getArgument(computer, 2)); const char *s = nn_toCString(nn_getArgument(computer, 2));
bool isVertical = nn_toBoolean(nn_getArgument(computer, 3)); bool isVertical = nn_toBoolean(nn_getArgument(computer, 3));
if(s == NULL) { if(s == NULL) {
nn_setCError(computer, "bad argument #4 (string expected)"); nn_setCError(computer, "bad argument #3 (string expected in set)");
return; return;
} }
@ -127,23 +138,25 @@ void nni_gpu_set(nni_gpu *gpu, void *_, nn_component *component, nn_computer *co
while(s[current]) { while(s[current]) {
int codepoint = nn_unicode_codepointAt(s, current); int codepoint = nn_unicode_codepointAt(s, current);
nn_setPixel(gpu->currentScreen, x, y, nni_gpu_makePixel(gpu, s + current)); nn_setPixel(gpu->currentScreen, x, y, nni_gpu_makePixel(gpu, s + current));
if(isVertical) if(isVertical) {
y++; y++;
else } else {
x++; x++;
}
current += nn_unicode_codepointSize(codepoint); current += nn_unicode_codepointSize(codepoint);
} }
} }
void nni_gpu_get(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) { void nni_gpu_get(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
if(gpu->screenAddress == NULL) return; if(gpu->screenAddress == NULL) return;
int x = nn_toInt(nn_getArgument(computer, 0)); int x = nn_toInt(nn_getArgument(computer, 0)) - 1;
int y = nn_toInt(nn_getArgument(computer, 1)); int y = nn_toInt(nn_getArgument(computer, 1)) - 1;
nn_scrchr_t pxl = nn_getPixel(gpu->currentScreen, x, y); nn_scrchr_t pxl = nn_getPixel(gpu->currentScreen, x, y);
size_t l; size_t l;
const char *chr = nn_unicode_codepointToChar(pxl.codepoint, &l); const char *chr = nn_unicode_codepointToChar(pxl.codepoint, &l);
// TODO: gosh darn palettes
nn_return(computer, nn_values_cstring(chr)); nn_return(computer, nn_values_cstring(chr));
nn_return(computer, nn_values_integer(pxl.fg)); nn_return(computer, nn_values_integer(pxl.fg));
nn_return(computer, nn_values_integer(pxl.bg)); nn_return(computer, nn_values_integer(pxl.bg));
@ -165,13 +178,39 @@ void nni_gpu_maxResolution(nni_gpu *gpu, void *_, nn_component *component, nn_co
void nni_gpu_getResolution(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) { void nni_gpu_getResolution(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
if(gpu->currentScreen == NULL) return; if(gpu->currentScreen == NULL) return;
int w, h; int w, h;
nn_maxResolution(gpu->currentScreen, &w, &h); nn_getResolution(gpu->currentScreen, &w, &h);
nn_return(computer, nn_values_integer(w)); nn_return(computer, nn_values_integer(w));
nn_return(computer, nn_values_integer(h)); nn_return(computer, nn_values_integer(h));
} }
void nni_gpu_setResolution(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) { void nni_gpu_setResolution(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
if(gpu->currentScreen == NULL) return; if(gpu->currentScreen == NULL) return;
int mw, mh;
nn_maxResolution(gpu->currentScreen, &mw, &mh);
int lw, lh;
nn_getResolution(gpu->currentScreen, &lw, &lh);
int w = nn_toInt(nn_getArgument(computer, 0));
int h = nn_toInt(nn_getArgument(computer, 1));
bool changed = w != lw || h != lh;
if(w <= 0) w = 1;
if(h <= 0) h = 1;
if(w > mw) w = mw;
if(h > mh) h = mh;
nn_setResolution(gpu->currentScreen, w, h);
nn_return(computer, nn_values_boolean(changed));
nn_value signalShit[] = {
nn_values_cstring("screen_resized"),
nn_values_cstring(gpu->screenAddress),
nn_values_integer(w),
nn_values_integer(h),
};
nn_pushSignal(computer, signalShit, 4);
} }
void nni_gpu_setBackground(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) { void nni_gpu_setBackground(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
@ -205,6 +244,10 @@ void nni_gpu_setBackground(nni_gpu *gpu, void *_, nn_component *component, nn_co
} }
} }
void nni_gpu_getBackground(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
nn_return(computer, nn_values_integer(gpu->currentBg));
}
void nni_gpu_setForeground(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) { void nni_gpu_setForeground(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
if(gpu->currentScreen == NULL) return; if(gpu->currentScreen == NULL) return;
int color = nn_toInt(nn_getArgument(computer, 0)); int color = nn_toInt(nn_getArgument(computer, 0));
@ -236,10 +279,14 @@ void nni_gpu_setForeground(nni_gpu *gpu, void *_, nn_component *component, nn_co
} }
} }
void nni_gpu_getForeground(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
nn_return(computer, nn_values_integer(gpu->currentFg));
}
void nni_gpu_fill(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) { void nni_gpu_fill(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
if(gpu->currentScreen == NULL) return; if(gpu->currentScreen == NULL) return;
int x = nn_toInt(nn_getArgument(computer, 0)); int x = nn_toInt(nn_getArgument(computer, 0)) - 1;
int y = nn_toInt(nn_getArgument(computer, 1)); int y = nn_toInt(nn_getArgument(computer, 1)) - 1;
int w = nn_toInt(nn_getArgument(computer, 2)); int w = nn_toInt(nn_getArgument(computer, 2));
int h = nn_toInt(nn_getArgument(computer, 3)); int h = nn_toInt(nn_getArgument(computer, 3));
const char *s = nn_toCString(nn_getArgument(computer, 4)); const char *s = nn_toCString(nn_getArgument(computer, 4));
@ -285,6 +332,56 @@ void nni_gpu_fill(nni_gpu *gpu, void *_, nn_component *component, nn_computer *c
nn_return(computer, nn_values_boolean(true)); nn_return(computer, nn_values_boolean(true));
} }
void nni_gpu_copy(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
if(gpu->currentScreen == NULL) return;
int x = nn_toInt(nn_getArgument(computer, 0)) - 1;
int y = nn_toInt(nn_getArgument(computer, 1)) - 1;
int w = nn_toInt(nn_getArgument(computer, 2));
int h = nn_toInt(nn_getArgument(computer, 3));
int tx = nn_toInt(nn_getArgument(computer, 4));
int ty = nn_toInt(nn_getArgument(computer, 5));
// prevent DoS
if(x < 0) x = 0;
if(y < 0) y = 0;
if(w > gpu->currentScreen->width - x) w = gpu->currentScreen->width - x;
if(h > gpu->currentScreen->height - y) y = gpu->currentScreen->height - y;
int changes = 0, clears = 0;
for(int cx = x; cx < x + w; cx++) {
for(int cy = y; cy < y + h; cy++) {
nn_scrchr_t src = nn_getPixel(gpu->currentScreen, cx, cy);
nn_scrchr_t old = nn_getPixel(gpu->currentScreen, cx + tx, cy + ty);
if(!nni_samePixel(old, src)) {
nn_setPixel(gpu->currentScreen, cx + tx, cy + ty, src);
if(src.codepoint == ' ')
clears++;
else changes++;
}
}
}
nn_addHeat(computer, gpu->ctrl.pixelChangeHeat * changes);
nn_callCost(computer, gpu->ctrl.pixelChangeCost * changes);
nn_removeEnergy(computer, gpu->ctrl.pixelChangeEnergy * changes);
nn_busySleep(gpu->ctrl.pixelChangeLatency * changes);
nn_addHeat(computer, gpu->ctrl.pixelChangeHeat * clears);
nn_callCost(computer, gpu->ctrl.pixelChangeCost * clears);
nn_removeEnergy(computer, gpu->ctrl.pixelChangeEnergy * clears);
nn_busySleep(gpu->ctrl.pixelChangeLatency * clears);
nn_return(computer, nn_values_boolean(true));
}
void nni_gpu_getViewport(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
int w, h;
nn_getViewport(gpu->currentScreen, &w, &h);
nn_return(computer, nn_values_integer(w));
nn_return(computer, nn_values_integer(h));
}
void nn_loadGraphicsCardTable(nn_universe *universe) { void nn_loadGraphicsCardTable(nn_universe *universe) {
nn_componentTable *gpuTable = nn_newComponentTable("gpu", NULL, NULL, (void *)nni_gpuDeinit); nn_componentTable *gpuTable = nn_newComponentTable("gpu", NULL, NULL, (void *)nni_gpuDeinit);
nn_storeUserdata(universe, "NN:GPU", gpuTable); nn_storeUserdata(universe, "NN:GPU", gpuTable);
@ -298,7 +395,11 @@ void nn_loadGraphicsCardTable(nn_universe *universe) {
nn_defineMethod(gpuTable, "setResolution", true, (void *)nni_gpu_setResolution, NULL, "maxResolution(): integer, integer - Changes the resolution of the bound screen."); nn_defineMethod(gpuTable, "setResolution", true, (void *)nni_gpu_setResolution, NULL, "maxResolution(): integer, integer - Changes the resolution of the bound screen.");
nn_defineMethod(gpuTable, "setBackground", true, (void *)nni_gpu_setBackground, NULL, "setBackground(color: integer, isPalette: boolean): integer, integer? - Sets the current background color. Returns the old one and palette index if applicable."); nn_defineMethod(gpuTable, "setBackground", true, (void *)nni_gpu_setBackground, NULL, "setBackground(color: integer, isPalette: boolean): integer, integer? - Sets the current background color. Returns the old one and palette index if applicable.");
nn_defineMethod(gpuTable, "setForeground", true, (void *)nni_gpu_setForeground, NULL, "setForeground(color: integer, isPalette: boolean): integer, integer? - Sets the current foreground color. Returns the old one and palette index if applicable."); nn_defineMethod(gpuTable, "setForeground", true, (void *)nni_gpu_setForeground, NULL, "setForeground(color: integer, isPalette: boolean): integer, integer? - Sets the current foreground color. Returns the old one and palette index if applicable.");
nn_defineMethod(gpuTable, "getBackground", true, (void *)nni_gpu_getBackground, NULL, "setBackground(color: integer, isPalette: boolean): integer, integer? - Sets the current background color. Returns the old one and palette index if applicable.");
nn_defineMethod(gpuTable, "getForeground", true, (void *)nni_gpu_getForeground, NULL, "setForeground(color: integer, isPalette: boolean): integer, integer? - Sets the current foreground color. Returns the old one and palette index if applicable.");
nn_defineMethod(gpuTable, "fill", true, (void *)nni_gpu_fill, NULL, "fill(x: integer, y: integer, w: integer, h: integer, s: string)"); nn_defineMethod(gpuTable, "fill", true, (void *)nni_gpu_fill, NULL, "fill(x: integer, y: integer, w: integer, h: integer, s: string)");
nn_defineMethod(gpuTable, "copy", true, (void *)nni_gpu_copy, NULL, "copy(x: integer, y: integer, w: integer, h: integer, tx: integer, ty: integer) - Copies stuff");
nn_defineMethod(gpuTable, "getViewport", true, (void *)nni_gpu_getViewport, NULL, "getViewport(): integer, integer - Gets the current viewport resolution");
} }
nn_component *nn_addGPU(nn_computer *computer, nn_address address, int slot, nn_gpuControl *control) { nn_component *nn_addGPU(nn_computer *computer, nn_address address, int slot, nn_gpuControl *control) {

11
src/components/keyboard.c Normal file
View File

@ -0,0 +1,11 @@
#include "../neonucleus.h"
void nn_loadKeyboardTable(nn_universe *universe) {
nn_componentTable *keyboardTable = nn_newComponentTable("keyboard", NULL, NULL, NULL);
nn_storeUserdata(universe, "NN:KEYBOARD", keyboardTable);
}
nn_component *nn_mountKeyboard(nn_computer *computer, nn_address address, int slot) {
nn_componentTable *keyboardTable = nn_queryUserdata(nn_getUniverse(computer), "NN:KEYBOARD");
return nn_newComponent(computer, address, slot, keyboardTable, NULL);
}

View File

@ -164,7 +164,7 @@ nn_scrchr_t nn_getPixel(nn_screen *screen, int x, int y) {
if(x < 0) return blank; if(x < 0) return blank;
if(y < 0) return blank; if(y < 0) return blank;
if(x >= screen->width) return blank; if(x >= screen->width) return blank;
if(x >= screen->height) return blank; if(y >= screen->height) return blank;
return screen->buffer[x + y * screen->maxWidth]; return screen->buffer[x + y * screen->maxWidth];
} }

View File

@ -158,22 +158,26 @@ const char *nn_pushSignal(nn_computer *computer, nn_value *values, size_t len) {
} }
nn_value nn_fetchSignalValue(nn_computer *computer, size_t index) { nn_value nn_fetchSignalValue(nn_computer *computer, size_t index) {
nn_signal *p = computer->signals + computer->signalCount - 1; if(computer->signalCount == 0) return nn_values_nil();
nn_signal *p = computer->signals;
if(index >= p->len) return nn_values_nil(); if(index >= p->len) return nn_values_nil();
return p->values[index]; return p->values[index];
} }
size_t nn_signalSize(nn_computer *computer) { size_t nn_signalSize(nn_computer *computer) {
if(computer->signalCount == 0) return 0; if(computer->signalCount == 0) return 0;
return computer->signals[computer->signalCount-1].len; return computer->signals[0].len;
} }
void nn_popSignal(nn_computer *computer) { void nn_popSignal(nn_computer *computer) {
if(computer->signalCount == 0) return; if(computer->signalCount == 0) return;
nn_signal *p = computer->signals + computer->signalCount - 1; nn_signal *p = computer->signals;
for(size_t i = 0; i < p->len; i++) { for(size_t i = 0; i < p->len; i++) {
nn_values_drop(p->values[i]); nn_values_drop(p->values[i]);
} }
for(size_t i = 1; i < computer->signalCount; i++) {
computer->signals[i-1] = computer->signals[i];
}
computer->signalCount--; computer->signalCount--;
} }

View File

@ -280,6 +280,7 @@ int main() {
nn_screen *s = nn_newScreen(80, 32, 16, 16, 256); nn_screen *s = nn_newScreen(80, 32, 16, 16, 256);
nn_addKeyboard(s, "shitty keyboard"); nn_addKeyboard(s, "shitty keyboard");
nn_mountKeyboard(computer, "shitty keyboard", 2);
nn_addScreen(computer, "Main Screen", 2, s); nn_addScreen(computer, "Main Screen", 2, s);
nn_gpuControl gpuCtrl = { nn_gpuControl gpuCtrl = {
@ -358,10 +359,10 @@ render:
ClearBackground(BLACK); ClearBackground(BLACK);
int scrW, scrH = 1; int scrW = 1, scrH = 1;
nn_getResolution(s, &scrW, &scrH); nn_getResolution(s, &scrW, &scrH);
int pixelHeight = GetScreenHeight() / scrH; int pixelHeight = GetScreenHeight() / scrH;
int pixelWidth = MeasureText("a", pixelHeight); int pixelWidth = MeasureText("A", pixelHeight);
for(size_t x = 0; x < scrW; x++) { for(size_t x = 0; x < scrW; x++) {
for(size_t y = 0; y < scrH; y++) { for(size_t y = 0; y < scrH; y++) {

View File

@ -156,14 +156,14 @@ bool nn_decRef(nn_refc *refc);
bool nn_unicode_validate(const char *s); bool nn_unicode_validate(const char *s);
// returned string must be nn_free()'d // returned string must be nn_free()'d
char *nn_unicode_char(int *codepoints, size_t codepointCount); char *nn_unicode_char(unsigned int *codepoints, size_t codepointCount);
// returned array must be nn_free()'d // returned array must be nn_free()'d
int *nn_unicode_codepoints(const char *s); unsigned int *nn_unicode_codepoints(const char *s);
size_t nn_unicode_len(const char *s); size_t nn_unicode_len(const char *s);
int nn_unicode_codepointAt(const char *s, size_t byteOffset); unsigned int nn_unicode_codepointAt(const char *s, size_t byteOffset);
size_t nn_unicode_codepointSize(int codepoint); size_t nn_unicode_codepointSize(unsigned int codepoint);
const char *nn_unicode_codepointToChar(int codepoint, size_t *len); const char *nn_unicode_codepointToChar(unsigned int codepoint, size_t *len);
size_t nn_unicode_charWidth(int codepoint); size_t nn_unicode_charWidth(unsigned int codepoint);
size_t nn_unicode_wlen(const char *s); size_t nn_unicode_wlen(const char *s);
void nn_unicode_upper(char *s); void nn_unicode_upper(char *s);
void nn_unicode_lower(char *s); void nn_unicode_lower(char *s);
@ -365,6 +365,9 @@ void nn_loadFilesystemTable(nn_universe *universe);
void nn_loadDriveTable(nn_universe *universe); void nn_loadDriveTable(nn_universe *universe);
void nn_loadScreenTable(nn_universe *universe); void nn_loadScreenTable(nn_universe *universe);
void nn_loadGraphicsCardTable(nn_universe *universe); void nn_loadGraphicsCardTable(nn_universe *universe);
void nn_loadKeyboardTable(nn_universe *universe);
nn_component *nn_mountKeyboard(nn_computer *computer, nn_address address, int slot);
// the helpers // the helpers

View File

@ -114,6 +114,7 @@ libcomponent = {
while true do while true do
local r = {pcall(component.invoke, addr, method, ...)} local r = {pcall(component.invoke, addr, method, ...)}
computer.clearError()
-- in this situation, either the temperature is above 100 C and we throttle -- in this situation, either the temperature is above 100 C and we throttle
-- or the call budget has been filled and we dont care -- or the call budget has been filled and we dont care
@ -392,7 +393,9 @@ sandbox = {
}, },
utf8 = copy(utf8), utf8 = copy(utf8),
unicode = copy(string), unicode = copy(unicode, {
wtrunc = function(s) return s end,
}),
checkArg = checkArg, checkArg = checkArg,
component = libcomponent, component = libcomponent,
computer = libcomputer, computer = libcomputer,

View File

@ -113,6 +113,12 @@ static void testLuaArch_pushValue(lua_State *L, nn_value val) {
} }
} }
static int testLuaArch_computer_clearError(lua_State *L) {
testLuaArch *s = testLuaArch_get(L);
nn_clearError(s->computer);
return 0;
}
static int testLuaArch_computer_usedMemory(lua_State *L) { static int testLuaArch_computer_usedMemory(lua_State *L) {
testLuaArch *s = testLuaArch_get(L); testLuaArch *s = testLuaArch_get(L);
lua_pushinteger(L, s->memoryUsed); lua_pushinteger(L, s->memoryUsed);
@ -416,9 +422,91 @@ static int testLuaArch_component_invoke(lua_State *L) {
return retc; return retc;
} }
int testLuaArch_unicode_sub(lua_State *L) {
const char *s = luaL_checkstring(L, 1);
int start = luaL_checkinteger(L, 2);
int stop = -1;
if(lua_isinteger(L, 3)) {
stop = luaL_checkinteger(L, 3);
}
if(!nn_unicode_validate(s)) {
luaL_error(L, "invalid utf-8");
}
int len = nn_unicode_len(s);
if(len < 0) {
luaL_error(L, "length overflow");
}
// OpenOS does this...
if(len == 0) {
lua_pushstring(L, "");
return 1;
}
// Lua indexing bullshit
if(start > 0) {
start -= 1;
} else if(start < 0) {
start = len + start;
}
if(stop > 0) {
stop -= 1;
} else if(stop < 0) {
stop = len + stop;
}
if(start < 0) start = 0;
if(stop < 0) stop = 0;
if(start >= len) start = len - 1;
if(stop >= len) stop = len - 1;
// there is a way to do it without an allocation
// however, I'm lazy
unsigned int *points = nn_unicode_codepoints(s);
if(points == NULL) {
luaL_error(L, "out of memory");
}
// there are a few cases where memory is leaked due to
// Lua's tendency to longjmp.
// TODO: fix them.
char *sub = nn_unicode_char(points + start, stop - start + 1);
lua_pushstring(L, sub);
nn_free(sub);
nn_free(points);
return 1;
}
int testLuaArch_unicode_char(lua_State *L) {
int argc = lua_gettop(L);
unsigned int *codepoints = nn_malloc(sizeof(unsigned int) * argc);
if(codepoints == NULL) {
luaL_error(L, "out of memory");
}
for(int i = 0; i < argc; i++) {
int idx = i + 1;
if(!lua_isinteger(L, idx)) {
nn_free(codepoints);
luaL_argerror(L, idx, "integer expected");
}
codepoints[i] = lua_tointeger(L, idx);
}
char *s = nn_unicode_char(codepoints, argc);
lua_pushstring(L, s);
nn_free(s);
nn_free(codepoints);
return 1;
}
int testLuaArch_unicode_len(lua_State *L) {
const char *s = luaL_checkstring(L, 1);
if(!nn_unicode_validate(s)) {
luaL_error(L, "invalid utf-8");
}
lua_pushinteger(L, nn_unicode_len(s));
return 1;
}
void testLuaArch_loadEnv(lua_State *L) { void testLuaArch_loadEnv(lua_State *L) {
lua_createtable(L, 0, 10); lua_createtable(L, 0, 10);
int computer = lua_gettop(L); int computer = lua_gettop(L);
lua_pushcfunction(L, testLuaArch_computer_clearError);
lua_setfield(L, computer, "clearError");
lua_pushcfunction(L, testLuaArch_computer_usedMemory); lua_pushcfunction(L, testLuaArch_computer_usedMemory);
lua_setfield(L, computer, "usedMemory"); lua_setfield(L, computer, "usedMemory");
lua_pushcfunction(L, testLuaArch_computer_freeMemory); lua_pushcfunction(L, testLuaArch_computer_freeMemory);
@ -501,6 +589,14 @@ void testLuaArch_loadEnv(lua_State *L) {
lua_createtable(L, 0, 20); lua_createtable(L, 0, 20);
int unicode = lua_gettop(L); int unicode = lua_gettop(L);
lua_pushcfunction(L, testLuaArch_unicode_sub);
lua_setfield(L, unicode, "sub");
lua_pushcfunction(L, testLuaArch_unicode_len);
lua_setfield(L, unicode, "len");
lua_pushcfunction(L, testLuaArch_unicode_len);
lua_setfield(L, unicode, "wlen");
lua_pushcfunction(L, testLuaArch_unicode_char);
lua_setfield(L, unicode, "char");
lua_setglobal(L, "unicode"); lua_setglobal(L, "unicode");
} }

View File

@ -1,4 +1,5 @@
#include "neonucleus.h" #include "neonucleus.h"
#include <stdio.h>
#include <string.h> #include <string.h>
bool nn_unicode_validate(const char *s) { bool nn_unicode_validate(const char *s) {
@ -10,10 +11,10 @@ bool nn_unicode_validate(const char *s) {
// It is used to power the Lua architecture's Unicode API re-implementation. // It is used to power the Lua architecture's Unicode API re-implementation.
// It can also just be used to deal with unicode. // It can also just be used to deal with unicode.
char *nn_unicode_char(int *codepoints, size_t codepointCount) { char *nn_unicode_char(unsigned int *codepoints, size_t codepointCount) {
size_t len = 0; size_t len = 0;
for (size_t i = 0; i < codepointCount; i++) { for (size_t i = 0; i < codepointCount; i++) {
int codepoint = codepoints[i]; unsigned int codepoint = codepoints[i];
len += nn_unicode_codepointSize(codepoint); len += nn_unicode_codepointSize(codepoint);
} }
@ -33,21 +34,61 @@ char *nn_unicode_char(int *codepoints, size_t codepointCount) {
return buf; return buf;
} }
int *nn_unicode_codepoints(const char *s); unsigned int *nn_unicode_codepoints(const char *s) {
size_t l = nn_unicode_len(s);
unsigned int *buf = nn_malloc(sizeof(unsigned int) * l);
if(buf == NULL) return NULL;
size_t cur = 0;
size_t bufidx = 0;
while(s[cur] != 0) {
unsigned int point = nn_unicode_codepointAt(s, cur);
cur += nn_unicode_codepointSize(point);
buf[bufidx++] = point;
}
return buf;
}
size_t nn_unicode_len(const char *s) { size_t nn_unicode_len(const char *s) {
size_t count = 0; size_t count = 0;
while (*s) { while (*s) {
count += (*s++ & 0xC0) != 0x80; count++;
if(s[0] <= 0x7F) {
s++;
} else if((s[0] >> 5) == 0b110) {
s += 2;
} else if((s[0] >> 4) == 0b1110) {
s += 3;
} else if((s[0] >> 3) == 0b11110) {
s += 4;
}
} }
return count; return count;
} }
int nn_unicode_codepointAt(const char *s, size_t byteOffset) { unsigned int nn_unicode_codepointAt(const char *s, size_t byteOffset) {
return s[byteOffset]; unsigned int point = 0;
const unsigned char *b = (const unsigned char *)s + byteOffset;
const unsigned int subpartMask = 0b111111;
// look into nn_unicode_codepointToChar as well.
if(b[0] <= 0x7F) {
return b[0];
} else if((b[0] >> 5) == 0b110) {
point += b[0] & 0b11111;
point += (b[1] & subpartMask) << 5;
} else if((b[0] >> 4) == 0b1110) {
point += b[0] & 0b1111;
point += (b[1] & subpartMask) << 4;
point += (b[2] & subpartMask) << 10;
} else if((b[0] >> 3) == 0b11110) {
point += b[0] & 0b111;
point += (b[1] & subpartMask) << 3;
point += (b[2] & subpartMask) << 9;
point += (b[3] & subpartMask) << 15;
}
return point;
} }
size_t nn_unicode_codepointSize(int codepoint) { size_t nn_unicode_codepointSize(unsigned int codepoint) {
if (codepoint <= 0x007f) { if (codepoint <= 0x007f) {
return 1; return 1;
} else if (codepoint <= 0x07ff) { } else if (codepoint <= 0x07ff) {
@ -61,7 +102,7 @@ size_t nn_unicode_codepointSize(int codepoint) {
return 0; return 0;
} }
const char *nn_unicode_codepointToChar(int codepoint, size_t *len) { const char *nn_unicode_codepointToChar(unsigned int codepoint, size_t *len) {
size_t codepointSize = nn_unicode_codepointSize(codepoint); size_t codepointSize = nn_unicode_codepointSize(codepoint);
*len = codepointSize; *len = codepointSize;
@ -86,9 +127,10 @@ const char *nn_unicode_codepointToChar(int codepoint, size_t *len) {
return buffer; return buffer;
} }
size_t nn_unicode_charWidth(int codepoint); size_t nn_unicode_charWidth(unsigned int codepoint);
size_t nn_unicode_wlen(const char *s); size_t nn_unicode_wlen(const char *s);
// NOT IMPLEMENTED YET
void nn_unicode_upper(char *s); void nn_unicode_upper(char *s);
void nn_unicode_lower(char *s); void nn_unicode_lower(char *s);

View File

@ -50,4 +50,5 @@ void nn_loadCoreComponentTables(nn_universe *universe) {
//nn_loadDriveTable(universe); //nn_loadDriveTable(universe);
nn_loadScreenTable(universe); nn_loadScreenTable(universe);
nn_loadGraphicsCardTable(universe); nn_loadGraphicsCardTable(universe);
nn_loadKeyboardTable(universe);
} }