Compare commits
23 Commits
f9905d14fa
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f06a5659c | |||
| de13eeb85a | |||
| 7c086f6b8e | |||
| c58e57b7c7 | |||
| 3b04fd45c7 | |||
| b88fd280ea | |||
| b732f67b06 | |||
| 5c905e6f77 | |||
| 2275cbf47d | |||
| 79ea1c7f6f | |||
| 60b12ee507 | |||
| a6d7278735 | |||
| 810bf23942 | |||
| bcf0c06458 | |||
| f0f6a21fef | |||
| a41e53f98f | |||
| 172b7ce783 | |||
| 37faa466f3 | |||
| fbd91be56d | |||
| 461416362c | |||
| e4d342a36f | |||
| e7a166f85c | |||
| f832369ce0 |
26
Makefile
26
Makefile
@@ -6,20 +6,23 @@ CC=cc
|
|||||||
LD=$(CC)
|
LD=$(CC)
|
||||||
AR=ar
|
AR=ar
|
||||||
RANLIB=ranlib
|
RANLIB=ranlib
|
||||||
|
WARN=-Wall -Werror -Wno-format-truncation
|
||||||
|
|
||||||
ifeq ($(MODE), release)
|
ifeq ($(MODE), release)
|
||||||
OPT=-Oz
|
OPT=-Oz
|
||||||
ifneq ($(CC), clang)
|
DEBUG=
|
||||||
# clang emits LLVM bitcode in lto mode, which only clang and lld understand
|
else ifeq ($(MODE), release-lto)
|
||||||
OPT += -flto
|
OPT=-Oz -flto
|
||||||
endif
|
|
||||||
DEBUG=
|
DEBUG=
|
||||||
else
|
else
|
||||||
OPT=-O0
|
OPT=-O0
|
||||||
SANITIZE=undefined,address
|
SANITIZE=undefined,address
|
||||||
DEBUG=-ggdb
|
DEBUG=-g
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
NN_STD=gnu99
|
||||||
|
EMU_STD=gnu23
|
||||||
|
|
||||||
NNFLAGS=
|
NNFLAGS=
|
||||||
|
|
||||||
SANITIZE_FLAGS=
|
SANITIZE_FLAGS=
|
||||||
@@ -28,7 +31,8 @@ ifdef SANITIZE
|
|||||||
SANITIZE_FLAGS += -fsanitize=$(SANITIZE)
|
SANITIZE_FLAGS += -fsanitize=$(SANITIZE)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS=-fPIC $(OPT) $(SANITIZE_FLAGS) $(DEBUG) $(NNFLAGS)
|
# no-omit-frame-pointer so if a crash does happen we can trace it
|
||||||
|
CFLAGS=-fPIC -fno-omit-frame-pointer $(OPT) $(SANITIZE_FLAGS) $(DEBUG) $(NNFLAGS) $(WARN)
|
||||||
|
|
||||||
LDFLAGS=$(OPT) $(DEBUG) $(SANITIZE_FLAGS)
|
LDFLAGS=$(OPT) $(DEBUG) $(SANITIZE_FLAGS)
|
||||||
|
|
||||||
@@ -44,21 +48,21 @@ SRC_DIR=src
|
|||||||
all: bin lib dynlib
|
all: bin lib dynlib
|
||||||
|
|
||||||
$(BUILD_DIR)/neonucleus.o: $(SRC_DIR)/neonucleus.c $(SRC_DIR)/neonucleus.h
|
$(BUILD_DIR)/neonucleus.o: $(SRC_DIR)/neonucleus.c $(SRC_DIR)/neonucleus.h
|
||||||
$(CC) -o $(BUILD_DIR)/neonucleus.o -c $(SRC_DIR)/neonucleus.c $(CFLAGS)
|
$(CC) -o $(BUILD_DIR)/neonucleus.o -c $(SRC_DIR)/neonucleus.c $(CFLAGS) -std=$(NN_STD)
|
||||||
|
|
||||||
$(BUILD_DIR)/ncomplib.o: $(SRC_DIR)/ncomplib.c $(SRC_DIR)/ncomplib.h
|
$(BUILD_DIR)/ncomplib.o: $(SRC_DIR)/ncomplib.c $(SRC_DIR)/ncomplib.h
|
||||||
$(CC) -o $(BUILD_DIR)/ncomplib.o -c $(SRC_DIR)/ncomplib.c $(CFLAGS)
|
$(CC) -o $(BUILD_DIR)/ncomplib.o -c $(SRC_DIR)/ncomplib.c $(CFLAGS) -std=$(NN_STD)
|
||||||
|
|
||||||
nn: $(BUILD_DIR)/neonucleus.o $(BUILD_DIR)/ncomplib.o
|
nn: $(BUILD_DIR)/neonucleus.o $(BUILD_DIR)/ncomplib.o
|
||||||
|
|
||||||
$(BUILD_DIR)/luaarch.o: $(SRC_DIR)/luaarch.c $(SRC_DIR)/machine.lua
|
$(BUILD_DIR)/luaarch.o: $(SRC_DIR)/luaarch.c $(SRC_DIR)/machine.lua
|
||||||
$(CC) -o $(BUILD_DIR)/luaarch.o -c $(SRC_DIR)/luaarch.c $(CFLAGS) $(INCLUA)
|
$(CC) -o $(BUILD_DIR)/luaarch.o -c $(SRC_DIR)/luaarch.c $(CFLAGS) $(INCLUA) -std=$(EMU_STD)
|
||||||
|
|
||||||
$(BUILD_DIR)/glyphcache.o: $(SRC_DIR)/glyphcache.c $(SRC_DIR)/glyphcache.h
|
$(BUILD_DIR)/glyphcache.o: $(SRC_DIR)/glyphcache.c $(SRC_DIR)/glyphcache.h
|
||||||
$(CC) -o $(BUILD_DIR)/glyphcache.o -c $(SRC_DIR)/glyphcache.c $(CFLAGS)
|
$(CC) -o $(BUILD_DIR)/glyphcache.o -c $(SRC_DIR)/glyphcache.c $(CFLAGS) -std=$(EMU_STD)
|
||||||
|
|
||||||
$(BUILD_DIR)/main.o: $(SRC_DIR)/main.c $(SRC_DIR)/minBIOS.lua
|
$(BUILD_DIR)/main.o: $(SRC_DIR)/main.c $(SRC_DIR)/minBIOS.lua
|
||||||
$(CC) -o $(BUILD_DIR)/main.o -c $(SRC_DIR)/main.c $(CFLAGS) $(INCLUA)
|
$(CC) -o $(BUILD_DIR)/main.o -c $(SRC_DIR)/main.c $(CFLAGS) $(INCLUA) -std=$(EMU_STD)
|
||||||
|
|
||||||
bin: nn $(BUILD_DIR)/main.o $(BUILD_DIR)/luaarch.o $(BUILD_DIR)/glyphcache.o
|
bin: nn $(BUILD_DIR)/main.o $(BUILD_DIR)/luaarch.o $(BUILD_DIR)/glyphcache.o
|
||||||
$(LD) $(LDFLAGS) -o $(BIN) $(BUILD_DIR)/neonucleus.o $(BUILD_DIR)/ncomplib.o $(BUILD_DIR)/main.o $(BUILD_DIR)/glyphcache.o $(BUILD_DIR)/luaarch.o $(LINKLIBC) $(LINKLIBM) $(LINKRAYLIB) $(LINKLUA)
|
$(LD) $(LDFLAGS) -o $(BIN) $(BUILD_DIR)/neonucleus.o $(BUILD_DIR)/ncomplib.o $(BUILD_DIR)/main.o $(BUILD_DIR)/glyphcache.o $(BUILD_DIR)/luaarch.o $(LINKLIBC) $(LINKLIBM) $(LINKRAYLIB) $(LINKLUA)
|
||||||
|
|||||||
23
TODO.md
23
TODO.md
@@ -1,21 +1,8 @@
|
|||||||
# To improve the API
|
|
||||||
|
|
||||||
- finish tmpfs (rework the whole thing)
|
|
||||||
|
|
||||||
# To re-evaluate
|
|
||||||
|
|
||||||
- Make the hashmap growing/shrinking to save on memory.
|
|
||||||
- Exposing the internal hashmap implementation.
|
|
||||||
- Having a copy of the context stored directly in requests instead of having to use getComputerContext, as it simplifies the APIs and allows them
|
|
||||||
to be made more portable.
|
|
||||||
- Exposing more internal functions that may be useful to the user to prevent pointless rewriting and duplicate machine code.
|
|
||||||
|
|
||||||
# Vanilla components needed
|
# Vanilla components needed
|
||||||
|
|
||||||
Not everything OC has (as a few of them are really MC-centered) but most of it.
|
Not everything OC has (as a few of them are really MC-centered) but most of it.
|
||||||
|
|
||||||
- `computer` component
|
- `computer` component
|
||||||
- `tunnel` component
|
|
||||||
- `internet` component (note: NN does not handle internet requests, those are up to the emulator)
|
- `internet` component (note: NN does not handle internet requests, those are up to the emulator)
|
||||||
- `relay` component (note: OCDoc still refers to it as `access_point`)
|
- `relay` component (note: OCDoc still refers to it as `access_point`)
|
||||||
- `geolyzer` component
|
- `geolyzer` component
|
||||||
@@ -45,7 +32,7 @@ Not everything OC has (as a few of them are really MC-centered) but most of it.
|
|||||||
- `iron_noteblock` component
|
- `iron_noteblock` component
|
||||||
- `colorful_lamp` component
|
- `colorful_lamp` component
|
||||||
|
|
||||||
# To make it good (after API is stable)
|
# To make it good
|
||||||
|
|
||||||
- make more stuff const if it can be. Gotta help out the optimizer
|
- make more stuff const if it can be. Gotta help out the optimizer
|
||||||
- put a bunch of internal-only functions as fastcall
|
- put a bunch of internal-only functions as fastcall
|
||||||
@@ -227,3 +214,11 @@ TODO: interface
|
|||||||
## OLED/IPU
|
## OLED/IPU
|
||||||
|
|
||||||
TODO: interface
|
TODO: interface
|
||||||
|
|
||||||
|
# To re-evaluate
|
||||||
|
|
||||||
|
- Make the hashmap growing/shrinking to save on memory.
|
||||||
|
- Exposing the internal hashmap implementation.
|
||||||
|
- Having a copy of the context stored directly in requests instead of having to use getComputerContext, as it simplifies the APIs and allows them
|
||||||
|
to be made more portable.
|
||||||
|
- Exposing more internal functions that may be useful to the user to prevent pointless rewriting and duplicate machine code.
|
||||||
|
|||||||
11
build.zig
11
build.zig
@@ -17,10 +17,9 @@ fn addEngineSources(b: *std.Build, opts: LibBuildOpts) *std.Build.Module {
|
|||||||
.strip = if (opts.optimize == .Debug) false else true,
|
.strip = if (opts.optimize == .Debug) false else true,
|
||||||
.unwind_tables = if (opts.optimize == .Debug) null else .none,
|
.unwind_tables = if (opts.optimize == .Debug) null else .none,
|
||||||
.pic = true,
|
.pic = true,
|
||||||
.sanitize_c = if(strict) .full else null,
|
.sanitize_c = if (strict) .full else null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
dataMod.addCSourceFiles(.{
|
dataMod.addCSourceFiles(.{
|
||||||
.files = &[_][]const u8{
|
.files = &[_][]const u8{
|
||||||
"src/neonucleus.c",
|
"src/neonucleus.c",
|
||||||
@@ -62,7 +61,7 @@ fn compileRaylib(b: *std.Build, os: std.Target.Os.Tag, buildOpts: LibBuildOpts,
|
|||||||
|
|
||||||
// passing it breaks it for some reason?
|
// passing it breaks it for some reason?
|
||||||
// TODO: make it not break
|
// TODO: make it not break
|
||||||
const raylib = b.addSystemCommand(&.{ "zig", "build"});
|
const raylib = b.addSystemCommand(&.{ "zig", "build" });
|
||||||
raylib.setCwd(b.path("foreign/raylib/"));
|
raylib.setCwd(b.path("foreign/raylib/"));
|
||||||
raylib.stdio = .inherit;
|
raylib.stdio = .inherit;
|
||||||
|
|
||||||
@@ -89,11 +88,7 @@ fn compileTheRightLua(b: *std.Build, target: std.Build.ResolvedTarget, version:
|
|||||||
// its a static library because COFF is a pile of shit
|
// its a static library because COFF is a pile of shit
|
||||||
const c = b.addLibrary(.{
|
const c = b.addLibrary(.{
|
||||||
.name = "lua",
|
.name = "lua",
|
||||||
.root_module = b.addModule("luamod", .{
|
.root_module = b.addModule("luamod", .{ .link_libc = true, .optimize = .ReleaseFast, .target = target, .pic = true }),
|
||||||
.link_libc = true,
|
|
||||||
.optimize = .ReleaseFast,
|
|
||||||
.target = target,
|
|
||||||
}),
|
|
||||||
.linkage = .static,
|
.linkage = .static,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -124,6 +124,27 @@ static void luaArch_nnToLua(luaArch *arch, lua_State *L, size_t nnIdx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int luaArch_computer_beep(lua_State *L) {
|
static int luaArch_computer_beep(lua_State *L) {
|
||||||
|
if(lua_type(L, 1) == LUA_TSTRING) {
|
||||||
|
nn_MorseBeep beep = {.frequency = 1000, .beepDuration = 200, .volume = 1};
|
||||||
|
beep.pattern = lua_tostring(L, 1);
|
||||||
|
if(lua_isnumber(L, 2)) {
|
||||||
|
beep.frequency = lua_tonumber(L, 2);
|
||||||
|
}
|
||||||
|
if(lua_isnumber(L, 3)) {
|
||||||
|
beep.beepDuration = lua_tonumber(L, 3);
|
||||||
|
}
|
||||||
|
if(lua_isnumber(L, 4)) {
|
||||||
|
beep.volume = lua_tonumber(L, 4);
|
||||||
|
}
|
||||||
|
if(beep.frequency < 20) beep.frequency = 20;
|
||||||
|
if(beep.beepDuration < 0) beep.beepDuration = 0;
|
||||||
|
if(beep.volume < 0) beep.volume = 0;
|
||||||
|
if(beep.frequency > 20000) beep.frequency = 20000;
|
||||||
|
if(beep.beepDuration > 5) beep.beepDuration = 5;
|
||||||
|
if(beep.volume > 1) beep.volume = 1;
|
||||||
|
nn_beepComputerMorse(luaArch_from(L)->computer, beep);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
nn_Beep beep = {.frequency = 1000, .duration = 1, .volume = 1};
|
nn_Beep beep = {.frequency = 1000, .duration = 1, .volume = 1};
|
||||||
if(lua_isnumber(L, 1)) {
|
if(lua_isnumber(L, 1)) {
|
||||||
beep.frequency = lua_tonumber(L, 1);
|
beep.frequency = lua_tonumber(L, 1);
|
||||||
@@ -751,7 +772,7 @@ static void luaArch_loadEnv(lua_State *L) {
|
|||||||
lua_setfield(L, unicode, "len");
|
lua_setfield(L, unicode, "len");
|
||||||
lua_pushcfunction(L, luaArch_unicode_sub);
|
lua_pushcfunction(L, luaArch_unicode_sub);
|
||||||
lua_setfield(L, unicode, "sub");
|
lua_setfield(L, unicode, "sub");
|
||||||
lua_pushcfunction(L, luaArch_unicode_len);
|
lua_pushcfunction(L, luaArch_unicode_wlen);
|
||||||
lua_setfield(L, unicode, "wlen");
|
lua_setfield(L, unicode, "wlen");
|
||||||
lua_pushcfunction(L, luaArch_unicode_wtrunc);
|
lua_pushcfunction(L, luaArch_unicode_wtrunc);
|
||||||
lua_setfield(L, unicode, "wtrunc");
|
lua_setfield(L, unicode, "wtrunc");
|
||||||
|
|||||||
@@ -70,6 +70,24 @@ end
|
|||||||
|
|
||||||
local syncedMethodStats
|
local syncedMethodStats
|
||||||
|
|
||||||
|
local function unsandboxValue(val)
|
||||||
|
if type(val) == "table" then
|
||||||
|
local meta = getmetatable(val)
|
||||||
|
if meta then
|
||||||
|
if type(meta.__userdata) == "userdata" then
|
||||||
|
return meta.__userdata
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local nt = {}
|
||||||
|
for sk, sv in pairs(val) do
|
||||||
|
local k, v = unsandboxValue(sk), unsandboxValue(sv)
|
||||||
|
if k ~= nil then nt[k] = v end
|
||||||
|
end
|
||||||
|
return nt
|
||||||
|
end
|
||||||
|
return val
|
||||||
|
end
|
||||||
|
|
||||||
local function sandboxValue(val)
|
local function sandboxValue(val)
|
||||||
if type(val) == "table" then
|
if type(val) == "table" then
|
||||||
local nt = {}
|
local nt = {}
|
||||||
@@ -87,6 +105,7 @@ local function sandboxValue(val)
|
|||||||
__gc = function()
|
__gc = function()
|
||||||
userdata.free(val)
|
userdata.free(val)
|
||||||
end,
|
end,
|
||||||
|
__userdata = val,
|
||||||
}
|
}
|
||||||
|
|
||||||
local wrapped = {type = "userdata", userdata = val}
|
local wrapped = {type = "userdata", userdata = val}
|
||||||
@@ -108,16 +127,18 @@ local function sandboxValue(val)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function realInvoke(address, method, ...)
|
local function realInvoke(address, method, ...)
|
||||||
local t = {pcall(cinvoke, address, method, ...)}
|
local args = {...}
|
||||||
|
for i=1,#args do args[i] = unsandboxValue(args[i]) end
|
||||||
|
local t = {pcall(cinvoke, address, method, table.unpack(args))}
|
||||||
if not _SYNCED and not os.getenv("NN_FAST") then
|
if not _SYNCED and not os.getenv("NN_FAST") then
|
||||||
if computer.energy() <= 0 then sysyield() end -- out of power
|
if computer.energy() <= 0 then sysyield() end -- out of power
|
||||||
if computer.isOverused() then sysyield() end -- overused
|
if computer.isOverused() then sysyield() end -- overused
|
||||||
if computer.isIdle() then sysyield() end -- machine idle
|
if computer.isIdle() then sysyield() end -- machine idle
|
||||||
end
|
end
|
||||||
|
|
||||||
if os.getenv("NN_INVDBG") and component.type(address) == os.getenv("NN_INVDBG") then
|
if component.type(address) == os.getenv("NN_INVDBG") or string.find(os.getenv("NN_METDBG") or "", method, nil, true) then
|
||||||
print("invoked", address, method, ...)
|
print("invoked", address, method, ...)
|
||||||
print("got", table.unpack(t))
|
print(string.format("got %d values", #t), table.unpack(t))
|
||||||
end
|
end
|
||||||
|
|
||||||
for i=1,#t do t[i] = sandboxValue(t[i]) end
|
for i=1,#t do t[i] = sandboxValue(t[i]) end
|
||||||
@@ -231,6 +252,7 @@ function computer.pullSignal(timeout)
|
|||||||
while true do
|
while true do
|
||||||
if computer.uptime() >= deadline then return end
|
if computer.uptime() >= deadline then return end
|
||||||
local t = {computer.popSignal()}
|
local t = {computer.popSignal()}
|
||||||
|
for i=1,#t do t[i] = unsandboxValue(t[i]) end
|
||||||
if #t == 0 then
|
if #t == 0 then
|
||||||
sysyield()
|
sysyield()
|
||||||
else
|
else
|
||||||
@@ -465,7 +487,18 @@ sandbox = {
|
|||||||
isRobot = computer.isRobot,
|
isRobot = computer.isRobot,
|
||||||
maxEnergy = computer.maxEnergy,
|
maxEnergy = computer.maxEnergy,
|
||||||
pullSignal = computer.pullSignal,
|
pullSignal = computer.pullSignal,
|
||||||
pushSignal = computer.pushSignal,
|
pushSignal = function(name, ...)
|
||||||
|
checkArg(1, name, "string")
|
||||||
|
local t = {...}
|
||||||
|
for i=1,#t do
|
||||||
|
local v = unsandboxValue(t[i])
|
||||||
|
if type(v) == "userdata" then
|
||||||
|
return nil, "userdata is forbidden"
|
||||||
|
end
|
||||||
|
t[i] = v
|
||||||
|
end
|
||||||
|
return computer.pushSignal(name, table.unpack(t))
|
||||||
|
end,
|
||||||
removeUser = computer.removeUser,
|
removeUser = computer.removeUser,
|
||||||
setArchitecture = computer.setArchitecture,
|
setArchitecture = computer.setArchitecture,
|
||||||
shutdown = computer.shutdown,
|
shutdown = computer.shutdown,
|
||||||
@@ -516,9 +549,6 @@ sandbox = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
utf8 = utf8,
|
utf8 = utf8,
|
||||||
|
|
||||||
-- unsafe, don't care
|
|
||||||
userdata = userdata,
|
|
||||||
}
|
}
|
||||||
sandbox._G = sandbox
|
sandbox._G = sandbox
|
||||||
|
|
||||||
|
|||||||
126
src/main.c
126
src/main.c
@@ -104,10 +104,17 @@ static nn_Exit ne_dataBullshit(nn_DataCardRequest *req) {
|
|||||||
return NN_OK;
|
return NN_OK;
|
||||||
}
|
}
|
||||||
if(action == NN_DATA_SHA256) {
|
if(action == NN_DATA_SHA256) {
|
||||||
// does not match OC, dunno why
|
|
||||||
unsigned int *out = ComputeSHA256((unsigned char *)req->sha256.data, req->sha256.datalen);
|
unsigned int *out = ComputeSHA256((unsigned char *)req->sha256.data, req->sha256.datalen);
|
||||||
if(out == NULL) return NN_ENOMEM;
|
if(out == NULL) return NN_ENOMEM;
|
||||||
memcpy(req->sha256.checksum, out, 32);
|
unsigned char buf[32];
|
||||||
|
for(size_t i = 0; i < 8; i++) {
|
||||||
|
// OC does BE
|
||||||
|
buf[i*4+3] = (out[i] >> 0) & 0xFF;
|
||||||
|
buf[i*4+2] = (out[i] >> 8) & 0xFF;
|
||||||
|
buf[i*4+1] = (out[i] >> 16) & 0xFF;
|
||||||
|
buf[i*4+0] = (out[i] >> 24) & 0xFF;
|
||||||
|
}
|
||||||
|
memcpy(req->sha256.checksum, buf, 32);
|
||||||
return NN_OK;
|
return NN_OK;
|
||||||
}
|
}
|
||||||
if(action == NN_DATA_RANDOM) {
|
if(action == NN_DATA_RANDOM) {
|
||||||
@@ -191,8 +198,9 @@ static nn_Exit ne_modemBullshit(nn_ModemRequest *req) {
|
|||||||
|
|
||||||
if(req->action == NN_MODEM_SEND) {
|
if(req->action == NN_MODEM_SEND) {
|
||||||
req->send.strengthSent = req->modem->maxRange;
|
req->send.strengthSent = req->modem->maxRange;
|
||||||
printf("Transmission from %s to %s (port %zu) of %zu bytes (%zu values)\n", req->localAddress, req->send.address == NULL ? "*" : req->send.address, req->send.port, req->send.contents->buflen, req->send.contents->valueCount);
|
const char *dest = req->send.address == NULL ? "*" : req->send.address;
|
||||||
return nn_pushModemMessage(C, req->localAddress, nn_getComputerAddress(C), req->send.port, 0, req->send.contents);
|
printf("Transmission from %s to %s (port %zu) of %zu bytes (%zu values)\n", req->localAddress, dest, req->send.port, req->send.contents->buflen, req->send.contents->valueCount);
|
||||||
|
return nn_pushModemMessage(C, req->localAddress, dest, req->send.port, 0, req->send.contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(req->action == NN_MODEM_GETWAKEMESSAGE) {
|
if(req->action == NN_MODEM_GETWAKEMESSAGE) {
|
||||||
@@ -209,6 +217,36 @@ static nn_Exit ne_modemBullshit(nn_ModemRequest *req) {
|
|||||||
return NN_EBADCALL;
|
return NN_EBADCALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static nn_Exit ne_tunnelBullshit(nn_TunnelRequest *req) {
|
||||||
|
nn_Computer *C = req->computer;
|
||||||
|
|
||||||
|
if(req->action == NN_TUNNEL_DROP) {
|
||||||
|
return NN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req->action == NN_TUNNEL_GETCHANNEL) {
|
||||||
|
return nn_pushstring(C, "creative");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req->action == NN_TUNNEL_SEND) {
|
||||||
|
printf("Transmission from tunnel %s of %zu bytes (%zu values)\n", req->localAddress, req->toSend->buflen, req->toSend->valueCount);
|
||||||
|
return nn_pushModemMessage(C, req->localAddress, nn_getComputerAddress(C), NN_TUNNEL_PORT, 0, req->toSend);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req->action == NN_TUNNEL_GETWAKEMESSAGE) {
|
||||||
|
req->getWake.len = 0;
|
||||||
|
req->getWake.isFuzzy = false;
|
||||||
|
return NN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req->action == NN_TUNNEL_SETWAKEMESSAGE) {
|
||||||
|
return NN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(C) nn_setError(C, "ne: modem method not implemented");
|
||||||
|
return NN_EBADCALL;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned char ne_processColorPart(unsigned char channel, double brightness) {
|
static unsigned char ne_processColorPart(unsigned char channel, double brightness) {
|
||||||
double n = (double)channel / 255;
|
double n = (double)channel / 255;
|
||||||
n *= brightness;
|
n *= brightness;
|
||||||
@@ -462,6 +500,7 @@ typedef struct ne_memSand {
|
|||||||
char *buf;
|
char *buf;
|
||||||
size_t used;
|
size_t used;
|
||||||
size_t cap;
|
size_t cap;
|
||||||
|
size_t active;
|
||||||
} ne_memSand;
|
} ne_memSand;
|
||||||
|
|
||||||
void *ne_sandbox_alloc(void *state, void *memory, size_t oldSize, size_t newSize) {
|
void *ne_sandbox_alloc(void *state, void *memory, size_t oldSize, size_t newSize) {
|
||||||
@@ -471,12 +510,16 @@ void *ne_sandbox_alloc(void *state, void *memory, size_t oldSize, size_t newSize
|
|||||||
newSize = ne_alignAlloc(newSize, NN_ALLOC_ALIGN);
|
newSize = ne_alignAlloc(newSize, NN_ALLOC_ALIGN);
|
||||||
|
|
||||||
// never free
|
// never free
|
||||||
if(newSize == 0) return NULL;
|
if(newSize == 0) {
|
||||||
|
sand->active -= oldSize;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if(memory == NULL) {
|
if(memory == NULL) {
|
||||||
if(sand->cap - sand->used < newSize) return NULL;
|
if(sand->cap - sand->used < newSize) return NULL;
|
||||||
// alloc new
|
// alloc new
|
||||||
void *mem = sand->buf + sand->used;
|
void *mem = sand->buf + sand->used;
|
||||||
sand->used += newSize;
|
sand->used += newSize;
|
||||||
|
sand->active += newSize;
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
// realloc
|
// realloc
|
||||||
@@ -484,6 +527,7 @@ void *ne_sandbox_alloc(void *state, void *memory, size_t oldSize, size_t newSize
|
|||||||
if(sand->cap - sand->used < newSize) return NULL;
|
if(sand->cap - sand->used < newSize) return NULL;
|
||||||
void *mem = sand->buf + sand->used;
|
void *mem = sand->buf + sand->used;
|
||||||
sand->used += newSize;
|
sand->used += newSize;
|
||||||
|
sand->active += newSize;
|
||||||
memcpy(mem, memory, oldSize);
|
memcpy(mem, memory, oldSize);
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
@@ -498,6 +542,10 @@ void ne_env(nn_EnvironmentRequest *req) {
|
|||||||
printf("beep: %f Hz %fs %.02f%%\n", req->beep.frequency, req->beep.duration, req->beep.volume*100);
|
printf("beep: %f Hz %fs %.02f%%\n", req->beep.frequency, req->beep.duration, req->beep.volume*100);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(req->action == NN_ENV_BEEPMORSE) {
|
||||||
|
printf("morse beep: %s, %f Hz %fs %.02f%%\n", req->morseBeep.pattern, req->morseBeep.frequency, req->morseBeep.beepDuration, req->morseBeep.volume*100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(req->action == NN_ENV_DRAWENERGY) {
|
if(req->action == NN_ENV_DRAWENERGY) {
|
||||||
accumulatedEnergyCost += req->energy;
|
accumulatedEnergyCost += req->energy;
|
||||||
totalEnergyLoss += req->energy;
|
totalEnergyLoss += req->energy;
|
||||||
@@ -508,6 +556,25 @@ void ne_env(nn_EnvironmentRequest *req) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nn_Exit ne_inetBullshit(nn_InternetRequest *req) {
|
||||||
|
// welcome to hell
|
||||||
|
nn_Computer *C = req->computer;
|
||||||
|
|
||||||
|
// TODO: make this shi connect to the real internet
|
||||||
|
// preferrably use libcurl, openssl and a basic blocking socket layer
|
||||||
|
|
||||||
|
if(req->action == NN_INTERNET_CONNECT) {
|
||||||
|
req->connection->state = ne_inetBullshit;
|
||||||
|
return NN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req->action == NN_INTERNET_CLOSE) {
|
||||||
|
return NN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(C) nn_setError(C, "inet bullshit: not supported");
|
||||||
|
return NN_EBADCALL;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
const char *player = getenv("USER");
|
const char *player = getenv("USER");
|
||||||
@@ -528,6 +595,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
ne_memSand sand;
|
ne_memSand sand;
|
||||||
sand.buf = NULL;
|
sand.buf = NULL;
|
||||||
|
sand.active = 0;
|
||||||
|
|
||||||
if(sandboxMem) {
|
if(sandboxMem) {
|
||||||
// 1 MiB pre-allocated to prevent erasing the free-list
|
// 1 MiB pre-allocated to prevent erasing the free-list
|
||||||
@@ -541,6 +609,10 @@ int main(int argc, char **argv) {
|
|||||||
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
||||||
InitWindow(800, 600, "NeoNucleus Test Emulator");
|
InitWindow(800, 600, "NeoNucleus Test Emulator");
|
||||||
|
|
||||||
|
const char *tierStr = getenv("NN_TIER");
|
||||||
|
if(tierStr == NULL) tierStr = "4";
|
||||||
|
int tier = atoi(tierStr);
|
||||||
|
|
||||||
// create the universe
|
// create the universe
|
||||||
nn_Universe *u = nn_createUniverse(&ctx, NULL);
|
nn_Universe *u = nn_createUniverse(&ctx, NULL);
|
||||||
|
|
||||||
@@ -556,6 +628,8 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
nn_Component *dataCard = nn_createDataCard(u, NULL, &nn_defaultDataCards[2], NULL, ne_dataBullshit);
|
nn_Component *dataCard = nn_createDataCard(u, NULL, &nn_defaultDataCards[2], NULL, ne_dataBullshit);
|
||||||
nn_Component *modem = nn_createModem(u, NULL, &nn_defaultWirelessModems[1], NULL, ne_modemBullshit);
|
nn_Component *modem = nn_createModem(u, NULL, &nn_defaultWirelessModems[1], NULL, ne_modemBullshit);
|
||||||
|
nn_Component *tunnel = nn_createTunnel(u, NULL, &nn_defaultTunnel, NULL, ne_tunnelBullshit);
|
||||||
|
nn_Component *inet = nn_createInternet(u, NULL, &nn_defaultInternetCard, NULL, ne_inetBullshit);
|
||||||
|
|
||||||
char *eepromCode = (char *)minBIOS;
|
char *eepromCode = (char *)minBIOS;
|
||||||
size_t eepromSize = strlen(minBIOS);
|
size_t eepromSize = strlen(minBIOS);
|
||||||
@@ -580,20 +654,12 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
nn_Component *eepromCard = ncl_createEEPROM(u, NULL, &nn_defaultEEPROMs[3], eepromCode, eepromSize, false);
|
nn_Component *eepromCard = ncl_createEEPROM(u, NULL, &nn_defaultEEPROMs[3], eepromCode, eepromSize, false);
|
||||||
|
|
||||||
nn_Filesystem mainfsconf;
|
|
||||||
nn_Filesystem fsparts[] = {
|
|
||||||
nn_defaultFilesystems[3],
|
|
||||||
nn_defaultFilesystems[3],
|
|
||||||
nn_defaultFilesystems[3],
|
|
||||||
};
|
|
||||||
nn_mergeFilesystems(&mainfsconf, fsparts, sizeof(fsparts) / sizeof(fsparts[0]));
|
|
||||||
|
|
||||||
char mainfspath[NN_MAX_PATH];
|
char mainfspath[NN_MAX_PATH];
|
||||||
snprintf(mainfspath, NN_MAX_PATH, "data/%s", mainDir);
|
snprintf(mainfspath, NN_MAX_PATH, "data/%s", mainDir);
|
||||||
nn_Component *managedfs = ncl_createFilesystem(u, NULL, mainfspath, &mainfsconf, true);
|
nn_Component *managedfs = ncl_createFilesystem(u, NULL, mainfspath, &nn_defaultFilesystems[tier-1], true);
|
||||||
//nn_Component *tmpfs = ncl_createTmpFS(u, NULL, &nn_defaultTmpFS, NCL_FILECOST_DEFAULT, false);
|
nn_Component *tmpfs = ncl_createTmpFS(u, NULL, &nn_defaultTmpFS, NCL_FILECOST_DEFAULT, false);
|
||||||
nn_Component *tmpfs = ncl_createFilesystem(u, NULL, "/tmp", &mainfsconf, false);
|
|
||||||
nn_Component *testingfs = ncl_createFilesystem(u, NULL, "aux", &nn_defaultFilesystems[3], false);
|
nn_Component *testingfs = ncl_createFilesystem(u, NULL, "aux", &nn_defaultFilesystems[3], false);
|
||||||
|
nn_Component *debugfs = ncl_createTmpFS(u, NULL, &nn_defaultFilesystems[3], NCL_FILECOST_DEFAULT, false);
|
||||||
|
|
||||||
const char * const testDriveData =
|
const char * const testDriveData =
|
||||||
"local g, s = component.list('gpu')(), component.list('screen')()\n"
|
"local g, s = component.list('gpu')(), component.list('screen')()\n"
|
||||||
@@ -620,18 +686,18 @@ int main(int argc, char **argv) {
|
|||||||
"while computer.uptime() < now + 3 do computer.pullSignal(0.05) end\n"
|
"while computer.uptime() < now + 3 do computer.pullSignal(0.05) end\n"
|
||||||
"computer.shutdown(true)\n"
|
"computer.shutdown(true)\n"
|
||||||
;
|
;
|
||||||
nn_Component *testDrive = ncl_createDrive(u, NULL, &nn_defaultDrives[3], testDriveData, strlen(testDriveData), false);
|
nn_Component *testDrive = ncl_createDrive(u, NULL, &nn_defaultDrives[tier-1], testDriveData, strlen(testDriveData), false);
|
||||||
nn_Component *testFlash = ncl_createFlash(u, NULL, &nn_defaultSSDs[3], testDriveData, strlen(testDriveData), false);
|
nn_Component *testFlash = ncl_createFlash(u, NULL, &nn_defaultSSDs[tier-1], testDriveData, strlen(testDriveData), false);
|
||||||
|
|
||||||
ncl_setCLabel(eepromCard, "EEPROM");
|
ncl_setCLabel(eepromCard, "EEPROM");
|
||||||
ncl_setCLabel(managedfs, "Main Filesystem");
|
ncl_setCLabel(managedfs, "Main Filesystem");
|
||||||
ncl_setCLabel(testingfs, "Secondary Filesystem");
|
ncl_setCLabel(testingfs, "Secondary Filesystem");
|
||||||
ncl_setCLabel(testDrive, "Unmanaged Storage");
|
ncl_setCLabel(testDrive, "Unmanaged Storage");
|
||||||
ncl_setCLabel(testFlash, "Flash Storage");
|
ncl_setCLabel(testFlash, "Flash Storage");
|
||||||
|
ncl_setCLabel(debugfs, "Debug Filesystem");
|
||||||
|
|
||||||
size_t ramTotal = 0;
|
size_t ramTotal = 0;
|
||||||
ramTotal += 4 * nn_ramSizes[7];
|
ramTotal += 4 * nn_ramSizes[tier*2-1];
|
||||||
//ramTotal += nn_ramSizes[0];
|
|
||||||
|
|
||||||
SetExitKey(KEY_NULL);
|
SetExitKey(KEY_NULL);
|
||||||
|
|
||||||
@@ -653,8 +719,9 @@ int main(int argc, char **argv) {
|
|||||||
double nextSecond = 0;
|
double nextSecond = 0;
|
||||||
double wattage = 0;
|
double wattage = 0;
|
||||||
|
|
||||||
nn_Component *screen = ncl_createScreen(u, NULL, &nn_defaultScreens[3]);
|
nn_Component *screen = ncl_createScreen(u, NULL, &nn_defaultScreens[tier-1]);
|
||||||
nn_Component *gpuCard = ncl_createGPU(u, NULL, &nn_defaultGPUs[3]);
|
nn_GPU gpuConf = nn_defaultGPUs[tier-1];
|
||||||
|
nn_Component *gpuCard = ncl_createGPU(u, NULL, &gpuConf);
|
||||||
nn_Component *keyboard = nn_createComponent(
|
nn_Component *keyboard = nn_createComponent(
|
||||||
u, "mainKB", "keyboard");
|
u, "mainKB", "keyboard");
|
||||||
|
|
||||||
@@ -662,13 +729,14 @@ int main(int argc, char **argv) {
|
|||||||
ncl_mountKeyboard(scrstate, "mainKB");
|
ncl_mountKeyboard(scrstate, "mainKB");
|
||||||
|
|
||||||
// we assume server basically
|
// we assume server basically
|
||||||
nn_Computer *c = nn_createComputer(u, NULL, NULL, ramTotal, nn_defaultComponentLimits[3] * 4, 256);
|
nn_Computer * volatile c = nn_createComputer(u, NULL, NULL, ramTotal, nn_defaultComponentLimits[tier-1] * 4, 256);
|
||||||
nn_Environment cEnv = {
|
nn_Environment cEnv = {
|
||||||
.userdata = NULL,
|
.userdata = NULL,
|
||||||
.handler = ne_env,
|
.handler = ne_env,
|
||||||
};
|
};
|
||||||
nn_setComputerEnvironment(c, cEnv);
|
nn_setComputerEnvironment(c, cEnv);
|
||||||
nn_setCallBudget(c, nn_defaultCallBudgets[3]);
|
// 5 cuz CPU + each RAM stick all have same tier call budgets
|
||||||
|
nn_setCallBudget(c, nn_defaultCallBudgets[tier-1] * 5);
|
||||||
nn_setTotalEnergy(c, allEnergy);
|
nn_setTotalEnergy(c, allEnergy);
|
||||||
if(getenv("NN_FAST") != NULL) {
|
if(getenv("NN_FAST") != NULL) {
|
||||||
tickDelay = 0;
|
tickDelay = 0;
|
||||||
@@ -705,6 +773,9 @@ int main(int argc, char **argv) {
|
|||||||
nn_mountComponent(c, testFlash, 5, false);
|
nn_mountComponent(c, testFlash, 5, false);
|
||||||
nn_mountComponent(c, dataCard, 6, false);
|
nn_mountComponent(c, dataCard, 6, false);
|
||||||
nn_mountComponent(c, modem, 7, false);
|
nn_mountComponent(c, modem, 7, false);
|
||||||
|
nn_mountComponent(c, tunnel, 8, false);
|
||||||
|
nn_mountComponent(c, debugfs, 9, false);
|
||||||
|
nn_mountComponent(c, inet, 10, false);
|
||||||
int ltx = 0, lty = 0;
|
int ltx = 0, lty = 0;
|
||||||
double scrollBuf = 0;
|
double scrollBuf = 0;
|
||||||
double tickTime = 0;
|
double tickTime = 0;
|
||||||
@@ -883,7 +954,6 @@ int main(int argc, char **argv) {
|
|||||||
if(noIdle) nn_resetIdleTime(c);
|
if(noIdle) nn_resetIdleTime(c);
|
||||||
// OC computers consume 0.5W when running, 0.05W when running but idle
|
// OC computers consume 0.5W when running, 0.05W when running but idle
|
||||||
double normalPowerUsage = 0.5, idlePowerUsage = 0.05;
|
double normalPowerUsage = 0.5, idlePowerUsage = 0.05;
|
||||||
bool isIdle = false;
|
|
||||||
nn_Exit e = nn_tick(c);
|
nn_Exit e = nn_tick(c);
|
||||||
tickTime = GetTime() - tickNow;
|
tickTime = GetTime() - tickNow;
|
||||||
if(tickTime < tickDelay) {
|
if(tickTime < tickDelay) {
|
||||||
@@ -943,11 +1013,17 @@ cleanup:;
|
|||||||
nn_dropComponent(keyboard);
|
nn_dropComponent(keyboard);
|
||||||
nn_dropComponent(dataCard);
|
nn_dropComponent(dataCard);
|
||||||
nn_dropComponent(modem);
|
nn_dropComponent(modem);
|
||||||
|
nn_dropComponent(tunnel);
|
||||||
|
nn_dropComponent(debugfs);
|
||||||
|
nn_dropComponent(inet);
|
||||||
// rip the universe
|
// rip the universe
|
||||||
nn_destroyUniverse(u);
|
nn_destroyUniverse(u);
|
||||||
ncl_destroyGlyphCache(gc);
|
ncl_destroyGlyphCache(gc);
|
||||||
if(eepromPath != NULL) free(eepromCode);
|
if(eepromPath != NULL) free(eepromCode);
|
||||||
CloseWindow();
|
CloseWindow();
|
||||||
free(sand.buf);
|
free(sand.buf);
|
||||||
|
if(sand.buf != NULL) {
|
||||||
|
printf("Leaked: %zu bytes\n", sand.active);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
843
src/ncomplib.c
843
src/ncomplib.c
File diff suppressed because it is too large
Load Diff
@@ -258,35 +258,29 @@ typedef struct ncl_ComponentStat {
|
|||||||
// specific properties
|
// specific properties
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
const nn_EEPROM *conf;
|
|
||||||
size_t codeUsed;
|
size_t codeUsed;
|
||||||
size_t dataUsed;
|
size_t dataUsed;
|
||||||
} eeprom;
|
} eeprom;
|
||||||
struct {
|
struct {
|
||||||
const nn_Filesystem *conf;
|
|
||||||
size_t spaceUsed;
|
size_t spaceUsed;
|
||||||
size_t realDiskUsage;
|
size_t realDiskUsage;
|
||||||
size_t filesOpen;
|
size_t filesOpen;
|
||||||
const char *path;
|
const char *path;
|
||||||
} fs;
|
} fs;
|
||||||
struct {
|
struct {
|
||||||
const nn_Drive *conf;
|
|
||||||
size_t lastSector;
|
size_t lastSector;
|
||||||
} drive;
|
} drive;
|
||||||
struct {
|
struct {
|
||||||
const nn_NandFlash *conf;
|
|
||||||
size_t currentWriteCount;
|
size_t currentWriteCount;
|
||||||
double wearlevel;
|
double wearlevel;
|
||||||
} flash;
|
} flash;
|
||||||
struct {
|
struct {
|
||||||
const nn_GPU *conf;
|
|
||||||
size_t vramFree;
|
size_t vramFree;
|
||||||
size_t bufferCount;
|
size_t bufferCount;
|
||||||
// can be NULL if there is none
|
// can be NULL if there is none
|
||||||
const char *boundScreen;
|
const char *boundScreen;
|
||||||
} gpu;
|
} gpu;
|
||||||
struct {
|
struct {
|
||||||
const nn_ScreenConfig *conf;
|
|
||||||
ncl_ScreenState *state;
|
ncl_ScreenState *state;
|
||||||
ncl_ScreenFlags flags;
|
ncl_ScreenFlags flags;
|
||||||
int viewportWidth;
|
int viewportWidth;
|
||||||
@@ -333,6 +327,8 @@ void ncl_unlockScreen(ncl_ScreenState *state);
|
|||||||
void ncl_resetScreen(ncl_ScreenState *state);
|
void ncl_resetScreen(ncl_ScreenState *state);
|
||||||
void ncl_getScreenResolution(const ncl_ScreenState *state, size_t *width, size_t *height);
|
void ncl_getScreenResolution(const ncl_ScreenState *state, size_t *width, size_t *height);
|
||||||
void ncl_setScreenResolution(ncl_ScreenState *state, size_t width, size_t height);
|
void ncl_setScreenResolution(ncl_ScreenState *state, size_t width, size_t height);
|
||||||
|
void ncl_getScreenMaxResolution(const ncl_ScreenState *state, size_t *width, size_t *height);
|
||||||
|
nn_Exit ncl_setScreenMaxResolution(ncl_ScreenState *state, size_t width, size_t height);
|
||||||
void ncl_getScreenViewport(const ncl_ScreenState *state, size_t *width, size_t *height);
|
void ncl_getScreenViewport(const ncl_ScreenState *state, size_t *width, size_t *height);
|
||||||
void ncl_setScreenViewport(ncl_ScreenState *state, size_t width, size_t height);
|
void ncl_setScreenViewport(ncl_ScreenState *state, size_t width, size_t height);
|
||||||
ncl_Pixel ncl_getScreenPixel(const ncl_ScreenState *state, int x, int y);
|
ncl_Pixel ncl_getScreenPixel(const ncl_ScreenState *state, int x, int y);
|
||||||
|
|||||||
598
src/neonucleus.c
598
src/neonucleus.c
@@ -70,10 +70,9 @@ bool nn_decRef(nn_refc_t *refc, size_t n) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct nn_Lock nn_Lock;
|
|
||||||
|
|
||||||
// the special includes
|
// the special includes
|
||||||
#ifndef NN_BAREMETAL
|
#ifndef NN_BAREMETAL
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -91,6 +90,7 @@ typedef struct nn_Lock nn_Lock;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NN_POSIX
|
#ifdef NN_POSIX
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -894,7 +894,7 @@ typedef struct nn_MethodEntry {
|
|||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
} nn_MethodEntry;
|
} nn_MethodEntry;
|
||||||
|
|
||||||
typedef struct nn_Component {
|
struct nn_Component {
|
||||||
nn_refc_t refc;
|
nn_refc_t refc;
|
||||||
nn_Universe *universe;
|
nn_Universe *universe;
|
||||||
char *address;
|
char *address;
|
||||||
@@ -906,7 +906,7 @@ typedef struct nn_Component {
|
|||||||
nn_Arena methodArena;
|
nn_Arena methodArena;
|
||||||
nn_HashMap methodsMap;
|
nn_HashMap methodsMap;
|
||||||
size_t methodCount;
|
size_t methodCount;
|
||||||
} nn_Component;
|
};
|
||||||
|
|
||||||
static size_t nn_methodHash(nn_HashAction act, void *_slot, void *_ent) {
|
static size_t nn_methodHash(nn_HashAction act, void *_slot, void *_ent) {
|
||||||
nn_MethodEntry *slot = _slot;
|
nn_MethodEntry *slot = _slot;
|
||||||
@@ -937,14 +937,14 @@ static const nn_HashContext nn_methodHasher = {
|
|||||||
.handler = (nn_HashHandler *)nn_methodHash,
|
.handler = (nn_HashHandler *)nn_methodHash,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct nn_Universe {
|
struct nn_Universe {
|
||||||
nn_Context ctx;
|
nn_Context ctx;
|
||||||
void *userdata;
|
void *userdata;
|
||||||
// 0 for unbounded
|
// 0 for unbounded
|
||||||
size_t memoryLimit;
|
size_t memoryLimit;
|
||||||
// 0 for unbounded
|
// 0 for unbounded
|
||||||
size_t storageLimit;
|
size_t storageLimit;
|
||||||
} nn_Universe;
|
};
|
||||||
|
|
||||||
typedef struct nn_ComponentEntry {
|
typedef struct nn_ComponentEntry {
|
||||||
const char *address;
|
const char *address;
|
||||||
@@ -1069,11 +1069,12 @@ typedef struct nn_Userdata {
|
|||||||
char *compAddress;
|
char *compAddress;
|
||||||
} nn_Userdata;
|
} nn_Userdata;
|
||||||
|
|
||||||
typedef struct nn_Computer {
|
struct nn_Computer {
|
||||||
nn_ComputerState state;
|
nn_ComputerState state;
|
||||||
nn_Universe *universe;
|
nn_Universe *universe;
|
||||||
nn_Environment env;
|
nn_Environment env;
|
||||||
nn_Lock *lock;
|
nn_Lock *lock;
|
||||||
|
nn_refc_t refc;
|
||||||
void *userdata;
|
void *userdata;
|
||||||
char *address;
|
char *address;
|
||||||
char *tmpaddress;
|
char *tmpaddress;
|
||||||
@@ -1082,6 +1083,7 @@ typedef struct nn_Computer {
|
|||||||
nn_Architecture desiredArch;
|
nn_Architecture desiredArch;
|
||||||
double callBudget;
|
double callBudget;
|
||||||
double totalCallBudget;
|
double totalCallBudget;
|
||||||
|
double directCost;
|
||||||
nn_HashMap components;
|
nn_HashMap components;
|
||||||
nn_DeviceInfoArray deviceInfo;
|
nn_DeviceInfoArray deviceInfo;
|
||||||
double totalEnergy;
|
double totalEnergy;
|
||||||
@@ -1098,7 +1100,7 @@ typedef struct nn_Computer {
|
|||||||
nn_Signal signals[NN_MAX_SIGNALS];
|
nn_Signal signals[NN_MAX_SIGNALS];
|
||||||
char *users[NN_MAX_USERS];
|
char *users[NN_MAX_USERS];
|
||||||
nn_Userdata uservals[NN_MAX_USERDATA];
|
nn_Userdata uservals[NN_MAX_USERDATA];
|
||||||
} nn_Computer;
|
};
|
||||||
|
|
||||||
nn_Universe *nn_createUniverse(nn_Context *ctx, void *userdata) {
|
nn_Universe *nn_createUniverse(nn_Context *ctx, void *userdata) {
|
||||||
nn_Universe *u = nn_alloc(ctx, sizeof(nn_Universe));
|
nn_Universe *u = nn_alloc(ctx, sizeof(nn_Universe));
|
||||||
@@ -1175,6 +1177,7 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char
|
|||||||
c->state = NN_BOOTUP;
|
c->state = NN_BOOTUP;
|
||||||
c->universe = universe;
|
c->universe = universe;
|
||||||
c->userdata = userdata;
|
c->userdata = userdata;
|
||||||
|
c->refc = 1;
|
||||||
|
|
||||||
c->lock = nn_createLock(ctx);
|
c->lock = nn_createLock(ctx);
|
||||||
if(c->lock == NULL) {
|
if(c->lock == NULL) {
|
||||||
@@ -1202,6 +1205,8 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char
|
|||||||
|
|
||||||
c->totalCallBudget = 1;
|
c->totalCallBudget = 1;
|
||||||
c->callBudget = c->totalCallBudget;
|
c->callBudget = c->totalCallBudget;
|
||||||
|
// OC defaults to Integer.MAX_VALUE, idk where the old number came from
|
||||||
|
c->directCost = 0;
|
||||||
|
|
||||||
if(nn_hashInit(&c->components, maxComponents, ctx, &nn_componentHasher)) {
|
if(nn_hashInit(&c->components, maxComponents, ctx, &nn_componentHasher)) {
|
||||||
nn_destroyLock(ctx, c->lock);
|
nn_destroyLock(ctx, c->lock);
|
||||||
@@ -1230,6 +1235,14 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nn_retainComputer(nn_Computer *computer) {
|
||||||
|
nn_retainComputerN(computer, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_retainComputerN(nn_Computer *computer, size_t n) {
|
||||||
|
nn_incRef(&computer->refc, n);
|
||||||
|
}
|
||||||
|
|
||||||
void nn_lockComputer(nn_Computer *computer) {
|
void nn_lockComputer(nn_Computer *computer) {
|
||||||
nn_lock(&computer->universe->ctx, computer->lock);
|
nn_lock(&computer->universe->ctx, computer->lock);
|
||||||
}
|
}
|
||||||
@@ -1240,13 +1253,6 @@ void nn_unlockComputer(nn_Computer *computer) {
|
|||||||
|
|
||||||
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) {
|
|
||||||
nn_ComponentEntry lookingFor = {
|
|
||||||
.address = address,
|
|
||||||
};
|
|
||||||
return nn_hashGet(&computer->components, &lookingFor);
|
|
||||||
}
|
|
||||||
|
|
||||||
nn_Exit nn_startComputer(nn_Computer *computer) {
|
nn_Exit nn_startComputer(nn_Computer *computer) {
|
||||||
if(nn_isComputerOn(computer)) {
|
if(nn_isComputerOn(computer)) {
|
||||||
nn_stopComputer(computer);
|
nn_stopComputer(computer);
|
||||||
@@ -1311,6 +1317,14 @@ void nn_setComputerEnvironment(nn_Computer *computer, nn_Environment env) {
|
|||||||
computer->env = env;
|
computer->env = env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nn_setDirectCost(nn_Computer *computer, double directCost) {
|
||||||
|
computer->directCost = directCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
double nn_getDirectCost(nn_Computer *computer) {
|
||||||
|
return computer->directCost;
|
||||||
|
}
|
||||||
|
|
||||||
const char *nn_deviceInfoAt(nn_Computer *computer, size_t idx) {
|
const char *nn_deviceInfoAt(nn_Computer *computer, size_t idx) {
|
||||||
return idx < computer->deviceInfo.len ? computer->deviceInfo.entries[idx].address : NULL;
|
return idx < computer->deviceInfo.len ? computer->deviceInfo.entries[idx].address : NULL;
|
||||||
}
|
}
|
||||||
@@ -1426,7 +1440,22 @@ void nn_beepComputer(nn_Computer *computer, nn_Beep beep) {
|
|||||||
computer->env.handler(&req);
|
computer->env.handler(&req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nn_beepComputerMorse(nn_Computer *computer, nn_MorseBeep beep) {
|
||||||
|
if(beep.beepDuration < 0) beep.beepDuration = 0;
|
||||||
|
nn_EnvironmentRequest req;
|
||||||
|
req.userdata = computer->env.userdata;
|
||||||
|
req.computer = computer;
|
||||||
|
req.action = NN_ENV_BEEPMORSE;
|
||||||
|
req.morseBeep = beep;
|
||||||
|
computer->env.handler(&req);
|
||||||
|
}
|
||||||
|
|
||||||
void nn_destroyComputer(nn_Computer *computer) {
|
void nn_destroyComputer(nn_Computer *computer) {
|
||||||
|
nn_destroyComputerN(computer, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn_destroyComputerN(nn_Computer *computer, size_t n) {
|
||||||
|
if(!nn_decRef(&computer->refc, n)) return;
|
||||||
nn_Context *ctx = &computer->universe->ctx;
|
nn_Context *ctx = &computer->universe->ctx;
|
||||||
nn_stopComputer(computer);
|
nn_stopComputer(computer);
|
||||||
|
|
||||||
@@ -2164,8 +2193,7 @@ nn_Exit nn_invokeComponent(nn_Computer *computer, const char *compAddress, const
|
|||||||
nn_pop(computer);
|
nn_pop(computer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: configurable cost
|
nn_costComponent(computer, computer->directCost);
|
||||||
nn_costComponent(computer, 22000);
|
|
||||||
|
|
||||||
nn_ComponentRequest req;
|
nn_ComponentRequest req;
|
||||||
req.ctx = &c->universe->ctx;
|
req.ctx = &c->universe->ctx;
|
||||||
@@ -2973,32 +3001,32 @@ const nn_EEPROM nn_defaultEEPROMs[4] = {
|
|||||||
const nn_Filesystem nn_defaultFilesystems[4] = {
|
const nn_Filesystem nn_defaultFilesystems[4] = {
|
||||||
NN_INIT(nn_Filesystem) {
|
NN_INIT(nn_Filesystem) {
|
||||||
.spaceTotal = 1 * NN_MiB,
|
.spaceTotal = 1 * NN_MiB,
|
||||||
.readsPerTick = 4,
|
.readsPerTick = 7,
|
||||||
.writesPerTick = 2,
|
.writesPerTick = 3,
|
||||||
.opensPerTick = 4,
|
.opensPerTick = 4,
|
||||||
.dataEnergyCost = 0.1 / NN_KiB,
|
.dataEnergyCost = 0.1 / NN_KiB,
|
||||||
.maxReadSize = 4096,
|
.maxReadSize = 4096,
|
||||||
},
|
},
|
||||||
NN_INIT(nn_Filesystem) {
|
NN_INIT(nn_Filesystem) {
|
||||||
.spaceTotal = 2 * NN_MiB,
|
.spaceTotal = 2 * NN_MiB,
|
||||||
.readsPerTick = 4,
|
.readsPerTick = 10,
|
||||||
.writesPerTick = 2,
|
.writesPerTick = 4,
|
||||||
.opensPerTick = 8,
|
.opensPerTick = 8,
|
||||||
.dataEnergyCost = 0.1 / NN_KiB,
|
.dataEnergyCost = 0.1 / NN_KiB,
|
||||||
.maxReadSize = 8192,
|
.maxReadSize = 8192,
|
||||||
},
|
},
|
||||||
NN_INIT(nn_Filesystem) {
|
NN_INIT(nn_Filesystem) {
|
||||||
.spaceTotal = 4 * NN_MiB,
|
.spaceTotal = 4 * NN_MiB,
|
||||||
.readsPerTick = 7,
|
.readsPerTick = 13,
|
||||||
.writesPerTick = 3,
|
.writesPerTick = 5,
|
||||||
.opensPerTick = 16,
|
.opensPerTick = 16,
|
||||||
.dataEnergyCost = 0.1 / NN_KiB,
|
.dataEnergyCost = 0.1 / NN_KiB,
|
||||||
.maxReadSize = 16384,
|
.maxReadSize = 16384,
|
||||||
},
|
},
|
||||||
NN_INIT(nn_Filesystem) {
|
NN_INIT(nn_Filesystem) {
|
||||||
.spaceTotal = 8 * NN_MiB,
|
.spaceTotal = 8 * NN_MiB,
|
||||||
.readsPerTick = 13,
|
.readsPerTick = 15,
|
||||||
.writesPerTick = 5,
|
.writesPerTick = 6,
|
||||||
.opensPerTick = 32,
|
.opensPerTick = 32,
|
||||||
.dataEnergyCost = 0.1 / NN_KiB,
|
.dataEnergyCost = 0.1 / NN_KiB,
|
||||||
.maxReadSize = 32768,
|
.maxReadSize = 32768,
|
||||||
@@ -3008,17 +3036,18 @@ const nn_Filesystem nn_defaultFilesystems[4] = {
|
|||||||
|
|
||||||
const nn_Filesystem nn_defaultFloppy = NN_INIT(nn_Filesystem) {
|
const nn_Filesystem nn_defaultFloppy = NN_INIT(nn_Filesystem) {
|
||||||
.spaceTotal = 512 * NN_KiB,
|
.spaceTotal = 512 * NN_KiB,
|
||||||
.readsPerTick = 1,
|
.readsPerTick = 4,
|
||||||
.writesPerTick = 1,
|
.writesPerTick = 2,
|
||||||
.dataEnergyCost = 0.1 / NN_KiB,
|
.dataEnergyCost = 0.1 / NN_KiB,
|
||||||
.maxReadSize = 2048,
|
.maxReadSize = 2048,
|
||||||
};
|
};
|
||||||
|
|
||||||
const nn_Filesystem nn_defaultTmpFS = NN_INIT(nn_Filesystem) {
|
const nn_Filesystem nn_defaultTmpFS = NN_INIT(nn_Filesystem) {
|
||||||
.spaceTotal = 64 * NN_KiB,
|
.spaceTotal = 64 * NN_KiB,
|
||||||
.readsPerTick = 1024,
|
.readsPerTick = 15,
|
||||||
.writesPerTick = 512,
|
.writesPerTick = 6,
|
||||||
.dataEnergyCost = 0.1 / NN_MiB,
|
.dataEnergyCost = 0.1 / NN_MiB,
|
||||||
|
.maxReadSize = 2048,
|
||||||
};
|
};
|
||||||
|
|
||||||
const nn_Drive nn_defaultDrives[4] = {
|
const nn_Drive nn_defaultDrives[4] = {
|
||||||
@@ -3026,8 +3055,8 @@ const nn_Drive nn_defaultDrives[4] = {
|
|||||||
.capacity = 1 * NN_MiB,
|
.capacity = 1 * NN_MiB,
|
||||||
.sectorSize = 512,
|
.sectorSize = 512,
|
||||||
.platterCount = 2,
|
.platterCount = 2,
|
||||||
.readsPerTick = 20,
|
.readsPerTick = 30,
|
||||||
.writesPerTick = 10,
|
.writesPerTick = 15,
|
||||||
.rpm = 3600,
|
.rpm = 3600,
|
||||||
.onlySpinForwards = false,
|
.onlySpinForwards = false,
|
||||||
.dataEnergyCost = 4.0 / NN_MiB,
|
.dataEnergyCost = 4.0 / NN_MiB,
|
||||||
@@ -3036,8 +3065,8 @@ const nn_Drive nn_defaultDrives[4] = {
|
|||||||
.capacity = 2 * NN_MiB,
|
.capacity = 2 * NN_MiB,
|
||||||
.sectorSize = 512,
|
.sectorSize = 512,
|
||||||
.platterCount = 4,
|
.platterCount = 4,
|
||||||
.readsPerTick = 30,
|
.readsPerTick = 40,
|
||||||
.writesPerTick = 15,
|
.writesPerTick = 20,
|
||||||
.rpm = 5400,
|
.rpm = 5400,
|
||||||
.onlySpinForwards = false,
|
.onlySpinForwards = false,
|
||||||
.dataEnergyCost = 4.0 / NN_MiB,
|
.dataEnergyCost = 4.0 / NN_MiB,
|
||||||
@@ -3046,8 +3075,8 @@ const nn_Drive nn_defaultDrives[4] = {
|
|||||||
.capacity = 4 * NN_MiB,
|
.capacity = 4 * NN_MiB,
|
||||||
.sectorSize = 512,
|
.sectorSize = 512,
|
||||||
.platterCount = 8,
|
.platterCount = 8,
|
||||||
.readsPerTick = 40,
|
.readsPerTick = 50,
|
||||||
.writesPerTick = 20,
|
.writesPerTick = 25,
|
||||||
.rpm = 7200,
|
.rpm = 7200,
|
||||||
.onlySpinForwards = false,
|
.onlySpinForwards = false,
|
||||||
.dataEnergyCost = 4.0 / NN_MiB,
|
.dataEnergyCost = 4.0 / NN_MiB,
|
||||||
@@ -3068,8 +3097,8 @@ const nn_Drive nn_floppyDrive = {
|
|||||||
.capacity = 512 * NN_KiB,
|
.capacity = 512 * NN_KiB,
|
||||||
.sectorSize = 512,
|
.sectorSize = 512,
|
||||||
.platterCount = 1,
|
.platterCount = 1,
|
||||||
.readsPerTick = 10,
|
.readsPerTick = 20,
|
||||||
.writesPerTick = 5,
|
.writesPerTick = 10,
|
||||||
.rpm = 1800,
|
.rpm = 1800,
|
||||||
.onlySpinForwards = true,
|
.onlySpinForwards = true,
|
||||||
.dataEnergyCost = 4.0 / NN_MiB,
|
.dataEnergyCost = 4.0 / NN_MiB,
|
||||||
@@ -3196,7 +3225,9 @@ const nn_GPU nn_defaultGPUs[4] = {
|
|||||||
.setPerTick = 64,
|
.setPerTick = 64,
|
||||||
.setForegroundPerTick = 32,
|
.setForegroundPerTick = 32,
|
||||||
.setBackgroundPerTick = 32,
|
.setBackgroundPerTick = 32,
|
||||||
.energyPerWrite = 0.2 / (50*16),
|
.energyPerWrite = 2.0 / (50*16),
|
||||||
|
.energyPerFill = 1.0 / (50*16),
|
||||||
|
.energyPerCopy = 0.5 / (50*16),
|
||||||
.energyPerClear = 0.1 / (50*16),
|
.energyPerClear = 0.1 / (50*16),
|
||||||
},
|
},
|
||||||
NN_INIT(nn_GPU) {
|
NN_INIT(nn_GPU) {
|
||||||
@@ -3209,7 +3240,9 @@ const nn_GPU nn_defaultGPUs[4] = {
|
|||||||
.setPerTick = 128,
|
.setPerTick = 128,
|
||||||
.setForegroundPerTick = 64,
|
.setForegroundPerTick = 64,
|
||||||
.setBackgroundPerTick = 64,
|
.setBackgroundPerTick = 64,
|
||||||
.energyPerWrite = 0.2 / (50*16),
|
.energyPerWrite = 2.0 / (50*16),
|
||||||
|
.energyPerFill = 1.0 / (50*16),
|
||||||
|
.energyPerCopy = 0.5 / (50*16),
|
||||||
.energyPerClear = 0.1 / (50*16),
|
.energyPerClear = 0.1 / (50*16),
|
||||||
},
|
},
|
||||||
NN_INIT(nn_GPU) {
|
NN_INIT(nn_GPU) {
|
||||||
@@ -3222,7 +3255,9 @@ const nn_GPU nn_defaultGPUs[4] = {
|
|||||||
.setPerTick = 256,
|
.setPerTick = 256,
|
||||||
.setForegroundPerTick = 128,
|
.setForegroundPerTick = 128,
|
||||||
.setBackgroundPerTick = 128,
|
.setBackgroundPerTick = 128,
|
||||||
.energyPerWrite = 0.2 / (50*16),
|
.energyPerWrite = 2.0 / (50*16),
|
||||||
|
.energyPerFill = 1.0 / (50*16),
|
||||||
|
.energyPerCopy = 0.5 / (50*16),
|
||||||
.energyPerClear = 0.1 / (50*16),
|
.energyPerClear = 0.1 / (50*16),
|
||||||
},
|
},
|
||||||
NN_INIT(nn_GPU) {
|
NN_INIT(nn_GPU) {
|
||||||
@@ -3235,7 +3270,9 @@ const nn_GPU nn_defaultGPUs[4] = {
|
|||||||
.setPerTick = 512,
|
.setPerTick = 512,
|
||||||
.setForegroundPerTick = 256,
|
.setForegroundPerTick = 256,
|
||||||
.setBackgroundPerTick = 256,
|
.setBackgroundPerTick = 256,
|
||||||
.energyPerWrite = 0.2 / (50*16),
|
.energyPerWrite = 2.0 / (50*16),
|
||||||
|
.energyPerFill = 1.0 / (50*16),
|
||||||
|
.energyPerCopy = 0.5 / (50*16),
|
||||||
.energyPerClear = 0.1 / (50*16),
|
.energyPerClear = 0.1 / (50*16),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -3367,7 +3404,7 @@ int nn_mapDepth(int color, int depth) {
|
|||||||
// TODO: map the other depths
|
// TODO: map the other depths
|
||||||
if(depth == 4) return nn_mapColor(color, nn_ocpalette4, 16);
|
if(depth == 4) return nn_mapColor(color, nn_ocpalette4, 16);
|
||||||
if(depth == 8) return nn_mapColor(color, nn_ocpalette8, 256);
|
if(depth == 8) return nn_mapColor(color, nn_ocpalette8, 256);
|
||||||
if(depth == 16) return color & 0xF0FFF0;
|
if(depth == 16) return (color & 0xF0FFF0) | ((color & 0xF000F0) >> 4);
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3913,9 +3950,44 @@ nn_Exit nn_pushLClipboard(nn_Computer *computer, const char *keyboardAddress, co
|
|||||||
return nn_pushSignal(computer, 3);
|
return nn_pushSignal(computer, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
nn_Exit nn_pushRedstoneChanged(nn_Computer *computer, const char *redstoneAddress, int side, int oldValue, int newValue, int color);
|
nn_Exit nn_pushRedstoneChanged(nn_Computer *computer, const char *redstoneAddress, int side, int oldValue, int newValue, int color) {
|
||||||
|
nn_Exit err = nn_pushstring(computer, "redstone_changed");
|
||||||
|
if(err) return err;
|
||||||
|
err = nn_pushstring(computer, redstoneAddress);
|
||||||
|
if(err) return err;
|
||||||
|
err = nn_pushinteger(computer, side);
|
||||||
|
if(err) return err;
|
||||||
|
err = nn_pushinteger(computer, oldValue);
|
||||||
|
if(err) return err;
|
||||||
|
err = nn_pushinteger(computer, newValue);
|
||||||
|
if(err) return err;
|
||||||
|
err = color < 0 ? nn_pushnull(computer) : nn_pushinteger(computer, newValue);
|
||||||
|
if(err) return err;
|
||||||
|
return nn_pushSignal(computer, 6);
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
nn_Exit err = nn_pushstring(computer, "motion");
|
||||||
|
if(err) return err;
|
||||||
|
err = nn_pushnumber(computer, relX);
|
||||||
|
if(err) return err;
|
||||||
|
err = nn_pushnumber(computer, relY);
|
||||||
|
if(err) return err;
|
||||||
|
err = nn_pushnumber(computer, relZ);
|
||||||
|
if(err) return err;
|
||||||
|
// remember: safe to push NULL to pushstring in which cases it pushes null.
|
||||||
|
err = nn_pushstring(computer, entityName);
|
||||||
|
if(err) return err;
|
||||||
|
return nn_pushSignal(computer, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_Exit nn_pushInternetReady(nn_Computer *computer, const char *id, size_t idlen) {
|
||||||
|
nn_Exit err = nn_pushstring(computer, "internet_ready");
|
||||||
|
if(err) return err;
|
||||||
|
err = nn_pushlstring(computer, id, idlen);
|
||||||
|
if(err) return err;
|
||||||
|
return nn_pushSignal(computer, 2);
|
||||||
|
}
|
||||||
|
|
||||||
typedef enum nn_NetworkValueTag {
|
typedef enum nn_NetworkValueTag {
|
||||||
NN_NETVAL_NULL = 0x00,
|
NN_NETVAL_NULL = 0x00,
|
||||||
@@ -4427,6 +4499,7 @@ static nn_Exit nn_fsHandler(nn_ComponentRequest *req) {
|
|||||||
nn_Context *ctx = req->ctx;
|
nn_Context *ctx = req->ctx;
|
||||||
nn_FSState *state = req->classState;
|
nn_FSState *state = req->classState;
|
||||||
nn_FSRequest freq;
|
nn_FSRequest freq;
|
||||||
|
freq.action = NN_FS_DROP;
|
||||||
freq.ctx = req->ctx;
|
freq.ctx = req->ctx;
|
||||||
freq.computer = req->computer;
|
freq.computer = req->computer;
|
||||||
freq.state = req->state;
|
freq.state = req->state;
|
||||||
@@ -5880,7 +5953,7 @@ static nn_Exit nn_gpuHandler(nn_ComponentRequest *req) {
|
|||||||
req->returnCount = 1;
|
req->returnCount = 1;
|
||||||
if(isScreen) {
|
if(isScreen) {
|
||||||
nn_costComponent(C, cls->gpu.copyPerTick);
|
nn_costComponent(C, cls->gpu.copyPerTick);
|
||||||
nn_removeEnergy(C, cls->gpu.energyPerWrite * g.copy.w * g.copy.h);
|
nn_removeEnergy(C, cls->gpu.energyPerCopy * g.copy.w * g.copy.h);
|
||||||
}
|
}
|
||||||
return nn_pushbool(C, true);
|
return nn_pushbool(C, true);
|
||||||
}
|
}
|
||||||
@@ -5911,7 +5984,7 @@ static nn_Exit nn_gpuHandler(nn_ComponentRequest *req) {
|
|||||||
req->returnCount = 1;
|
req->returnCount = 1;
|
||||||
if(isScreen) {
|
if(isScreen) {
|
||||||
nn_costComponent(C, cls->gpu.fillPerTick);
|
nn_costComponent(C, cls->gpu.fillPerTick);
|
||||||
nn_removeEnergy(C, (g.fill.codepoint == ' ' ? cls->gpu.energyPerClear : cls->gpu.energyPerWrite) * g.fill.w * g.fill.h);
|
nn_removeEnergy(C, (g.fill.codepoint == ' ' ? cls->gpu.energyPerClear : cls->gpu.energyPerFill) * g.fill.w * g.fill.h);
|
||||||
}
|
}
|
||||||
return nn_pushbool(C, true);
|
return nn_pushbool(C, true);
|
||||||
}
|
}
|
||||||
@@ -6027,7 +6100,7 @@ static nn_Exit nn_gpuHandler(nn_ComponentRequest *req) {
|
|||||||
if(g.bitblt.dst == 0 || g.bitblt.src == 0) {
|
if(g.bitblt.dst == 0 || g.bitblt.src == 0) {
|
||||||
// taxed as a copy
|
// taxed as a copy
|
||||||
nn_costComponent(C, g.gpu->copyPerTick);
|
nn_costComponent(C, g.gpu->copyPerTick);
|
||||||
nn_removeEnergy(C, g.gpu->energyPerWrite * g.bitblt.w * g.bitblt.h);
|
nn_removeEnergy(C, g.gpu->energyPerCopy * g.bitblt.w * g.bitblt.h);
|
||||||
}
|
}
|
||||||
e = cls->handler(&g);
|
e = cls->handler(&g);
|
||||||
if(e) return e;
|
if(e) return e;
|
||||||
@@ -7052,7 +7125,7 @@ static nn_Exit nn_modemHandler(nn_ComponentRequest *req) {
|
|||||||
nn_setError(C, "invalid port");
|
nn_setError(C, "invalid port");
|
||||||
return NN_EBADCALL;
|
return NN_EBADCALL;
|
||||||
}
|
}
|
||||||
size_t valcount = nn_getstacksize(C) - 1;
|
size_t valcount = nn_getstacksize(C) - 2;
|
||||||
if(valcount > state->modem.maxValues) return NN_EBADCALL;
|
if(valcount > state->modem.maxValues) return NN_EBADCALL;
|
||||||
int cost = nn_countValueCost(C, valcount);
|
int cost = nn_countValueCost(C, valcount);
|
||||||
if(cost < 0) {
|
if(cost < 0) {
|
||||||
@@ -7178,7 +7251,7 @@ nn_Modem nn_defaultWirelessModems[2] = {
|
|||||||
.maxValues = 8,
|
.maxValues = 8,
|
||||||
.maxPacketSize = 8192,
|
.maxPacketSize = 8192,
|
||||||
.maxOpenPorts = 1,
|
.maxOpenPorts = 1,
|
||||||
.isWired = true,
|
.isWired = false,
|
||||||
.basePacketCost = 0.1,
|
.basePacketCost = 0.1,
|
||||||
.fullPacketCost = 0.5,
|
.fullPacketCost = 0.5,
|
||||||
.costPerStrength = 0.05,
|
.costPerStrength = 0.05,
|
||||||
@@ -7201,3 +7274,430 @@ nn_Tunnel nn_defaultTunnel = {
|
|||||||
.basePacketCost = 100,
|
.basePacketCost = 100,
|
||||||
.fullPacketCost = 256,
|
.fullPacketCost = 256,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum nn_TunnelNum {
|
||||||
|
NN_TUNNELNUM_MAXPACKETSIZE,
|
||||||
|
NN_TUNNELNUM_MAXVALUES,
|
||||||
|
|
||||||
|
NN_TUNNELNUM_GETCHANNEL,
|
||||||
|
NN_TUNNELNUM_SEND,
|
||||||
|
|
||||||
|
NN_TUNNELNUM_GETWAKE,
|
||||||
|
NN_TUNNELNUM_SETWAKE,
|
||||||
|
|
||||||
|
NN_TUNNELNUM_COUNT,
|
||||||
|
} nn_TunnelNum;
|
||||||
|
|
||||||
|
typedef struct nn_TunnelState {
|
||||||
|
nn_Context *ctx;
|
||||||
|
nn_Tunnel tunnel;
|
||||||
|
nn_TunnelHandler *handler;
|
||||||
|
} nn_TunnelState;
|
||||||
|
|
||||||
|
static nn_Exit nn_tunnelHandler(nn_ComponentRequest *req) {
|
||||||
|
if(req->action == NN_COMP_USERDATA) return NN_OK;
|
||||||
|
nn_Context *ctx = req->ctx;
|
||||||
|
nn_TunnelState *state = req->classState;
|
||||||
|
nn_Computer *C = req->computer;
|
||||||
|
|
||||||
|
nn_TunnelNum method = req->methodIdx;
|
||||||
|
|
||||||
|
if(req->action == NN_COMP_CHECKMETHOD) return NN_OK;
|
||||||
|
|
||||||
|
nn_TunnelRequest treq;
|
||||||
|
treq.ctx = ctx;
|
||||||
|
treq.computer = C;
|
||||||
|
treq.state = req->state;
|
||||||
|
treq.tunnel = &state->tunnel;
|
||||||
|
treq.localAddress = req->compAddress;
|
||||||
|
nn_Exit e;
|
||||||
|
|
||||||
|
if(req->action == NN_COMP_DROP) {
|
||||||
|
treq.action = NN_TUNNEL_DROP;
|
||||||
|
state->handler(&treq);
|
||||||
|
nn_free(ctx, state, sizeof(*state));
|
||||||
|
return NN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(method == NN_TUNNELNUM_MAXPACKETSIZE) {
|
||||||
|
req->returnCount = 1;
|
||||||
|
return nn_pushinteger(C, state->tunnel.maxPacketSize);
|
||||||
|
}
|
||||||
|
if(method == NN_TUNNELNUM_MAXVALUES) {
|
||||||
|
req->returnCount = 1;
|
||||||
|
return nn_pushinteger(C, state->tunnel.maxValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(method == NN_TUNNELNUM_GETCHANNEL) {
|
||||||
|
treq.action = NN_TUNNEL_GETCHANNEL;
|
||||||
|
req->returnCount = 1;
|
||||||
|
return state->handler(&treq);
|
||||||
|
}
|
||||||
|
if(method == NN_TUNNELNUM_SEND) {
|
||||||
|
size_t valcount = nn_getstacksize(C);
|
||||||
|
if(valcount > state->tunnel.maxValues) return NN_EBADCALL;
|
||||||
|
int cost = nn_countValueCost(C, valcount);
|
||||||
|
if(cost < 0) {
|
||||||
|
nn_setError(C, "invalid contents");
|
||||||
|
return NN_EBADCALL;
|
||||||
|
}
|
||||||
|
if(cost > state->tunnel.maxPacketSize) return NN_ELIMIT;
|
||||||
|
nn_EncodedNetworkContents data;
|
||||||
|
e = nn_encodeNetworkContents(C, &data, valcount);
|
||||||
|
if(e) return e;
|
||||||
|
treq.action = NN_TUNNEL_SEND;
|
||||||
|
treq.toSend = &data;
|
||||||
|
e = state->handler(&treq);
|
||||||
|
nn_dropNetworkContents(&data);
|
||||||
|
if(!e) {
|
||||||
|
nn_removeEnergy(C, state->tunnel.basePacketCost + state->tunnel.fullPacketCost * cost / state->tunnel.maxPacketSize);
|
||||||
|
req->returnCount = 1;
|
||||||
|
e = nn_pushbool(C, true);
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(method == NN_TUNNELNUM_GETWAKE) {
|
||||||
|
char buf[NN_MAX_WAKEUPMSG];
|
||||||
|
treq.action = NN_TUNNEL_GETWAKEMESSAGE;
|
||||||
|
treq.getWake.buf = buf;
|
||||||
|
treq.getWake.len = NN_MAX_WAKEUPMSG;
|
||||||
|
e = state->handler(&treq);
|
||||||
|
if(e) return e;
|
||||||
|
|
||||||
|
req->returnCount = 2;
|
||||||
|
e = treq.getWake.len == 0 ? nn_pushnull(C) : nn_pushlstring(C, buf, treq.getWake.len);
|
||||||
|
if(e) return e;
|
||||||
|
return nn_pushbool(C, treq.getWake.isFuzzy);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(method == NN_TUNNELNUM_SETWAKE) {
|
||||||
|
e = nn_defaultstring(C, 0, "");
|
||||||
|
if(e) return e;
|
||||||
|
if(nn_checkstring(C, 0, "bad argument #1 (string expected)")) return NN_EBADCALL;
|
||||||
|
e = nn_defaultboolean(C, 1, false);
|
||||||
|
if(e) return e;
|
||||||
|
if(nn_checkboolean(C, 1, "bad argument #2 (boolean expected)")) return NN_EBADCALL;
|
||||||
|
treq.action = NN_TUNNEL_SETWAKEMESSAGE;
|
||||||
|
treq.setWake.buf = nn_tolstring(C, 0, &treq.setWake.len);
|
||||||
|
if(treq.setWake.len > NN_MAX_WAKEUPMSG) return NN_ELIMIT;
|
||||||
|
treq.setWake.isFuzzy = nn_toboolean(C, 1);
|
||||||
|
e = state->handler(&treq);
|
||||||
|
if(e) return e;
|
||||||
|
|
||||||
|
req->returnCount = 1;
|
||||||
|
return nn_pushbool(C, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(C) nn_setError(C, "tunnel: not implemented yet");
|
||||||
|
return NN_EBADCALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_Component *nn_createTunnel(nn_Universe *universe, const char *address, const nn_Tunnel *tunnel, void *state, nn_TunnelHandler *handler) {
|
||||||
|
nn_Component *c = nn_createComponent(
|
||||||
|
universe, address, "tunnel");
|
||||||
|
if(c == NULL) return NULL;
|
||||||
|
|
||||||
|
const nn_Method methods[NN_TUNNELNUM_COUNT] = {
|
||||||
|
[NN_TUNNELNUM_MAXPACKETSIZE] = {"maxPacketSize", "function(): integer - Returns the maximum logical packet size", NN_DIRECT},
|
||||||
|
[NN_TUNNELNUM_MAXVALUES] = {"maxValues", "function(): integer - Returns the maximum amount of values", NN_DIRECT},
|
||||||
|
|
||||||
|
[NN_TUNNELNUM_GETCHANNEL] = {"getChannel", "function(): string - Get the ID of the channel", NN_DIRECT},
|
||||||
|
[NN_TUNNELNUM_SEND] = {"send", "function(...): boolean - Send a packet", NN_INDIRECT},
|
||||||
|
|
||||||
|
[NN_TUNNELNUM_GETWAKE] = {"getWakeMessage", "function(): string?, boolean - Returns the wake message, if any, and whether it is fuzzy", NN_DIRECT},
|
||||||
|
[NN_TUNNELNUM_SETWAKE] = {"setWakeMessage", "function(message: string?, fuzzy: boolean) - Changes the wake-up message of the modem", NN_INDIRECT},
|
||||||
|
};
|
||||||
|
|
||||||
|
nn_Exit e = nn_setComponentMethodsArray(
|
||||||
|
c, methods, NN_TUNNELNUM_COUNT);
|
||||||
|
if(e) { nn_dropComponent(c); return NULL; }
|
||||||
|
|
||||||
|
nn_Context *ctx = &universe->ctx;
|
||||||
|
nn_TunnelState *cls = nn_alloc(ctx, sizeof(*cls));
|
||||||
|
if(cls == NULL) {
|
||||||
|
nn_dropComponent(c);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
cls->ctx = ctx;
|
||||||
|
cls->tunnel = *tunnel;
|
||||||
|
cls->handler = handler;
|
||||||
|
nn_setComponentState(c, state);
|
||||||
|
nn_setComponentClassState(c, cls);
|
||||||
|
nn_setComponentHandler(c, nn_tunnelHandler);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_InternetCard nn_defaultInternetCard = {
|
||||||
|
.protocolsSupported = NN_INET_ALL,
|
||||||
|
.maxReadSize = 64 * NN_KiB,
|
||||||
|
.transmissionEnergyCost = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum nn_InternetNum {
|
||||||
|
NN_INETNUM_MAXREADSIZE,
|
||||||
|
|
||||||
|
// is*Enabled
|
||||||
|
NN_INETNUM_ISHTTP,
|
||||||
|
NN_INETNUM_ISTCP,
|
||||||
|
NN_INETNUM_ISTLS,
|
||||||
|
NN_INETNUM_ISUDP,
|
||||||
|
NN_INETNUM_ISWEBSOCK,
|
||||||
|
|
||||||
|
// TCP/TLS connection
|
||||||
|
NN_INETNUM_CONNECT,
|
||||||
|
// WebSocket/UDP connection
|
||||||
|
NN_INETNUM_CHANNEL,
|
||||||
|
// HTTP/HTTPS request
|
||||||
|
NN_INETNUM_REQUEST,
|
||||||
|
|
||||||
|
NN_INETNUM_COUNT,
|
||||||
|
} nn_InternetNum;
|
||||||
|
|
||||||
|
typedef struct nn_InternetState {
|
||||||
|
nn_Context *ctx;
|
||||||
|
nn_InternetCard inet;
|
||||||
|
nn_InternetHandler *handler;
|
||||||
|
} nn_InternetState;
|
||||||
|
|
||||||
|
static nn_Exit nn_inetCloseConn(nn_InternetRequest req, nn_InternetHandler *handler, nn_InternetConnection *conn) {
|
||||||
|
if(conn == NULL) return NN_OK;
|
||||||
|
if(conn->state != NULL) {
|
||||||
|
req.connection = conn;
|
||||||
|
req.action = NN_INTERNET_CLOSE;
|
||||||
|
nn_Exit e = handler(&req);
|
||||||
|
if(e) return e;
|
||||||
|
}
|
||||||
|
conn->state = NULL;
|
||||||
|
return NN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pushes a userdata that makes the connection, to save on brain power.
|
||||||
|
static nn_Exit nn_inetMakeConn(nn_InternetRequest req, nn_InternetHandler *handler, nn_InternetProtocol proto) {
|
||||||
|
if(req.action != NN_INTERNET_CONNECT) return NN_EBADSTATE;
|
||||||
|
nn_Context *ctx = req.ctx;
|
||||||
|
|
||||||
|
nn_InternetConnection *conn = NULL;
|
||||||
|
nn_Exit e = NN_OK;
|
||||||
|
|
||||||
|
conn = nn_alloc(ctx, sizeof(*conn));
|
||||||
|
if(conn == NULL) {
|
||||||
|
e = NN_ENOMEM;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->protocol = proto;
|
||||||
|
conn->port = req.connect.port;
|
||||||
|
conn->state = NULL;
|
||||||
|
nn_randomUUID(ctx, conn->id);
|
||||||
|
|
||||||
|
req.connection = conn;
|
||||||
|
e = handler(&req);
|
||||||
|
if(e) goto fail;
|
||||||
|
|
||||||
|
int idx = nn_allocUserdata(req.computer, conn, req.localAddress);
|
||||||
|
if(idx < 0) {
|
||||||
|
e = NN_ELIMIT;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = nn_pushuserdata(req.computer, idx);
|
||||||
|
if(e) goto fail;
|
||||||
|
|
||||||
|
return NN_OK;
|
||||||
|
fail:
|
||||||
|
nn_inetCloseConn(req, handler, conn);
|
||||||
|
nn_free(ctx, conn, sizeof(*conn));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nn_Exit nn_inetHandler(nn_ComponentRequest *req) {
|
||||||
|
nn_Context *ctx = req->ctx;
|
||||||
|
nn_InternetState *state = req->classState;
|
||||||
|
nn_Computer *C = req->computer;
|
||||||
|
nn_Exit e;
|
||||||
|
|
||||||
|
if(req->action == NN_COMP_CHECKMETHOD) return NN_OK;
|
||||||
|
|
||||||
|
nn_InternetRequest ireq;
|
||||||
|
ireq.ctx = ctx;
|
||||||
|
ireq.computer = C;
|
||||||
|
ireq.state = req->state;
|
||||||
|
ireq.inet = &state->inet;
|
||||||
|
ireq.localAddress = req->compAddress;
|
||||||
|
ireq.connection = NULL;
|
||||||
|
|
||||||
|
if(req->action == NN_COMP_DROP) {
|
||||||
|
ireq.action = NN_INTERNET_DROP;
|
||||||
|
state->handler(&ireq);
|
||||||
|
nn_free(ctx, state, sizeof(*state));
|
||||||
|
return NN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req->action == NN_COMP_USERDATA) {
|
||||||
|
nn_UserdataRequest *ureq = req->user;
|
||||||
|
nn_InternetConnection *conn = ureq->state;
|
||||||
|
|
||||||
|
if(conn->state == NULL) return NN_EBADSTATE;
|
||||||
|
|
||||||
|
if(ureq->action == NN_USER_DROP) {
|
||||||
|
nn_inetCloseConn(ireq, state->handler, conn);
|
||||||
|
nn_free(ctx, conn, sizeof(*conn));
|
||||||
|
return NN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ureq->action == NN_USER_GETMETHOD) {
|
||||||
|
size_t idx = ureq->getmethod.idx;
|
||||||
|
nn_Method *method = ureq->getmethod.method;
|
||||||
|
|
||||||
|
if(idx == 0) {
|
||||||
|
method->name = "finishConnect";
|
||||||
|
method->doc = "function(): boolean - Returns whether the connection finished. Can also return an error if the connection failed, or no error if still pending";
|
||||||
|
method->flags = NN_DIRECT;
|
||||||
|
} else if(idx == 1) {
|
||||||
|
method->name = "id";
|
||||||
|
method->doc = "function(): string - Returns the id of the connection";
|
||||||
|
method->flags = NN_DIRECT;
|
||||||
|
} else if(idx == 2) {
|
||||||
|
method->name = "close";
|
||||||
|
method->doc = "function() - Closes the connection";
|
||||||
|
method->flags = NN_DIRECT;
|
||||||
|
} else if(idx == 3) {
|
||||||
|
method->name = "read";
|
||||||
|
method->doc = "function(n?: number): string? - Reads data from the connection. Returns the data, or nil if EoF";
|
||||||
|
method->flags = NN_DIRECT;
|
||||||
|
} else if(idx == 4) {
|
||||||
|
method->name = conn->protocol == NN_INET_HTTP ? NULL : "write";
|
||||||
|
method->doc = "function(data: string): integer - Writes data to the connection. Returns how much data was successfully written";
|
||||||
|
method->flags = NN_DIRECT;
|
||||||
|
} else {
|
||||||
|
ureq->getmethod.method = NULL;
|
||||||
|
}
|
||||||
|
return NN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ureq->action == NN_USER_INVOKE) {
|
||||||
|
const char *method = ureq->invoke.method;
|
||||||
|
|
||||||
|
if(nn_strcmp(method, "id") == 0) {
|
||||||
|
ureq->invoke.returnCount = 1;
|
||||||
|
return nn_pushlstring(C, conn->id, 36);
|
||||||
|
}
|
||||||
|
if(nn_strcmp(method, "close") == 0) {
|
||||||
|
e = nn_inetCloseConn(ireq, state->handler, conn);
|
||||||
|
if(e) return e;
|
||||||
|
ureq->invoke.returnCount = 1;
|
||||||
|
return nn_pushbool(C, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(C) nn_setError(C, "internet: not implemented yet");
|
||||||
|
return NN_EBADCALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_InternetNum method = req->methodIdx;
|
||||||
|
|
||||||
|
if(method == NN_INETNUM_MAXREADSIZE) {
|
||||||
|
req->returnCount = 1;
|
||||||
|
return nn_pushinteger(C, state->inet.maxReadSize);
|
||||||
|
}
|
||||||
|
if(method == NN_INETNUM_ISHTTP) {
|
||||||
|
req->returnCount = 1;
|
||||||
|
return nn_pushbool(C, (state->inet.protocolsSupported & NN_INET_HTTP) != 0);
|
||||||
|
}
|
||||||
|
if(method == NN_INETNUM_ISTCP) {
|
||||||
|
req->returnCount = 1;
|
||||||
|
return nn_pushbool(C, (state->inet.protocolsSupported & NN_INET_TCP) != 0);
|
||||||
|
}
|
||||||
|
if(method == NN_INETNUM_ISTLS) {
|
||||||
|
req->returnCount = 1;
|
||||||
|
return nn_pushbool(C, (state->inet.protocolsSupported & NN_INET_TLS) != 0);
|
||||||
|
}
|
||||||
|
if(method == NN_INETNUM_ISUDP) {
|
||||||
|
req->returnCount = 1;
|
||||||
|
return nn_pushbool(C, (state->inet.protocolsSupported & NN_INET_UDP) != 0);
|
||||||
|
}
|
||||||
|
if(method == NN_INETNUM_ISWEBSOCK) {
|
||||||
|
req->returnCount = 1;
|
||||||
|
return nn_pushbool(C, (state->inet.protocolsSupported & NN_INET_WEBSOCKET) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(method == NN_INETNUM_REQUEST) {
|
||||||
|
if((state->inet.protocolsSupported & NN_INET_HTTP) == 0) {
|
||||||
|
nn_setError(C, "protocol disabled");
|
||||||
|
return NN_EBADCALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nn_checkstring(C, 0, "bad argument #1 (string expected")) return NN_EBADCALL;
|
||||||
|
e = nn_defaultstring(C, 1, "");
|
||||||
|
if(e) return e;
|
||||||
|
if(nn_checkstring(C, 1, "bad argument #2 (string expected")) return NN_EBADCALL;
|
||||||
|
e = nn_defaulttable(C, 2);
|
||||||
|
if(e) return e;
|
||||||
|
if(nn_checktable(C, 2, "bad argument #3 (table expected)")) return NN_EBADCALL;
|
||||||
|
|
||||||
|
ireq.action = NN_INTERNET_CONNECT;
|
||||||
|
ireq.connect.url = nn_tostring(C, 0);
|
||||||
|
ireq.connect.http.postdata = nn_tolstring(C, 1, &ireq.connect.http.postdatalen);
|
||||||
|
size_t headerlen = 0;
|
||||||
|
e = nn_dumptable(C, 2, &headerlen);
|
||||||
|
if(e) return e;
|
||||||
|
ireq.connect.http.headerlen = headerlen;
|
||||||
|
nn_HTTPHeader *headers = nn_alloc(ctx, sizeof(nn_HTTPHeader) * headerlen);
|
||||||
|
if(headers == NULL) return NN_ENOMEM;
|
||||||
|
|
||||||
|
for(size_t i = 3; i < 3 + headerlen * 2; i += 2) {
|
||||||
|
if(!nn_isstring(C, i) || !nn_isstring(C, i+1)) {
|
||||||
|
nn_free(ctx, headers, sizeof(nn_HTTPHeader) * headerlen);
|
||||||
|
nn_setError(C, "malformed headers");
|
||||||
|
return NN_EBADCALL;
|
||||||
|
}
|
||||||
|
headers[i].name = nn_tostring(C, i);
|
||||||
|
headers[i].value = nn_tostring(C, i+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
req->returnCount = 1;
|
||||||
|
e = nn_inetMakeConn(ireq, state->handler, NN_INET_HTTP);
|
||||||
|
nn_free(ctx, headers, sizeof(nn_HTTPHeader) * headerlen);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(C) nn_setError(C, "internet: not implemented yet");
|
||||||
|
return NN_EBADCALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_Component *nn_createInternet(nn_Universe *universe, const char *address, const nn_InternetCard *inet, void *state, nn_InternetHandler *handler) {
|
||||||
|
nn_Component *c = nn_createComponent(
|
||||||
|
universe, address, "internet");
|
||||||
|
if(c == NULL) return NULL;
|
||||||
|
|
||||||
|
const nn_Method methods[NN_INETNUM_COUNT] = {
|
||||||
|
[NN_INETNUM_MAXREADSIZE] = {"maxReadSize", "function(): integer - Returns the maximum size of a read", NN_DIRECT},
|
||||||
|
[NN_INETNUM_ISHTTP] = {"isHttpEnabled", "function(): boolean - Returns whether HTTP/HTTPS support is enabled", NN_DIRECT},
|
||||||
|
[NN_INETNUM_ISTCP] = {"isTcpEnabled", "function(): boolean - Returns whether TCP support is enabled", NN_DIRECT},
|
||||||
|
[NN_INETNUM_ISTLS] = {"isTlsEnabled", "function(): boolean - Returns whether TLS support is enabled", NN_DIRECT},
|
||||||
|
[NN_INETNUM_ISWEBSOCK] = {"isWebsocketEnabled", "function(): boolean - Returns whether WebSocket / WSS support is enabled", NN_DIRECT},
|
||||||
|
[NN_INETNUM_ISUDP] = {"isUdpEnabled", "function(): boolean - Returns whether UDP support is enabled", NN_DIRECT},
|
||||||
|
[NN_INETNUM_CONNECT] = {"connect", "function(address: string, port: number = -1, protocol: string = 'tcp'): userdata - Opens a socket connection and returns a handle to it. Valid protocols are tcp and tls", NN_INDIRECT},
|
||||||
|
[NN_INETNUM_CHANNEL] = {"channel", "function(address: string, port: number = -1, protocol: string = 'websocket', subprotocols?: string[]): userdata - Opens a packet channel and reutrns a handle to it. Valid protocols are websocket and udp", NN_INDIRECT},
|
||||||
|
[NN_INETNUM_REQUEST] = {"request", "function(url: string, portData?: string, headers?: table): userdata - Sends an HTTP/HTTPS requests, returns a handle to it", NN_INDIRECT},
|
||||||
|
};
|
||||||
|
|
||||||
|
nn_Exit e = nn_setComponentMethodsArray(
|
||||||
|
c, methods, NN_INETNUM_COUNT);
|
||||||
|
if(e) { nn_dropComponent(c); return NULL; }
|
||||||
|
|
||||||
|
nn_Context *ctx = &universe->ctx;
|
||||||
|
nn_InternetState *cls = nn_alloc(ctx, sizeof(*cls));
|
||||||
|
if(cls == NULL) {
|
||||||
|
nn_dropComponent(c);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
cls->ctx = ctx;
|
||||||
|
cls->inet = *inet;
|
||||||
|
cls->handler = handler;
|
||||||
|
nn_setComponentState(c, state);
|
||||||
|
nn_setComponentClassState(c, cls);
|
||||||
|
nn_setComponentHandler(c, nn_inetHandler);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|||||||
650
src/neonucleus.h
650
src/neonucleus.h
@@ -108,9 +108,9 @@ void *_alloca(size_t);
|
|||||||
// maximum size of an address.
|
// maximum size of an address.
|
||||||
// This only matters in places where an address is returned through a component, as it is the amount of space to allocate for the response.
|
// This only matters in places where an address is returned through a component, as it is the amount of space to allocate for the response.
|
||||||
// Past this there would be a truncation which would invalidate the address.
|
// Past this there would be a truncation which would invalidate the address.
|
||||||
// However, 256 is unrealistically long, as UUIDv4 only needs 36.
|
// However, 64 is unrealistically long, as UUIDv4 only needs 36.
|
||||||
// Please, do not go above this.
|
// Please, do not go above this.
|
||||||
#define NN_MAX_ADDRESS 256
|
#define NN_MAX_ADDRESS 64
|
||||||
// the port used by tunnel cards. This port is invalid for modems.
|
// the port used by tunnel cards. This port is invalid for modems.
|
||||||
#define NN_TUNNEL_PORT 0
|
#define NN_TUNNEL_PORT 0
|
||||||
// maximum amount of users a computer can have
|
// maximum amount of users a computer can have
|
||||||
@@ -393,17 +393,36 @@ typedef struct nn_Architecture {
|
|||||||
extern size_t nn_ramSizes[8];
|
extern size_t nn_ramSizes[8];
|
||||||
|
|
||||||
typedef struct nn_Beep {
|
typedef struct nn_Beep {
|
||||||
|
// frequenc, in Hz
|
||||||
double frequency;
|
double frequency;
|
||||||
|
// duration, in seconds
|
||||||
double duration;
|
double duration;
|
||||||
|
// 0 is mute, 1 is 100%
|
||||||
double volume;
|
double volume;
|
||||||
} nn_Beep;
|
} nn_Beep;
|
||||||
|
|
||||||
|
// Morse beep, like a normal beep except it follows a morse code pattern.
|
||||||
|
// . is a short sound
|
||||||
|
// - is a long sound, 2x in length
|
||||||
|
// a space is a pause, 2x in length and dead silent.
|
||||||
|
// Every sound, including actual pauses, have a 50ms pause between them.
|
||||||
|
typedef struct nn_MorseBeep {
|
||||||
|
const char *pattern;
|
||||||
|
// frequency, in Hz
|
||||||
|
double frequency;
|
||||||
|
// duration of a ., in seconds
|
||||||
|
double beepDuration;
|
||||||
|
// 0 is mute, 1 is 100%
|
||||||
|
double volume;
|
||||||
|
} nn_MorseBeep;
|
||||||
|
|
||||||
typedef enum nn_EnvironmentAction {
|
typedef enum nn_EnvironmentAction {
|
||||||
NN_ENV_DRAWENERGY,
|
NN_ENV_DRAWENERGY,
|
||||||
NN_ENV_POWERON,
|
NN_ENV_POWERON,
|
||||||
NN_ENV_POWEROFF,
|
NN_ENV_POWEROFF,
|
||||||
NN_ENV_CRASHED,
|
NN_ENV_CRASHED,
|
||||||
NN_ENV_BEEP,
|
NN_ENV_BEEP,
|
||||||
|
NN_ENV_BEEPMORSE,
|
||||||
} nn_EnvironmentAction;
|
} nn_EnvironmentAction;
|
||||||
|
|
||||||
typedef struct nn_EnvironmentRequest {
|
typedef struct nn_EnvironmentRequest {
|
||||||
@@ -415,6 +434,8 @@ typedef struct nn_EnvironmentRequest {
|
|||||||
double energy;
|
double energy;
|
||||||
// for BEEP, information about the beep
|
// for BEEP, information about the beep
|
||||||
nn_Beep beep;
|
nn_Beep beep;
|
||||||
|
// for BEEPMORSE, information about the beep
|
||||||
|
nn_MorseBeep morseBeep;
|
||||||
};
|
};
|
||||||
} nn_EnvironmentRequest;
|
} nn_EnvironmentRequest;
|
||||||
|
|
||||||
@@ -435,8 +456,11 @@ typedef struct nn_Environment {
|
|||||||
// maxComponents and maxDevices determine how many components can be connected simultaneously to this computer, and how much device info can be
|
// maxComponents and maxDevices determine how many components can be connected simultaneously to this computer, and how much device info can be
|
||||||
// registered on this computer.
|
// registered on this computer.
|
||||||
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);
|
||||||
|
void nn_retainComputer(nn_Computer *computer);
|
||||||
|
void nn_retainComputerN(nn_Computer *computer, size_t n);
|
||||||
// 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_destroyComputerN(nn_Computer *computer, size_t n);
|
||||||
void nn_lockComputer(nn_Computer *computer);
|
void nn_lockComputer(nn_Computer *computer);
|
||||||
void nn_unlockComputer(nn_Computer *computer);
|
void nn_unlockComputer(nn_Computer *computer);
|
||||||
// stops the computer if an architecture state is already present,
|
// stops the computer if an architecture state is already present,
|
||||||
@@ -450,6 +474,9 @@ void nn_forceCrashComputer(nn_Computer *computer, const char *s);
|
|||||||
bool nn_isComputerOn(nn_Computer *computer);
|
bool nn_isComputerOn(nn_Computer *computer);
|
||||||
void nn_setComputerEnvironment(nn_Computer *computer, nn_Environment env);
|
void nn_setComputerEnvironment(nn_Computer *computer, nn_Environment env);
|
||||||
|
|
||||||
|
void nn_setDirectCost(nn_Computer *computer, double directCost);
|
||||||
|
double nn_getDirectCost(nn_Computer *computer);
|
||||||
|
|
||||||
// Device information
|
// Device information
|
||||||
|
|
||||||
// Standard device attribute fields
|
// Standard device attribute fields
|
||||||
@@ -514,6 +541,7 @@ void nn_clearCommonDeviceInfo(nn_CommonDeviceInfo *info);
|
|||||||
bool nn_removeDeviceInfo(nn_Computer *computer, const char *addr);
|
bool nn_removeDeviceInfo(nn_Computer *computer, const char *addr);
|
||||||
|
|
||||||
void nn_beepComputer(nn_Computer *computer, nn_Beep beep);
|
void nn_beepComputer(nn_Computer *computer, nn_Beep beep);
|
||||||
|
void nn_beepComputerMorse(nn_Computer *computer, nn_MorseBeep beep);
|
||||||
|
|
||||||
// get the userdata pointer
|
// get the userdata pointer
|
||||||
void *nn_getComputerUserdata(nn_Computer *computer);
|
void *nn_getComputerUserdata(nn_Computer *computer);
|
||||||
@@ -1042,6 +1070,262 @@ nn_Exit nn_popSignal(nn_Computer *computer, size_t *valueCount);
|
|||||||
|
|
||||||
nn_Exit nn_transferErrorFrom(nn_Exit exit, nn_Computer *from, nn_Computer *to);
|
nn_Exit nn_transferErrorFrom(nn_Exit exit, nn_Computer *from, nn_Computer *to);
|
||||||
|
|
||||||
|
// Signal helpers
|
||||||
|
|
||||||
|
// common mouse buttons, not an exhaustive list
|
||||||
|
#define NN_BUTTON_LEFT 0
|
||||||
|
#define NN_BUTTON_RIGHT 1
|
||||||
|
#define NN_BUTTON_MIDDLE 2
|
||||||
|
|
||||||
|
// OC keycodes
|
||||||
|
// taken from https://github.com/MightyPirates/OpenComputers/blob/52da41b5e171b43fea80342dc75d808f97a0f797/src/main/resources/assets/opencomputers/loot/openos/lib/core/full_keyboard.lua
|
||||||
|
#define NN_KEY_UNKNOWN 0
|
||||||
|
#define NN_KEY_1 0x02
|
||||||
|
#define NN_KEY_2 0x03
|
||||||
|
#define NN_KEY_3 0x04
|
||||||
|
#define NN_KEY_4 0x05
|
||||||
|
#define NN_KEY_5 0x06
|
||||||
|
#define NN_KEY_6 0x07
|
||||||
|
#define NN_KEY_7 0x08
|
||||||
|
#define NN_KEY_8 0x09
|
||||||
|
#define NN_KEY_9 0x0A
|
||||||
|
#define NN_KEY_0 0x0B
|
||||||
|
#define NN_KEY_A 0x1E
|
||||||
|
#define NN_KEY_B 0x30
|
||||||
|
#define NN_KEY_C 0x2E
|
||||||
|
#define NN_KEY_D 0x20
|
||||||
|
#define NN_KEY_E 0x12
|
||||||
|
#define NN_KEY_F 0x21
|
||||||
|
#define NN_KEY_G 0x22
|
||||||
|
#define NN_KEY_H 0x23
|
||||||
|
#define NN_KEY_I 0x17
|
||||||
|
#define NN_KEY_J 0x24
|
||||||
|
#define NN_KEY_K 0x25
|
||||||
|
#define NN_KEY_L 0x26
|
||||||
|
#define NN_KEY_M 0x32
|
||||||
|
#define NN_KEY_N 0x31
|
||||||
|
#define NN_KEY_O 0x18
|
||||||
|
#define NN_KEY_P 0x19
|
||||||
|
#define NN_KEY_Q 0x10
|
||||||
|
#define NN_KEY_R 0x13
|
||||||
|
#define NN_KEY_S 0x1F
|
||||||
|
#define NN_KEY_T 0x14
|
||||||
|
#define NN_KEY_U 0x16
|
||||||
|
#define NN_KEY_V 0x2F
|
||||||
|
#define NN_KEY_W 0x11
|
||||||
|
#define NN_KEY_X 0x2D
|
||||||
|
#define NN_KEY_Y 0x15
|
||||||
|
#define NN_KEY_Z 0x2C
|
||||||
|
|
||||||
|
#define NN_KEY_APOSTROPHE 0x28
|
||||||
|
#define NN_KEY_AT 0x91
|
||||||
|
#define NN_KEY_BACK 0x0E
|
||||||
|
#define NN_KEY_BACKSLASH 0x2B
|
||||||
|
// caps-lock
|
||||||
|
#define NN_KEY_CAPITAL 0x3A
|
||||||
|
#define NN_KEY_COLON 0x92
|
||||||
|
#define NN_KEY_COMMA 0x33
|
||||||
|
#define NN_KEY_ENTER 0x1C
|
||||||
|
#define NN_KEY_EQUALS 0x0D
|
||||||
|
// accent grave
|
||||||
|
#define NN_KEY_GRAVE 0x29
|
||||||
|
#define NN_KEY_LBRACKET 0x1A
|
||||||
|
#define NN_KEY_LCONTROL 0x1D
|
||||||
|
// left alt
|
||||||
|
#define NN_KEY_LMENU 0x38
|
||||||
|
#define NN_KEY_LSHIFT 0x2A
|
||||||
|
#define NN_KEY_MINUS 0x0C
|
||||||
|
#define NN_KEY_NUMLOCK 0x45
|
||||||
|
#define NN_KEY_PAUSE 0xC5
|
||||||
|
#define NN_KEY_PERIOD 0x34
|
||||||
|
#define NN_KEY_RBRACKET 0x1B
|
||||||
|
#define NN_KEY_RCONTROL 0x9D
|
||||||
|
// right alt
|
||||||
|
#define NN_KEY_RMENU 0xB8
|
||||||
|
#define NN_KEY_RSHIFT 0x36
|
||||||
|
// scroll lock
|
||||||
|
#define NN_KEY_SCROLL 0x46
|
||||||
|
#define NN_KEY_SEMICOLON 0x27
|
||||||
|
#define NN_KEY_SLASH 0x35
|
||||||
|
#define NN_KEY_SPACE 0x39
|
||||||
|
#define NN_KEY_STOP 0x95
|
||||||
|
#define NN_KEY_TAB 0x0F
|
||||||
|
#define NN_KEY_UNDERLINE 0x93
|
||||||
|
|
||||||
|
#define NN_KEY_UP 0xC8
|
||||||
|
#define NN_KEY_DOWN 0xD0
|
||||||
|
#define NN_KEY_LEFT 0xCB
|
||||||
|
#define NN_KEY_RIGHT 0xCD
|
||||||
|
#define NN_KEY_HOME 0xC7
|
||||||
|
#define NN_KEY_END 0xCF
|
||||||
|
#define NN_KEY_PAGEUP 0xC9
|
||||||
|
#define NN_KEY_PAGEDOWN 0xD1
|
||||||
|
#define NN_KEY_INSERT 0xD2
|
||||||
|
#define NN_KEY_DELETE 0xD3
|
||||||
|
|
||||||
|
#define NN_KEY_F1 0x3B
|
||||||
|
#define NN_KEY_F2 0x3C
|
||||||
|
#define NN_KEY_F3 0x3D
|
||||||
|
#define NN_KEY_F4 0x3E
|
||||||
|
#define NN_KEY_F5 0x3F
|
||||||
|
#define NN_KEY_F6 0x40
|
||||||
|
#define NN_KEY_F7 0x41
|
||||||
|
#define NN_KEY_F8 0x42
|
||||||
|
#define NN_KEY_F9 0x43
|
||||||
|
#define NN_KEY_F10 0x44
|
||||||
|
#define NN_KEY_F11 0x57
|
||||||
|
#define NN_KEY_F12 0x58
|
||||||
|
#define NN_KEY_F13 0x64
|
||||||
|
#define NN_KEY_F14 0x65
|
||||||
|
#define NN_KEY_F15 0x66
|
||||||
|
#define NN_KEY_F16 0x67
|
||||||
|
#define NN_KEY_F17 0x68
|
||||||
|
#define NN_KEY_F18 0x69
|
||||||
|
#define NN_KEY_F19 0x71
|
||||||
|
|
||||||
|
#define NN_KEY_KANA 0x70
|
||||||
|
#define NN_KEY_KANJI 0x94
|
||||||
|
#define NN_KEY_CONVERT 0x79
|
||||||
|
#define NN_KEY_NOCONVERT 0x7B
|
||||||
|
#define NN_KEY_YEN 0x7D
|
||||||
|
#define NN_KEY_CIRCUMFLEX 0x90
|
||||||
|
#define NN_KEY_AX 0x96
|
||||||
|
|
||||||
|
#define NN_KEY_NUMPAD0 0x52
|
||||||
|
#define NN_KEY_NUMPAD1 0x4F
|
||||||
|
#define NN_KEY_NUMPAD2 0x50
|
||||||
|
#define NN_KEY_NUMPAD3 0x51
|
||||||
|
#define NN_KEY_NUMPAD4 0x4B
|
||||||
|
#define NN_KEY_NUMPAD5 0x4C
|
||||||
|
#define NN_KEY_NUMPAD6 0x4D
|
||||||
|
#define NN_KEY_NUMPAD7 0x47
|
||||||
|
#define NN_KEY_NUMPAD8 0x48
|
||||||
|
#define NN_KEY_NUMPAD9 0x49
|
||||||
|
#define NN_KEY_NUMPADMUL 0x37
|
||||||
|
#define NN_KEY_NUMPADDIV 0xB5
|
||||||
|
#define NN_KEY_NUMPADSUB 0x4A
|
||||||
|
#define NN_KEY_NUMPADADD 0x4E
|
||||||
|
#define NN_KEY_NUMPADDECIMAL 0x53
|
||||||
|
#define NN_KEY_NUMPADCOMMA 0xB3
|
||||||
|
#define NN_KEY_NUMPADENTER 0x9C
|
||||||
|
#define NN_KEY_NUMPADEQUALS 0x8D
|
||||||
|
|
||||||
|
// the bottom side, can also be downwards / negative y
|
||||||
|
#define NN_SIDE_BOTTOM 0
|
||||||
|
// the top side, can also be upwards / positive y
|
||||||
|
#define NN_SIDE_TOP 1
|
||||||
|
// backwards, can also be north / negative z
|
||||||
|
#define NN_SIDE_BACK 2
|
||||||
|
// forwards, can also be south / positive z
|
||||||
|
#define NN_SIDE_FRONT 3
|
||||||
|
// to the right, can also be west / negative x
|
||||||
|
#define NN_SIDE_RIGHT 4
|
||||||
|
// to the left, can also be east / positive x
|
||||||
|
#define NN_SIDE_LEFT 5
|
||||||
|
// absolutely no clue
|
||||||
|
#define NN_SIDE_UNKNOWN 6
|
||||||
|
|
||||||
|
// pushes a screen_resized signal
|
||||||
|
nn_Exit nn_pushScreenResized(nn_Computer *computer, const char *screenAddress, int newWidth, int newHeight);
|
||||||
|
// pushes a touch signal
|
||||||
|
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
||||||
|
nn_Exit nn_pushTouch(nn_Computer *computer, const char *screenAddress, double x, double y, int button, const char *player);
|
||||||
|
// pushes a drag signal
|
||||||
|
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
||||||
|
nn_Exit nn_pushDrag(nn_Computer *computer, const char *screenAddress, double x, double y, int button, const char *player);
|
||||||
|
// pushes a drop signal
|
||||||
|
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
||||||
|
nn_Exit nn_pushDrop(nn_Computer *computer, const char *screenAddress, double x, double y, int button, const char *player);
|
||||||
|
// pushes a scroll signal
|
||||||
|
// A positive direction usually means up, a negative one usually means down.
|
||||||
|
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
||||||
|
nn_Exit nn_pushScroll(nn_Computer *computer, const char *screenAddress, double x, double y, double direction, const char *player);
|
||||||
|
// pushes a walk signal
|
||||||
|
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
||||||
|
nn_Exit nn_pushWalk(nn_Computer *computer, const char *screenAddress, double x, double y, const char *player);
|
||||||
|
|
||||||
|
// pushes a key_down event
|
||||||
|
// charcode is the unicode code-point of the typed character. It should be uppercase/lowercase depending on shift or capslock.
|
||||||
|
// keycode is an OC-specific keycode, and should be from the NN_KEY_* constants.
|
||||||
|
// player is the name of the player which used the keyboard. Some programs use it for splitscreen games.
|
||||||
|
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
||||||
|
nn_Exit nn_pushKeyDown(nn_Computer *computer, const char *keyboardAddress, nn_codepoint charcode, int keycode, const char *player);
|
||||||
|
// pushes a key_up event
|
||||||
|
// charcode is the unicode code-point of the typed character. It should be uppercase/lowercase depending on shift or capslock.
|
||||||
|
// keycode is an OC-specific keycode, and should be from the NN_KEY_* constants.
|
||||||
|
// player is the name of the player which used the keyboard. Some programs use it for splitscreen games.
|
||||||
|
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
||||||
|
nn_Exit nn_pushKeyUp(nn_Computer *computer, const char *keyboardAddress, nn_codepoint charcode, int keycode, const char *player);
|
||||||
|
// pushes a clipboard event
|
||||||
|
// clipboard should be a NULL-terminated string.
|
||||||
|
// NN does no truncation of the contents, but it is best to limit it.
|
||||||
|
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
||||||
|
nn_Exit nn_pushClipboard(nn_Computer *computer, const char *keyboardAddress, const char *clipboard, const char *player);
|
||||||
|
// pushes a clipboard event
|
||||||
|
// len is the length of the clipboard.
|
||||||
|
// NN does no truncation of the contents, but it is best to limit it.
|
||||||
|
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
||||||
|
nn_Exit nn_pushLClipboard(nn_Computer *computer, const char *keyboardAddress, const char *clipboard, size_t len, const char *player);
|
||||||
|
|
||||||
|
// pushes a redstone_changed signal.
|
||||||
|
// side is the side of the device the redstone changed on
|
||||||
|
// oldValue is the old value
|
||||||
|
// newValue is the new value, must not be equal to oldValue
|
||||||
|
// color is the color of the redstone signal
|
||||||
|
// if color < 0, it is set to null
|
||||||
|
nn_Exit nn_pushRedstoneChanged(nn_Computer *computer, const char *redstoneAddress, int side, int oldValue, int newValue, int color);
|
||||||
|
|
||||||
|
// pushes a motion signal.
|
||||||
|
// Do note that it is meant to only be sent if the entity has a direct line of sight and if |(relX, relY, relZ)| >= sensitivity.
|
||||||
|
// This signal does *not* check if the motion sensor actually is sensitive enough to detect it, so make sure to check it yourself.
|
||||||
|
// relX, relY and relZ are the relative postion in 3D Cartesian space.
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Pushes an internet_ready signal.
|
||||||
|
// This signal is queued when an internet socket is ready for commmunication.
|
||||||
|
nn_Exit nn_pushInternetReady(nn_Computer *computer, const char *id, size_t idlen);
|
||||||
|
|
||||||
|
// A buffer with encoded values
|
||||||
|
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.
|
||||||
|
// 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.
|
||||||
|
// 2. Simplify implementing packet queues, which should be used in relays. The lack of access to raw values would force implementers to use
|
||||||
|
// an encoding anyways.
|
||||||
|
// This only encodes the contents, not the sender, hops, or other metadata which may be needed in the queue.
|
||||||
|
// This does not pop the values, in case you need them afterwards. If you don't just call nn_popn().
|
||||||
|
// The encoding is architecture-dependent, so be careful with storing it on-disk.
|
||||||
|
// Do note that the architecture-dependent parts are sizeof(double), sizeof(size_t) and endianness.
|
||||||
|
// The encoding is simple:
|
||||||
|
// - 0x00 for null
|
||||||
|
// - 0x01 for true
|
||||||
|
// - 0x02 for false
|
||||||
|
// - 0x03 + <bytes of double> for a number
|
||||||
|
// - 0x04 + <bytes of size_t length> + <bytes> for a string
|
||||||
|
// - 0x05 + <bytes of size_t id> for resource
|
||||||
|
// - 0x06 + <bytes of size_t length> + <values> for a table
|
||||||
|
nn_Exit nn_encodeNetworkContents(nn_Computer *computer, nn_EncodedNetworkContents *contents, size_t valueCount);
|
||||||
|
// Allocates a copy of [buf] and stores it in contents.
|
||||||
|
// This is useful for copying network contents, either from storage or from another buffer.
|
||||||
|
nn_Exit nn_copyNetworkContents(nn_Context *ctx, nn_EncodedNetworkContents *contents, const char *buf, size_t buflen, size_t valueCount);
|
||||||
|
void nn_dropNetworkContents(nn_EncodedNetworkContents *contents);
|
||||||
|
// Pushes the encoded contents onto the stack.
|
||||||
|
// This does not drop the network contents.
|
||||||
|
nn_Exit nn_pushNetworkContents(nn_Computer *computer, const nn_EncodedNetworkContents *contents);
|
||||||
|
|
||||||
|
// push a modem_message, can be queued by both modems and tunnels.
|
||||||
|
// This does not check if the modem has that port open, so make sure to check it yourself.
|
||||||
|
// It does not check if the distance is within the modem's range, if it is wireless, and thus does not send it.
|
||||||
|
// Note that relays should change the sender.
|
||||||
|
nn_Exit nn_pushModemMessage(nn_Computer *computer, const char *modemAddress, const char *sender, int port, double distance, const nn_EncodedNetworkContents *contents);
|
||||||
|
|
||||||
// EEPROM class
|
// EEPROM class
|
||||||
|
|
||||||
// reads and writes are always 1/1
|
// reads and writes are always 1/1
|
||||||
@@ -1520,8 +1804,12 @@ typedef struct nn_GPU {
|
|||||||
int setForegroundPerTick;
|
int setForegroundPerTick;
|
||||||
// amount of times setBackground can be called before running out of budget.
|
// amount of times setBackground can be called before running out of budget.
|
||||||
int setBackgroundPerTick;
|
int setBackgroundPerTick;
|
||||||
// energy per non-space set.
|
// energy per pixel set.
|
||||||
double energyPerWrite;
|
double energyPerWrite;
|
||||||
|
// energy per pixel filled
|
||||||
|
double energyPerFill;
|
||||||
|
// energy per pixel copied
|
||||||
|
double energyPerCopy;
|
||||||
// energy per space set.
|
// energy per space set.
|
||||||
double energyPerClear;
|
double energyPerClear;
|
||||||
} nn_GPU;
|
} nn_GPU;
|
||||||
@@ -1923,14 +2211,6 @@ typedef struct nn_Modem {
|
|||||||
double costPerStrength;
|
double costPerStrength;
|
||||||
} nn_Modem;
|
} 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_defaultWiredModem;
|
||||||
extern nn_Modem nn_defaultWirelessModems[2];
|
extern nn_Modem nn_defaultWirelessModems[2];
|
||||||
|
|
||||||
@@ -2039,7 +2319,7 @@ typedef struct nn_TunnelRequest {
|
|||||||
void *state;
|
void *state;
|
||||||
const nn_Tunnel *tunnel;
|
const nn_Tunnel *tunnel;
|
||||||
const char *localAddress;
|
const char *localAddress;
|
||||||
nn_ModemAction action;
|
nn_TunnelAction action;
|
||||||
union {
|
union {
|
||||||
// for send
|
// for send
|
||||||
const nn_EncodedNetworkContents *toSend;
|
const nn_EncodedNetworkContents *toSend;
|
||||||
@@ -2060,6 +2340,108 @@ typedef nn_Exit (nn_TunnelHandler)(nn_TunnelRequest *req);
|
|||||||
|
|
||||||
nn_Component *nn_createTunnel(nn_Universe *universe, const char *address, const nn_Tunnel *modem, void *state, nn_TunnelHandler *handler);
|
nn_Component *nn_createTunnel(nn_Universe *universe, const char *address, const nn_Tunnel *modem, void *state, nn_TunnelHandler *handler);
|
||||||
|
|
||||||
|
typedef enum nn_InternetProtocol {
|
||||||
|
NN_INET_NONE = 0,
|
||||||
|
NN_INET_HTTP = 1<<0,
|
||||||
|
NN_INET_TCP = 1<<1,
|
||||||
|
NN_INET_UDP = 1<<2,
|
||||||
|
NN_INET_WEBSOCKET = 1<<3,
|
||||||
|
NN_INET_TLS = 1<<4,
|
||||||
|
|
||||||
|
NN_INET_ALL = NN_INET_HTTP | NN_INET_TCP | NN_INET_UDP | NN_INET_WEBSOCKET | NN_INET_TLS,
|
||||||
|
} nn_InternetProtocol;
|
||||||
|
|
||||||
|
typedef struct nn_InternetCard {
|
||||||
|
// bitwise OR multiple of them
|
||||||
|
unsigned char protocolsSupported;
|
||||||
|
unsigned int maxReadSize;
|
||||||
|
// per-byte cost of a write
|
||||||
|
double transmissionEnergyCost;
|
||||||
|
} nn_InternetCard;
|
||||||
|
|
||||||
|
extern nn_InternetCard nn_defaultInternetCard;
|
||||||
|
|
||||||
|
typedef struct nn_InternetConnection {
|
||||||
|
nn_InternetProtocol protocol;
|
||||||
|
int port;
|
||||||
|
void *state;
|
||||||
|
nn_uuid id;
|
||||||
|
} nn_InternetConnection;
|
||||||
|
|
||||||
|
typedef struct nn_HTTPHeader {
|
||||||
|
const char *name;
|
||||||
|
const char *value;
|
||||||
|
} nn_HTTPHeader;
|
||||||
|
|
||||||
|
typedef enum nn_InternetAction {
|
||||||
|
NN_INTERNET_DROP,
|
||||||
|
|
||||||
|
// start a connection, remember to check connection->protocol to know which type of connection to establish
|
||||||
|
NN_INTERNET_CONNECT,
|
||||||
|
|
||||||
|
// Ensure a connection is established, error if not.
|
||||||
|
// It is assumed this operation will return whether it is currently connected,
|
||||||
|
// and should be called repeatedly until it works
|
||||||
|
NN_INTERNET_FINISHCONNECT,
|
||||||
|
|
||||||
|
// close a connection
|
||||||
|
NN_INTERNET_CLOSE,
|
||||||
|
|
||||||
|
// read from a connection. Set read.buf to NULL to mark EoF. read.len is the capacity, but also set how much was read in it.
|
||||||
|
NN_INTERNET_READ,
|
||||||
|
|
||||||
|
// write to a connection. HTTP connections do not have this method
|
||||||
|
NN_INTERNET_WRITE,
|
||||||
|
|
||||||
|
// get an HTTP response. Should push the response code, message (ie. OK for 200) and table
|
||||||
|
NN_INTERNET_RESPONSE,
|
||||||
|
} nn_INternetAction;
|
||||||
|
|
||||||
|
typedef struct nn_InternetRequest {
|
||||||
|
nn_Context *ctx;
|
||||||
|
nn_Computer *computer;
|
||||||
|
void *state;
|
||||||
|
const nn_InternetCard *inet;
|
||||||
|
const char *localAddress;
|
||||||
|
nn_InternetConnection *connection;
|
||||||
|
nn_INternetAction action;
|
||||||
|
union {
|
||||||
|
// does a socket connection, for any of the supported protocols
|
||||||
|
struct {
|
||||||
|
// URL of connection
|
||||||
|
const char *url;
|
||||||
|
// port. Useless for HTTP connections, as they should use 80 for HTTP and 443 for HTTPS
|
||||||
|
unsigned short port;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
// HTTP specific
|
||||||
|
size_t postdatalen;
|
||||||
|
const char *postdata;
|
||||||
|
const nn_HTTPHeader *headers;
|
||||||
|
size_t headerlen;
|
||||||
|
} http;
|
||||||
|
struct {
|
||||||
|
const char * const * subprotocols;
|
||||||
|
size_t subprotocolcount;
|
||||||
|
} websockets;
|
||||||
|
};
|
||||||
|
} connect;
|
||||||
|
struct {
|
||||||
|
const char *buf;
|
||||||
|
size_t len;
|
||||||
|
} write;
|
||||||
|
struct {
|
||||||
|
char *buf;
|
||||||
|
size_t len;
|
||||||
|
} read;
|
||||||
|
bool isConnected;
|
||||||
|
};
|
||||||
|
} nn_InternetRequest;
|
||||||
|
|
||||||
|
typedef nn_Exit (nn_InternetHandler)(nn_InternetRequest *req);
|
||||||
|
|
||||||
|
nn_Component *nn_createInternet(nn_Universe *universe, const char *address, const nn_InternetCard *inet, void *state, nn_InternetHandler *handler);
|
||||||
|
|
||||||
// Colors and palettes.
|
// Colors and palettes.
|
||||||
// Do note that the
|
// Do note that the
|
||||||
|
|
||||||
@@ -2097,250 +2479,6 @@ int nn_mapDepth(int color, int depth);
|
|||||||
// Valid depths are 1, 2, 3, 4, 8, 16 and 24.
|
// Valid depths are 1, 2, 3, 4, 8, 16 and 24.
|
||||||
const char *nn_depthName(int depth);
|
const char *nn_depthName(int depth);
|
||||||
|
|
||||||
// Signal helpers
|
|
||||||
|
|
||||||
// common mouse buttons, not an exhaustive list
|
|
||||||
#define NN_BUTTON_LEFT 0
|
|
||||||
#define NN_BUTTON_RIGHT 1
|
|
||||||
#define NN_BUTTON_MIDDLE 2
|
|
||||||
|
|
||||||
// OC keycodes
|
|
||||||
// taken from https://github.com/MightyPirates/OpenComputers/blob/52da41b5e171b43fea80342dc75d808f97a0f797/src/main/resources/assets/opencomputers/loot/openos/lib/core/full_keyboard.lua
|
|
||||||
#define NN_KEY_UNKNOWN 0
|
|
||||||
#define NN_KEY_1 0x02
|
|
||||||
#define NN_KEY_2 0x03
|
|
||||||
#define NN_KEY_3 0x04
|
|
||||||
#define NN_KEY_4 0x05
|
|
||||||
#define NN_KEY_5 0x06
|
|
||||||
#define NN_KEY_6 0x07
|
|
||||||
#define NN_KEY_7 0x08
|
|
||||||
#define NN_KEY_8 0x09
|
|
||||||
#define NN_KEY_9 0x0A
|
|
||||||
#define NN_KEY_0 0x0B
|
|
||||||
#define NN_KEY_A 0x1E
|
|
||||||
#define NN_KEY_B 0x30
|
|
||||||
#define NN_KEY_C 0x2E
|
|
||||||
#define NN_KEY_D 0x20
|
|
||||||
#define NN_KEY_E 0x12
|
|
||||||
#define NN_KEY_F 0x21
|
|
||||||
#define NN_KEY_G 0x22
|
|
||||||
#define NN_KEY_H 0x23
|
|
||||||
#define NN_KEY_I 0x17
|
|
||||||
#define NN_KEY_J 0x24
|
|
||||||
#define NN_KEY_K 0x25
|
|
||||||
#define NN_KEY_L 0x26
|
|
||||||
#define NN_KEY_M 0x32
|
|
||||||
#define NN_KEY_N 0x31
|
|
||||||
#define NN_KEY_O 0x18
|
|
||||||
#define NN_KEY_P 0x19
|
|
||||||
#define NN_KEY_Q 0x10
|
|
||||||
#define NN_KEY_R 0x13
|
|
||||||
#define NN_KEY_S 0x1F
|
|
||||||
#define NN_KEY_T 0x14
|
|
||||||
#define NN_KEY_U 0x16
|
|
||||||
#define NN_KEY_V 0x2F
|
|
||||||
#define NN_KEY_W 0x11
|
|
||||||
#define NN_KEY_X 0x2D
|
|
||||||
#define NN_KEY_Y 0x15
|
|
||||||
#define NN_KEY_Z 0x2C
|
|
||||||
|
|
||||||
#define NN_KEY_APOSTROPHE 0x28
|
|
||||||
#define NN_KEY_AT 0x91
|
|
||||||
#define NN_KEY_BACK 0x0E
|
|
||||||
#define NN_KEY_BACKSLASH 0x2B
|
|
||||||
// caps-lock
|
|
||||||
#define NN_KEY_CAPITAL 0x3A
|
|
||||||
#define NN_KEY_COLON 0x92
|
|
||||||
#define NN_KEY_COMMA 0x33
|
|
||||||
#define NN_KEY_ENTER 0x1C
|
|
||||||
#define NN_KEY_EQUALS 0x0D
|
|
||||||
// accent grave
|
|
||||||
#define NN_KEY_GRAVE 0x29
|
|
||||||
#define NN_KEY_LBRACKET 0x1A
|
|
||||||
#define NN_KEY_LCONTROL 0x1D
|
|
||||||
// left alt
|
|
||||||
#define NN_KEY_LMENU 0x38
|
|
||||||
#define NN_KEY_LSHIFT 0x2A
|
|
||||||
#define NN_KEY_MINUS 0x0C
|
|
||||||
#define NN_KEY_NUMLOCK 0x45
|
|
||||||
#define NN_KEY_PAUSE 0xC5
|
|
||||||
#define NN_KEY_PERIOD 0x34
|
|
||||||
#define NN_KEY_RBRACKET 0x1B
|
|
||||||
#define NN_KEY_RCONTROL 0x9D
|
|
||||||
// right alt
|
|
||||||
#define NN_KEY_RMENU 0xB8
|
|
||||||
#define NN_KEY_RSHIFT 0x36
|
|
||||||
// scroll lock
|
|
||||||
#define NN_KEY_SCROLL 0x46
|
|
||||||
#define NN_KEY_SEMICOLON 0x27
|
|
||||||
#define NN_KEY_SLASH 0x35
|
|
||||||
#define NN_KEY_SPACE 0x39
|
|
||||||
#define NN_KEY_STOP 0x95
|
|
||||||
#define NN_KEY_TAB 0x0F
|
|
||||||
#define NN_KEY_UNDERLINE 0x93
|
|
||||||
|
|
||||||
#define NN_KEY_UP 0xC8
|
|
||||||
#define NN_KEY_DOWN 0xD0
|
|
||||||
#define NN_KEY_LEFT 0xCB
|
|
||||||
#define NN_KEY_RIGHT 0xCD
|
|
||||||
#define NN_KEY_HOME 0xC7
|
|
||||||
#define NN_KEY_END 0xCF
|
|
||||||
#define NN_KEY_PAGEUP 0xC9
|
|
||||||
#define NN_KEY_PAGEDOWN 0xD1
|
|
||||||
#define NN_KEY_INSERT 0xD2
|
|
||||||
#define NN_KEY_DELETE 0xD3
|
|
||||||
|
|
||||||
#define NN_KEY_F1 0x3B
|
|
||||||
#define NN_KEY_F2 0x3C
|
|
||||||
#define NN_KEY_F3 0x3D
|
|
||||||
#define NN_KEY_F4 0x3E
|
|
||||||
#define NN_KEY_F5 0x3F
|
|
||||||
#define NN_KEY_F6 0x40
|
|
||||||
#define NN_KEY_F7 0x41
|
|
||||||
#define NN_KEY_F8 0x42
|
|
||||||
#define NN_KEY_F9 0x43
|
|
||||||
#define NN_KEY_F10 0x44
|
|
||||||
#define NN_KEY_F11 0x57
|
|
||||||
#define NN_KEY_F12 0x58
|
|
||||||
#define NN_KEY_F13 0x64
|
|
||||||
#define NN_KEY_F14 0x65
|
|
||||||
#define NN_KEY_F15 0x66
|
|
||||||
#define NN_KEY_F16 0x67
|
|
||||||
#define NN_KEY_F17 0x68
|
|
||||||
#define NN_KEY_F18 0x69
|
|
||||||
#define NN_KEY_F19 0x71
|
|
||||||
|
|
||||||
#define NN_KEY_KANA 0x70
|
|
||||||
#define NN_KEY_KANJI 0x94
|
|
||||||
#define NN_KEY_CONVERT 0x79
|
|
||||||
#define NN_KEY_NOCONVERT 0x7B
|
|
||||||
#define NN_KEY_YEN 0x7D
|
|
||||||
#define NN_KEY_CIRCUMFLEX 0x90
|
|
||||||
#define NN_KEY_AX 0x96
|
|
||||||
|
|
||||||
#define NN_KEY_NUMPAD0 0x52
|
|
||||||
#define NN_KEY_NUMPAD1 0x4F
|
|
||||||
#define NN_KEY_NUMPAD2 0x50
|
|
||||||
#define NN_KEY_NUMPAD3 0x51
|
|
||||||
#define NN_KEY_NUMPAD4 0x4B
|
|
||||||
#define NN_KEY_NUMPAD5 0x4C
|
|
||||||
#define NN_KEY_NUMPAD6 0x4D
|
|
||||||
#define NN_KEY_NUMPAD7 0x47
|
|
||||||
#define NN_KEY_NUMPAD8 0x48
|
|
||||||
#define NN_KEY_NUMPAD9 0x49
|
|
||||||
#define NN_KEY_NUMPADMUL 0x37
|
|
||||||
#define NN_KEY_NUMPADDIV 0xB5
|
|
||||||
#define NN_KEY_NUMPADSUB 0x4A
|
|
||||||
#define NN_KEY_NUMPADADD 0x4E
|
|
||||||
#define NN_KEY_NUMPADDECIMAL 0x53
|
|
||||||
#define NN_KEY_NUMPADCOMMA 0xB3
|
|
||||||
#define NN_KEY_NUMPADENTER 0x9C
|
|
||||||
#define NN_KEY_NUMPADEQUALS 0x8D
|
|
||||||
|
|
||||||
// the bottom side, can also be downwards / negative y
|
|
||||||
#define NN_SIDE_BOTTOM 0
|
|
||||||
// the top side, can also be upwards / positive y
|
|
||||||
#define NN_SIDE_TOP 1
|
|
||||||
// backwards, can also be north / negative z
|
|
||||||
#define NN_SIDE_BACK 2
|
|
||||||
// forwards, can also be south / positive z
|
|
||||||
#define NN_SIDE_FRONT 3
|
|
||||||
// to the right, can also be west / negative x
|
|
||||||
#define NN_SIDE_RIGHT 4
|
|
||||||
// to the left, can also be east / positive x
|
|
||||||
#define NN_SIDE_LEFT 5
|
|
||||||
// absolutely no clue
|
|
||||||
#define NN_SIDE_UNKNOWN 6
|
|
||||||
|
|
||||||
// pushes a screen_resized signal
|
|
||||||
nn_Exit nn_pushScreenResized(nn_Computer *computer, const char *screenAddress, int newWidth, int newHeight);
|
|
||||||
// pushes a touch signal
|
|
||||||
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
|
||||||
nn_Exit nn_pushTouch(nn_Computer *computer, const char *screenAddress, double x, double y, int button, const char *player);
|
|
||||||
// pushes a drag signal
|
|
||||||
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
|
||||||
nn_Exit nn_pushDrag(nn_Computer *computer, const char *screenAddress, double x, double y, int button, const char *player);
|
|
||||||
// pushes a drop signal
|
|
||||||
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
|
||||||
nn_Exit nn_pushDrop(nn_Computer *computer, const char *screenAddress, double x, double y, int button, const char *player);
|
|
||||||
// pushes a scroll signal
|
|
||||||
// A positive direction usually means up, a negative one usually means down.
|
|
||||||
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
|
||||||
nn_Exit nn_pushScroll(nn_Computer *computer, const char *screenAddress, double x, double y, double direction, const char *player);
|
|
||||||
// pushes a walk signal
|
|
||||||
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
|
||||||
nn_Exit nn_pushWalk(nn_Computer *computer, const char *screenAddress, double x, double y, const char *player);
|
|
||||||
|
|
||||||
// pushes a key_down event
|
|
||||||
// charcode is the unicode code-point of the typed character. It should be uppercase/lowercase depending on shift or capslock.
|
|
||||||
// keycode is an OC-specific keycode, and should be from the NN_KEY_* constants.
|
|
||||||
// player is the name of the player which used the keyboard. Some programs use it for splitscreen games.
|
|
||||||
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
|
||||||
nn_Exit nn_pushKeyDown(nn_Computer *computer, const char *keyboardAddress, nn_codepoint charcode, int keycode, const char *player);
|
|
||||||
// pushes a key_up event
|
|
||||||
// charcode is the unicode code-point of the typed character. It should be uppercase/lowercase depending on shift or capslock.
|
|
||||||
// keycode is an OC-specific keycode, and should be from the NN_KEY_* constants.
|
|
||||||
// player is the name of the player which used the keyboard. Some programs use it for splitscreen games.
|
|
||||||
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
|
||||||
nn_Exit nn_pushKeyUp(nn_Computer *computer, const char *keyboardAddress, nn_codepoint charcode, int keycode, const char *player);
|
|
||||||
// pushes a clipboard event
|
|
||||||
// clipboard should be a NULL-terminated string.
|
|
||||||
// NN does no truncation of the contents, but it is best to limit it.
|
|
||||||
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
|
||||||
nn_Exit nn_pushClipboard(nn_Computer *computer, const char *keyboardAddress, const char *clipboard, const char *player);
|
|
||||||
// pushes a clipboard event
|
|
||||||
// len is the length of the clipboard.
|
|
||||||
// NN does no truncation of the contents, but it is best to limit it.
|
|
||||||
// The signal is checked, as in, the player must be a user of the computer if users are defined.
|
|
||||||
nn_Exit nn_pushLClipboard(nn_Computer *computer, const char *keyboardAddress, const char *clipboard, size_t len, const char *player);
|
|
||||||
|
|
||||||
// pushes a redstone_changed signal.
|
|
||||||
// side is the side of the device the redstone changed on
|
|
||||||
// oldValue is the old value
|
|
||||||
// newValue is the new value, must not be equal to oldValue
|
|
||||||
// color is the color of the redstone signal
|
|
||||||
// if color < 0, it is set to null
|
|
||||||
nn_Exit nn_pushRedstoneChanged(nn_Computer *computer, const char *redstoneAddress, int side, int oldValue, int newValue, int color);
|
|
||||||
|
|
||||||
// pushes a motion signal.
|
|
||||||
// Do note that it is meant to only be sent if the entity has a direct line of sight and if |(relX, relY, relZ)| >= sensitivity.
|
|
||||||
// This signal does *not* check if the motion sensor actually is sensitive enough to detect it, so make sure to check it yourself.
|
|
||||||
// relX, relY and relZ are the relative postion in 3D Cartesian space.
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// applies basic encoding to a network message. This encoding has a header, and thus should remain backwards-compatible.
|
|
||||||
// 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.
|
|
||||||
// 2. Simplify implementing packet queues, which should be used in relays. The lack of access to raw values would force implementers to use
|
|
||||||
// an encoding anyways.
|
|
||||||
// This only encodes the contents, not the sender, hops, or other metadata which may be needed in the queue.
|
|
||||||
// This does not pop the values, in case you need them afterwards. If you don't just call nn_popn().
|
|
||||||
// The encoding is architecture-dependent, so be careful with storing it on-disk.
|
|
||||||
// Do note that the architecture-dependent parts are sizeof(double), sizeof(size_t) and endianness.
|
|
||||||
// The encoding is simple:
|
|
||||||
// - 0x00 for null
|
|
||||||
// - 0x01 for true
|
|
||||||
// - 0x02 for false
|
|
||||||
// - 0x03 + <bytes of double> for a number
|
|
||||||
// - 0x04 + <bytes of size_t length> + <bytes> for a string
|
|
||||||
// - 0x05 + <bytes of size_t id> for resource
|
|
||||||
// - 0x06 + <bytes of size_t length> + <values> for a table
|
|
||||||
nn_Exit nn_encodeNetworkContents(nn_Computer *computer, nn_EncodedNetworkContents *contents, size_t valueCount);
|
|
||||||
// Allocates a copy of [buf] and stores it in contents.
|
|
||||||
// This is useful for copying network contents, either from storage or from another buffer.
|
|
||||||
nn_Exit nn_copyNetworkContents(nn_Context *ctx, nn_EncodedNetworkContents *contents, const char *buf, size_t buflen, size_t valueCount);
|
|
||||||
void nn_dropNetworkContents(nn_EncodedNetworkContents *contents);
|
|
||||||
// Pushes the encoded contents onto the stack.
|
|
||||||
// This does not drop the network contents.
|
|
||||||
nn_Exit nn_pushNetworkContents(nn_Computer *computer, const nn_EncodedNetworkContents *contents);
|
|
||||||
|
|
||||||
// push a modem_message, can be queued by both modems and tunnels.
|
|
||||||
// This does not check if the modem has that port open, so make sure to check it yourself.
|
|
||||||
// It does not check if the distance is within the modem's range, if it is wireless, and thus does not send it.
|
|
||||||
// Note that relays should change the sender.
|
|
||||||
nn_Exit nn_pushModemMessage(nn_Computer *computer, const char *modemAddress, const char *sender, int port, double distance, const nn_EncodedNetworkContents *contents);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user