mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 09:03:32 +02:00
Compare commits
4 Commits
820e63aa83
...
db064a691e
Author | SHA1 | Date | |
---|---|---|---|
|
db064a691e | ||
|
710ec2103e | ||
|
b30a180c90 | ||
|
2cd485b355 |
2
TODO.md
2
TODO.md
@ -8,12 +8,10 @@
|
||||
|
||||
# Parity with Vanilla OC (only the stuff that makes sense for an emulator)
|
||||
|
||||
- support `rename` in tmpfs
|
||||
- complete the GPU implementation (screen buffers and missing methods)
|
||||
- complete the screen implementation (bunch of missing methods)
|
||||
- `hologram` component
|
||||
- `computer` component
|
||||
- `modem` component
|
||||
- `tunnel` component
|
||||
- `data` component (with error correction codes and maybe synthesizing audio)
|
||||
- `redstone` component
|
||||
|
@ -39,6 +39,7 @@ fn addEngineSources(b: *std.Build, opts: LibBuildOpts) *std.Build.Module {
|
||||
"src/components/gpu.c",
|
||||
"src/components/keyboard.c",
|
||||
"src/components/modem.c",
|
||||
"src/components/loopbackModem.c",
|
||||
},
|
||||
.flags = &.{
|
||||
if(opts.baremetal) "-DNN_BAREMETAL" else "",
|
||||
|
@ -431,6 +431,10 @@ void nni_gpu_maxDepth(nni_gpu *gpu, void *_, nn_component *component, nn_compute
|
||||
nn_return(computer, nn_values_integer(gpu->currentScreen->maxDepth));
|
||||
}
|
||||
|
||||
void nni_gpu_useless(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_return_boolean(computer, true);
|
||||
}
|
||||
|
||||
void nn_loadGraphicsCardTable(nn_universe *universe) {
|
||||
nn_componentTable *gpuTable = nn_newComponentTable(nn_getAllocator(universe), "gpu", NULL, NULL, (nn_componentDestructor *)nni_gpuDeinit);
|
||||
nn_storeUserdata(universe, "NN:GPU", gpuTable);
|
||||
@ -456,6 +460,8 @@ void nn_loadGraphicsCardTable(nn_universe *universe) {
|
||||
nn_defineMethod(gpuTable, "fill", (nn_componentMethod *)nni_gpu_fill, "fill(x: integer, y: integer, w: integer, h: integer, s: string)");
|
||||
nn_defineMethod(gpuTable, "copy", (nn_componentMethod *)nni_gpu_copy, "copy(x: integer, y: integer, w: integer, h: integer, tx: integer, ty: integer) - Copies stuff");
|
||||
nn_defineMethod(gpuTable, "getViewport", (nn_componentMethod *)nni_gpu_getViewport, "getViewport(): integer, integer - Gets the current viewport resolution");
|
||||
|
||||
nn_defineMethod(gpuTable, "freeAllBuffers", (nn_componentMethod *)nni_gpu_useless, "dummy for now");
|
||||
}
|
||||
|
||||
nn_component *nn_addGPU(nn_computer *computer, nn_address address, int slot, nn_gpuControl *control) {
|
||||
|
144
src/components/loopbackModem.c
Normal file
144
src/components/loopbackModem.c
Normal file
@ -0,0 +1,144 @@
|
||||
#include "../neonucleus.h"
|
||||
|
||||
typedef struct nn_modemLoop {
|
||||
nn_Context ctx;
|
||||
nn_debugLoopbackNetworkOpts opts;
|
||||
nn_size_t *openPorts;
|
||||
nn_size_t strength;
|
||||
char wakeup[NN_MAX_WAKEUPMSG];
|
||||
nn_size_t wakeupLen;
|
||||
} nn_modemLoop;
|
||||
|
||||
void nn_loopModem_deinit(nn_modemLoop *loop) {
|
||||
nn_Context ctx = loop->ctx;
|
||||
|
||||
nn_deallocStr(&ctx.allocator, loop->opts.address);
|
||||
nn_dealloc(&ctx.allocator, loop->openPorts, loop->opts.maxOpenPorts * sizeof(nn_size_t));
|
||||
nn_dealloc(&ctx.allocator, loop, sizeof(nn_modemLoop));
|
||||
}
|
||||
|
||||
nn_bool_t nn_loopModem_isOpen(nn_modemLoop *loop, nn_size_t port, nn_errorbuf_t err) {
|
||||
for(nn_size_t i = 0; i < loop->opts.maxOpenPorts; i++) {
|
||||
if(loop->openPorts[i] == port) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nn_bool_t nn_loopModem_open(nn_modemLoop *loop, nn_size_t port, nn_errorbuf_t err) {
|
||||
int slot = -1;
|
||||
for(nn_size_t i = 0; i < loop->opts.maxOpenPorts; i++) {
|
||||
if(loop->openPorts[i] == NN_PORT_CLOSEALL) {
|
||||
slot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(slot == -1) {
|
||||
nn_error_write(err, "too many open ports");
|
||||
return false;
|
||||
}
|
||||
|
||||
loop->openPorts[slot] = port;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nn_bool_t nn_loopModem_close(nn_modemLoop *loop, nn_size_t port, nn_errorbuf_t err) {
|
||||
if(port == NN_PORT_CLOSEALL) {
|
||||
for(nn_size_t i = 0; i < loop->opts.maxOpenPorts; i++) loop->openPorts[i] = NN_PORT_CLOSEALL;
|
||||
return true;
|
||||
}
|
||||
|
||||
for(nn_size_t i = 0; i < loop->opts.maxOpenPorts; i++) {
|
||||
if(loop->openPorts[i] == port) {
|
||||
loop->openPorts[i] = NN_PORT_CLOSEALL;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
nn_error_write(err, "port already closed");
|
||||
return false;
|
||||
}
|
||||
|
||||
nn_size_t nn_loopModem_getPorts(nn_modemLoop *loop, nn_size_t *ports, nn_errorbuf_t err) {
|
||||
nn_size_t len = 0;
|
||||
for(nn_size_t i = 0; i < loop->opts.maxOpenPorts; i++) {
|
||||
if(loop->openPorts[i] != NN_PORT_CLOSEALL) {
|
||||
ports[len] = loop->openPorts[i];
|
||||
len++;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
nn_bool_t nn_loopModem_send(nn_modemLoop *loop, nn_address address, nn_size_t port, nn_value *values, nn_size_t valuec, nn_errorbuf_t err) {
|
||||
if(address == NULL) {
|
||||
// broadcasting, set it to our address
|
||||
address = loop->opts.address;
|
||||
}
|
||||
|
||||
// error is discarded as packet loss
|
||||
nn_pushNetworkMessage(loop->opts.computer, loop->opts.address, address, port, loop->strength, values, valuec);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
double nn_loopModem_getStrength(nn_modemLoop *loop, nn_errorbuf_t err) {
|
||||
return loop->strength;
|
||||
}
|
||||
|
||||
double nn_loopModem_setStrength(nn_modemLoop *loop, double n, nn_errorbuf_t err) {
|
||||
loop->strength = n;
|
||||
return n;
|
||||
}
|
||||
|
||||
nn_size_t nn_loopModem_getWakeMessage(nn_modemLoop *loop, char *msg, nn_errorbuf_t err) {
|
||||
nn_memcpy(msg, loop->wakeup, loop->wakeupLen);
|
||||
return loop->wakeupLen;
|
||||
}
|
||||
|
||||
nn_size_t nn_loopModem_setWakeMessage(nn_modemLoop *loop, const char *msg, nn_size_t msglen, nn_bool_t fuzzy, nn_errorbuf_t err) {
|
||||
loop->wakeupLen = msglen;
|
||||
nn_memcpy(loop->wakeup, msg, loop->wakeupLen);
|
||||
return loop->wakeupLen;
|
||||
}
|
||||
|
||||
nn_modem *nn_debugLoopbackModem(nn_Context *context, nn_debugLoopbackNetworkOpts opts, nn_networkControl control) {
|
||||
opts.address = nn_strdup(&context->allocator, opts.address);
|
||||
nn_modemLoop *m = nn_alloc(&context->allocator, sizeof(nn_modemLoop));
|
||||
m->ctx = *context;
|
||||
m->opts = opts;
|
||||
m->strength = opts.maxStrength;
|
||||
m->wakeupLen = 0;
|
||||
m->openPorts = nn_alloc(&context->allocator, opts.maxOpenPorts * sizeof(nn_size_t));
|
||||
for(nn_size_t i = 0; i < opts.maxOpenPorts; i++) {
|
||||
m->openPorts[i] = NN_PORT_CLOSEALL; // used as a NULL port
|
||||
}
|
||||
nn_modemTable table = {
|
||||
.userdata = m,
|
||||
.deinit = (void *)nn_loopModem_deinit,
|
||||
|
||||
.wireless = opts.isWireless,
|
||||
.maxValues = opts.maxValues,
|
||||
.maxOpenPorts = opts.maxOpenPorts,
|
||||
.maxPacketSize = opts.maxPacketSize,
|
||||
|
||||
.isOpen = (void *)nn_loopModem_isOpen,
|
||||
.open = (void *)nn_loopModem_open,
|
||||
.close = (void *)nn_loopModem_close,
|
||||
.getPorts = (void *)nn_loopModem_getPorts,
|
||||
|
||||
.send = (void *)nn_loopModem_send,
|
||||
|
||||
.maxStrength = opts.maxStrength,
|
||||
.getStrength = (void *)nn_loopModem_getStrength,
|
||||
.setStrength = (void *)nn_loopModem_setStrength,
|
||||
|
||||
.setWakeMessage = (void *)nn_loopModem_setWakeMessage,
|
||||
.getWakeMessage = (void *)nn_loopModem_getWakeMessage,
|
||||
};
|
||||
return nn_newModem(context, table, control);
|
||||
}
|
@ -44,9 +44,305 @@ void nn_modem_destroy(void *_, nn_component *component, nn_modem *modem) {
|
||||
nn_destroyModem(modem);
|
||||
}
|
||||
|
||||
static void nni_modem_isWireless(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_return_boolean(computer, modem->table.wireless);
|
||||
}
|
||||
|
||||
static void nni_modem_maxPacketSize(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_return_integer(computer, modem->table.maxPacketSize);
|
||||
}
|
||||
|
||||
static void nni_modem_maxOpenPorts(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_return_integer(computer, modem->table.maxOpenPorts);
|
||||
}
|
||||
|
||||
static void nni_modem_maxValues(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_return_integer(computer, modem->table.maxValues);
|
||||
}
|
||||
|
||||
static nn_bool_t nni_modem_wirelessOnly(nn_modem *modem, void *_) {
|
||||
return modem->table.wireless;
|
||||
}
|
||||
|
||||
static void nni_modem_maxStrength(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_return_number(computer, modem->table.maxStrength);
|
||||
}
|
||||
|
||||
static void nni_modem_getStrength(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_errorbuf_t err = "";
|
||||
|
||||
nn_lock(&modem->ctx, modem->lock);
|
||||
double n = modem->table.getStrength(modem->table.userdata, err);
|
||||
nn_unlock(&modem->ctx, modem->lock);
|
||||
|
||||
if(!nn_error_isEmpty(err)) {
|
||||
nn_setError(computer, err);
|
||||
return;
|
||||
}
|
||||
|
||||
nn_return_number(computer, n);
|
||||
}
|
||||
|
||||
static void nni_modem_setStrength(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
double n = nn_toNumber(nn_getArgument(computer, 0));
|
||||
|
||||
if(n < 0) n = 0;
|
||||
if(n > modem->table.maxStrength) n = modem->table.maxStrength;
|
||||
|
||||
nn_errorbuf_t err = "";
|
||||
|
||||
nn_lock(&modem->ctx, modem->lock);
|
||||
n = modem->table.setStrength(modem->table.userdata, n, err);
|
||||
nn_unlock(&modem->ctx, modem->lock);
|
||||
|
||||
if(!nn_error_isEmpty(err)) {
|
||||
nn_setError(computer, err);
|
||||
return;
|
||||
}
|
||||
|
||||
nn_return_number(computer, n);
|
||||
}
|
||||
|
||||
static nn_bool_t nni_modem_validSendPort(nn_intptr_t port) {
|
||||
// 9 quintillion ports just died
|
||||
if(port < 0) return false;
|
||||
// the only valid range
|
||||
if(port > NN_PORT_MAX) return false;
|
||||
if(port < 1) return false;
|
||||
// whichever it is reserved as (clean code moment)
|
||||
if(port == NN_TUNNEL_PORT) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nni_modem_isOpen(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_intptr_t port = nn_toInt(nn_getArgument(computer, 0));
|
||||
if(!nni_modem_validSendPort(port)) {
|
||||
nn_setCError(computer, "invalid port");
|
||||
return;
|
||||
}
|
||||
nn_errorbuf_t err = "";
|
||||
nn_lock(&modem->ctx, modem->lock);
|
||||
nn_bool_t res = modem->table.isOpen(modem->table.userdata, port, err);
|
||||
nn_unlock(&modem->ctx, modem->lock);
|
||||
if(!nn_error_isEmpty(err)) {
|
||||
nn_setError(computer, err);
|
||||
return;
|
||||
}
|
||||
nn_return_boolean(computer, res);
|
||||
}
|
||||
|
||||
static void nni_modem_open(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_intptr_t port = nn_toInt(nn_getArgument(computer, 0));
|
||||
if(!nni_modem_validSendPort(port)) {
|
||||
nn_setCError(computer, "invalid port");
|
||||
return;
|
||||
}
|
||||
nn_errorbuf_t err = "";
|
||||
nn_lock(&modem->ctx, modem->lock);
|
||||
nn_bool_t res = modem->table.open(modem->table.userdata, port, err);
|
||||
nn_unlock(&modem->ctx, modem->lock);
|
||||
if(!nn_error_isEmpty(err)) {
|
||||
nn_setError(computer, err);
|
||||
return;
|
||||
}
|
||||
nn_return_boolean(computer, res);
|
||||
}
|
||||
|
||||
static void nni_modem_close(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_value portVal = nn_getArgument(computer, 0);
|
||||
nn_intptr_t port = portVal.tag == NN_VALUE_NIL ? NN_PORT_CLOSEALL : nn_toInt(portVal);
|
||||
if(!nni_modem_validSendPort(port) && port != NN_PORT_CLOSEALL) {
|
||||
nn_setCError(computer, "invalid port");
|
||||
return;
|
||||
}
|
||||
nn_errorbuf_t err = "";
|
||||
nn_lock(&modem->ctx, modem->lock);
|
||||
nn_bool_t res = modem->table.close(modem->table.userdata, port, err);
|
||||
nn_unlock(&modem->ctx, modem->lock);
|
||||
if(!nn_error_isEmpty(err)) {
|
||||
nn_setError(computer, err);
|
||||
return;
|
||||
}
|
||||
nn_return_boolean(computer, res);
|
||||
}
|
||||
|
||||
static void nni_modem_getPorts(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_size_t ports[modem->table.maxOpenPorts];
|
||||
nn_errorbuf_t err = "";
|
||||
nn_lock(&modem->ctx, modem->lock);
|
||||
nn_size_t portCount = modem->table.getPorts(modem->table.userdata, ports, err);
|
||||
nn_unlock(&modem->ctx, modem->lock);
|
||||
if(!nn_error_isEmpty(err)) {
|
||||
nn_setError(computer, err);
|
||||
return;
|
||||
}
|
||||
|
||||
nn_value arr = nn_return_array(computer, portCount);
|
||||
for(nn_size_t i = 0; i < portCount; i++) {
|
||||
nn_values_set(arr, i, nn_values_integer(ports[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static void nni_modem_send(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
// we pinky promise it won't do a fucky wucky
|
||||
nn_address addr = (nn_address)nn_toCString(nn_getArgument(computer, 0));
|
||||
if(addr == NULL) {
|
||||
nn_setCError(computer, "invalid address");
|
||||
return;
|
||||
}
|
||||
nn_value portVal = nn_getArgument(computer, 1);
|
||||
nn_intptr_t port = portVal.tag == NN_VALUE_NIL ? NN_PORT_CLOSEALL : nn_toInt(portVal);
|
||||
if(!nni_modem_validSendPort(port) && port != NN_PORT_CLOSEALL) {
|
||||
nn_setCError(computer, "invalid port");
|
||||
return;
|
||||
}
|
||||
nn_value vals[modem->table.maxValues];
|
||||
nn_size_t valLen = nn_getArgumentCount(computer) - 2;
|
||||
|
||||
if(valLen > modem->table.maxValues) {
|
||||
nn_setCError(computer, "too many values");
|
||||
return;
|
||||
}
|
||||
|
||||
for(nn_size_t i = 0; i < valLen; i++) {
|
||||
vals[i] = nn_getArgument(computer, i + 2);
|
||||
}
|
||||
|
||||
nn_size_t bytesSent = nn_measurePacketSize(vals, valLen);
|
||||
if(bytesSent > modem->table.maxPacketSize) {
|
||||
nn_setCError(computer, "packet too big");
|
||||
return;
|
||||
}
|
||||
nn_simulateBufferedIndirect(component, bytesSent, modem->ctrl.packetBytesPerTick);
|
||||
double d = (double)bytesSent / modem->table.maxPacketSize;
|
||||
nn_addHeat(computer, d * modem->ctrl.heatPerFullPacket);
|
||||
nn_removeEnergy(computer, d * modem->ctrl.energyPerFullPacket);
|
||||
|
||||
nn_errorbuf_t err = "";
|
||||
nn_lock(&modem->ctx, modem->lock);
|
||||
nn_bool_t res = modem->table.send(modem->table.userdata, addr, port, vals, valLen, err);
|
||||
nn_unlock(&modem->ctx, modem->lock);
|
||||
if(!nn_error_isEmpty(err)) {
|
||||
nn_setError(computer, err);
|
||||
return;
|
||||
}
|
||||
|
||||
nn_return_boolean(computer, res);
|
||||
}
|
||||
|
||||
static void nni_modem_broadcast(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_value portVal = nn_getArgument(computer, 0);
|
||||
nn_intptr_t port = portVal.tag == NN_VALUE_NIL ? NN_PORT_CLOSEALL : nn_toInt(portVal);
|
||||
if(!nni_modem_validSendPort(port) && port != NN_PORT_CLOSEALL) {
|
||||
nn_setCError(computer, "invalid port");
|
||||
return;
|
||||
}
|
||||
nn_value vals[modem->table.maxValues];
|
||||
nn_size_t valLen = nn_getArgumentCount(computer) - 1;
|
||||
|
||||
if(valLen > modem->table.maxValues) {
|
||||
nn_setCError(computer, "too many values");
|
||||
return;
|
||||
}
|
||||
|
||||
for(nn_size_t i = 0; i < valLen; i++) {
|
||||
vals[i] = nn_getArgument(computer, i + 1);
|
||||
}
|
||||
|
||||
nn_size_t bytesSent = nn_measurePacketSize(vals, valLen);
|
||||
if(bytesSent > modem->table.maxPacketSize) {
|
||||
nn_setCError(computer, "packet too big");
|
||||
return;
|
||||
}
|
||||
nn_simulateBufferedIndirect(component, bytesSent, modem->ctrl.packetBytesPerTick);
|
||||
double d = (double)bytesSent / modem->table.maxPacketSize;
|
||||
nn_addHeat(computer, d * modem->ctrl.heatPerFullPacket);
|
||||
nn_removeEnergy(computer, d * modem->ctrl.energyPerFullPacket);
|
||||
|
||||
nn_errorbuf_t err = "";
|
||||
nn_lock(&modem->ctx, modem->lock);
|
||||
nn_bool_t res = modem->table.send(modem->table.userdata, NULL, port, vals, valLen, err);
|
||||
nn_unlock(&modem->ctx, modem->lock);
|
||||
if(!nn_error_isEmpty(err)) {
|
||||
nn_setError(computer, err);
|
||||
return;
|
||||
}
|
||||
|
||||
nn_return_boolean(computer, res);
|
||||
}
|
||||
|
||||
static void nni_modem_getWake(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
char msg[NN_MAX_WAKEUPMSG];
|
||||
nn_errorbuf_t err = "";
|
||||
|
||||
nn_lock(&modem->ctx, modem->lock);
|
||||
nn_size_t len = modem->table.getWakeMessage(modem->table.userdata, msg, err);
|
||||
nn_unlock(&modem->ctx, modem->lock);
|
||||
|
||||
if(!nn_error_isEmpty(err)) {
|
||||
nn_setError(computer, err);
|
||||
return;
|
||||
}
|
||||
|
||||
nn_return_string(computer, msg, len);
|
||||
}
|
||||
|
||||
static void nni_modem_setWake(nn_modem *modem, void *_, nn_component *component, nn_computer *computer) {
|
||||
nn_size_t buflen;
|
||||
const char *buf = nn_toString(nn_getArgument(computer, 0), &buflen);
|
||||
|
||||
if(buf == NULL) {
|
||||
nn_setCError(computer, "invalid wake message");
|
||||
return;
|
||||
}
|
||||
|
||||
if(buflen > NN_MAX_WAKEUPMSG) {
|
||||
buflen = NN_MAX_WAKEUPMSG;
|
||||
}
|
||||
|
||||
nn_bool_t fuzzy = nn_toBoolean(nn_getArgument(computer, 1)); // nil is false
|
||||
|
||||
nn_errorbuf_t err = "";
|
||||
|
||||
nn_lock(&modem->ctx, modem->lock);
|
||||
buflen = modem->table.setWakeMessage(modem->table.userdata, buf, buflen, fuzzy, err);
|
||||
nn_unlock(&modem->ctx, modem->lock);
|
||||
|
||||
if(!nn_error_isEmpty(err)) {
|
||||
nn_setError(computer, err);
|
||||
return;
|
||||
}
|
||||
|
||||
nn_return_string(computer, buf, buflen);
|
||||
}
|
||||
|
||||
void nn_loadModemTable(nn_universe *universe) {
|
||||
nn_componentTable *modemTable = nn_newComponentTable(nn_getAllocator(universe), "modem", NULL, NULL, (nn_componentDestructor *)nn_modem_destroy);
|
||||
nn_storeUserdata(universe, "NN:MODEM", modemTable);
|
||||
|
||||
nn_method_t *method;
|
||||
nn_defineMethod(modemTable, "isWireless", (nn_componentMethod *)nni_modem_isWireless, "isWireless(): boolean - Returns whether this modem has wireless capabilities");
|
||||
nn_defineMethod(modemTable, "maxPacketSize", (nn_componentMethod *)nni_modem_maxPacketSize, "maxPacketSize(): integer - Returns the maximum size of a packet");
|
||||
nn_defineMethod(modemTable, "maxOpenPorts", (nn_componentMethod *)nni_modem_maxOpenPorts, "maxOpenPorts(): integer - Returns the maximum number of ports that can be open at the same time");
|
||||
nn_defineMethod(modemTable, "maxValues", (nn_componentMethod *)nni_modem_maxValues, "maxValues(): integer - Returns the maximum number of values which can be sent in a packet");
|
||||
nn_defineMethod(modemTable, "isOpen", (nn_componentMethod *)nni_modem_isOpen, "isOpen(port: integer): boolean - Returns whether a port is open (allows receiving)");
|
||||
nn_defineMethod(modemTable, "open", (nn_componentMethod *)nni_modem_open, "open(port: integer): boolean - Opens a port, returns whether it was successful");
|
||||
nn_defineMethod(modemTable, "close", (nn_componentMethod *)nni_modem_close, "close([port: integer]): boolean - Closes a port, or nil for all ports");
|
||||
nn_defineMethod(modemTable, "getPorts", (nn_componentMethod *)nni_modem_getPorts, "close([port: integer]): boolean - Closes a port, or nil for all ports");
|
||||
nn_defineMethod(modemTable, "send", (nn_componentMethod *)nni_modem_send, "send(address: string, port: integer, ...): boolean - Sends a message to the specified address at the given port. It returns whether the message was sent, not received");
|
||||
nn_defineMethod(modemTable, "broadcast", (nn_componentMethod *)nni_modem_broadcast, "broadcast(port: integer, ...): boolean - Broadcasts a message at the given port. It returns whether the message was sent, not received");
|
||||
nn_defineMethod(modemTable, "setWakeMessage", (nn_componentMethod *)nni_modem_setWake, "setWakeMessage(msg: string[, fuzzy: boolean]): string - Sets the wake-up message. This will be compared with the first value of modem messages to turn on computers. Set it to nothing to disable this functionality.");
|
||||
nn_defineMethod(modemTable, "getWakeMessage", (nn_componentMethod *)nni_modem_getWake, "getWakeMessage(): string - Returns the current wake-up message");
|
||||
|
||||
// wireless stuff
|
||||
method = nn_defineMethod(modemTable, "maxStrength", (nn_componentMethod *)nni_modem_maxStrength, "maxStrength(): number - Returns the maximum strength of the device");
|
||||
nn_method_setCondition(method, (nn_componentMethodCondition_t *)nni_modem_wirelessOnly);
|
||||
|
||||
method = nn_defineMethod(modemTable, "getStrength", (nn_componentMethod *)nni_modem_getStrength, "getStrength(): number - Returns the current strength of the device");
|
||||
nn_method_setCondition(method, (nn_componentMethodCondition_t *)nni_modem_wirelessOnly);
|
||||
|
||||
method = nn_defineMethod(modemTable, "setStrength", (nn_componentMethod *)nni_modem_setStrength, "setStrength(value: number): number - Returns the current strength of the device");
|
||||
nn_method_setCondition(method, (nn_componentMethodCondition_t *)nni_modem_wirelessOnly);
|
||||
}
|
||||
|
||||
nn_component *nn_addModem(nn_computer *computer, nn_address address, int slot, nn_modem *modem) {
|
||||
|
@ -206,6 +206,26 @@ nn_bool_t nn_vf_treeHasHandles(nn_vfnode *node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void nn_vf_appendNode(nn_vfnode *parent, nn_vfnode *node) {
|
||||
if(!parent->isDirectory) return;
|
||||
if(parent->len == parent->cap) return;
|
||||
parent->entries[parent->len] = node;
|
||||
parent->len++;
|
||||
node->parent = parent; // just to be sure
|
||||
}
|
||||
|
||||
void nn_vf_removeNode(nn_vfnode *parent, nn_vfnode *node) {
|
||||
if(!parent->isDirectory) return;
|
||||
nn_size_t j = 0;
|
||||
for(nn_size_t i = 0; i < parent->len; i++) {
|
||||
if(parent->entries[i] != node) {
|
||||
parent->entries[j] = parent->entries[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
parent->len = j;
|
||||
}
|
||||
|
||||
// methods
|
||||
|
||||
void nn_vfs_deinit(nn_vfilesystem *fs) {
|
||||
@ -261,14 +281,7 @@ nn_size_t nn_vfs_remove(nn_vfilesystem *fs, const char *path, nn_errorbuf_t err)
|
||||
}
|
||||
nn_size_t removed = nn_vf_countTree(node);
|
||||
// it is super easy to delete a tree
|
||||
nn_size_t j = 0;
|
||||
for(nn_size_t i = 0; i < parent->len; i++) {
|
||||
if(parent->entries[i] != node) {
|
||||
parent->entries[j] = parent->entries[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
parent->len = j;
|
||||
nn_vf_removeNode(parent, node);
|
||||
parent->lastModified = nn_vf_now(fs);
|
||||
nn_vf_freeNode(node);
|
||||
return removed;
|
||||
@ -286,7 +299,48 @@ nn_size_t nn_vfs_lastModified(nn_vfilesystem *fs, const char *path, nn_errorbuf_
|
||||
nn_size_t nn_vfs_rename(nn_vfilesystem *fs, const char *from, const char *to, nn_errorbuf_t err) {
|
||||
// TODO: implement rename
|
||||
nn_error_write(err, "Unsupported operation");
|
||||
nn_vfnode *srcNode = nn_vf_resolvePath(fs, from);
|
||||
if(srcNode == NULL) {
|
||||
nn_error_write(err, "No such file");
|
||||
return 0;
|
||||
}
|
||||
nn_vfnode *srcParent = srcNode->parent;
|
||||
if(srcParent == NULL) {
|
||||
// root, can't move
|
||||
nn_error_write(err, "Unable to move root");
|
||||
return 0;
|
||||
}
|
||||
if(nn_vf_treeHasHandles(srcNode)) {
|
||||
nn_error_write(err, "Files are pinned by handles");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char name[NN_MAX_PATH];
|
||||
char parentPath[NN_MAX_PATH];
|
||||
nn_bool_t rootOut = nn_path_lastName(to, name, parentPath);
|
||||
nn_vfnode *destParent = rootOut ? fs->root : nn_vf_resolvePath(fs, parentPath);
|
||||
if(destParent == NULL) {
|
||||
nn_error_write(err, "No such directory");
|
||||
return 0;
|
||||
}
|
||||
if(!destParent->isDirectory) {
|
||||
nn_error_write(err, "Is a file");
|
||||
return 0;
|
||||
}
|
||||
if(nn_vf_find(destParent, name) != NULL) {
|
||||
nn_error_write(err, "Already exists");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(destParent->len == destParent->cap) {
|
||||
nn_error_write(err, "Too many entries");
|
||||
return 0;
|
||||
}
|
||||
nn_size_t moved = nn_vf_countTree(srcNode);
|
||||
// super efficient moving
|
||||
nn_vf_removeNode(srcParent, srcNode);
|
||||
nn_vf_appendNode(destParent, srcNode);
|
||||
return moved;
|
||||
}
|
||||
|
||||
nn_bool_t nn_vfs_exists(nn_vfilesystem *fs, const char *path, nn_errorbuf_t err) {
|
||||
|
@ -154,13 +154,11 @@ nn_bool_t ne_eeprom_set(void *addr, const char *buf, size_t len, nn_errorbuf_t e
|
||||
}
|
||||
|
||||
nn_size_t ne_eeprom_getData(void *_, char *buf, nn_errorbuf_t err) {
|
||||
nn_error_write(err, "unsupported");
|
||||
return 0;
|
||||
}
|
||||
|
||||
nn_bool_t ne_eeprom_setData(void *_, const char *buf, size_t len, nn_errorbuf_t err) {
|
||||
nn_error_write(err, "unsupported");
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
nn_bool_t ne_eeprom_isReadonly(void *userdata, nn_errorbuf_t err) {
|
||||
@ -708,7 +706,7 @@ int main() {
|
||||
nn_drive *genericDrive = nn_volatileDrive(&ctx, vdriveOpts, vdriveCtrl);
|
||||
nn_addDrive(computer, NULL, 4, genericDrive);
|
||||
|
||||
int maxWidth = 80, maxHeight = 32;
|
||||
int maxWidth = 160, maxHeight = 48;
|
||||
|
||||
nn_screen *s = nn_newScreen(&ctx, maxWidth, maxHeight, 24, 16, 256);
|
||||
nn_setDepth(s, 4); // looks cool
|
||||
@ -725,9 +723,9 @@ int main() {
|
||||
.screenSetsPerTick = 32,
|
||||
.screenColorChangesPerTick = 64,
|
||||
|
||||
.heatPerPixelChange = 0.0005,
|
||||
.heatPerPixelReset = 0.0001,
|
||||
.heatPerVRAMChange = 0.000015,
|
||||
.heatPerPixelChange = 0.00005,
|
||||
.heatPerPixelReset = 0.00001,
|
||||
.heatPerVRAMChange = 0.00000015,
|
||||
|
||||
.energyPerPixelChange = 0.05,
|
||||
.energyPerPixelReset = 0.01,
|
||||
@ -736,6 +734,28 @@ int main() {
|
||||
|
||||
nn_addGPU(computer, NULL, 3, &gpuCtrl);
|
||||
|
||||
nn_networkControl modemCtrl = {
|
||||
.energyPerFullPacket = 5,
|
||||
.heatPerFullPacket = 8,
|
||||
.packetBytesPerTick = 16384,
|
||||
};
|
||||
|
||||
nn_address networkAddr = "lan";
|
||||
|
||||
nn_debugLoopbackNetworkOpts opts = {
|
||||
.isWireless = true,
|
||||
.maxPacketSize = 8192,
|
||||
.maxOpenPorts = 16,
|
||||
.maxValues = 8,
|
||||
.maxStrength = 400,
|
||||
.computer = computer,
|
||||
.address = networkAddr,
|
||||
};
|
||||
|
||||
nn_modem *modem = nn_debugLoopbackModem(&ctx, opts, modemCtrl);
|
||||
|
||||
nn_addModem(computer, networkAddr, 12, modem);
|
||||
|
||||
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
||||
InitWindow(800, 600, "emulator");
|
||||
|
||||
@ -896,16 +916,6 @@ render:
|
||||
}
|
||||
}
|
||||
|
||||
Color heatColor = GREEN;
|
||||
if(heat > 60) heatColor = YELLOW;
|
||||
if(heat > 80) heatColor = RED;
|
||||
|
||||
size_t memUsage = nn_getComputerMemoryUsed(computer);
|
||||
size_t memTotal = nn_getComputerMemoryTotal(computer);
|
||||
|
||||
DrawText(TextFormat("Heat: %.02lf Memory Used: %.2lf%%", heat, (double)memUsage / memTotal * 100), 10, GetScreenHeight() - 30, 20, heatColor);
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
|
@ -118,6 +118,7 @@ extern "C" {
|
||||
#define NN_MAX_WAKEUPMSG 2048
|
||||
#define NN_MAX_CHANNEL_SIZE 256
|
||||
#define NN_TUNNEL_PORT 0
|
||||
#define NN_PORT_CLOSEALL 0
|
||||
|
||||
#define NN_OVERHEAT_MIN 100
|
||||
#define NN_CALL_HEAT 0.05
|
||||
@ -920,8 +921,9 @@ typedef struct nn_modemTable {
|
||||
|
||||
nn_bool_t (*isOpen)(void *userdata, nn_size_t port, nn_errorbuf_t err);
|
||||
nn_bool_t (*open)(void *userdata, nn_size_t port, nn_errorbuf_t err);
|
||||
// port NN_TUNNEL_PORT means close all
|
||||
// port NN_PORT_CLOSEALL means close all
|
||||
nn_bool_t (*close)(void *userdata, nn_size_t port, nn_errorbuf_t err);
|
||||
nn_size_t (*getPorts)(void *userdata, nn_size_t *ports, nn_errorbuf_t err);
|
||||
|
||||
// messages
|
||||
|
||||
@ -929,13 +931,13 @@ typedef struct nn_modemTable {
|
||||
nn_bool_t (*send)(void *userdata, nn_address address, nn_size_t port, nn_value *values, nn_size_t valueCount, nn_errorbuf_t err);
|
||||
|
||||
// signal strength
|
||||
nn_size_t maxStrength;
|
||||
nn_size_t (*getStrength)(void *userdata, nn_errorbuf_t err);
|
||||
nn_bool_t (*setStrength)(void *userdata, nn_size_t strength, nn_errorbuf_t err);
|
||||
double maxStrength;
|
||||
double (*getStrength)(void *userdata, nn_errorbuf_t err);
|
||||
double (*setStrength)(void *userdata, double strength, nn_errorbuf_t err);
|
||||
|
||||
// wake message
|
||||
void (*getWakeMessage)(void *userdata, char *buf, nn_size_t *buflen);
|
||||
nn_size_t (*setWakeMessage)(void *userdata, const char *buf, nn_size_t buflen, nn_bool_t fuzzy);
|
||||
nn_size_t (*getWakeMessage)(void *userdata, char *buf, nn_errorbuf_t err);
|
||||
nn_size_t (*setWakeMessage)(void *userdata, const char *buf, nn_size_t buflen, nn_bool_t fuzzy, nn_errorbuf_t err);
|
||||
} nn_modemTable;
|
||||
|
||||
typedef struct nn_modem nn_modem;
|
||||
@ -945,11 +947,13 @@ typedef struct nn_debugLoopbackNetworkOpts {
|
||||
nn_address address;
|
||||
nn_size_t maxValues;
|
||||
nn_size_t maxPacketSize;
|
||||
nn_size_t maxOpenPorts;
|
||||
double maxStrength;
|
||||
nn_bool_t isWireless;
|
||||
} nn_debugLoopbackNetworkOpts;
|
||||
|
||||
nn_modem *nn_newModem(nn_Context *context, nn_modemTable table, nn_networkControl control);
|
||||
nn_modem *nn_debugLoopbackModem(nn_Context *context, nn_modemTable table, nn_networkControl control);
|
||||
nn_modem *nn_debugLoopbackModem(nn_Context *context, nn_debugLoopbackNetworkOpts opts, nn_networkControl control);
|
||||
nn_guard *nn_getModemLock(nn_modem *modem);
|
||||
void nn_retainModem(nn_modem *modem);
|
||||
nn_bool_t nn_destroyModem(nn_modem *modem);
|
||||
|
Loading…
x
Reference in New Issue
Block a user