mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 09:03:32 +02:00
eeproms
This commit is contained in:
parent
21b44a71bf
commit
f6f6fb89fd
@ -12,6 +12,8 @@ fn addEngineSources(c: *std.Build.Step.Compile) void {
|
|||||||
"src/component.c",
|
"src/component.c",
|
||||||
"src/computer.c",
|
"src/computer.c",
|
||||||
"src/universe.c",
|
"src/universe.c",
|
||||||
|
// components
|
||||||
|
"src/components/eeprom.c",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
135
src/components/eeprom.c
Normal file
135
src/components/eeprom.c
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#include "../neonucleus.h"
|
||||||
|
|
||||||
|
void nn_eeprom_destroy(void *_, nn_component *component, nn_eeprom *eeprom) {
|
||||||
|
if(atomic_fetch_sub(&eeprom->refc, 1) > 1) return;
|
||||||
|
|
||||||
|
if(eeprom->deinit == NULL) {
|
||||||
|
eeprom->deinit(component, eeprom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_eeprom_getSize(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
nn_return(computer, nn_values_integer(eeprom->getSize(component, eeprom->userdata)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_eeprom_getDataSize(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
nn_return(computer, nn_values_integer(eeprom->getDataSize(component, eeprom->userdata)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_eeprom_getLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
char buf[NN_LABEL_SIZE];
|
||||||
|
size_t l = NN_LABEL_SIZE;
|
||||||
|
eeprom->getLabel(component, eeprom->userdata, buf, &l);
|
||||||
|
if(l == 0) {
|
||||||
|
nn_return(computer, nn_values_nil());
|
||||||
|
} else {
|
||||||
|
nn_return(computer, nn_values_string(buf, l));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_eeprom_setLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
size_t l = 0;
|
||||||
|
nn_value label = nn_getArgument(computer, 0);
|
||||||
|
const char *buf = nn_toString(label, &l);
|
||||||
|
if(buf == NULL) {
|
||||||
|
nn_setCError(computer, "bad label (string expected)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
l = eeprom->setLabel(component, eeprom->userdata, buf, l);
|
||||||
|
nn_return(computer, nn_values_string(buf, l));
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_eeprom_get(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
size_t cap = eeprom->getSize(component, eeprom->userdata);
|
||||||
|
char *buf = nn_malloc(cap);
|
||||||
|
if(buf == NULL) {
|
||||||
|
nn_setCError(computer, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t len = eeprom->get(component, eeprom->userdata, buf);
|
||||||
|
nn_return(computer, nn_values_string(buf, len));
|
||||||
|
nn_free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
nn_value data = nn_getArgument(computer, 0);
|
||||||
|
size_t len;
|
||||||
|
const char *buf = nn_toString(data, &len);
|
||||||
|
if(len > eeprom->getSize(component, eeprom->userdata)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
eeprom->set(component, eeprom->userdata, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_eeprom_getData(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
size_t cap = eeprom->getDataSize(component, eeprom->userdata);
|
||||||
|
char *buf = nn_malloc(cap);
|
||||||
|
if(buf == NULL) {
|
||||||
|
nn_setCError(computer, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int len = eeprom->getData(component, eeprom->userdata, buf);
|
||||||
|
if(len < 0) {
|
||||||
|
nn_return(computer, nn_values_nil());
|
||||||
|
} else {
|
||||||
|
nn_return(computer, nn_values_string(buf, len));
|
||||||
|
}
|
||||||
|
nn_free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_eeprom_setData(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
nn_value data = nn_getArgument(computer, 0);
|
||||||
|
size_t len;
|
||||||
|
const char *buf = nn_toString(data, &len);
|
||||||
|
eeprom->setData(component, eeprom->userdata, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_eeprom_isReadOnly(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
nn_return(computer, nn_values_boolean(eeprom->isReadonly(component, eeprom->userdata)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_eeprom_makeReadonly(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
eeprom->makeReadonly(component, eeprom->userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make good
|
||||||
|
void nn_eeprom_getChecksum(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
|
||||||
|
size_t cap = eeprom->getDataSize(component, eeprom->userdata);
|
||||||
|
char *buf = nn_malloc(cap);
|
||||||
|
if(buf == NULL) {
|
||||||
|
nn_setCError(computer, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t len = eeprom->getData(component, eeprom->userdata, buf);
|
||||||
|
size_t sum = 0;
|
||||||
|
for(size_t i = 0; i < len; i++) {
|
||||||
|
sum += buf[i];
|
||||||
|
}
|
||||||
|
nn_free(buf);
|
||||||
|
|
||||||
|
nn_return(computer, nn_values_string((void *)&sum, sizeof(sum)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_loadEepromTable(nn_universe *universe) {
|
||||||
|
nn_componentTable *eepromTable = nn_newComponentTable("eeprom", NULL, NULL, (void *)nn_eeprom_destroy);
|
||||||
|
nn_storeUserdata(universe, "NN:EEPROM", eepromTable);
|
||||||
|
|
||||||
|
nn_defineMethod(eepromTable, "getSize", true, (void *)nn_eeprom_getSize, NULL, "getSize(): integer - Returns the maximum code capacity of the EEPROM.");
|
||||||
|
nn_defineMethod(eepromTable, "getDataSize", true, (void *)nn_eeprom_getDataSize, NULL, "getDataSize(): integer - Returns the maximum data capacity of the EEPROM.");
|
||||||
|
nn_defineMethod(eepromTable, "getLabel", false, (void *)nn_eeprom_getLabel, NULL, "getLabel(): string - Returns the current label.");
|
||||||
|
nn_defineMethod(eepromTable, "setLabel", false, (void *)nn_eeprom_setLabel, NULL, "setLabel(label: string): string - Sets the new label. Returns the actual label set to, which may be truncated.");
|
||||||
|
nn_defineMethod(eepromTable, "get", false, (void *)nn_eeprom_get, NULL, "get(): string - Reads the current code contents.");
|
||||||
|
nn_defineMethod(eepromTable, "set", false, (void *)nn_eeprom_set, NULL, "set(data: string) - Sets the current code contents.");
|
||||||
|
nn_defineMethod(eepromTable, "getData", false, (void *)nn_eeprom_getData, NULL, "getData(): string - Reads the current data contents.");
|
||||||
|
nn_defineMethod(eepromTable, "setData", false, (void *)nn_eeprom_setData, NULL, "setData(data: string) - Sets the current data contents.");
|
||||||
|
nn_defineMethod(eepromTable, "isReadOnly", false, (void *)nn_eeprom_isReadOnly, NULL, "isReadOnly(): boolean - Returns whether this EEPROM is read-only.");
|
||||||
|
nn_defineMethod(eepromTable, "makeReadOnly", false, (void *)nn_eeprom_makeReadonly, NULL, "makeReadOnly() - Makes the current EEPROM read-only. Normally, this cannot be undone.");
|
||||||
|
nn_defineMethod(eepromTable, "makeReadonly", false, (void *)nn_eeprom_makeReadonly, NULL, "makeReadonly() - Legacy alias to makeReadOnly()");
|
||||||
|
nn_defineMethod(eepromTable, "getChecksum", false, (void *)nn_eeprom_getChecksum, NULL, "getChecksum(): string - Returns a checksum of the data on the EEPROM.");
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_component *nn_addEeprom(nn_computer *computer, nn_address address, int slot, nn_eeprom *eeprom) {
|
||||||
|
nn_componentTable *eepromTable = nn_queryUserdata(nn_getUniverse(computer), "NN:EEPROM");
|
||||||
|
|
||||||
|
return nn_newComponent(computer, address, slot, eepromTable, eeprom);
|
||||||
|
}
|
@ -44,6 +44,8 @@ nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_archit
|
|||||||
c->temperature = 30;
|
c->temperature = 30;
|
||||||
c->roomTemperature = 30;
|
c->roomTemperature = 30;
|
||||||
c->temperatureCoefficient = 1;
|
c->temperatureCoefficient = 1;
|
||||||
|
c->callCost = 0;
|
||||||
|
c->callBudget = 256;
|
||||||
|
|
||||||
// Setup Architecture
|
// Setup Architecture
|
||||||
c->archState = c->arch->setup(c, c->arch->userdata);
|
c->archState = c->arch->setup(c, c->arch->userdata);
|
||||||
@ -58,6 +60,10 @@ nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_archit
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nn_universe *nn_getUniverse(nn_computer *computer) {
|
||||||
|
return computer->universe;
|
||||||
|
}
|
||||||
|
|
||||||
void nn_setTmpAddress(nn_computer *computer, nn_address tmp) {
|
void nn_setTmpAddress(nn_computer *computer, nn_address tmp) {
|
||||||
nn_free(computer->tmpAddress);
|
nn_free(computer->tmpAddress);
|
||||||
computer->tmpAddress = nn_strdup(tmp);
|
computer->tmpAddress = nn_strdup(tmp);
|
||||||
@ -72,6 +78,7 @@ nn_address nn_getTmpAddress(nn_computer *computer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int nn_tickComputer(nn_computer *computer) {
|
int nn_tickComputer(nn_computer *computer) {
|
||||||
|
computer->callCost = 0;
|
||||||
computer->state = NN_STATE_RUNNING;
|
computer->state = NN_STATE_RUNNING;
|
||||||
nn_clearError(computer);
|
nn_clearError(computer);
|
||||||
computer->arch->tick(computer, computer->archState, computer->arch->userdata);
|
computer->arch->tick(computer, computer->archState, computer->arch->userdata);
|
||||||
@ -206,6 +213,26 @@ bool nn_isUser(nn_computer *computer, const char *name) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nn_setCallBudget(nn_computer *computer, size_t callBudget) {
|
||||||
|
computer->callBudget = callBudget;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nn_getCallBudget(nn_computer *computer) {
|
||||||
|
return computer->callBudget;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_callCost(nn_computer *computer, size_t cost) {
|
||||||
|
computer->callCost += cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nn_getCallCost(nn_computer *computer) {
|
||||||
|
return computer->callCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn_isOverworked(nn_computer *computer) {
|
||||||
|
return computer->callCost >= computer->callBudget;
|
||||||
|
}
|
||||||
|
|
||||||
int nn_getState(nn_computer *computer) {
|
int nn_getState(nn_computer *computer) {
|
||||||
return computer->state;
|
return computer->state;
|
||||||
}
|
}
|
||||||
@ -335,9 +362,9 @@ nn_component *nn_newComponent(nn_computer *computer, nn_address address, int slo
|
|||||||
c->slot = slot;
|
c->slot = slot;
|
||||||
c->computer = computer;
|
c->computer = computer;
|
||||||
if(table->constructor == NULL) {
|
if(table->constructor == NULL) {
|
||||||
c->statePtr = NULL;
|
c->statePtr = userdata;
|
||||||
} else {
|
} else {
|
||||||
c->statePtr = table->constructor(table->userdata);
|
c->statePtr = table->constructor(table->userdata, userdata);
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@ -353,7 +380,7 @@ void nn_removeComponent(nn_computer *computer, nn_address address) {
|
|||||||
void nn_destroyComponent(nn_component *component) {
|
void nn_destroyComponent(nn_component *component) {
|
||||||
nn_free(component->address);
|
nn_free(component->address);
|
||||||
if(component->table->destructor != NULL) {
|
if(component->table->destructor != NULL) {
|
||||||
component->table->destructor(component->table->userdata, component->statePtr);
|
component->table->destructor(component->table->userdata, component, component->statePtr);
|
||||||
}
|
}
|
||||||
component->address = NULL; // marks component as freed
|
component->address = NULL; // marks component as freed
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,8 @@ typedef struct nn_computer {
|
|||||||
double temperature;
|
double temperature;
|
||||||
double temperatureCoefficient;
|
double temperatureCoefficient;
|
||||||
double roomTemperature;
|
double roomTemperature;
|
||||||
|
size_t callCost;
|
||||||
|
size_t callBudget;
|
||||||
} nn_computer;
|
} nn_computer;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -4,17 +4,61 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "neonucleus.h"
|
#include "neonucleus.h"
|
||||||
#include "testLuaArch.h"
|
#include "testLuaArch.h"
|
||||||
|
|
||||||
void emulator_debugPrint(void *componentUserdata, void *methodUserdata, nn_component *component, nn_computer *computer) {
|
size_t ne_eeprom_getSize(nn_component *component, void *_) {
|
||||||
nn_value msg = nn_getArgument(computer, 0);
|
return 4096;
|
||||||
const char *m = nn_toCString(msg);
|
|
||||||
printf("[DEBUG] %s\n", m);
|
|
||||||
nn_return(computer, nn_values_integer(strlen(m)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ne_eeprom_getDataSize(nn_component *component, void *_) {
|
||||||
|
return 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ne_eeprom_getLabel(nn_component *component, void *_, char *buf, size_t *buflen) {
|
||||||
|
*buflen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ne_eeprom_setLabel(nn_component *component, void *_, const char *buf, size_t buflen) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *ne_eeprom_location(nn_address address) {
|
||||||
|
static char buffer[256];
|
||||||
|
snprintf(buffer, 256, "data/%s", address);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ne_eeprom_get(nn_component *component, void *_, char *buf) {
|
||||||
|
FILE *f = fopen(ne_eeprom_location(nn_getComponentAddress(component)), "rb");
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
size_t len = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
fread(buf, sizeof(char), len, f);
|
||||||
|
fclose(f);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ne_eeprom_set(nn_component *component, void *_, const char *buf, size_t len) {
|
||||||
|
FILE *f = fopen(ne_eeprom_location(nn_getComponentAddress(component)), "wb");
|
||||||
|
fwrite(buf, sizeof(char), len, f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ne_eeprom_getData(nn_component *component, void *_, char *buf) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ne_eeprom_setData(nn_component *component, void *_, const char *buf, size_t len) {}
|
||||||
|
|
||||||
|
bool ne_eeprom_isReadonly(nn_component *component, void *userdata) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ne_eeprom_makeReadonly(nn_component *component, void *userdata) {}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
printf("Setting up universe\n");
|
printf("Setting up universe\n");
|
||||||
nn_universe *universe = nn_newUniverse();
|
nn_universe *universe = nn_newUniverse();
|
||||||
|
nn_loadCoreComponentTables(universe);
|
||||||
|
|
||||||
nn_architecture *arch = testLuaArch_getArchitecture("src/sandbox.lua");
|
nn_architecture *arch = testLuaArch_getArchitecture("src/sandbox.lua");
|
||||||
assert(arch != NULL && "Loading architecture failed");
|
assert(arch != NULL && "Loading architecture failed");
|
||||||
@ -24,10 +68,23 @@ int main() {
|
|||||||
nn_setEnergyInfo(computer, 5000, 5000);
|
nn_setEnergyInfo(computer, 5000, 5000);
|
||||||
nn_addSupportedArchitecture(computer, arch);
|
nn_addSupportedArchitecture(computer, arch);
|
||||||
|
|
||||||
nn_componentTable *t = nn_newComponentTable("debugPrint", NULL, NULL, NULL);
|
nn_eeprom genericEEPROM = {
|
||||||
nn_defineMethod(t, "log", false, emulator_debugPrint, NULL, "logs stuff");
|
.userdata = NULL,
|
||||||
|
.refc = 1,
|
||||||
|
.deinit = NULL,
|
||||||
|
.getSize = ne_eeprom_getSize,
|
||||||
|
.getDataSize = ne_eeprom_getDataSize,
|
||||||
|
.getLabel = ne_eeprom_getLabel,
|
||||||
|
.setLabel = ne_eeprom_setLabel,
|
||||||
|
.get = ne_eeprom_get,
|
||||||
|
.set = ne_eeprom_set,
|
||||||
|
.getData = ne_eeprom_getData,
|
||||||
|
.setData = ne_eeprom_setData,
|
||||||
|
.isReadonly = ne_eeprom_isReadonly,
|
||||||
|
.makeReadonly = ne_eeprom_makeReadonly,
|
||||||
|
};
|
||||||
|
|
||||||
nn_newComponent(computer, "debugPrint", -1, t, NULL);
|
nn_addEeprom(computer, "luaBios.lua", 0, &genericEEPROM);
|
||||||
|
|
||||||
double lastTime = nn_realTime();
|
double lastTime = nn_realTime();
|
||||||
while(true) {
|
while(true) {
|
||||||
|
@ -13,13 +13,16 @@ nn_guard *nn_newGuard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void nn_lock(nn_guard *guard) {
|
void nn_lock(nn_guard *guard) {
|
||||||
|
if(guard == NULL) return;
|
||||||
mtx_lock(&guard->m);
|
mtx_lock(&guard->m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_unlock(nn_guard *guard) {
|
void nn_unlock(nn_guard *guard) {
|
||||||
|
if(guard == NULL) return;
|
||||||
mtx_unlock(&guard->m);
|
mtx_unlock(&guard->m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_deleteGuard(nn_guard *guard) {
|
void nn_deleteGuard(nn_guard *guard) {
|
||||||
|
if(guard == NULL) return;
|
||||||
mtx_destroy(&guard->m);
|
mtx_destroy(&guard->m);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
// Based off https://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor
|
// Based off https://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor
|
||||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
||||||
@ -58,6 +59,9 @@
|
|||||||
#define NN_MAX_USER_SIZE 128
|
#define NN_MAX_USER_SIZE 128
|
||||||
#define NN_MAX_SIGNAL_SIZE 8192
|
#define NN_MAX_SIGNAL_SIZE 8192
|
||||||
#define NN_OVERHEAT_MIN 100
|
#define NN_OVERHEAT_MIN 100
|
||||||
|
#define NN_CALL_HEAT 0.05
|
||||||
|
#define NN_CALL_COST 1
|
||||||
|
#define NN_LABEL_SIZE 128
|
||||||
|
|
||||||
typedef struct nn_guard nn_guard;
|
typedef struct nn_guard nn_guard;
|
||||||
typedef struct nn_universe nn_universe;
|
typedef struct nn_universe nn_universe;
|
||||||
@ -151,6 +155,7 @@ void nn_setClock(nn_universe *universe, nn_clock_t *clock, void *userdata);
|
|||||||
double nn_getTime(nn_universe *universe);
|
double nn_getTime(nn_universe *universe);
|
||||||
|
|
||||||
nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_architecture *arch, void *userdata, size_t memoryLimit, size_t componentLimit);
|
nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_architecture *arch, void *userdata, size_t memoryLimit, size_t componentLimit);
|
||||||
|
nn_universe *nn_getUniverse(nn_computer *computer);
|
||||||
int nn_tickComputer(nn_computer *computer);
|
int nn_tickComputer(nn_computer *computer);
|
||||||
double nn_getUptime(nn_computer *computer);
|
double nn_getUptime(nn_computer *computer);
|
||||||
size_t nn_getComputerMemoryUsed(nn_computer *computer);
|
size_t nn_getComputerMemoryUsed(nn_computer *computer);
|
||||||
@ -170,6 +175,11 @@ const char *nn_addUser(nn_computer *computer, const char *name);
|
|||||||
void nn_deleteUser(nn_computer *computer, const char *name);
|
void nn_deleteUser(nn_computer *computer, const char *name);
|
||||||
const char *nn_indexUser(nn_computer *computer, size_t idx);
|
const char *nn_indexUser(nn_computer *computer, size_t idx);
|
||||||
bool nn_isUser(nn_computer *computer, const char *name);
|
bool nn_isUser(nn_computer *computer, const char *name);
|
||||||
|
void nn_setCallBudget(nn_computer *computer, size_t callBudget);
|
||||||
|
size_t nn_getCallBudget(nn_computer *computer);
|
||||||
|
void nn_callCost(nn_computer *computer, size_t cost);
|
||||||
|
size_t nn_getCallCost(nn_computer *computer);
|
||||||
|
bool nn_isOverworked(nn_computer *computer);
|
||||||
|
|
||||||
/* The memory returned can be freed with nn_free() */
|
/* The memory returned can be freed with nn_free() */
|
||||||
char *nn_serializeProgram(nn_computer *computer, size_t *len);
|
char *nn_serializeProgram(nn_computer *computer, size_t *len);
|
||||||
@ -259,8 +269,8 @@ nn_component **nn_listComponent(nn_computer *computer, size_t *len);
|
|||||||
|
|
||||||
// Component VTable stuff
|
// Component VTable stuff
|
||||||
|
|
||||||
typedef void *nn_componentConstructor(void *userdata);
|
typedef void *nn_componentConstructor(void *tableUserdata, void *componentUserdata);
|
||||||
typedef void *nn_componentDestructor(void *tableUserdata, void *componentUserdata);
|
typedef void *nn_componentDestructor(void *tableUserdata, nn_component *component, void *componentUserdata);
|
||||||
typedef void nn_componentMethod(void *componentUserdata, void *methodUserdata, nn_component *component, nn_computer *computer);
|
typedef void nn_componentMethod(void *componentUserdata, void *methodUserdata, nn_component *component, nn_computer *computer);
|
||||||
|
|
||||||
nn_componentTable *nn_newComponentTable(const char *typeName, void *userdata, nn_componentConstructor *constructor, nn_componentDestructor *destructor);
|
nn_componentTable *nn_newComponentTable(const char *typeName, void *userdata, nn_componentConstructor *constructor, nn_componentDestructor *destructor);
|
||||||
@ -314,4 +324,34 @@ const char *nn_toString(nn_value val, size_t *len);
|
|||||||
*/
|
*/
|
||||||
size_t nn_measurePacketSize(nn_value *vals, size_t len);
|
size_t nn_measurePacketSize(nn_value *vals, size_t len);
|
||||||
|
|
||||||
|
// COMPONENTS
|
||||||
|
|
||||||
|
/* Loads the vtables for the default implementations of those components */
|
||||||
|
void nn_loadCoreComponentTables(nn_universe *universe);
|
||||||
|
|
||||||
|
// loading each component
|
||||||
|
void nn_loadEepromTable(nn_universe *universe);
|
||||||
|
|
||||||
|
// the helpers
|
||||||
|
|
||||||
|
// EEPROM
|
||||||
|
typedef struct nn_eeprom {
|
||||||
|
void *userdata;
|
||||||
|
atomic_size_t refc;
|
||||||
|
void (*deinit)(nn_component *component, void *userdata);
|
||||||
|
|
||||||
|
// methods
|
||||||
|
size_t (*getSize)(nn_component *component, void *userdata);
|
||||||
|
size_t (*getDataSize)(nn_component *component, void *userdata);
|
||||||
|
void (*getLabel)(nn_component *component, void *userdata, char *buf, size_t *buflen);
|
||||||
|
size_t (*setLabel)(nn_component *component, void *userdata, const char *buf, size_t buflen);
|
||||||
|
size_t (*get)(nn_component *component, void *userdata, char *buf);
|
||||||
|
void (*set)(nn_component *component, void *userdata, const char *buf, size_t len);
|
||||||
|
int (*getData)(nn_component *component, void *userdata, char *buf);
|
||||||
|
void (*setData)(nn_component *component, void *userdata, const char *buf, size_t len);
|
||||||
|
bool (*isReadonly)(nn_component *component, void *userdata);
|
||||||
|
void (*makeReadonly)(nn_component *component, void *userdata);
|
||||||
|
} nn_eeprom;
|
||||||
|
nn_component *nn_addEeprom(nn_computer *computer, nn_address address, int slot, nn_eeprom *eeprom);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,11 +1,35 @@
|
|||||||
print(component.doc("debugPrint", "log"))
|
-- sandbox stuff
|
||||||
print(component.invoke("debugPrint", "log", "Absolute cinema"))
|
|
||||||
|
|
||||||
computer.pushSignal("stuff", 123, "a", false, nil)
|
local clist = component.list
|
||||||
computer.pushSignal("stuf2", 456, "b", true, "shit")
|
function component.list(type, exact)
|
||||||
computer.pushSignal("stuf3", 789, "c", false, -13)
|
local m = clist()
|
||||||
|
if not type then return m end
|
||||||
|
local t = {}
|
||||||
|
for addr, kind in pairs(m) do
|
||||||
|
if exact then
|
||||||
|
if type == kind then
|
||||||
|
t[addr] = kind
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if string.match(kind, type) then
|
||||||
|
t[addr] = kind
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
setmetatable(t, {
|
||||||
|
__call = function()
|
||||||
|
return next(t)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
print(computer.popSignal())
|
for addr, kind in pairs(component.list()) do
|
||||||
print(computer.popSignal())
|
if kind == "eeprom" then
|
||||||
print(computer.popSignal())
|
local data = component.invoke(addr, "get")
|
||||||
print(computer.popSignal())
|
assert(load(data, "=eeprom"))()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
error("no bios")
|
||||||
|
@ -254,10 +254,27 @@ static int testLuaArch_computer_popSignal(lua_State *L) {
|
|||||||
return retc;
|
return retc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int testLuaArch_computer_users(lua_State *L) {
|
||||||
|
nn_computer *c = testLuaArch_getComputer(L);
|
||||||
|
size_t i = 0;
|
||||||
|
while(true) {
|
||||||
|
const char *name = nn_indexUser(c, i);
|
||||||
|
if(name == NULL) break;
|
||||||
|
lua_pushstring(L, name);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
static int testLuaArch_component_list(lua_State *L) {
|
static int testLuaArch_component_list(lua_State *L) {
|
||||||
nn_computer *c = testLuaArch_getComputer(L);
|
nn_computer *c = testLuaArch_getComputer(L);
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
nn_component **components = nn_listComponent(c, &len);
|
nn_component **components = nn_listComponent(c, &len);
|
||||||
|
if(components == NULL) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_pushstring(L, "out of memory");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
lua_createtable(L, 0, len);
|
lua_createtable(L, 0, len);
|
||||||
int list = lua_gettop(L);
|
int list = lua_gettop(L);
|
||||||
for(size_t i = 0; i < len; i++) {
|
for(size_t i = 0; i < len; i++) {
|
||||||
@ -292,6 +309,62 @@ static int testLuaArch_component_doc(lua_State *L) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int testLuaArch_component_fields(lua_State *L) {
|
||||||
|
lua_createtable(L, 0, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int testLuaArch_component_methods(lua_State *L) {
|
||||||
|
nn_computer *c = testLuaArch_getComputer(L);
|
||||||
|
const char *addr = luaL_checkstring(L, 1);
|
||||||
|
nn_component *component = nn_findComponent(c, (char *)addr);
|
||||||
|
if(component == NULL) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_pushstring(L, "no such component");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
nn_componentTable *table = nn_getComponentTable(component);
|
||||||
|
lua_createtable(L, 0, 0);
|
||||||
|
int methods = lua_gettop(L);
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while(true) {
|
||||||
|
bool direct = false;
|
||||||
|
const char *name = nn_getTableMethod(table, i, &direct);
|
||||||
|
if(name == NULL) break;
|
||||||
|
i++;
|
||||||
|
lua_pushboolean(L, direct);
|
||||||
|
lua_setfield(L, methods, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int testLuaArch_component_slot(lua_State *L) {
|
||||||
|
nn_computer *c = testLuaArch_getComputer(L);
|
||||||
|
const char *addr = luaL_checkstring(L, 1);
|
||||||
|
nn_component *component = nn_findComponent(c, (char *)addr);
|
||||||
|
if(component == NULL) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_pushstring(L, "no such component");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
lua_pushinteger(L, nn_getComponentSlot(component));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int testLuaArch_component_type(lua_State *L) {
|
||||||
|
nn_computer *c = testLuaArch_getComputer(L);
|
||||||
|
const char *addr = luaL_checkstring(L, 1);
|
||||||
|
nn_component *component = nn_findComponent(c, (char *)addr);
|
||||||
|
if(component == NULL) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_pushstring(L, "no such component");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
lua_pushstring(L, nn_getComponentType(nn_getComponentTable(component)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int testLuaArch_component_invoke(lua_State *L) {
|
static int testLuaArch_component_invoke(lua_State *L) {
|
||||||
nn_computer *c = testLuaArch_getComputer(L);
|
nn_computer *c = testLuaArch_getComputer(L);
|
||||||
@ -314,6 +387,10 @@ static int testLuaArch_component_invoke(lua_State *L) {
|
|||||||
lua_pushstring(L, "no such method");
|
lua_pushstring(L, "no such method");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
if(nn_getError(c) != NULL) {
|
||||||
|
nn_resetCall(c);
|
||||||
|
luaL_error(L, "%s", nn_getError(c));
|
||||||
|
}
|
||||||
size_t retc = nn_getReturnCount(c);
|
size_t retc = nn_getReturnCount(c);
|
||||||
for(size_t i = 0; i < retc; i++) {
|
for(size_t i = 0; i < retc; i++) {
|
||||||
testLuaArch_pushValue(L, nn_getReturn(c, i));
|
testLuaArch_pushValue(L, nn_getReturn(c, i));
|
||||||
@ -359,6 +436,8 @@ void testLuaArch_loadEnv(lua_State *L) {
|
|||||||
lua_setfield(L, computer, "pushSignal");
|
lua_setfield(L, computer, "pushSignal");
|
||||||
lua_pushcfunction(L, testLuaArch_computer_popSignal);
|
lua_pushcfunction(L, testLuaArch_computer_popSignal);
|
||||||
lua_setfield(L, computer, "popSignal");
|
lua_setfield(L, computer, "popSignal");
|
||||||
|
lua_pushcfunction(L, testLuaArch_computer_users);
|
||||||
|
lua_setfield(L, computer, "users");
|
||||||
lua_setglobal(L, "computer");
|
lua_setglobal(L, "computer");
|
||||||
|
|
||||||
lua_createtable(L, 0, 10);
|
lua_createtable(L, 0, 10);
|
||||||
@ -367,8 +446,16 @@ void testLuaArch_loadEnv(lua_State *L) {
|
|||||||
lua_setfield(L, component, "list");
|
lua_setfield(L, component, "list");
|
||||||
lua_pushcfunction(L, testLuaArch_component_doc);
|
lua_pushcfunction(L, testLuaArch_component_doc);
|
||||||
lua_setfield(L, component, "doc");
|
lua_setfield(L, component, "doc");
|
||||||
|
lua_pushcfunction(L, testLuaArch_component_fields);
|
||||||
|
lua_setfield(L, component, "fields");
|
||||||
|
lua_pushcfunction(L, testLuaArch_component_methods);
|
||||||
|
lua_setfield(L, component, "methods");
|
||||||
lua_pushcfunction(L, testLuaArch_component_invoke);
|
lua_pushcfunction(L, testLuaArch_component_invoke);
|
||||||
lua_setfield(L, component, "invoke");
|
lua_setfield(L, component, "invoke");
|
||||||
|
lua_pushcfunction(L, testLuaArch_component_slot);
|
||||||
|
lua_setfield(L, component, "slot");
|
||||||
|
lua_pushcfunction(L, testLuaArch_component_type);
|
||||||
|
lua_setfield(L, component, "type");
|
||||||
lua_setglobal(L, "component");
|
lua_setglobal(L, "component");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,3 +43,7 @@ void nn_storeUserdata(nn_universe *universe, const char *name, void *data) {
|
|||||||
double nn_getTime(nn_universe *universe) {
|
double nn_getTime(nn_universe *universe) {
|
||||||
return universe->currentClock(universe->clockUserdata);
|
return universe->currentClock(universe->clockUserdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nn_loadCoreComponentTables(nn_universe *universe) {
|
||||||
|
nn_loadEepromTable(universe);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user