diff --git a/build.zig b/build.zig index d13ff59..cd8a907 100644 --- a/build.zig +++ b/build.zig @@ -62,6 +62,7 @@ pub fn build(b: *std.Build) void { }); emulator.linkLibC(); emulator.linkSystemLibrary("lua"); + emulator.linkSystemLibrary("raylib"); emulator.addCSourceFiles(.{ .files = &.{ "src/testLuaArch.c", diff --git a/src/components/eeprom.c b/src/components/eeprom.c index 5f23c94..6e9f92e 100644 --- a/src/components/eeprom.c +++ b/src/components/eeprom.c @@ -98,6 +98,15 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu nn_setCError(computer, "out of space"); return; } + if(buf == NULL) { + if(data.tag == NN_VALUE_NIL) { + buf = ""; + len = 0; + } else { + nn_setCError(computer, "bad data (string expected)"); + return; + } + } eeprom->set(component, eeprom->userdata, buf, len); nn_eepromControl control = nn_eeprom_getControl(component, eeprom); @@ -132,8 +141,17 @@ void nn_eeprom_getData(nn_eeprom *eeprom, void *_, nn_component *component, nn_c void nn_eeprom_setData(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { nn_value data = nn_getArgument(computer, 0); - size_t len; + size_t len = 0; const char *buf = nn_toString(data, &len); + if(buf == NULL) { + if(data.tag == NN_VALUE_NIL) { + buf = ""; + len = 0; + } else { + nn_setCError(computer, "bad data (string expected)"); + return; + } + } if(len > eeprom->getDataSize(component, eeprom->userdata)) { nn_setCError(computer, "out of space"); return; diff --git a/src/components/filesystem.c b/src/components/filesystem.c index d723f4c..da3895b 100644 --- a/src/components/filesystem.c +++ b/src/components/filesystem.c @@ -1,4 +1,5 @@ #include "../neonucleus.h" +#include #include void nn_fs_destroy(void *_, nn_component *component, nn_filesystem *fs) { @@ -266,7 +267,7 @@ void nn_fs_list(nn_filesystem *fs, void *_, nn_component *component, nn_computer // operation succeeded nn_value arr = nn_values_array(fileCount); for(size_t i = 0; i < fileCount; i++) { - nn_values_set(arr, i, nn_values_cstring(files[i])); + nn_values_set(arr, i, nn_values_string(files[i], strlen(files[i]))); nn_free(files[i]); } nn_free(files); @@ -336,7 +337,7 @@ void nn_fs_write(nn_filesystem *fs, void *_, nn_component *component, nn_compute void nn_fs_read(nn_filesystem *fs, void *_, nn_component *component, nn_computer *computer) { nn_value fdValue = nn_getArgument(computer, 0); - size_t fd = nn_toInt(fdValue); + int fd = nn_toInt(fdValue); nn_value lenValue = nn_getArgument(computer, 1); double len = nn_toNumber(lenValue); @@ -423,6 +424,5 @@ void nn_loadFilesystemTable(nn_universe *universe) { nn_component *nn_addFileSystem(nn_computer *computer, nn_address address, int slot, nn_filesystem *filesystem) { nn_componentTable *fsTable = nn_queryUserdata(nn_getUniverse(computer), "NN:FILESYSTEM"); - return nn_newComponent(computer, address, slot, fsTable, filesystem); } diff --git a/src/emulator.c b/src/emulator.c index b808890..440f44a 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -1,9 +1,11 @@ #include +#include #include #include #include #include "neonucleus.h" #include "testLuaArch.h" +#include nn_eepromControl ne_eeprom_getControl(nn_component *component, void *_) { return (nn_eepromControl) { @@ -69,6 +71,126 @@ bool ne_eeprom_isReadonly(nn_component *component, void *userdata) { void ne_eeprom_makeReadonly(nn_component *component, void *userdata) {} +#define NE_FS_MAX 128 + +typedef struct ne_fs { + FILE *files[NE_FS_MAX]; + size_t fileLen; +} ne_fs; + +nn_filesystemControl ne_fs_getControl(nn_component *component, ne_fs *_) { + return (nn_filesystemControl) { + .pretendChunkSize = 512, + .pretendRPM = 1800, + .writeHeatPerChunk = 0.01, + .writeCostPerChunk = 3, + .writeEnergyCost = 0.015, + .writeLatencyPerChunk = 0.0003, + .readEnergyCost = 0.007, + .readCostPerChunk = 1, + .readLatencyPerChunk = 0.0001, + .randomLatencyMin = 0.0005, + .randomLatencyMax = 0.0019, + .seekCostPerChunk = 1, + .motorHeat = 0.03, + .motorEnergyCost = 0.5, + }; +} + +size_t ne_fs_spaceUsed(nn_component *component, void *_) { + return 0; // ultra accurate +} + +size_t ne_fs_spaceTotal(nn_component *component, void *_) { + return 1*1024*1024; +} + +const char *ne_fs_diskPath(nn_component *component, const char *path) { + static char buf[256]; + const char *root = ne_location(nn_getComponentAddress(component)); + if(path[0] == '/') { + snprintf(buf, 256, "%s%s", root, path); + } else { + snprintf(buf, 256, "%s/%s", root, path); + } + + return buf; +} + +size_t ne_fs_open(nn_component *component, ne_fs *fs, const char *path, const char *mode) { + if(fs->fileLen == NE_FS_MAX) { + nn_setCError(nn_getComputerOfComponent(component), "too many files"); + return 0; + } + + const char *trueMode = "rb"; + if(strcmp(mode, "w") == 0) { + trueMode = "wb"; + } + if(strcmp(mode, "a") == 0) { + trueMode = "ab"; + } + + const char *p = ne_fs_diskPath(component, path); + FILE *f = fopen(p, trueMode); + + if(f == NULL) { + nn_setCError(nn_getComputerOfComponent(component), strerror(errno)); + return 0; + } + + for(size_t i = 0; i < fs->fileLen; i++) { + if(fs->files[i] == NULL) { + fs->files[i] = f; + return i; + } + } + + size_t i = fs->fileLen++; + fs->files[i] = f; + return i; +} + +bool ne_fs_close(nn_component *component, ne_fs *fs, int fd) { + // we pray + fclose(fs->files[fd]); + fs->files[fd] = NULL; + return true; +} + +bool ne_fs_write(nn_component *component, ne_fs *fs, int fd, const char *buf, size_t len) { + FILE *f = fs->files[fd]; + return fwrite(buf, sizeof(char), len, f) > 0; +} + +size_t ne_fs_read(nn_component *component, ne_fs *fs, int fd, char *buf, size_t required) { + FILE *f = fs->files[fd]; + if(feof(f)) return 0; + return fread(buf, sizeof(char), required, f); +} + +char **ne_fs_list(nn_component *component, ne_fs *fs, const char *path, size_t *len) { + const char *p = ne_fs_diskPath(component, path); + + FilePathList files = LoadDirectoryFiles(p); + *len = files.count; + + char **buf = nn_malloc(sizeof(char *) * files.count); + for(size_t i = 0; i < files.count; i++) { + buf[i] = nn_strdup(GetFileName(files.paths[i])); + } + + UnloadDirectoryFiles(files); + + return buf; +} + +bool ne_fs_isDirectory(nn_component *component, ne_fs *fs, const char *path) { + const char *p = ne_fs_diskPath(component, path); + + return DirectoryExists(p); +} + int main() { printf("Setting up universe\n"); nn_universe *universe = nn_newUniverse(); @@ -80,6 +202,7 @@ int main() { // 1MB of RAM, 16 components max nn_computer *computer = nn_newComputer(universe, "testMachine", arch, NULL, 1*1024*1024, 16); nn_setEnergyInfo(computer, 5000, 5000); + nn_setCallBudget(computer, 18000); nn_addSupportedArchitecture(computer, arch); nn_eeprom genericEEPROM = { @@ -101,6 +224,37 @@ int main() { nn_addEeprom(computer, "luaBios.lua", 0, &genericEEPROM); + ne_fs fs = { + .files = {NULL}, + .fileLen = 0, + }; + + nn_filesystem genericFS = { + .refc = 0, + .userdata = &fs, + .deinit = NULL, + .control = (void *)ne_fs_getControl, + .getLabel = ne_eeprom_getLabel, + .setLabel = ne_eeprom_setLabel, + .spaceUsed = ne_fs_spaceUsed, + .spaceTotal = ne_fs_spaceTotal, + .isReadOnly = ne_eeprom_isReadonly, + .size = NULL, + .remove = NULL, + .lastModified = NULL, + .rename = NULL, + .exists = NULL, + .isDirectory = (void *)ne_fs_isDirectory, + .makeDirectory = NULL, + .list = (void *)ne_fs_list, + .open = (void *)ne_fs_open, + .close = (void *)ne_fs_close, + .write = (void *)ne_fs_write, + .read = (void *)ne_fs_read, + .seek = NULL, + }; + nn_addFileSystem(computer, "OpenOS", 1, &genericFS); + double lastTime = nn_realTime(); while(true) { double now = nn_realTime(); @@ -116,6 +270,9 @@ int main() { } int state = nn_tickComputer(computer); + if(nn_isOverworked(computer)) { + printf("Machine overworked.\n"); + } if(state == NN_STATE_SWITCH) { nn_architecture *nextArch = nn_getNextArchitecture(computer); printf("Next architecture: %s\n", nextArch->archName); diff --git a/src/sandbox.lua b/src/sandbox.lua index a8cc488..75b0560 100644 --- a/src/sandbox.lua +++ b/src/sandbox.lua @@ -76,7 +76,7 @@ local function checkArg(idx, v, ...) local bad = true local n = select("#", ...) for i=1,n do - local t = select(i, ...) + local t = select(i, ...) if type(v) == t then bad = false break end end if not bad then return end @@ -390,9 +390,11 @@ sandbox = { }, utf8 = copy(utf8), + unicode = copy(unicode), checkArg = checkArg, component = libcomponent, computer = libcomputer, + print = print, } sandbox._G = sandbox @@ -418,12 +420,10 @@ while true do local ok, err = resume(co) if not ok then - error(err) + error(debug.traceback(co, err), 0) elseif coroutine.status(co) == "dead" then error("computer halted", 0) else coroutine.yield() end end - -error("machine halted") diff --git a/src/testLuaArch.c b/src/testLuaArch.c index b4bb9b8..3cde68b 100644 --- a/src/testLuaArch.c +++ b/src/testLuaArch.c @@ -19,14 +19,12 @@ void *testLuaArch_alloc(testLuaArch *arch, void *ptr, size_t osize, size_t nsize nn_free(ptr); return NULL; } else { - if(arch->memoryUsed - osize + nsize > nn_getComputerMemoryTotal(arch->computer)) { + size_t actualOldSize = osize; + if(ptr == NULL) actualOldSize = 0; + if(arch->memoryUsed - actualOldSize + nsize > nn_getComputerMemoryTotal(arch->computer)) { return NULL; // OOM condition } - if(ptr != NULL) { - // if ptr is NULL, osize will actually encode the type. - // We do not want that to mess us up. - arch->memoryUsed -= osize; - } + arch->memoryUsed -= actualOldSize; arch->memoryUsed += nsize; return nn_realloc(ptr, nsize); } @@ -397,8 +395,9 @@ static int testLuaArch_component_invoke(lua_State *L) { return 2; } nn_resetCall(c); + printf("%s %s %d\n", addr, method, argc); for(size_t i = 0; i < argc; i++) { - nn_addArgument(c, testLuaArch_getValue(L, 2 + argc)); + nn_addArgument(c, testLuaArch_getValue(L, 3 + i)); } if(!nn_invokeComponentMethod(component, method)) { nn_resetCall(c); @@ -500,6 +499,10 @@ void testLuaArch_loadEnv(lua_State *L) { lua_pushinteger(L, NN_STATE_SWITCH); lua_setfield(L, states, "switch"); lua_setglobal(L, "states"); + + lua_createtable(L, 0, 20); + int unicode = lua_gettop(L); + lua_setglobal(L, "unicode"); } testLuaArch *testLuaArch_setup(nn_computer *computer, void *_) {