mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 09:03:32 +02:00
the gpu like kinda functions idfk
This commit is contained in:
parent
e2bc6bd469
commit
6a21b83d5a
@ -18,6 +18,7 @@ fn addEngineSources(c: *std.Build.Step.Compile) void {
|
||||
"src/components/filesystem.c",
|
||||
"src/components/screen.c",
|
||||
"src/components/gpu.c",
|
||||
"src/components/keyboard.c",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "../neonucleus.h"
|
||||
#include "screen.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct nni_gpu {
|
||||
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 *gpu = nn_malloc(sizeof(nni_gpu));
|
||||
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) {
|
||||
if(gpu->currentScreen == NULL) return;
|
||||
int x = nn_toInt(nn_getArgument(computer, 0));
|
||||
int y = nn_toInt(nn_getArgument(computer, 1));
|
||||
int x = nn_toInt(nn_getArgument(computer, 0)) - 1;
|
||||
int y = nn_toInt(nn_getArgument(computer, 1)) - 1;
|
||||
const char *s = nn_toCString(nn_getArgument(computer, 2));
|
||||
bool isVertical = nn_toBoolean(nn_getArgument(computer, 3));
|
||||
|
||||
if(s == NULL) {
|
||||
nn_setCError(computer, "bad argument #4 (string expected)");
|
||||
nn_setCError(computer, "bad argument #3 (string expected in set)");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -127,23 +138,25 @@ void nni_gpu_set(nni_gpu *gpu, void *_, nn_component *component, nn_computer *co
|
||||
while(s[current]) {
|
||||
int codepoint = nn_unicode_codepointAt(s, current);
|
||||
nn_setPixel(gpu->currentScreen, x, y, nni_gpu_makePixel(gpu, s + current));
|
||||
if(isVertical)
|
||||
if(isVertical) {
|
||||
y++;
|
||||
else
|
||||
} else {
|
||||
x++;
|
||||
}
|
||||
current += nn_unicode_codepointSize(codepoint);
|
||||
}
|
||||
}
|
||||
|
||||
void nni_gpu_get(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
|
||||
if(gpu->screenAddress == NULL) return;
|
||||
int x = nn_toInt(nn_getArgument(computer, 0));
|
||||
int y = nn_toInt(nn_getArgument(computer, 1));
|
||||
int x = nn_toInt(nn_getArgument(computer, 0)) - 1;
|
||||
int y = nn_toInt(nn_getArgument(computer, 1)) - 1;
|
||||
nn_scrchr_t pxl = nn_getPixel(gpu->currentScreen, x, y);
|
||||
|
||||
size_t 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_integer(pxl.fg));
|
||||
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) {
|
||||
if(gpu->currentScreen == NULL) return;
|
||||
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(h));
|
||||
}
|
||||
|
||||
void nni_gpu_setResolution(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
|
||||
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) {
|
||||
@ -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) {
|
||||
if(gpu->currentScreen == NULL) return;
|
||||
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) {
|
||||
if(gpu->currentScreen == NULL) return;
|
||||
int x = nn_toInt(nn_getArgument(computer, 0));
|
||||
int y = nn_toInt(nn_getArgument(computer, 1));
|
||||
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));
|
||||
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));
|
||||
}
|
||||
|
||||
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) {
|
||||
nn_componentTable *gpuTable = nn_newComponentTable("gpu", NULL, NULL, (void *)nni_gpuDeinit);
|
||||
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, "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, "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, "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) {
|
||||
|
11
src/components/keyboard.c
Normal file
11
src/components/keyboard.c
Normal 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);
|
||||
}
|
@ -164,7 +164,7 @@ nn_scrchr_t nn_getPixel(nn_screen *screen, int x, int y) {
|
||||
if(x < 0) return blank;
|
||||
if(y < 0) 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];
|
||||
}
|
||||
|
||||
|
@ -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_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();
|
||||
return p->values[index];
|
||||
}
|
||||
|
||||
size_t nn_signalSize(nn_computer *computer) {
|
||||
if(computer->signalCount == 0) return 0;
|
||||
return computer->signals[computer->signalCount-1].len;
|
||||
return computer->signals[0].len;
|
||||
}
|
||||
|
||||
void nn_popSignal(nn_computer *computer) {
|
||||
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++) {
|
||||
nn_values_drop(p->values[i]);
|
||||
}
|
||||
for(size_t i = 1; i < computer->signalCount; i++) {
|
||||
computer->signals[i-1] = computer->signals[i];
|
||||
}
|
||||
computer->signalCount--;
|
||||
}
|
||||
|
||||
|
@ -280,6 +280,7 @@ int main() {
|
||||
|
||||
nn_screen *s = nn_newScreen(80, 32, 16, 16, 256);
|
||||
nn_addKeyboard(s, "shitty keyboard");
|
||||
nn_mountKeyboard(computer, "shitty keyboard", 2);
|
||||
nn_addScreen(computer, "Main Screen", 2, s);
|
||||
|
||||
nn_gpuControl gpuCtrl = {
|
||||
@ -358,10 +359,10 @@ render:
|
||||
|
||||
ClearBackground(BLACK);
|
||||
|
||||
int scrW, scrH = 1;
|
||||
int scrW = 1, scrH = 1;
|
||||
nn_getResolution(s, &scrW, &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 y = 0; y < scrH; y++) {
|
||||
|
@ -156,14 +156,14 @@ bool nn_decRef(nn_refc *refc);
|
||||
|
||||
bool nn_unicode_validate(const char *s);
|
||||
// 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
|
||||
int *nn_unicode_codepoints(const char *s);
|
||||
unsigned int *nn_unicode_codepoints(const char *s);
|
||||
size_t nn_unicode_len(const char *s);
|
||||
int nn_unicode_codepointAt(const char *s, size_t byteOffset);
|
||||
size_t nn_unicode_codepointSize(int codepoint);
|
||||
const char *nn_unicode_codepointToChar(int codepoint, size_t *len);
|
||||
size_t nn_unicode_charWidth(int codepoint);
|
||||
unsigned int nn_unicode_codepointAt(const char *s, size_t byteOffset);
|
||||
size_t nn_unicode_codepointSize(unsigned int codepoint);
|
||||
const char *nn_unicode_codepointToChar(unsigned int codepoint, size_t *len);
|
||||
size_t nn_unicode_charWidth(unsigned int codepoint);
|
||||
size_t nn_unicode_wlen(const char *s);
|
||||
void nn_unicode_upper(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_loadScreenTable(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
|
||||
|
||||
|
@ -114,6 +114,7 @@ libcomponent = {
|
||||
|
||||
while true do
|
||||
local r = {pcall(component.invoke, addr, method, ...)}
|
||||
computer.clearError()
|
||||
|
||||
-- in this situation, either the temperature is above 100 C and we throttle
|
||||
-- or the call budget has been filled and we dont care
|
||||
@ -392,7 +393,9 @@ sandbox = {
|
||||
},
|
||||
|
||||
utf8 = copy(utf8),
|
||||
unicode = copy(string),
|
||||
unicode = copy(unicode, {
|
||||
wtrunc = function(s) return s end,
|
||||
}),
|
||||
checkArg = checkArg,
|
||||
component = libcomponent,
|
||||
computer = libcomputer,
|
||||
|
@ -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) {
|
||||
testLuaArch *s = testLuaArch_get(L);
|
||||
lua_pushinteger(L, s->memoryUsed);
|
||||
@ -416,9 +422,91 @@ static int testLuaArch_component_invoke(lua_State *L) {
|
||||
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) {
|
||||
lua_createtable(L, 0, 10);
|
||||
int computer = lua_gettop(L);
|
||||
lua_pushcfunction(L, testLuaArch_computer_clearError);
|
||||
lua_setfield(L, computer, "clearError");
|
||||
lua_pushcfunction(L, testLuaArch_computer_usedMemory);
|
||||
lua_setfield(L, computer, "usedMemory");
|
||||
lua_pushcfunction(L, testLuaArch_computer_freeMemory);
|
||||
@ -501,6 +589,14 @@ void testLuaArch_loadEnv(lua_State *L) {
|
||||
|
||||
lua_createtable(L, 0, 20);
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "neonucleus.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
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 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;
|
||||
for (size_t i = 0; i < codepointCount; i++) {
|
||||
int codepoint = codepoints[i];
|
||||
unsigned int codepoint = codepoints[i];
|
||||
len += nn_unicode_codepointSize(codepoint);
|
||||
}
|
||||
|
||||
@ -33,21 +34,61 @@ char *nn_unicode_char(int *codepoints, size_t codepointCount) {
|
||||
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 count = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
int nn_unicode_codepointAt(const char *s, size_t byteOffset) {
|
||||
return s[byteOffset];
|
||||
unsigned int nn_unicode_codepointAt(const char *s, size_t 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) {
|
||||
return 1;
|
||||
} else if (codepoint <= 0x07ff) {
|
||||
@ -61,7 +102,7 @@ size_t nn_unicode_codepointSize(int codepoint) {
|
||||
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);
|
||||
*len = codepointSize;
|
||||
|
||||
@ -86,9 +127,10 @@ const char *nn_unicode_codepointToChar(int codepoint, size_t *len) {
|
||||
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);
|
||||
|
||||
// NOT IMPLEMENTED YET
|
||||
void nn_unicode_upper(char *s);
|
||||
void nn_unicode_lower(char *s);
|
||||
|
@ -50,4 +50,5 @@ void nn_loadCoreComponentTables(nn_universe *universe) {
|
||||
//nn_loadDriveTable(universe);
|
||||
nn_loadScreenTable(universe);
|
||||
nn_loadGraphicsCardTable(universe);
|
||||
nn_loadKeyboardTable(universe);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user