mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 09:03:32 +02:00
huge progress on filesystem
This commit is contained in:
parent
c3ebf82981
commit
7daf034d25
@ -62,6 +62,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
});
|
});
|
||||||
emulator.linkLibC();
|
emulator.linkLibC();
|
||||||
emulator.linkSystemLibrary("lua");
|
emulator.linkSystemLibrary("lua");
|
||||||
|
emulator.linkSystemLibrary("raylib");
|
||||||
emulator.addCSourceFiles(.{
|
emulator.addCSourceFiles(.{
|
||||||
.files = &.{
|
.files = &.{
|
||||||
"src/testLuaArch.c",
|
"src/testLuaArch.c",
|
||||||
|
@ -98,6 +98,15 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu
|
|||||||
nn_setCError(computer, "out of space");
|
nn_setCError(computer, "out of space");
|
||||||
return;
|
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);
|
eeprom->set(component, eeprom->userdata, buf, len);
|
||||||
|
|
||||||
nn_eepromControl control = nn_eeprom_getControl(component, eeprom);
|
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) {
|
void nn_eeprom_setData(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
|
||||||
nn_value data = nn_getArgument(computer, 0);
|
nn_value data = nn_getArgument(computer, 0);
|
||||||
size_t len;
|
size_t len = 0;
|
||||||
const char *buf = nn_toString(data, &len);
|
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)) {
|
if(len > eeprom->getDataSize(component, eeprom->userdata)) {
|
||||||
nn_setCError(computer, "out of space");
|
nn_setCError(computer, "out of space");
|
||||||
return;
|
return;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "../neonucleus.h"
|
#include "../neonucleus.h"
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
void nn_fs_destroy(void *_, nn_component *component, nn_filesystem *fs) {
|
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
|
// operation succeeded
|
||||||
nn_value arr = nn_values_array(fileCount);
|
nn_value arr = nn_values_array(fileCount);
|
||||||
for(size_t i = 0; i < fileCount; i++) {
|
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[i]);
|
||||||
}
|
}
|
||||||
nn_free(files);
|
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) {
|
void nn_fs_read(nn_filesystem *fs, void *_, nn_component *component, nn_computer *computer) {
|
||||||
nn_value fdValue = nn_getArgument(computer, 0);
|
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);
|
nn_value lenValue = nn_getArgument(computer, 1);
|
||||||
double len = nn_toNumber(lenValue);
|
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_component *nn_addFileSystem(nn_computer *computer, nn_address address, int slot, nn_filesystem *filesystem) {
|
||||||
nn_componentTable *fsTable = nn_queryUserdata(nn_getUniverse(computer), "NN:FILESYSTEM");
|
nn_componentTable *fsTable = nn_queryUserdata(nn_getUniverse(computer), "NN:FILESYSTEM");
|
||||||
|
|
||||||
return nn_newComponent(computer, address, slot, fsTable, filesystem);
|
return nn_newComponent(computer, address, slot, fsTable, filesystem);
|
||||||
}
|
}
|
||||||
|
157
src/emulator.c
157
src/emulator.c
@ -1,9 +1,11 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "neonucleus.h"
|
#include "neonucleus.h"
|
||||||
#include "testLuaArch.h"
|
#include "testLuaArch.h"
|
||||||
|
#include <raylib.h>
|
||||||
|
|
||||||
nn_eepromControl ne_eeprom_getControl(nn_component *component, void *_) {
|
nn_eepromControl ne_eeprom_getControl(nn_component *component, void *_) {
|
||||||
return (nn_eepromControl) {
|
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) {}
|
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() {
|
int main() {
|
||||||
printf("Setting up universe\n");
|
printf("Setting up universe\n");
|
||||||
nn_universe *universe = nn_newUniverse();
|
nn_universe *universe = nn_newUniverse();
|
||||||
@ -80,6 +202,7 @@ int main() {
|
|||||||
// 1MB of RAM, 16 components max
|
// 1MB of RAM, 16 components max
|
||||||
nn_computer *computer = nn_newComputer(universe, "testMachine", arch, NULL, 1*1024*1024, 16);
|
nn_computer *computer = nn_newComputer(universe, "testMachine", arch, NULL, 1*1024*1024, 16);
|
||||||
nn_setEnergyInfo(computer, 5000, 5000);
|
nn_setEnergyInfo(computer, 5000, 5000);
|
||||||
|
nn_setCallBudget(computer, 18000);
|
||||||
nn_addSupportedArchitecture(computer, arch);
|
nn_addSupportedArchitecture(computer, arch);
|
||||||
|
|
||||||
nn_eeprom genericEEPROM = {
|
nn_eeprom genericEEPROM = {
|
||||||
@ -101,6 +224,37 @@ int main() {
|
|||||||
|
|
||||||
nn_addEeprom(computer, "luaBios.lua", 0, &genericEEPROM);
|
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();
|
double lastTime = nn_realTime();
|
||||||
while(true) {
|
while(true) {
|
||||||
double now = nn_realTime();
|
double now = nn_realTime();
|
||||||
@ -116,6 +270,9 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int state = nn_tickComputer(computer);
|
int state = nn_tickComputer(computer);
|
||||||
|
if(nn_isOverworked(computer)) {
|
||||||
|
printf("Machine overworked.\n");
|
||||||
|
}
|
||||||
if(state == NN_STATE_SWITCH) {
|
if(state == NN_STATE_SWITCH) {
|
||||||
nn_architecture *nextArch = nn_getNextArchitecture(computer);
|
nn_architecture *nextArch = nn_getNextArchitecture(computer);
|
||||||
printf("Next architecture: %s\n", nextArch->archName);
|
printf("Next architecture: %s\n", nextArch->archName);
|
||||||
|
@ -76,7 +76,7 @@ local function checkArg(idx, v, ...)
|
|||||||
local bad = true
|
local bad = true
|
||||||
local n = select("#", ...)
|
local n = select("#", ...)
|
||||||
for i=1,n do
|
for i=1,n do
|
||||||
local t = select(i, ...)
|
local t = select(i, ...)
|
||||||
if type(v) == t then bad = false break end
|
if type(v) == t then bad = false break end
|
||||||
end
|
end
|
||||||
if not bad then return end
|
if not bad then return end
|
||||||
@ -390,9 +390,11 @@ sandbox = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
utf8 = copy(utf8),
|
utf8 = copy(utf8),
|
||||||
|
unicode = copy(unicode),
|
||||||
checkArg = checkArg,
|
checkArg = checkArg,
|
||||||
component = libcomponent,
|
component = libcomponent,
|
||||||
computer = libcomputer,
|
computer = libcomputer,
|
||||||
|
print = print,
|
||||||
}
|
}
|
||||||
sandbox._G = sandbox
|
sandbox._G = sandbox
|
||||||
|
|
||||||
@ -418,12 +420,10 @@ while true do
|
|||||||
local ok, err = resume(co)
|
local ok, err = resume(co)
|
||||||
|
|
||||||
if not ok then
|
if not ok then
|
||||||
error(err)
|
error(debug.traceback(co, err), 0)
|
||||||
elseif coroutine.status(co) == "dead" then
|
elseif coroutine.status(co) == "dead" then
|
||||||
error("computer halted", 0)
|
error("computer halted", 0)
|
||||||
else
|
else
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
error("machine halted")
|
|
||||||
|
@ -19,14 +19,12 @@ void *testLuaArch_alloc(testLuaArch *arch, void *ptr, size_t osize, size_t nsize
|
|||||||
nn_free(ptr);
|
nn_free(ptr);
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} 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
|
return NULL; // OOM condition
|
||||||
}
|
}
|
||||||
if(ptr != NULL) {
|
arch->memoryUsed -= actualOldSize;
|
||||||
// if ptr is NULL, osize will actually encode the type.
|
|
||||||
// We do not want that to mess us up.
|
|
||||||
arch->memoryUsed -= osize;
|
|
||||||
}
|
|
||||||
arch->memoryUsed += nsize;
|
arch->memoryUsed += nsize;
|
||||||
return nn_realloc(ptr, nsize);
|
return nn_realloc(ptr, nsize);
|
||||||
}
|
}
|
||||||
@ -397,8 +395,9 @@ static int testLuaArch_component_invoke(lua_State *L) {
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
nn_resetCall(c);
|
nn_resetCall(c);
|
||||||
|
printf("%s %s %d\n", addr, method, argc);
|
||||||
for(size_t i = 0; i < argc; i++) {
|
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)) {
|
if(!nn_invokeComponentMethod(component, method)) {
|
||||||
nn_resetCall(c);
|
nn_resetCall(c);
|
||||||
@ -500,6 +499,10 @@ void testLuaArch_loadEnv(lua_State *L) {
|
|||||||
lua_pushinteger(L, NN_STATE_SWITCH);
|
lua_pushinteger(L, NN_STATE_SWITCH);
|
||||||
lua_setfield(L, states, "switch");
|
lua_setfield(L, states, "switch");
|
||||||
lua_setglobal(L, "states");
|
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 *_) {
|
testLuaArch *testLuaArch_setup(nn_computer *computer, void *_) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user