diff --git a/claw/repo-claw.lua b/claw/repo-claw.lua index c565b55..571aa60 100644 --- a/claw/repo-claw.lua +++ b/claw/repo-claw.lua @@ -251,6 +251,24 @@ return { "docs/repoauthors/app-slaunch" }, }, + ["svc-virtudev"] = { + desc = "a clone of vcomponent", + v = 0, + deps = { + "neo", + "zzz-license-pd" + }, + dirs = { + "apps", + "docs", + "docs/repoauthors" + }, + files = { + "apps/svc-virtudev.lua", + "apps/app-vdrslamp.lua", + "docs/repoauthors/svc-virtudev" + }, + }, -- libraries ["lib-knbs"] = { desc = "NBS reader/writer library", diff --git a/laboratory/reset.sh b/laboratory/reset.sh index ba4e8fa..ce86009 100755 --- a/laboratory/reset.sh +++ b/laboratory/reset.sh @@ -6,9 +6,5 @@ cp ocemu.cfg.default ocemu.cfg && rm -rf c1-sda c1-sdb mkdir c1-sda c1-sdb echo -n c1-sda > c1-eeprom/data.bin -cd .. -cp -r code/* laboratory/c1-sdb/ -cp -r repository/* laboratory/c1-sdb/ -lua claw/clawconv.lua laboratory/c1-sdb/data/app-claw/ < claw/code-claw.lua > /dev/null -lua claw/clawconv.lua laboratory/c1-sdb/data/app-claw/ < claw/repo-claw.lua >> /dev/null -cp -r laboratory/c1-sdb/* laboratory/c1-sda/ + +./update.sh diff --git a/laboratory/update.sh b/laboratory/update.sh new file mode 100755 index 0000000..4f23621 --- /dev/null +++ b/laboratory/update.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# This is released into the public domain. +# No warranty is provided, implied or otherwise. + +cd .. +cp -r code/* laboratory/c1-sdb/ +cp -r repository/* laboratory/c1-sdb/ +lua claw/clawconv.lua laboratory/c1-sdb/data/app-claw/ < claw/code-claw.lua > /dev/null +lua claw/clawconv.lua laboratory/c1-sdb/data/app-claw/ < claw/repo-claw.lua >> /dev/null +cp -r laboratory/c1-sdb/* laboratory/c1-sda/ diff --git a/repository/apps/app-vdrslamp.lua b/repository/apps/app-vdrslamp.lua new file mode 100644 index 0000000..68f7246 --- /dev/null +++ b/repository/apps/app-vdrslamp.lua @@ -0,0 +1,49 @@ +-- This is released into the public domain. +-- No warranty is provided, implied or otherwise. + +-- svc-vdrslamp.lua : Virtual Redstone Lamp +-- Authors: 20kdc + +local vdev = neo.requireAccess("x.svc.virtudev", "lamp dev") + +local evr = neo.requireAccess("x.neo.pub.window", "the lamp") +local wnd = evr(12, 6) + +local bLine = (" "):rep(12) + +local function blank() + return 0 +end + +local total = 0 + +vdev.install({ + type = "redstone", + address = "vdrslamp-" .. neo.pid, + slot = 0, + getWakeThreshold = blank, + setWakeThreshold = blank, + getInput = blank, + getOutput = function (i) + return total + end, + setOutput = function (i, v) + total = v + wnd.setSize(12, 6) + end +}) + +while true do + local e = {coroutine.yield()} + if e[1] == "x.neo.pub.window" then + if e[3] == "close" then + -- the ignorance of unregistration is deliberate + -- a working impl. will properly recover + return + elseif e[3] == "line" then + local bg = 0xFFFFFF + if total == 0 then bg = 0 end + wnd.span(1, e[4], bLine, bg, bg) + end + end +end diff --git a/repository/apps/svc-virtudev.lua b/repository/apps/svc-virtudev.lua new file mode 100644 index 0000000..68b2d00 --- /dev/null +++ b/repository/apps/svc-virtudev.lua @@ -0,0 +1,156 @@ +-- This is released into the public domain. +-- No warranty is provided, implied or otherwise. + +-- svc-virtudev.lua : Virtual Device interface +-- Authors: 20kdc + +local ic = neo.requireAccess("x.neo.pub.base", "to lock x.svc.virtudev") +-- this is a pretty powerful permission, and PROBABLY EXPLOITABLE +ic.lockPerm("x.svc.virtudev") +local r = neo.requireAccess("r.svc.virtudev", "api endpoint") + +local root = neo.requireAccess("k.root", "the ability to modify the component API") + +local proxies = {} +local types = {} + +local function uninstall(k) + proxies[k] = nil + types[k] = nil + root.computer.pushSignal("component_removed", k, types[k]) +end + +local users = {} +local userCount = 0 + +r(function (pkg, pid, sendSig) + local userAddresses = {} + users[pid] = userAddresses + userCount = userCount + 1 + return { + install = function (proxy) + local proxyAddress = proxy.address + local proxyType = proxy.type + assert(type(proxyAddress) == "string") + assert(type(proxyType) == "string") + assert(not proxies[proxyAddress], "proxy address in use: " .. proxyAddress) + proxies[proxyAddress] = proxy + types[proxyAddress] = proxyType + userAddresses[proxyAddress] = true + root.computer.pushSignal("component_added", proxyAddress, proxyType) + return function (a, ...) + root.computer.pushSignal(a, proxyAddress, ...) + end + end, + uninstall = function (k) + if userAddresses[k] then + uninstall(k) + userAddresses[k] = nil + end + end + } +end) + +local componentProxyRaw = root.component.proxy +local componentTypeRaw = root.component.type +local componentMethodsRaw = root.component.methods +local componentFieldsRaw = root.component.fields +local componentDocRaw = root.component.doc +local componentInvokeRaw = root.component.invoke +local componentListRaw = root.component.list + +root.component.proxy = function (address) + if proxies[address] then + return proxies[address] + end + return componentProxyRaw(address) +end + +root.component.type = function (address) + if types[address] then + return types[address] + end + return componentTypeRaw(address) +end + +local function methodsFieldsHandler(address, methods) + if proxies[address] then + local mt = {} + for k, v in pairs(proxies[address]) do + if (type(v) == "function") == methods then + mt[k] = true + end + end + return mt + end + if methods then + return componentMethodsRaw(address) + else + return componentFieldsRaw(address) + end +end + +root.component.methods = function (address) return methodsFieldsHandler(address, true) end +root.component.fields = function (address) return methodsFieldsHandler(address, false) end +root.component.doc = function (address, method) + if proxies[address] then + return tostring(proxies[address][method]) + end + return componentDocRaw(address, method) +end +root.component.invoke = function (address, method, ...) + if proxies[address] then + return proxies[address][method](...) + end + return componentInvokeRaw(address, method, ...) +end + +root.component.list = function (f, e) + local iter = componentListRaw(f, e) + local ended = false + local others = {} + for k, v in pairs(types) do + if (f == v) or ((not e) and v:find(f, 1, true)) then + table.insert(others, {k, v}) + end + end + return function () + if not ended then + local a, t = iter() + if not a then + ended = true + else + return a, t + end + end + -- at end of that, so what about others + local ent = table.remove(others, 1) + if ent then + return table.unpack(ent) + end + end +end + +while true do + local e1, e2, e3 = coroutine.yield() + if e1 == "k.procdie" then + if users[e3] then + for k, _ in pairs(users[e3]) do + uninstall(k) + end + users[e3] = nil + userCount = userCount - 1 + if userCount == 0 then + break + end + end + end +end + +root.component.proxy = componentProxyRaw +root.component.type = componentTypeRaw +root.component.methods = componentMethodsRaw +root.component.fields = componentFieldsRaw +root.component.doc = componentDocRaw +root.component.invoke = componentInvokeRaw +root.component.list = componentListRaw diff --git a/repository/docs/repoauthors/svc-virtudev b/repository/docs/repoauthors/svc-virtudev new file mode 100644 index 0000000..c031a1f --- /dev/null +++ b/repository/docs/repoauthors/svc-virtudev @@ -0,0 +1,3 @@ +repository/apps/svc-virtudev.lua: 20kdc, Public Domain +repository/apps/app-vdrslamp.lua: 20kdc, Public Domain +