initial work on modems
This commit is contained in:
218
src/neonucleus.c
218
src/neonucleus.c
@@ -1023,6 +1023,7 @@ typedef struct nn_Signal {
|
|||||||
typedef struct nn_Computer {
|
typedef struct nn_Computer {
|
||||||
nn_ComputerState state;
|
nn_ComputerState state;
|
||||||
nn_Universe *universe;
|
nn_Universe *universe;
|
||||||
|
nn_Lock *lock;
|
||||||
void *userdata;
|
void *userdata;
|
||||||
char *address;
|
char *address;
|
||||||
char *tmpaddress;
|
char *tmpaddress;
|
||||||
@@ -1126,8 +1127,15 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char
|
|||||||
c->universe = universe;
|
c->universe = universe;
|
||||||
c->userdata = userdata;
|
c->userdata = userdata;
|
||||||
|
|
||||||
|
c->lock = nn_createLock(ctx);
|
||||||
|
if(c->lock == NULL) {
|
||||||
|
nn_free(ctx, c, sizeof(nn_Computer));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
c->address = nn_strdup(ctx, address);
|
c->address = nn_strdup(ctx, address);
|
||||||
if(c->address == NULL) {
|
if(c->address == NULL) {
|
||||||
|
nn_destroyLock(ctx, c->lock);
|
||||||
nn_free(ctx, c, sizeof(nn_Computer));
|
nn_free(ctx, c, sizeof(nn_Computer));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1142,6 +1150,7 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char
|
|||||||
c->callBudget = c->totalCallBudget;
|
c->callBudget = c->totalCallBudget;
|
||||||
|
|
||||||
if(nn_hashInit(&c->components, maxComponents, ctx, &nn_componentHasher)) {
|
if(nn_hashInit(&c->components, maxComponents, ctx, &nn_componentHasher)) {
|
||||||
|
nn_destroyLock(ctx, c->lock);
|
||||||
nn_strfree(ctx, c->address);
|
nn_strfree(ctx, c->address);
|
||||||
nn_free(ctx, c, sizeof(nn_Computer));
|
nn_free(ctx, c, sizeof(nn_Computer));
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1163,6 +1172,14 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nn_lockComputer(nn_Computer *computer) {
|
||||||
|
nn_lock(&computer->universe->ctx, computer->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_unlockComputer(nn_Computer *computer) {
|
||||||
|
nn_unlock(&computer->universe->ctx, computer->lock);
|
||||||
|
}
|
||||||
|
|
||||||
static void nn_dropValue(nn_Value val);
|
static void nn_dropValue(nn_Value val);
|
||||||
|
|
||||||
static nn_ComponentEntry *nn_getInternalComponent(nn_Computer *computer, const char *address) {
|
static nn_ComponentEntry *nn_getInternalComponent(nn_Computer *computer, const char *address) {
|
||||||
@@ -1195,9 +1212,6 @@ void nn_destroyComputer(nn_Computer *computer) {
|
|||||||
nn_dropValue(computer->callstack[i]);
|
nn_dropValue(computer->callstack[i]);
|
||||||
}
|
}
|
||||||
for(nn_ComponentEntry *c = nn_hashIterate(&computer->components, NULL); c != NULL; c = nn_hashIterate(&computer->components, c)) {
|
for(nn_ComponentEntry *c = nn_hashIterate(&computer->components, NULL); c != NULL; c = nn_hashIterate(&computer->components, c)) {
|
||||||
if(c->slot >= 0 || (computer->tmpaddress != NULL && nn_strcmp(computer->tmpaddress, c->address))) {
|
|
||||||
nn_signalComponent(c->comp, computer, NN_CSIGRESET);
|
|
||||||
}
|
|
||||||
nn_dropComponent(c->comp);
|
nn_dropComponent(c->comp);
|
||||||
}
|
}
|
||||||
for(size_t i = 0; i < computer->signalCount; i++) {
|
for(size_t i = 0; i < computer->signalCount; i++) {
|
||||||
@@ -1800,6 +1814,7 @@ nn_Exit nn_mountComponent(nn_Computer *c, nn_Component *comp, int slot) {
|
|||||||
};
|
};
|
||||||
if(!nn_hashPut(&c->components, &ent)) return NN_ELIMIT;
|
if(!nn_hashPut(&c->components, &ent)) return NN_ELIMIT;
|
||||||
nn_retainComponent(comp);
|
nn_retainComponent(comp);
|
||||||
|
nn_signalComponent(comp, c, NN_CSIGMOUNTED);
|
||||||
if(c->state == NN_RUNNING) {
|
if(c->state == NN_RUNNING) {
|
||||||
return nn_pushComponentAdded(c, comp->address, comp->type);
|
return nn_pushComponentAdded(c, comp->address, comp->type);
|
||||||
}
|
}
|
||||||
@@ -1816,6 +1831,7 @@ nn_Exit nn_unmountComponent(nn_Computer *c, const char *address) {
|
|||||||
if(c->state == NN_RUNNING) {
|
if(c->state == NN_RUNNING) {
|
||||||
e = nn_pushComponentRemoved(c, address, comp->type);
|
e = nn_pushComponentRemoved(c, address, comp->type);
|
||||||
}
|
}
|
||||||
|
nn_signalComponent(comp, c, NN_CSIGUNMOUNTED);
|
||||||
nn_dropComponent(comp);
|
nn_dropComponent(comp);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -4757,41 +4773,39 @@ nn_Component *nn_createScreen(
|
|||||||
const nn_Method methods[NN_SCRNUM_COUNT] = {
|
const nn_Method methods[NN_SCRNUM_COUNT] = {
|
||||||
[NN_SCRNUM_ISON] = {
|
[NN_SCRNUM_ISON] = {
|
||||||
"isOn",
|
"isOn",
|
||||||
"function():boolean -- Screen powered?",
|
"function(): boolean - Returns whether the screen is on",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_SCRNUM_TURNON] = {
|
[NN_SCRNUM_TURNON] = {
|
||||||
"turnOn",
|
"turnOn",
|
||||||
"function():boolean,boolean -- Turn on",
|
"function(): boolean, boolean - Turn on",
|
||||||
NN_INDIRECT},
|
NN_INDIRECT},
|
||||||
[NN_SCRNUM_TURNOFF] = {
|
[NN_SCRNUM_TURNOFF] = {
|
||||||
"turnOff",
|
"turnOff",
|
||||||
"function():boolean,boolean -- Turn off",
|
"function(): boolean, boolean - Turn off",
|
||||||
NN_INDIRECT},
|
NN_INDIRECT},
|
||||||
[NN_SCRNUM_GETASPECTRATIO] = {
|
[NN_SCRNUM_GETASPECTRATIO] = {
|
||||||
"getAspectRatio",
|
"getAspectRatio",
|
||||||
"function():number,number -- Block ratio",
|
"function(): integer, integer - Block ratio",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_SCRNUM_GETKEYBOARDS] = {
|
[NN_SCRNUM_GETKEYBOARDS] = {
|
||||||
"getKeyboards",
|
"getKeyboards",
|
||||||
"function():table -- Attached keyboards",
|
"function(): string[] - Gets the keyboards attached to the screen",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_SCRNUM_SETPRECISE] = {
|
[NN_SCRNUM_SETPRECISE] = {
|
||||||
"setPrecise",
|
"setPrecise",
|
||||||
"function(on:boolean):boolean"
|
"function(on: boolean): boolean - Enable/disable high-precision mouse events",
|
||||||
" -- High-precision mouse",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_SCRNUM_ISPRECISE] = {
|
[NN_SCRNUM_ISPRECISE] = {
|
||||||
"isPrecise",
|
"isPrecise",
|
||||||
"function():boolean -- Precision enabled?",
|
"function():boolean -- Returns whether high-precision mouse events are enabled",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_SCRNUM_SETTOUCHINVERTED] = {
|
[NN_SCRNUM_SETTOUCHINVERTED] = {
|
||||||
"setTouchModeInverted",
|
"setTouchModeInverted",
|
||||||
"function(on:boolean):boolean"
|
"function(on: boolean): boolean - Enables/disables inverse touch mode, which changes how the user interacts with the screen",
|
||||||
" -- Invert touch mode",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_SCRNUM_ISTOUCHINVERTED] = {
|
[NN_SCRNUM_ISTOUCHINVERTED] = {
|
||||||
"isTouchModeInverted",
|
"isTouchModeInverted",
|
||||||
"function():boolean -- Touch inverted?",
|
"function(): boolean - Returns whether inverse touch mode is enabled",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5030,7 +5044,9 @@ static nn_Exit nn_gpuHandler(nn_ComponentRequest *req) {
|
|||||||
const char *name = nn_depthName(g.depth.oldDepth);
|
const char *name = nn_depthName(g.depth.oldDepth);
|
||||||
if(name == NULL) name = "Unknown";
|
if(name == NULL) name = "Unknown";
|
||||||
req->returnCount = 1;
|
req->returnCount = 1;
|
||||||
return nn_pushstring(C, name);
|
e = nn_pushstring(C, name);
|
||||||
|
if(e) return e;
|
||||||
|
return nn_pushinteger(C, g.depth.oldDepth);
|
||||||
}
|
}
|
||||||
// maxResolution
|
// maxResolution
|
||||||
if(m == NN_GPUNUM_MAXRES) {
|
if(m == NN_GPUNUM_MAXRES) {
|
||||||
@@ -5368,112 +5384,101 @@ nn_Component *nn_createGPU(
|
|||||||
const nn_Method methods[NN_GPUNUM_COUNT] = {
|
const nn_Method methods[NN_GPUNUM_COUNT] = {
|
||||||
[NN_GPUNUM_BIND] = {
|
[NN_GPUNUM_BIND] = {
|
||||||
"bind",
|
"bind",
|
||||||
"function(address:string[,reset:boolean])"
|
"function(address: string, reset?:boolean): boolean - Attempts to bind the GPU to a screen",
|
||||||
":boolean -- Bind to screen",
|
|
||||||
NN_INDIRECT},
|
NN_INDIRECT},
|
||||||
[NN_GPUNUM_GETSCREEN] = {
|
[NN_GPUNUM_GETSCREEN] = {
|
||||||
"getScreen",
|
"getScreen",
|
||||||
"function():string -- Bound screen address",
|
"function(): string? - Get the bound screen, if any",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_GETBG] = {
|
[NN_GPUNUM_GETBG] = {
|
||||||
"getBackground",
|
"getBackground",
|
||||||
"function():number,boolean -- Current bg",
|
"function(): integer, boolean - Returns the current background, and whether its a palette index",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_SETBG] = {
|
[NN_GPUNUM_SETBG] = {
|
||||||
"setBackground",
|
"setBackground",
|
||||||
"function(color:number[,palette:boolean])"
|
"function(color: integer, palette?: boolean): integer, integer? - Sets the current background, returns the old one",
|
||||||
":number[,number] -- Set bg",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_GETFG] = {
|
[NN_GPUNUM_GETFG] = {
|
||||||
"getForeground",
|
"getForeground",
|
||||||
"function():number,boolean -- Current fg",
|
"function(): integer,boolean - Returns the current foreground, and whether its a plette index",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_SETFG] = {
|
[NN_GPUNUM_SETFG] = {
|
||||||
"setForeground",
|
"setForeground",
|
||||||
"function(color:number[,palette:boolean])"
|
"function(color: integer, palette: boolean): integer, integer? - Sets the current foreground, returns the old one",
|
||||||
":number[,number] -- Set fg",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_GETPALETTE] = {
|
[NN_GPUNUM_GETPALETTE] = {
|
||||||
"getPaletteColor",
|
"getPaletteColor",
|
||||||
"function(index:number):number"
|
"function(index: integer): integer - Returns a color from the palette",
|
||||||
" -- Get palette color",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_SETPALETTE] = {
|
[NN_GPUNUM_SETPALETTE] = {
|
||||||
"setPaletteColor",
|
"setPaletteColor",
|
||||||
"function(index:number,value:number):number"
|
"function(index: integer, value: integer): integer - Changes a color from the palette, returns the old one",
|
||||||
" -- Set palette color",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_MAXDEPTH] = {
|
[NN_GPUNUM_MAXDEPTH] = {
|
||||||
"maxDepth",
|
"maxDepth",
|
||||||
"function():number -- Max color depth",
|
"function(): integer - Returns the maximum supported color depth (by GPU and/or screen)",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_GETDEPTH] = {
|
[NN_GPUNUM_GETDEPTH] = {
|
||||||
"getDepth",
|
"getDepth",
|
||||||
"function():number -- Current depth",
|
"function(): integer - Returns the current depth",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_SETDEPTH] = {
|
[NN_GPUNUM_SETDEPTH] = {
|
||||||
"setDepth",
|
"setDepth",
|
||||||
"function(depth:number):string -- Set depth",
|
"function(depth:integer): string, integer - Change the current depth, returns the name of the old one, and its value",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_MAXRES] = {
|
[NN_GPUNUM_MAXRES] = {
|
||||||
"maxResolution",
|
"maxResolution",
|
||||||
"function():number,number -- Max resolution",
|
"function(): integer, integer - Retuns the maximum supported resolution (by GPU and/or screen)",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_GETRES] = {
|
[NN_GPUNUM_GETRES] = {
|
||||||
"getResolution",
|
"getResolution",
|
||||||
"function():number,number -- Resolution",
|
"function(): integer, integer - Returns the current screen resolution",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_SETRES] = {
|
[NN_GPUNUM_SETRES] = {
|
||||||
"setResolution",
|
"setResolution",
|
||||||
"function(w:number,h:number):boolean"
|
"function(width: integer, height: integer): boolean - Changes the current screen resolution",
|
||||||
" -- Set resolution",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_GETVIEWPORT] = {
|
[NN_GPUNUM_GETVIEWPORT] = {
|
||||||
"getViewport",
|
"getViewport",
|
||||||
"function():number,number -- Viewport size",
|
"function(): integer, integer - Get the current viewport, the region of the screen that can actually be seen",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_SETVIEWPORT] = {
|
[NN_GPUNUM_SETVIEWPORT] = {
|
||||||
"setViewport",
|
"setViewport",
|
||||||
"function(w:number,h:number):boolean"
|
"function(width: integer, height: integer): boolean - Change the viewport to a new size",
|
||||||
" -- Set viewport",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_GET] = {
|
[NN_GPUNUM_GET] = {
|
||||||
"get",
|
"get",
|
||||||
"function(x:number,y:number):string,"
|
"function(x: integer, y: integer): string, integer, integer, integer?, integer? - Get the character, foreground, background, foreground index and "
|
||||||
"number,number,number?,number? -- Read pixel",
|
"background index of a pixel",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_SET] = {
|
[NN_GPUNUM_SET] = {
|
||||||
"set",
|
"set",
|
||||||
"function(x:number,y:number,s:string"
|
"function(x: integer, y: integer, s: string, vertical?: boolean): boolean - Set a horizontal/vertical line of text at a given (x,y) coordinate.",
|
||||||
"[,vertical:boolean]):boolean -- Write text",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_COPY] = {
|
[NN_GPUNUM_COPY] = {
|
||||||
"copy",
|
"copy",
|
||||||
"function(x,y,w,h,tx,ty):boolean"
|
"function(x: integer, y: integer, w: integer, h: integer, tx: integer, ty: integer): boolean - Copy a region on the screen. (tx, ty) is relative "
|
||||||
" -- Copy region",
|
"to the top-left corner",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_FILL] = {
|
[NN_GPUNUM_FILL] = {
|
||||||
"fill",
|
"fill",
|
||||||
"function(x,y,w,h,char):boolean"
|
"function(x: integer, y: integer, w: integer, h: integer, char: string): boolean - Fill a rectangle with a specific character",
|
||||||
" -- Fill region",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_GETACTIVEBUF] = {
|
[NN_GPUNUM_GETACTIVEBUF] = {
|
||||||
"getActiveBuffer",
|
"getActiveBuffer",
|
||||||
"function():number -- Active buffer index",
|
"function(): integer - Get the current active buffer index, 0 means the bound screen. May return 0 even when there is no screen",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_SETACTIVEBUF] = {
|
[NN_GPUNUM_SETACTIVEBUF] = {
|
||||||
"setActiveBuffer",
|
"setActiveBuffer",
|
||||||
"function(index:number):number"
|
"function(index: integer): integer - Set the active buffer, returns the old one",
|
||||||
" -- Set active buffer",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_BUFFERS] = {
|
[NN_GPUNUM_BUFFERS] = {
|
||||||
"buffers",
|
"buffers",
|
||||||
"function():table -- List buffer indices",
|
"function(): integer[] - Returns the list of VRAM buffers; this never includes 0, as it is the screen",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_ALLOCBUF] = {
|
[NN_GPUNUM_ALLOCBUF] = {
|
||||||
"allocateBuffer",
|
"allocateBuffer",
|
||||||
"function([w:number,h:number]):number"
|
"function(width: integer, height: integer): integer - Allocate a new VRAM buffer",
|
||||||
" -- Allocate VRAM page",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_FREEBUF] = {
|
[NN_GPUNUM_FREEBUF] = {
|
||||||
"freeBuffer",
|
"freeBuffer",
|
||||||
@@ -5486,21 +5491,20 @@ nn_Component *nn_createGPU(
|
|||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_TOTALMEM] = {
|
[NN_GPUNUM_TOTALMEM] = {
|
||||||
"totalMemory",
|
"totalMemory",
|
||||||
"function():number -- Total VRAM",
|
"function(): integer - Returns the VRAM capacity, in pixels",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_FREEMEM] = {
|
[NN_GPUNUM_FREEMEM] = {
|
||||||
"freeMemory",
|
"freeMemory",
|
||||||
"function():number -- Free VRAM",
|
"function(): integer - Returns the amount of unused VRAM, in pixels",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_GETBUFSIZE] = {
|
[NN_GPUNUM_GETBUFSIZE] = {
|
||||||
"getBufferSize",
|
"getBufferSize",
|
||||||
"function([index:number]):number,number"
|
"function(index?: integer): integer, integer - Returns buffer dimensions",
|
||||||
" -- Buffer dimensions",
|
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
[NN_GPUNUM_BITBLT] = {
|
[NN_GPUNUM_BITBLT] = {
|
||||||
"bitblt",
|
"bitblt",
|
||||||
"function([dst,col,row,w,h,src,fc,fr])"
|
"function(dst: integer, col: integer, row:integer, width:integer, height: integer, src: integer, fromCol: integer, fromRow: integer): boolean - "
|
||||||
":boolean -- Blit between buffers",
|
"Copy from buffer to buffer, buffer to screen or screen to buffer",
|
||||||
NN_DIRECT},
|
NN_DIRECT},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5522,3 +5526,101 @@ nn_Component *nn_createGPU(
|
|||||||
nn_setComponentHandler(c, nn_gpuHandler);
|
nn_setComponentHandler(c, nn_gpuHandler);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum nn_ModemNum {
|
||||||
|
NN_MODEMNUM_ISWIRED,
|
||||||
|
NN_MODEMNUM_ISWIRELESS,
|
||||||
|
NN_MODEMNUM_MAXPACKETSIZE,
|
||||||
|
NN_MODEMNUM_MAXVALUES,
|
||||||
|
|
||||||
|
NN_MODEMNUM_GETSTRENGTH,
|
||||||
|
NN_MODEMNUM_SETSTRENGTH,
|
||||||
|
NN_MODEMNUM_MAXSTRENGTH,
|
||||||
|
|
||||||
|
NN_MODEMNUM_ISOPEN,
|
||||||
|
NN_MODEMNUM_OPEN,
|
||||||
|
NN_MODEMNUM_CLOSE,
|
||||||
|
NN_MODEMNUM_GETPORTS,
|
||||||
|
|
||||||
|
NN_MODEMNUM_SEND,
|
||||||
|
NN_MODEMNUM_BROADCAST,
|
||||||
|
|
||||||
|
NN_MODEMNUM_COUNT,
|
||||||
|
} nn_ModemNum;
|
||||||
|
|
||||||
|
typedef struct nn_ModemState {
|
||||||
|
nn_Context *ctx;
|
||||||
|
nn_Modem modem;
|
||||||
|
nn_ModemHandler *handler;
|
||||||
|
} nn_ModemState;
|
||||||
|
|
||||||
|
static nn_Exit nn_modemHandler(nn_ComponentRequest *req) {
|
||||||
|
nn_Context *ctx = req->ctx;
|
||||||
|
nn_ModemState *state = req->classState;
|
||||||
|
nn_Computer *C = req->computer;
|
||||||
|
|
||||||
|
bool isWired = state->modem.isWired;
|
||||||
|
bool isWireless = state->modem.maxRange > 0;
|
||||||
|
nn_ModemNum method = req->methodIdx;
|
||||||
|
|
||||||
|
if(req->action == NN_COMP_CHECKMETHOD) {
|
||||||
|
if(method == NN_MODEMNUM_GETSTRENGTH || method == NN_MODEMNUM_SETSTRENGTH || method == NN_MODEMNUM_MAXSTRENGTH) {
|
||||||
|
req->methodEnabled = isWireless;
|
||||||
|
return NN_OK;
|
||||||
|
}
|
||||||
|
return NN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_ModemRequest mreq;
|
||||||
|
mreq.ctx = ctx;
|
||||||
|
mreq.computer = C;
|
||||||
|
mreq.state = req->state;
|
||||||
|
mreq.modem = &state->modem;
|
||||||
|
mreq.localAddress = req->compAddress;
|
||||||
|
|
||||||
|
if(C) nn_setError(C, "modem: not implemented yet");
|
||||||
|
return NN_EBADCALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_Component *nn_createModem(nn_Universe *universe, const char *address, const nn_Modem *modem, void *state, nn_ModemHandler *handler) {
|
||||||
|
nn_Component *c = nn_createComponent(
|
||||||
|
universe, address, "gpu");
|
||||||
|
if(c == NULL) return NULL;
|
||||||
|
|
||||||
|
const nn_Method methods[NN_MODEMNUM_COUNT] = {
|
||||||
|
[NN_MODEMNUM_ISWIRED] = {"isWired", "function(): boolean - Returns whether the modem supports wired connectivity", NN_DIRECT},
|
||||||
|
[NN_MODEMNUM_ISWIRELESS] = {"isWireless", "function(): boolean - Returns whether the modem supports wireless connectivity", NN_DIRECT},
|
||||||
|
[NN_MODEMNUM_MAXPACKETSIZE] = {"maxPacketSize", "function(): integer - Returns the maximum logical packet size", NN_DIRECT},
|
||||||
|
[NN_MODEMNUM_MAXVALUES] = {"maxValues", "function(): integer - Returns the maximum amount of values", NN_DIRECT},
|
||||||
|
|
||||||
|
[NN_MODEMNUM_GETSTRENGTH] = {"getStrength", "function(): integer - Returns the range of wireless message", NN_DIRECT},
|
||||||
|
[NN_MODEMNUM_SETSTRENGTH] = {"setStrength", "function(strength: integer): integer - Changes the wireless signal strength", NN_INDIRECT},
|
||||||
|
[NN_MODEMNUM_MAXSTRENGTH] = {"maxStrength", "function(): integer - Returns the maximum strength of wireless messages", NN_DIRECT},
|
||||||
|
|
||||||
|
[NN_MODEMNUM_ISOPEN] = {"isOpen", "function(port: integer): boolean - Returns whether a port is open", NN_DIRECT},
|
||||||
|
[NN_MODEMNUM_OPEN] = {"open", "function(port: integer): boolean - Open a port", NN_DIRECT},
|
||||||
|
[NN_MODEMNUM_CLOSE] = {"close", "function(port?: integer): boolean - Close a port, or all ports if none specified", NN_DIRECT},
|
||||||
|
[NN_MODEMNUM_GETPORTS] = {"getOpenPorts", "function(): integer[] - Returns a list of all open ports", NN_DIRECT},
|
||||||
|
|
||||||
|
[NN_MODEMNUM_SEND] = {"send", "function(targetAddress: string, port: integer, ...): boolean - Send a packet", NN_INDIRECT},
|
||||||
|
[NN_MODEMNUM_BROADCAST] = {"broadcast", "function(port: integer, ...): boolean - Broadcast a packet", NN_INDIRECT},
|
||||||
|
};
|
||||||
|
|
||||||
|
nn_Exit e = nn_setComponentMethodsArray(
|
||||||
|
c, methods, NN_MODEMNUM_COUNT);
|
||||||
|
if(e) { nn_dropComponent(c); return NULL; }
|
||||||
|
|
||||||
|
nn_Context *ctx = &universe->ctx;
|
||||||
|
nn_ModemState *cls = nn_alloc(ctx, sizeof(*cls));
|
||||||
|
if(cls == NULL) {
|
||||||
|
nn_dropComponent(c);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
cls->ctx = ctx;
|
||||||
|
cls->modem = *modem;
|
||||||
|
cls->handler = handler;
|
||||||
|
nn_setComponentState(c, state);
|
||||||
|
nn_setComponentClassState(c, cls);
|
||||||
|
nn_setComponentHandler(c, nn_modemHandler);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|||||||
132
src/neonucleus.h
132
src/neonucleus.h
@@ -408,6 +408,8 @@ extern size_t nn_ramSizes[8];
|
|||||||
nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char *address, size_t totalMemory, size_t maxComponents, size_t maxDevices);
|
nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char *address, size_t totalMemory, size_t maxComponents, size_t maxDevices);
|
||||||
// Destroys the state, effectively shutting down the computer.
|
// Destroys the state, effectively shutting down the computer.
|
||||||
void nn_destroyComputer(nn_Computer *computer);
|
void nn_destroyComputer(nn_Computer *computer);
|
||||||
|
void nn_lockComputer(nn_Computer *computer);
|
||||||
|
void nn_unlockComputer(nn_Computer *computer);
|
||||||
// get the userdata pointer
|
// get the userdata pointer
|
||||||
void *nn_getComputerUserdata(nn_Computer *computer);
|
void *nn_getComputerUserdata(nn_Computer *computer);
|
||||||
const char *nn_getComputerAddress(nn_Computer *computer);
|
const char *nn_getComputerAddress(nn_Computer *computer);
|
||||||
@@ -571,9 +573,10 @@ typedef struct nn_Method {
|
|||||||
|
|
||||||
// component signals
|
// component signals
|
||||||
|
|
||||||
// tells the component to reset its state
|
// mounted
|
||||||
// sent to the components with slot >= 0 and to tmpfs when computer state is dropped
|
#define NN_CSIGMOUNTED "mounted"
|
||||||
#define NN_CSIGRESET "reset"
|
// unmounted
|
||||||
|
#define NN_CSIGUNMOUNTED "unmounted"
|
||||||
|
|
||||||
typedef enum nn_ComponentAction {
|
typedef enum nn_ComponentAction {
|
||||||
// component dropped
|
// component dropped
|
||||||
@@ -1529,6 +1532,122 @@ nn_Component *nn_createScreen(
|
|||||||
nn_ScreenHandler *handler
|
nn_ScreenHandler *handler
|
||||||
);
|
);
|
||||||
|
|
||||||
|
typedef struct nn_Modem {
|
||||||
|
// maximum range. Set to 0 for non-wireless modems
|
||||||
|
size_t maxRange;
|
||||||
|
// maximum values in a packet
|
||||||
|
size_t maxValues;
|
||||||
|
// maximum logical packet size. Note that the encoding is more efficient than the packet size algorithm estimates
|
||||||
|
size_t maxPacketSize;
|
||||||
|
// the maximum amount of open ports
|
||||||
|
size_t maxOpenPorts;
|
||||||
|
// whether the modem supports wired connectivity.
|
||||||
|
// Support for wireless checks if maxRange > 0.
|
||||||
|
bool isWired;
|
||||||
|
// base energy cost of 1 network message
|
||||||
|
double basePacketCost;
|
||||||
|
// energy cost of a full packet, at the maximum logical size
|
||||||
|
double fullPacketCost;
|
||||||
|
// energy cost per wireless packet strength level
|
||||||
|
double costPerStrength;
|
||||||
|
} nn_Modem;
|
||||||
|
|
||||||
|
// A buffer with encoded values
|
||||||
|
typedef struct nn_EncodedNetworkContents {
|
||||||
|
nn_Context *ctx;
|
||||||
|
char *buf;
|
||||||
|
size_t buflen;
|
||||||
|
size_t valueCount;
|
||||||
|
} nn_EncodedNetworkContents;
|
||||||
|
|
||||||
|
extern nn_Modem nn_defaultWiredModem;
|
||||||
|
extern nn_Modem nn_defaultWirelessModems[2];
|
||||||
|
|
||||||
|
typedef enum nn_ModemAction {
|
||||||
|
// modem dropped
|
||||||
|
NN_MODEM_DROP,
|
||||||
|
// modem mounted to a computer, meant to bind
|
||||||
|
NN_MODEM_MOUNTED,
|
||||||
|
// modem unmounted to a computer, meant to unbind
|
||||||
|
NN_MODEM_UNMOUNTED,
|
||||||
|
// check whether a port is open
|
||||||
|
NN_MODEM_ISOPEN,
|
||||||
|
// open a port
|
||||||
|
NN_MODEM_OPEN,
|
||||||
|
// close a port
|
||||||
|
NN_MODEM_CLOSE,
|
||||||
|
// get open ports
|
||||||
|
NN_MODEM_GETPORTS,
|
||||||
|
// send/broadcast a message
|
||||||
|
NN_MODEM_SEND,
|
||||||
|
// get current modem strength
|
||||||
|
NN_MODEM_GETSTRENGTH,
|
||||||
|
// returns the wake message
|
||||||
|
NN_MODEM_GETWAKEMESSAGE,
|
||||||
|
// set the wake message
|
||||||
|
NN_MODEM_SETWAKEMESSAGE,
|
||||||
|
} nn_ModemAction;
|
||||||
|
|
||||||
|
typedef struct nn_ModemRequest {
|
||||||
|
nn_Context *ctx;
|
||||||
|
nn_Computer *computer;
|
||||||
|
void *state;
|
||||||
|
const nn_Modem *modem;
|
||||||
|
const char *localAddress;
|
||||||
|
nn_ModemAction action;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
size_t port;
|
||||||
|
bool opened;
|
||||||
|
} isOpen;
|
||||||
|
size_t openPort;
|
||||||
|
// NN_CLOSEPORTS means close all
|
||||||
|
size_t closePort;
|
||||||
|
struct {
|
||||||
|
// store the port numbers in this buffer
|
||||||
|
size_t *activePorts;
|
||||||
|
// the amount of active ports.
|
||||||
|
// the initial value is the capacity of activePorts
|
||||||
|
size_t len;
|
||||||
|
} getPorts;
|
||||||
|
struct {
|
||||||
|
const nn_EncodedNetworkContents *contents;
|
||||||
|
// NULL for broadcast
|
||||||
|
const char *address;
|
||||||
|
size_t port;
|
||||||
|
} send;
|
||||||
|
// for getStrength, setStrength.
|
||||||
|
size_t strength;
|
||||||
|
struct {
|
||||||
|
char *buf;
|
||||||
|
size_t len;
|
||||||
|
bool isFuzzy;
|
||||||
|
} getWake;
|
||||||
|
struct {
|
||||||
|
const char *buf;
|
||||||
|
size_t len;
|
||||||
|
bool isFuzzy;
|
||||||
|
} setWake;
|
||||||
|
};
|
||||||
|
} nn_ModemRequest;
|
||||||
|
|
||||||
|
typedef nn_Exit (nn_ModemHandler)(nn_ModemRequest *req);
|
||||||
|
|
||||||
|
nn_Component *nn_createModem(nn_Universe *universe, const char *address, const nn_Modem *modem, void *state, nn_ModemHandler *handler);
|
||||||
|
|
||||||
|
typedef struct nn_Tunnel {
|
||||||
|
// maximum range. Set to 0 for wired modems
|
||||||
|
size_t maxRange;
|
||||||
|
// maximum values in a packet
|
||||||
|
size_t maxValues;
|
||||||
|
// maximum logical packet size. Note that the encoding is more efficient than the packet size algorithm estimates
|
||||||
|
size_t maxPacketSize;
|
||||||
|
// the maximum amount of open ports
|
||||||
|
size_t maxOpenPorts;
|
||||||
|
} nn_Tunnel;
|
||||||
|
|
||||||
|
extern nn_Tunnel nn_defaultTunnel;
|
||||||
|
|
||||||
// Colors and palettes.
|
// Colors and palettes.
|
||||||
// Do note that the
|
// Do note that the
|
||||||
|
|
||||||
@@ -1778,13 +1897,6 @@ nn_Exit nn_pushRedstoneChanged(nn_Computer *computer, const char *redstoneAddres
|
|||||||
// entityName can be NULL if the entity has no name.
|
// entityName can be NULL if the entity has no name.
|
||||||
nn_Exit nn_pushMotion(nn_Computer *computer, double relX, double relY, double relZ, const char *entityName);
|
nn_Exit nn_pushMotion(nn_Computer *computer, double relX, double relY, double relZ, const char *entityName);
|
||||||
|
|
||||||
typedef struct nn_EncodedNetworkContents {
|
|
||||||
nn_Context *ctx;
|
|
||||||
char *buf;
|
|
||||||
size_t buflen;
|
|
||||||
size_t valueCount;
|
|
||||||
} nn_EncodedNetworkContents;
|
|
||||||
|
|
||||||
// applies basic encoding to a network message. This encoding has a header, and thus should remain backwards-compatible.
|
// applies basic encoding to a network message. This encoding has a header, and thus should remain backwards-compatible.
|
||||||
// The encoding serves 2 purposes:
|
// The encoding serves 2 purposes:
|
||||||
// 1. Prevent shared memory between computers. Values do not use atomic reference counting, and thus this could lead to UAF or memory leaks.
|
// 1. Prevent shared memory between computers. Values do not use atomic reference counting, and thus this could lead to UAF or memory leaks.
|
||||||
|
|||||||
Reference in New Issue
Block a user