mirror of
https://github.com/20kdc/OC-KittenOS.git
synced 2024-11-23 10:58:06 +11:00
All the current progress, including KTC1 draft in case there's no other standard
KTC1 is only a draft for now, and if there's something equivalent to replace it, I will not hesitate to do so.
This commit is contained in:
parent
6c0659de60
commit
a5372eafe1
52
KTC1.md
Normal file
52
KTC1.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# KTC1 Specification
|
||||||
|
|
||||||
|
KittenOS Texture Compression 1 is an image compression format that, while not
|
||||||
|
size-optimized or performance-optimized for OC screens, is optimized for
|
||||||
|
streaming from disk, and always produces precise results.
|
||||||
|
|
||||||
|
KTC1's concepts are "inspired by" ETC1, and it was conceived after evaluating
|
||||||
|
ETC1 for use in KittenOS NEO. ETC1, however, is not optimally fit for
|
||||||
|
OpenComputers rendering, and thus KTC1 was created to provide an equal-size
|
||||||
|
solution that better fit these requirements.
|
||||||
|
|
||||||
|
A 256-colour palette is assumed, and it is assumed that the palette is provided
|
||||||
|
outside of KTC1's context.
|
||||||
|
|
||||||
|
A KTC1 block is one OpenComputers character (2x4 pixels), and is 4 bytes long.
|
||||||
|
|
||||||
|
The format amounts to a foreground palette index, a background palette index,
|
||||||
|
and a Unicode character index in the Basic Multilingual Plane.
|
||||||
|
|
||||||
|
The unicode character is displayed with the given colours at the position of the
|
||||||
|
block.
|
||||||
|
|
||||||
|
The renderer does not get more complicated when more blocks are involved.
|
||||||
|
|
||||||
|
Simply put, blocks that are overlapped by a previous wide character are to be
|
||||||
|
totally ignored.
|
||||||
|
|
||||||
|
The size of this format is equivalent to 4-bit indexed data and to ETC1.
|
||||||
|
|
||||||
|
For standardization's sake, the container format for KTC1 has an 8-byte header:
|
||||||
|
"OC" followed by two 16-bit big-endian unsigned integers, for width
|
||||||
|
and height in blocks, the bytes-per-block count for this format (4) as
|
||||||
|
an unsigned byte, and the amount of "comment" bytes that go after the image,
|
||||||
|
as another unsigned byte.
|
||||||
|
|
||||||
|
Example image, showing a 4x4 white "A" on black, with a standard text
|
||||||
|
black "A" on white underneath:
|
||||||
|
|
||||||
|
4F 43 00 02 00 02 04 00
|
||||||
|
FF 00 28 6E FF 00 28 B5
|
||||||
|
00 FF 00 41 00 FF 00 00
|
||||||
|
|
||||||
|
## Additional Notes
|
||||||
|
|
||||||
|
A KTC1 file is theoretically a "lossless" screenshot under the limits of the
|
||||||
|
OpenComputers system assuming the palette is correct.
|
||||||
|
|
||||||
|
The Basic Multilingual Plane access allows mixing images and text inside a
|
||||||
|
KTC1 file, and covers all characters that OpenComputers supports.
|
||||||
|
|
||||||
|
This makes KTC1 an interesting option for use as a mixed text/image interchange
|
||||||
|
format between applications.
|
@ -120,11 +120,11 @@ local function monitorGPUColours(m, cb, bg, fg)
|
|||||||
local nbg = m[5]
|
local nbg = m[5]
|
||||||
local nfg = m[6]
|
local nfg = m[6]
|
||||||
if nbg ~= bg then
|
if nbg ~= bg then
|
||||||
cb.setBackground(bg)
|
pcall(cb.setBackground, bg)
|
||||||
m[5] = bg
|
m[5] = bg
|
||||||
end
|
end
|
||||||
if nfg ~= fg then
|
if nfg ~= fg then
|
||||||
cb.setForeground(fg)
|
pcall(cb.setForeground, fg)
|
||||||
m[6] = fg
|
m[6] = fg
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -138,11 +138,11 @@ local function doBackgroundLine(m, mg, bdx, bdy, bdl)
|
|||||||
monitorGPUColours(m, mg, 0x000000, 0xFFFFFF)
|
monitorGPUColours(m, mg, 0x000000, 0xFFFFFF)
|
||||||
local str = unicode.sub(statusLine, bdx, bdx + bdl - 1)
|
local str = unicode.sub(statusLine, bdx, bdx + bdl - 1)
|
||||||
local strl = unicode.len(str)
|
local strl = unicode.len(str)
|
||||||
mg.set(bdx, bdy, unicode.undoSafeTextFormat(str))
|
pcall(mg.set, bdx, bdy, unicode.undoSafeTextFormat(str))
|
||||||
mg.fill(bdx + strl, bdy, bdl - strl, 1, " ")
|
pcall(mg.fill, bdx + strl, bdy, bdl - strl, 1, " ")
|
||||||
else
|
else
|
||||||
monitorGPUColours(m, mg, 0x000020, 0)
|
monitorGPUColours(m, mg, 0x000020, 0)
|
||||||
mg.fill(bdx, bdy, bdl, 1, " ")
|
pcall(mg.fill, bdx, bdy, bdl, 1, " ")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -265,7 +265,7 @@ local function moveSurface(surface, m, x, y, w, h, force)
|
|||||||
if renderingAllowed() and not force then
|
if renderingAllowed() and not force then
|
||||||
local cb, b = monitors[m][1]()
|
local cb, b = monitors[m][1]()
|
||||||
if b then
|
if b then
|
||||||
monitorResetBF(b)
|
monitorResetBF(monitors[m])
|
||||||
end
|
end
|
||||||
if cb then
|
if cb then
|
||||||
cb.copy(ox, oy, w, h, x - ox, y - oy)
|
cb.copy(ox, oy, w, h, x - ox, y - oy)
|
||||||
@ -326,7 +326,7 @@ local function handleSpan(target, x, y, text, bg, fg)
|
|||||||
base = unicode.sub(text, buildingSegment, buildingSegmentE)
|
base = unicode.sub(text, buildingSegment, buildingSegmentE)
|
||||||
-- rely on undoSafeTextFormat for this transform now
|
-- rely on undoSafeTextFormat for this transform now
|
||||||
monitorGPUColours(m, cb, bg, fg)
|
monitorGPUColours(m, cb, bg, fg)
|
||||||
cb.set(buildingSegmentWX, buildingSegmentWY, unicode.undoSafeTextFormat(base))
|
pcall(cb.set, buildingSegmentWX, buildingSegmentWY, unicode.undoSafeTextFormat(base))
|
||||||
buildingSegment = nil
|
buildingSegment = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -520,15 +520,37 @@ everestProvider(function (pkg, pid, sendSig)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
-- THE EVEREST USER API ENDS (now for the session API, which just does boring stuff)
|
-- THE EVEREST USER API ENDS (now for the session API, which just does boring stuff)
|
||||||
|
-- used later on for lost monitor, too
|
||||||
|
local function disclaimMonitor(mon)
|
||||||
|
neo.ensureType(mon, "string")
|
||||||
|
screens.disclaim(mon)
|
||||||
|
for k, v in ipairs(monitors) do
|
||||||
|
if v[2] == mon then
|
||||||
|
table.remove(monitors, k)
|
||||||
|
reconcileAll()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
everestSessionProvider(function (pkg, pid, sendSig)
|
everestSessionProvider(function (pkg, pid, sendSig)
|
||||||
return {
|
return {
|
||||||
endSession = function (gotoBristol)
|
endSession = function (gotoBristol)
|
||||||
|
neo.ensureType(gotoBristol, "boolean")
|
||||||
shuttingDown = true
|
shuttingDown = true
|
||||||
if gotoBristol then
|
if gotoBristol then
|
||||||
suggestAppsStop()
|
suggestAppsStop()
|
||||||
dying()
|
dying()
|
||||||
end
|
end
|
||||||
end
|
end,
|
||||||
|
getMonitors = function ()
|
||||||
|
local details = {}
|
||||||
|
for k, v in ipairs(monitors) do
|
||||||
|
details[k] = v[2]
|
||||||
|
end
|
||||||
|
return details
|
||||||
|
end,
|
||||||
|
disclaimMonitor = disclaimMonitor
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
-- THE EVEREST SESSION API ENDS
|
-- THE EVEREST SESSION API ENDS
|
||||||
@ -539,7 +561,14 @@ end)
|
|||||||
-- Alt-Up/Down/Left/Right: Move surface
|
-- Alt-Up/Down/Left/Right: Move surface
|
||||||
local isAltDown = false
|
local isAltDown = false
|
||||||
local isCtrDown = false
|
local isCtrDown = false
|
||||||
local function key(ka, kc, down)
|
local function key(ku, ka, kc, down)
|
||||||
|
local ku = screens.getMonitorByKeyboard(ku)
|
||||||
|
if not ku then return end
|
||||||
|
for k, v in ipairs(monitors) do
|
||||||
|
if v[2] == mu then
|
||||||
|
lIM = k
|
||||||
|
end
|
||||||
|
end
|
||||||
local focus = surfaces[1]
|
local focus = surfaces[1]
|
||||||
if kc == 29 then isCtrDown = down end
|
if kc == 29 then isCtrDown = down end
|
||||||
if kc == 56 then isAltDown = down end
|
if kc == 56 then isAltDown = down end
|
||||||
@ -617,16 +646,10 @@ while not shuttingDown do
|
|||||||
local s = {coroutine.yield()}
|
local s = {coroutine.yield()}
|
||||||
if renderingAllowed() then
|
if renderingAllowed() then
|
||||||
if s[1] == "h.key_down" then
|
if s[1] == "h.key_down" then
|
||||||
local m = screens.getMonitorByKeyboard(s[2])
|
key(s[2], s[3], s[4], true)
|
||||||
for k, v in ipairs(monitors) do
|
|
||||||
if v[2] == m then
|
|
||||||
lIM = k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
key(s[3], s[4], true)
|
|
||||||
end
|
end
|
||||||
if s[1] == "h.key_up" then
|
if s[1] == "h.key_up" then
|
||||||
key(s[3], s[4], false)
|
key(s[2], s[3], s[4], false)
|
||||||
end
|
end
|
||||||
if s[1] == "h.clipboard" then
|
if s[1] == "h.clipboard" then
|
||||||
if surfaces[1] then
|
if surfaces[1] then
|
||||||
@ -697,13 +720,7 @@ while not shuttingDown do
|
|||||||
performClaim(s[3])
|
performClaim(s[3])
|
||||||
end
|
end
|
||||||
if s[2] == "lost" then
|
if s[2] == "lost" then
|
||||||
for k, v in ipairs(monitors) do
|
handleLostMonitor(s[3])
|
||||||
if v[2] == s[3] then
|
|
||||||
table.remove(monitors, k)
|
|
||||||
reconcileAll()
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if s[1] == "x.neo.sys.manage" then
|
if s[1] == "x.neo.sys.manage" then
|
||||||
|
@ -47,14 +47,14 @@ local settings = {
|
|||||||
|
|
||||||
local function loadSettings()
|
local function loadSettings()
|
||||||
pcall(function ()
|
pcall(function ()
|
||||||
local fw = require("sys-filewrap")
|
local fw = require("sys-filewrap").create
|
||||||
local se = require("serial")
|
local se = require("serial").deserialize
|
||||||
local st = fw(fs.primary, "data/sys-glacier/sysconf.lua", false)
|
local st = fw(fs.primary, "data/sys-glacier/sysconf.lua", false)
|
||||||
local cfg = st.read("*a")
|
local cfg = st.read("*a")
|
||||||
st.close()
|
st.close()
|
||||||
st = nil
|
st = nil
|
||||||
fw = nil
|
fw = nil
|
||||||
cfg = se.deserialize(cfg)
|
cfg = se(cfg)
|
||||||
for k, v in pairs(cfg) do
|
for k, v in pairs(cfg) do
|
||||||
if type(k) == "string" then
|
if type(k) == "string" then
|
||||||
if type(v) == "string" then
|
if type(v) == "string" then
|
||||||
@ -65,11 +65,11 @@ local function loadSettings()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
local function saveSettings()
|
local function saveSettings()
|
||||||
local fw = require("sys-filewrap")
|
local fw = require("sys-filewrap").create
|
||||||
local se = require("serial")
|
local se = require("serial").serialize
|
||||||
fs.primary.makeDirectory("data/sys-glacier")
|
fs.primary.makeDirectory("data/sys-glacier")
|
||||||
local st = fw(fs.primary, "data/sys-glacier/sysconf.lua", true)
|
local st = fw(fs.primary, "data/sys-glacier/sysconf.lua", true)
|
||||||
st.write(se.serialize(settings))
|
st.write(se(settings))
|
||||||
st.close()
|
st.close()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -252,7 +252,6 @@ donkonitRDProvider(function (pkg, pid, sendSig)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
getClaimable = function ()
|
getClaimable = function ()
|
||||||
local c = {}
|
local c = {}
|
||||||
-- do we have gpu?
|
-- do we have gpu?
|
||||||
|
@ -78,24 +78,31 @@ nexus = {
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
local function matchesSvc(xd, pkg, perm)
|
local function getPfx(xd, pkg)
|
||||||
-- This is to ensure the prefix naming scheme is FOLLOWED!
|
-- This is to ensure the prefix naming scheme is FOLLOWED!
|
||||||
-- sys- : System, part of KittenOS NEO and thus tries to present a "unified fragmented interface" in 'neo'
|
-- sys- : System, part of KittenOS NEO and thus tries to present a "unified fragmented interface" in 'neo'
|
||||||
-- app- : Application - these can have ad-hoc relationships. It is EXPECTED these have a GUI
|
-- app- : Application - these can have ad-hoc relationships. It is EXPECTED these have a GUI
|
||||||
-- svc- : Service - Same as Application but with no expectation of desktop usability
|
-- svc- : Service - Same as Application but with no expectation of desktop usability
|
||||||
-- Libraries "have no rights" as they are essentially loadable blobs of Lua code.
|
-- Libraries "have no rights" as they are essentially loadable blobs of Lua code.
|
||||||
-- They have access via the calling program, and have a subset of the NEO Kernel API
|
-- They have access via the calling program, and have a subset of the NEO Kernel API
|
||||||
|
-- Apps can register with their own name, w/ details
|
||||||
local pfx = nil
|
local pfx = nil
|
||||||
if pkg:sub(1, 4) == "app-" then pfx = "app" end
|
if pkg:sub(1, 4) == "app-" then pfx = "app" end
|
||||||
if pkg:sub(1, 4) == "svc-" then pfx = "svc" end
|
if pkg:sub(1, 4) == "svc-" then pfx = "svc" end
|
||||||
if pfx then
|
if pfx then
|
||||||
-- Apps can register with their own name, w/ details
|
return xd .. pfx .. "." .. pkg:sub(5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function matchesSvc(xd, pkg, perm)
|
||||||
|
local pfx = getPfx(xd, pkg)
|
||||||
|
if pfx then
|
||||||
local permAct = perm
|
local permAct = perm
|
||||||
local paP = permAct:match("/[a-z0-9/%.]*$")
|
local paP = permAct:match("/[a-z0-9/%.]*$")
|
||||||
if paP then
|
if paP then
|
||||||
permAct = permAct:sub(1, #permAct - #paP)
|
permAct = permAct:sub(1, #permAct - #paP)
|
||||||
end
|
end
|
||||||
if permAct == xd .. pfx .. "." .. pkg:sub(5) then
|
if permAct == pfx then
|
||||||
return "allow"
|
return "allow"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -113,6 +120,9 @@ donkonitDFProvider(function (pkg, pid, sendSig)
|
|||||||
end
|
end
|
||||||
return {
|
return {
|
||||||
showFileDialogAsync = function (forWrite)
|
showFileDialogAsync = function (forWrite)
|
||||||
|
if not rawequal(forWrite, nil) then
|
||||||
|
require("sys-filewrap").ensureMode(forWrite)
|
||||||
|
end
|
||||||
-- Not hooked into the event API, so can't safely interfere
|
-- Not hooked into the event API, so can't safely interfere
|
||||||
-- Thus, this is async and uses a return event.
|
-- Thus, this is async and uses a return event.
|
||||||
local tag = {}
|
local tag = {}
|
||||||
@ -124,6 +134,7 @@ donkonitDFProvider(function (pkg, pid, sendSig)
|
|||||||
end)
|
end)
|
||||||
return tag
|
return tag
|
||||||
end,
|
end,
|
||||||
|
myApi = getPfx("", pkg),
|
||||||
lockPerm = function (perm)
|
lockPerm = function (perm)
|
||||||
-- Are we allowed to?
|
-- Are we allowed to?
|
||||||
if not matchesSvc("x.", pkg, perm) then
|
if not matchesSvc("x.", pkg, perm) then
|
||||||
@ -141,22 +152,22 @@ donkonitDFProvider(function (pkg, pid, sendSig)
|
|||||||
end,
|
end,
|
||||||
-- Paths must begin with / implicitly
|
-- Paths must begin with / implicitly
|
||||||
list = function (path)
|
list = function (path)
|
||||||
if type(path) ~= "string" then error("Expected path to be string") end
|
neo.ensureType(path, "string")
|
||||||
path = prefixNS .. path
|
path = prefixNS .. path
|
||||||
neo.ensurePath(path, prefixWS)
|
neo.ensurePath(path, prefixWS)
|
||||||
if path:sub(#path, #path) ~= "/" then error("Expected / at end") end
|
if path:sub(#path, #path) ~= "/" then error("Expected / at end") end
|
||||||
return fs.primary.list(path:sub(1, #path - 1))
|
return fs.primary.list(path:sub(1, #path - 1))
|
||||||
end,
|
end,
|
||||||
makeDirectory = function (path)
|
makeDirectory = function (path)
|
||||||
if type(path) ~= "string" then error("Expected path to be string") end
|
neo.ensureType(path, "string")
|
||||||
path = prefixNS .. path
|
path = prefixNS .. path
|
||||||
neo.ensurePath(path, prefixWS)
|
neo.ensurePath(path, prefixWS)
|
||||||
if path:sub(#path, #path) == "/" then error("Expected no / at end") end
|
if path:sub(#path, #path) == "/" then error("Expected no / at end") end
|
||||||
return fs.primary.makeDirectory(path)
|
return fs.primary.makeDirectory(path)
|
||||||
end,
|
end,
|
||||||
rename = function (path1, path2)
|
rename = function (path1, path2)
|
||||||
if type(path1) ~= "string" then error("Expected path to be string") end
|
neo.ensureType(path1, "string")
|
||||||
if type(path2) ~= "string" then error("Expected path to be string") end
|
neo.ensureType(path2, "string")
|
||||||
path1 = prefixNS .. path1
|
path1 = prefixNS .. path1
|
||||||
path2 = prefixNS .. path2
|
path2 = prefixNS .. path2
|
||||||
neo.ensurePath(path1, prefixWS)
|
neo.ensurePath(path1, prefixWS)
|
||||||
@ -166,12 +177,12 @@ donkonitDFProvider(function (pkg, pid, sendSig)
|
|||||||
return fs.primary.rename(path1, path2)
|
return fs.primary.rename(path1, path2)
|
||||||
end,
|
end,
|
||||||
open = function (path, mode)
|
open = function (path, mode)
|
||||||
if type(path) ~= "string" then error("Expected path to be string") end
|
neo.ensureType(path, "string")
|
||||||
if type(mode) ~= "boolean" then error("Expected mode to be boolean (writing)") end
|
-- mode verified by filewrap
|
||||||
path = prefixNS .. path
|
path = prefixNS .. path
|
||||||
neo.ensurePath(path, prefixWS)
|
neo.ensurePath(path, prefixWS)
|
||||||
if path:sub(#path, #path) == "/" then error("Expected no / at end") end
|
if path:sub(#path, #path) == "/" then error("Expected no / at end") end
|
||||||
local fw, closer = require("sys-filewrap")(fs.primary, path, mode)
|
local fw, closer = require("sys-filewrap").create(fs.primary, path, mode)
|
||||||
local oc = fw.close
|
local oc = fw.close
|
||||||
fw.close = function ()
|
fw.close = function ()
|
||||||
oc()
|
oc()
|
||||||
@ -181,14 +192,14 @@ donkonitDFProvider(function (pkg, pid, sendSig)
|
|||||||
return fw
|
return fw
|
||||||
end,
|
end,
|
||||||
remove = function (path)
|
remove = function (path)
|
||||||
if type(path) ~= "string" then error("Expected path to be string") end
|
neo.ensureType(path, "string")
|
||||||
path = prefixNS .. path
|
path = prefixNS .. path
|
||||||
neo.ensurePath(path, prefixWS)
|
neo.ensurePath(path, prefixWS)
|
||||||
if path:sub(#path, #path) == "/" then error("Expected no / at end") end
|
if path:sub(#path, #path) == "/" then error("Expected no / at end") end
|
||||||
return fs.primary.remove(path)
|
return fs.primary.remove(path)
|
||||||
end,
|
end,
|
||||||
stat = function (path)
|
stat = function (path)
|
||||||
if type(path) ~= "string" then error("Expected path to be string") end
|
neo.ensureType(path, "string")
|
||||||
path = prefixNS .. path
|
path = prefixNS .. path
|
||||||
neo.ensurePath(path, prefixWS)
|
neo.ensurePath(path, prefixWS)
|
||||||
if path:sub(#path, #path) == "/" then error("Expected no / at end") end
|
if path:sub(#path, #path) == "/" then error("Expected no / at end") end
|
||||||
|
@ -31,22 +31,24 @@ local function shutdown(reboot)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function rstfbDraw(gpu)
|
local function rstfbDraw(gpu)
|
||||||
gpu.setBackground(0xFFFFFF)
|
pcall(gpu.setBackground, 0xFFFFFF)
|
||||||
gpu.setForeground(0x000000)
|
pcall(gpu.setForeground, 0x000000)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function basicDraw(gpu)
|
local function basicDraw(gpu)
|
||||||
scrW, scrH = gpu.getResolution()
|
local ok, sw, sh = pcall(gpu.getResolution)
|
||||||
gpu.fill(1, 1, scrW, scrH, " ")
|
if not ok then return end
|
||||||
gpu.set(2, 2, "KittenOS NEO")
|
scrW, scrH = sw, sh
|
||||||
|
pcall(gpu.fill, 1, 1, scrW, scrH, " ")
|
||||||
|
pcall(gpu.set, 2, 2, "KittenOS NEO")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function advDraw(gpu)
|
local function advDraw(gpu)
|
||||||
basicDraw(gpu)
|
basicDraw(gpu)
|
||||||
local usage = math.floor((os.totalMemory() - os.freeMemory()) / 1024)
|
local usage = math.floor((os.totalMemory() - os.freeMemory()) / 1024)
|
||||||
gpu.set(2, 3, "RAM Usage: " .. usage .. "K / " .. math.floor(os.totalMemory() / 1024) .. "K")
|
pcall(gpu.set, 2, 3, "RAM Usage: " .. usage .. "K / " .. math.floor(os.totalMemory() / 1024) .. "K")
|
||||||
for i = 1, #warnings do
|
for i = 1, #warnings do
|
||||||
gpu.set(2, 6 + i, warnings[i])
|
pcall(gpu.set, 2, 6 + i, warnings[i])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -91,10 +93,12 @@ local function retrieveNssMonitor(nss)
|
|||||||
if gpu then
|
if gpu then
|
||||||
local gcb = gpu()
|
local gcb = gpu()
|
||||||
if gcb then
|
if gcb then
|
||||||
table.insert(subpool, {gpu, v})
|
pcall(function ()
|
||||||
gcb.setBackground(0x000020)
|
gcb.setBackground(0x000020)
|
||||||
local w, h = gcb.getResolution()
|
local w, h = gcb.getResolution()
|
||||||
gcb.fill(1, 1, w, h, " ")
|
gcb.fill(1, 1, w, h, " ")
|
||||||
|
table.insert(subpool, {gpu, v})
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -107,9 +111,7 @@ local function retrieveNssMonitor(nss)
|
|||||||
end
|
end
|
||||||
-- done with search
|
-- done with search
|
||||||
local gpu = gpuG()
|
local gpu = gpuG()
|
||||||
scrW, scrH = gpu.getResolution()
|
|
||||||
rstfbDraw(gpu)
|
rstfbDraw(gpu)
|
||||||
gpu.fill(1, 1, scrW, scrH, " ")
|
|
||||||
performDisclaim = function (full)
|
performDisclaim = function (full)
|
||||||
nss.disclaim(subpool[1][2])
|
nss.disclaim(subpool[1][2])
|
||||||
if full then
|
if full then
|
||||||
@ -212,7 +214,7 @@ local function finalPrompt()
|
|||||||
local gpu = gpuG()
|
local gpu = gpuG()
|
||||||
rstfbDraw(gpu)
|
rstfbDraw(gpu)
|
||||||
basicDraw(gpu)
|
basicDraw(gpu)
|
||||||
gpu.set(2, 4, "Shutting down...")
|
pcall(gpu.set, 2, 4, "Shutting down...")
|
||||||
shutdown(false)
|
shutdown(false)
|
||||||
end
|
end
|
||||||
end, 2, scrH - 1, unicode.len(shButton)},
|
end, 2, scrH - 1, unicode.len(shButton)},
|
||||||
@ -223,7 +225,7 @@ local function finalPrompt()
|
|||||||
local gpu = gpuG()
|
local gpu = gpuG()
|
||||||
rstfbDraw(gpu)
|
rstfbDraw(gpu)
|
||||||
basicDraw(gpu)
|
basicDraw(gpu)
|
||||||
gpu.set(2, 4, "Rebooting...")
|
pcall(gpu.set, 2, 4, "Rebooting...")
|
||||||
shutdown(true)
|
shutdown(true)
|
||||||
end
|
end
|
||||||
end, 3 + unicode.len(shButton), scrH - 1, unicode.len(rbButton)},
|
end, 3 + unicode.len(shButton), scrH - 1, unicode.len(rbButton)},
|
||||||
@ -234,7 +236,7 @@ local function finalPrompt()
|
|||||||
local gpu = gpuG()
|
local gpu = gpuG()
|
||||||
rstfbDraw(gpu)
|
rstfbDraw(gpu)
|
||||||
basicDraw(gpu)
|
basicDraw(gpu)
|
||||||
gpu.set(2, 4, "Login to activate Safe Mode.")
|
pcall(gpu.set, 2, 4, "Login to activate Safe Mode.")
|
||||||
sleep(1)
|
sleep(1)
|
||||||
gpu = gpuG()
|
gpu = gpuG()
|
||||||
safeModeActive = true
|
safeModeActive = true
|
||||||
@ -249,14 +251,14 @@ local function finalPrompt()
|
|||||||
local gpu = gpuG()
|
local gpu = gpuG()
|
||||||
for k, v in ipairs(controls) do
|
for k, v in ipairs(controls) do
|
||||||
if k == control then
|
if k == control then
|
||||||
gpu.setBackground(0x000000)
|
pcall(gpu.setBackground, 0x000000)
|
||||||
gpu.setForeground(0xFFFFFF)
|
pcall(gpu.setForeground, 0xFFFFFF)
|
||||||
else
|
else
|
||||||
gpu.setBackground(0xFFFFFF)
|
pcall(gpu.setBackground, 0xFFFFFF)
|
||||||
gpu.setForeground(0x000000)
|
pcall(gpu.setForeground, 0x000000)
|
||||||
end
|
end
|
||||||
gpu.fill(v[3], v[4], v[5], 1, " ")
|
pcall(gpu.fill, v[3], v[4], v[5], 1, " ")
|
||||||
gpu.set(v[3], v[4], v[1]())
|
pcall(gpu.set, v[3], v[4], v[1]())
|
||||||
end
|
end
|
||||||
-- event handling...
|
-- event handling...
|
||||||
local sig = {coroutine.yield()}
|
local sig = {coroutine.yield()}
|
||||||
@ -336,9 +338,9 @@ local function initializeSystem()
|
|||||||
gpu.bind(screen, true)
|
gpu.bind(screen, true)
|
||||||
local gW, gH = gpu.maxResolution()
|
local gW, gH = gpu.maxResolution()
|
||||||
gW, gH = math.min(80, gW), math.min(25, gH)
|
gW, gH = math.min(80, gW), math.min(25, gH)
|
||||||
gpu.setResolution(gW, gH)
|
pcall(gpu.setResolution, gW, gH)
|
||||||
pcall(gpu.setDepth, gpu.maxDepth()) -- can crash on OCEmu if done at the "wrong time"
|
pcall(gpu.setDepth, gpu.maxDepth()) -- can crash on OCEmu if done at the "wrong time"
|
||||||
gpu.setForeground(0x000000)
|
pcall(gpu.setForeground, 0x000000)
|
||||||
end
|
end
|
||||||
local w = 1
|
local w = 1
|
||||||
local steps = {
|
local steps = {
|
||||||
@ -373,12 +375,12 @@ local function initializeSystem()
|
|||||||
end
|
end
|
||||||
if ev[1] == "k.timer" then
|
if ev[1] == "k.timer" then
|
||||||
if gpu then
|
if gpu then
|
||||||
gpu.setForeground(0x000000)
|
pcall(gpu.setForeground, 0x000000)
|
||||||
if w < stepCount then
|
if w < stepCount then
|
||||||
local n = math.floor((w / stepCount) * 255)
|
local n = math.floor((w / stepCount) * 255)
|
||||||
gpu.setBackground((n * 0x10000) + (n * 0x100) + n)
|
pcall(gpu.setBackground, (n * 0x10000) + (n * 0x100) + n)
|
||||||
else
|
else
|
||||||
gpu.setBackground(0xFFFFFF)
|
pcall(gpu.setBackground, 0xFFFFFF)
|
||||||
end
|
end
|
||||||
basicDraw(gpu)
|
basicDraw(gpu)
|
||||||
end
|
end
|
||||||
@ -440,7 +442,7 @@ if finalPrompt() then
|
|||||||
basicDraw(gpu)
|
basicDraw(gpu)
|
||||||
local nsm = neo.requestAccess("x.neo.sys.manage")
|
local nsm = neo.requestAccess("x.neo.sys.manage")
|
||||||
if nsm then
|
if nsm then
|
||||||
gpu.set(2, 4, "Rebooting for Safe Mode...")
|
pcall(gpu.set, 2, 4, "Rebooting for Safe Mode...")
|
||||||
for _, v in ipairs(nsm.listSettings()) do
|
for _, v in ipairs(nsm.listSettings()) do
|
||||||
if v ~= "password" then
|
if v ~= "password" then
|
||||||
nsm.delSetting(v)
|
nsm.delSetting(v)
|
||||||
@ -448,10 +450,10 @@ if finalPrompt() then
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- assume sysconf.lua did something very bad
|
-- assume sysconf.lua did something very bad
|
||||||
gpu.set(2, 4, "No NSM. Wiping configuration completely.")
|
pcall(gpu.set, 2, 4, "No NSM. Wiping configuration completely.")
|
||||||
local fs = neo.requestAccess("c.filesystem")
|
local fs = neo.requestAccess("c.filesystem")
|
||||||
if not fs then
|
if not fs then
|
||||||
gpu.set(2, 4, "Failed to get permission, you're doomed.")
|
pcall(gpu.set, 2, 4, "Failed to get permission, you're doomed.")
|
||||||
end
|
end
|
||||||
fs.primary.remove("/data/sys-glacier/sysconf.lua")
|
fs.primary.remove("/data/sys-glacier/sysconf.lua")
|
||||||
end
|
end
|
||||||
|
@ -270,13 +270,17 @@ wrapTable = wrapMeta(table)
|
|||||||
wrapString = wrapMeta(string)
|
wrapString = wrapMeta(string)
|
||||||
wrapUnicode = wrapMeta(unicode)
|
wrapUnicode = wrapMeta(unicode)
|
||||||
wrapCoroutine = wrapMeta(coroutine)
|
wrapCoroutine = wrapMeta(coroutine)
|
||||||
wrapOs = wrapMeta({
|
-- inject stuff into os
|
||||||
totalMemory = computer.totalMemory, freeMemory = computer.freeMemory,
|
os.totalMemory = computer.totalMemory
|
||||||
energy = computer.energy, maxEnergy = computer.maxEnergy,
|
os.freeMemory = computer.freeMemory
|
||||||
clock = os.clock, date = os.date, difftime = os.difftime,
|
os.energy = computer.energy
|
||||||
time = os.time, uptime = computer.uptime, address = computer.address
|
os.maxEnergy = computer.maxEnergy
|
||||||
})
|
os.uptime = computer.uptime
|
||||||
|
os.address = computer.address
|
||||||
|
wrapOs = wrapMeta(os)
|
||||||
wrapDebug = wrapMeta(debug)
|
wrapDebug = wrapMeta(debug)
|
||||||
|
wrapBit32 = wrapMeta(bit32)
|
||||||
|
wrapUtf8 = wrapMeta(utf8)
|
||||||
|
|
||||||
baseProcEnvCore = {
|
baseProcEnvCore = {
|
||||||
_VERSION = _VERSION,
|
_VERSION = _VERSION,
|
||||||
@ -287,6 +291,8 @@ baseProcEnvCore = {
|
|||||||
coroutine = wrapCoroutine,
|
coroutine = wrapCoroutine,
|
||||||
os = wrapOs,
|
os = wrapOs,
|
||||||
debug = wrapDebug,
|
debug = wrapDebug,
|
||||||
|
bit32 = wrapBit32,
|
||||||
|
utf8 = wrapUtf8,
|
||||||
require = loadLibraryInner,
|
require = loadLibraryInner,
|
||||||
assert = assert, ipairs = ipairs,
|
assert = assert, ipairs = ipairs,
|
||||||
load = load,
|
load = load,
|
||||||
@ -382,7 +388,7 @@ function retrieveAccess(perm, pkg, pid)
|
|||||||
-- "c.<hw>": Component
|
-- "c.<hw>": Component
|
||||||
-- "s.<event>": Signal receiver (with responsibilities for Security Request watchers)
|
-- "s.<event>": Signal receiver (with responsibilities for Security Request watchers)
|
||||||
-- "s.k.<...>": Kernel stuff
|
-- "s.k.<...>": Kernel stuff
|
||||||
-- "s.k.procnew" : New process (pkg, pid)
|
-- "s.k.procnew" : New process (pkg, pid, ppkg, ppid)
|
||||||
-- "s.k.procdie" : Process dead (pkg, pid, reason, usage)
|
-- "s.k.procdie" : Process dead (pkg, pid, reason, usage)
|
||||||
-- "s.k.registration" : Registration of service alert ("x." .. etc)
|
-- "s.k.registration" : Registration of service alert ("x." .. etc)
|
||||||
-- "s.k.deregistration" : Registration of service alert ("x." .. etc)
|
-- "s.k.deregistration" : Registration of service alert ("x." .. etc)
|
||||||
@ -480,7 +486,7 @@ function retrieveAccess(perm, pkg, pid)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function start(pkg, ...)
|
function start(pkg, ppkg, ppid, ...)
|
||||||
local proc = {}
|
local proc = {}
|
||||||
local pid = lastPID
|
local pid = lastPID
|
||||||
lastPID = lastPID + 1
|
lastPID = lastPID + 1
|
||||||
@ -571,7 +577,7 @@ function start(pkg, ...)
|
|||||||
env.neo.scheduleTimer = function (time)
|
env.neo.scheduleTimer = function (time)
|
||||||
ensureType(time, "number")
|
ensureType(time, "number")
|
||||||
local tag = {}
|
local tag = {}
|
||||||
table.insert(timers, {time, execEvent, pid, "k.timer", tag, time, ofs})
|
table.insert(timers, {time, execEvent, pid, "k.timer", tag, time})
|
||||||
return tag
|
return tag
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -587,9 +593,9 @@ function start(pkg, ...)
|
|||||||
proc.deathCBs = {function () pcall(function () env.neo.dead = true end) end}
|
proc.deathCBs = {function () pcall(function () env.neo.dead = true end) end}
|
||||||
proc.cpuUsage = 0
|
proc.cpuUsage = 0
|
||||||
-- Note the target process doesn't get the procnew (the dist occurs before it's creation)
|
-- Note the target process doesn't get the procnew (the dist occurs before it's creation)
|
||||||
pcall(distEvent, nil, "k.procnew", pkg, pid)
|
pcall(distEvent, nil, "k.procnew", pkg, pid, ppkg, ppid)
|
||||||
processes[pid] = proc
|
processes[pid] = proc
|
||||||
table.insert(timers, {0, execEvent, pid, ...})
|
table.insert(timers, {0, execEvent, pid, ppkg, ppid, ...})
|
||||||
return pid
|
return pid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ getFsNode = function (fs, parent, fsc, path, mode)
|
|||||||
end,
|
end,
|
||||||
unknownAvailable = mode ~= nil,
|
unknownAvailable = mode ~= nil,
|
||||||
selectUnknown = function (text)
|
selectUnknown = function (text)
|
||||||
local rt, re = require("sys-filewrap")(fsc, path .. text, mode)
|
local rt, re = require("sys-filewrap").create(fsc, path .. text, mode)
|
||||||
if not rt then
|
if not rt then
|
||||||
return false, dialog("Open Error: " .. tostring(re), parent)
|
return false, dialog("Open Error: " .. tostring(re), parent)
|
||||||
end
|
end
|
||||||
@ -130,8 +130,14 @@ getFsNode = function (fs, parent, fsc, path, mode)
|
|||||||
return nil, parent
|
return nil, parent
|
||||||
end})
|
end})
|
||||||
if mode ~= nil then
|
if mode ~= nil then
|
||||||
table.insert(n, {"Open", function ()
|
local tx = "Open"
|
||||||
local rt, re = require("sys-filewrap")(fsc, path, mode)
|
if mode == true then
|
||||||
|
tx = "Save"
|
||||||
|
elseif mode == "append" then
|
||||||
|
tx = "Append"
|
||||||
|
end
|
||||||
|
table.insert(n, {tx, function ()
|
||||||
|
local rt, re = require("sys-filewrap").create(fsc, path, mode)
|
||||||
if not rt then
|
if not rt then
|
||||||
return false, dialog("Open Error: " .. tostring(re), parent)
|
return false, dialog("Open Error: " .. tostring(re), parent)
|
||||||
end
|
end
|
||||||
@ -139,7 +145,7 @@ getFsNode = function (fs, parent, fsc, path, mode)
|
|||||||
end})
|
end})
|
||||||
end
|
end
|
||||||
table.insert(n, {"Copy", function ()
|
table.insert(n, {"Copy", function ()
|
||||||
local rt, re = require("sys-filewrap")(fsc, path, false)
|
local rt, re = require("sys-filewrap").create(fsc, path, false)
|
||||||
if not rt then
|
if not rt then
|
||||||
return false, dialog("Open Error: " .. tostring(re), parent)
|
return false, dialog("Open Error: " .. tostring(re), parent)
|
||||||
end
|
end
|
||||||
|
@ -1,9 +1,25 @@
|
|||||||
-- This is released into the public domain.
|
-- This is released into the public domain.
|
||||||
-- No warranty is provided, implied or otherwise.
|
-- No warranty is provided, implied or otherwise.
|
||||||
|
|
||||||
return function(dev, file, mode)
|
local function ensureMode(mode)
|
||||||
local n = "rb"
|
local n = "rb"
|
||||||
if mode then n = "wb" end
|
if type(mode) == "boolean" then
|
||||||
|
if mode then
|
||||||
|
n = "wb"
|
||||||
|
end
|
||||||
|
elseif type(mode) == "string" then
|
||||||
|
if mode == "append" then
|
||||||
|
n = "ab"
|
||||||
|
else
|
||||||
|
error("Invalid fmode " .. mode)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
error("Invalid fmode")
|
||||||
|
end
|
||||||
|
return n
|
||||||
|
end
|
||||||
|
local function create(dev, file, mode)
|
||||||
|
local n = ensureMode(mode)
|
||||||
local handle, r = dev.open(file, n)
|
local handle, r = dev.open(file, n)
|
||||||
if not handle then return nil, r end
|
if not handle then return nil, r end
|
||||||
local open = true
|
local open = true
|
||||||
@ -14,37 +30,45 @@ return function(dev, file, mode)
|
|||||||
dev.close(handle)
|
dev.close(handle)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
local function reader(len)
|
||||||
|
if not open then return end
|
||||||
|
if len == "*a" then
|
||||||
|
local ch = ""
|
||||||
|
local c = dev.read(handle, neo.readBufSize)
|
||||||
|
while c do
|
||||||
|
ch = ch .. c
|
||||||
|
c = dev.read(handle, neo.readBufSize)
|
||||||
|
end
|
||||||
|
return ch
|
||||||
|
end
|
||||||
|
if type(len) ~= "number" then error("Length of read must be number or '*a'") end
|
||||||
|
return dev.read(handle, len)
|
||||||
|
end
|
||||||
|
local function writer(txt)
|
||||||
|
if not open then return end
|
||||||
|
neo.ensureType(txt, "string")
|
||||||
|
return dev.write(handle, txt)
|
||||||
|
end
|
||||||
local function seeker(whence, point)
|
local function seeker(whence, point)
|
||||||
if not open then return end
|
if not open then return end
|
||||||
return dev.seek(handle, whence, point)
|
return dev.seek(handle, whence, point)
|
||||||
end
|
end
|
||||||
if not mode then
|
if mode == "rb" then
|
||||||
return {
|
return {
|
||||||
close = closer,
|
close = closer,
|
||||||
seek = seeker,
|
seek = seeker,
|
||||||
read = function (len)
|
read = reader
|
||||||
if len == "*a" then
|
|
||||||
local ch = ""
|
|
||||||
local c = dev.read(handle, neo.readBufSize)
|
|
||||||
while c do
|
|
||||||
ch = ch .. c
|
|
||||||
c = dev.read(handle, neo.readBufSize)
|
|
||||||
end
|
|
||||||
return ch
|
|
||||||
end
|
|
||||||
if type(len) ~= "number" then error("Length of read must be number or '*a'") end
|
|
||||||
return dev.read(handle, len)
|
|
||||||
end
|
|
||||||
}, closer
|
}, closer
|
||||||
else
|
else
|
||||||
return {
|
return {
|
||||||
close = closer,
|
close = closer,
|
||||||
seek = seeker,
|
seek = seeker,
|
||||||
write = function (txt)
|
read = reader,
|
||||||
if type(txt) ~= "string" then error("Write data must be string-bytearray") end
|
write = writer
|
||||||
local ok, b = dev.write(handle, txt)
|
|
||||||
if not ok then error(tostring(b)) end
|
|
||||||
end
|
|
||||||
}, closer
|
}, closer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return {
|
||||||
|
createMode = createMode,
|
||||||
|
create = create
|
||||||
|
}
|
||||||
|
@ -36,6 +36,7 @@ return {
|
|||||||
"docs/us-nxapp",
|
"docs/us-nxapp",
|
||||||
"docs/us-setti",
|
"docs/us-setti",
|
||||||
"docs/ul-seria",
|
"docs/ul-seria",
|
||||||
|
"docs/ul-fwrap",
|
||||||
"docs/ul-event",
|
"docs/ul-event",
|
||||||
"docs/ul-fmttx",
|
"docs/ul-fmttx",
|
||||||
"docs/ul-neoux",
|
"docs/ul-neoux",
|
||||||
|
@ -57,7 +57,7 @@ The following are just wrapMeta'd
|
|||||||
host libraries (*: altered):
|
host libraries (*: altered):
|
||||||
|
|
||||||
math, table, string, unicode*,
|
math, table, string, unicode*,
|
||||||
coroutine, os*, debug
|
coroutine, os*, debug, utf8, bit32
|
||||||
|
|
||||||
unicode is extended with:
|
unicode is extended with:
|
||||||
safeTextFormat(s, p):
|
safeTextFormat(s, p):
|
||||||
@ -92,14 +92,11 @@ Programs that thus try to work around
|
|||||||
as-needed if and when the issue is
|
as-needed if and when the issue is
|
||||||
resolved.
|
resolved.
|
||||||
|
|
||||||
os is replaced with (wrapMeta'd):
|
os is extended with:
|
||||||
totalMemory = computer.totalMemory,
|
totalMemory = computer.totalMemory,
|
||||||
freeMemory = computer.freeMemory,
|
freeMemory = computer.freeMemory,
|
||||||
energy = computer.energy,
|
energy = computer.energy,
|
||||||
maxEnergy = computer.maxEnergy,
|
maxEnergy = computer.maxEnergy,
|
||||||
clock = os.clock, date = os.date,
|
|
||||||
difftime = os.difftime,
|
|
||||||
time = os.time,
|
|
||||||
uptime = computer.uptime,
|
uptime = computer.uptime,
|
||||||
address = computer.address
|
address = computer.address
|
||||||
|
|
||||||
@ -317,6 +314,38 @@ The additional things available to
|
|||||||
and timers stick around after the
|
and timers stick around after the
|
||||||
process that owns them is dead.
|
process that owns them is dead.
|
||||||
|
|
||||||
|
The list of events, tacked on at the
|
||||||
|
end here:
|
||||||
|
|
||||||
|
k.procnew(pkg, pid, ppkg, ppid):
|
||||||
|
New process creation, with parent
|
||||||
|
information (for seat tracking)
|
||||||
|
This is not given to the process
|
||||||
|
being created, as all of this gets
|
||||||
|
given to it anyway on main function
|
||||||
|
start.
|
||||||
|
|
||||||
|
k.procdie(pkg, pid, reason, cpuTime):
|
||||||
|
Process death.
|
||||||
|
|
||||||
|
k.registration(uid):
|
||||||
|
Registration of an access.
|
||||||
|
|
||||||
|
k.deregistration(uid):
|
||||||
|
Deregistration of an access.
|
||||||
|
|
||||||
|
k.securityresponse(perm, obj):
|
||||||
|
Response to a security request made
|
||||||
|
with neo.requestAccess or such.
|
||||||
|
|
||||||
|
k.timer(tag, time):
|
||||||
|
A timer. Includes the planned uptime
|
||||||
|
for comparison.
|
||||||
|
|
||||||
|
h.*(...):
|
||||||
|
Hardware signals, by type, such
|
||||||
|
as "h.key_up"
|
||||||
|
|
||||||
With that, I hope I have documented
|
With that, I hope I have documented
|
||||||
the kernel's interface to programs.
|
the kernel's interface to programs.
|
||||||
|
|
||||||
|
49
repository/docs/ul-fwrap
Normal file
49
repository/docs/ul-fwrap
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
"sys-filewrap" is responsible for
|
||||||
|
wrapping a filesystem object with a
|
||||||
|
file-like mechanism.
|
||||||
|
|
||||||
|
It simply provides two functions:
|
||||||
|
ensureMode(mode): Ensures that a
|
||||||
|
mode is valid, and translates it.
|
||||||
|
create(dev, file, mode):
|
||||||
|
Open a file using a given proxy,
|
||||||
|
filename and mode.
|
||||||
|
|
||||||
|
The mode you give to it can be one of
|
||||||
|
the following:
|
||||||
|
false: Read "rb"
|
||||||
|
true: Write "wb"
|
||||||
|
"append": Append "ab"
|
||||||
|
May have some readability
|
||||||
|
propertiues - just in
|
||||||
|
case, I've added 'read',
|
||||||
|
but don't get your hopes
|
||||||
|
up...
|
||||||
|
|
||||||
|
It returns two things - a table, that
|
||||||
|
being the file object, and the
|
||||||
|
'close' function from that object,
|
||||||
|
for closing the file without using
|
||||||
|
a potentially modifiable table.
|
||||||
|
|
||||||
|
If the table is nil, then the "close"
|
||||||
|
function is actually a string, that
|
||||||
|
being the error.
|
||||||
|
|
||||||
|
The possible functions are:
|
||||||
|
[arw] close(): Closes the file.
|
||||||
|
[arw] seek(whence, pos): Seeks in
|
||||||
|
the file.
|
||||||
|
[aw] write(data): Writes to the
|
||||||
|
file.
|
||||||
|
[arw] read(data): Reads from the
|
||||||
|
file.
|
||||||
|
|
||||||
|
NOTE: Some of these may not actually
|
||||||
|
work. They're just there as more or
|
||||||
|
less a "do no harm" approach.
|
||||||
|
|
||||||
|
-- This is released into
|
||||||
|
the public domain.
|
||||||
|
-- No warranty is provided,
|
||||||
|
implied or otherwise.
|
@ -18,6 +18,16 @@ For programs with the prefixes "svc-"
|
|||||||
pattern "/[a-z0-9/%.]*$", or none
|
pattern "/[a-z0-9/%.]*$", or none
|
||||||
at all.
|
at all.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
r.app.nucleus:
|
||||||
|
Registers x.app.nucleus from
|
||||||
|
app-nucleus
|
||||||
|
|
||||||
|
r.svc.nucleus/ABCD:
|
||||||
|
Registers x.svc.nucleus/ABCD from
|
||||||
|
svc-nucleus
|
||||||
|
|
||||||
For how this registration works,
|
For how this registration works,
|
||||||
and how to access the resulting
|
and how to access the resulting
|
||||||
service, please see the kn-perms
|
service, please see the kn-perms
|
||||||
@ -33,31 +43,149 @@ APIs registered in this manner are
|
|||||||
mechanism if they so wish, and this
|
mechanism if they so wish, and this
|
||||||
will cause a silent failure of the
|
will cause a silent failure of the
|
||||||
lockPerm function.)
|
lockPerm function.)
|
||||||
A mechanism may also be introduced
|
|
||||||
in later versions of KittenOS NEO to
|
|
||||||
easily allow changing your svc/app's
|
|
||||||
own API to a "ask"-style security
|
|
||||||
model, but this will not be the
|
|
||||||
default, and may still be overridden
|
|
||||||
by a user with access to the
|
|
||||||
Advanced Settings control panel.
|
|
||||||
|
|
||||||
As for the system APIs...
|
As for the system APIs...
|
||||||
|
|
||||||
-- x.neo.pub.base @ sys-icecap --
|
-- x.neo.pub.base @ sys-icecap --
|
||||||
|
|
||||||
-- x.neo.pub.session @ <a shell> --
|
Gaining access to this API creates
|
||||||
|
this application's data directory,
|
||||||
|
wherever that is.
|
||||||
|
|
||||||
This API is
|
Paths for the IO parts of this API
|
||||||
|
must start with "/", and must follow
|
||||||
|
the standard KittenOS NEO path
|
||||||
|
safety rules in the kernel.
|
||||||
|
|
||||||
-- x.neo.pub.window @ <a shell> --
|
showFileDialogAsync(mode): Shows a
|
||||||
|
filedialog with a given filemode,
|
||||||
|
or nil for "none". Returns a new,
|
||||||
|
empty table as a "tag", and emits a
|
||||||
|
"filedialog" event on completion.
|
||||||
|
|
||||||
|
myApi: A string such as "svc.abc"
|
||||||
|
for the program svc-abc, used for
|
||||||
|
automatically finding the correct
|
||||||
|
API name to register for your app.
|
||||||
|
|
||||||
|
lockPerm(perm): Changes the default
|
||||||
|
permission setting for anything the
|
||||||
|
process should have permission to
|
||||||
|
define according to the matchesSvc
|
||||||
|
function, so that the user must be
|
||||||
|
asked before a program can access
|
||||||
|
the permission.
|
||||||
|
|
||||||
|
NOTE: LIST REQUIRES "/" AT THE END
|
||||||
|
AND START, WHILE THE REST CANNOT
|
||||||
|
HAVE IT AT THE END BUT MUST AT THE
|
||||||
|
START, BECAUSE THE ROOT IS "/".
|
||||||
|
There's logic here, specifically to
|
||||||
|
stop you trying to do nonsense like
|
||||||
|
deleting your own data directory...
|
||||||
|
|
||||||
|
list(path): After ensuring that the
|
||||||
|
path has a "/" at the end, lists
|
||||||
|
the contents of a directory
|
||||||
|
accessible to the application.
|
||||||
|
Returns a table containing
|
||||||
|
file/directory names, with "/"
|
||||||
|
postfixes for directories. If this
|
||||||
|
contains the invalid names "." or
|
||||||
|
"..", please report as a bug at
|
||||||
|
once, this shouldn't happen.
|
||||||
|
|
||||||
|
Everything after here ensures that
|
||||||
|
there is a "/" at the start and no
|
||||||
|
"/" at the end
|
||||||
|
|
||||||
|
makeDirectory(path): Creates the
|
||||||
|
directory with the given path.
|
||||||
|
Returns whatever the component call
|
||||||
|
did.
|
||||||
|
|
||||||
|
rename(pathA, pathB): Renames or
|
||||||
|
moves a file or directory around.
|
||||||
|
Returns whatever the component call
|
||||||
|
did.
|
||||||
|
|
||||||
|
open(path, mode): Opens a file with
|
||||||
|
a given mode (see ul-fwrap for the
|
||||||
|
list of modes).
|
||||||
|
Returns the file object,
|
||||||
|
|
||||||
|
remove(path): Removes a file.
|
||||||
|
|
||||||
|
stat(path): "I got lazy, so I took 3
|
||||||
|
API functions and combined them as
|
||||||
|
one API function!" - 20kdc
|
||||||
|
Returns {
|
||||||
|
isDirectory
|
||||||
|
size
|
||||||
|
lastModified
|
||||||
|
}
|
||||||
|
|
||||||
|
spaceUsed, spaceTotal, isReadOnly:
|
||||||
|
The filesystem proxy functions.
|
||||||
|
|
||||||
|
Events:
|
||||||
|
api, "filedialog", tag, res
|
||||||
|
|
||||||
-- x.neo.pub.session @ <a shell> --
|
-- x.neo.pub.session @ <a shell> --
|
||||||
|
|
||||||
|
This API must be implemented by any
|
||||||
|
program that the user wants to use
|
||||||
|
as a shell.
|
||||||
|
|
||||||
|
A shell should set up a Saving Throw
|
||||||
|
with sys-glacier in case of errors.
|
||||||
|
|
||||||
|
endSession(backToInit): Stops the
|
||||||
|
current session, and optionally
|
||||||
|
starts up sys-init.
|
||||||
|
endSession(false) is for switching
|
||||||
|
to a new shell.
|
||||||
|
endSession(true) is for logging out
|
||||||
|
of the session.
|
||||||
|
|
||||||
|
getMonitors(): Returns an ipairs-
|
||||||
|
form list of screen addresses for
|
||||||
|
use in disclaimMonitor and the
|
||||||
|
subsequent screens.claim call.
|
||||||
|
|
||||||
|
disclaimMonitor(address):
|
||||||
|
Disclaims a monitor. Returns true
|
||||||
|
on success. The monitor may be
|
||||||
|
reclaimed if something causes the
|
||||||
|
shell to be notified of the
|
||||||
|
monitor's existence (such as a
|
||||||
|
monitor rescan in Glacier).
|
||||||
|
|
||||||
|
No events are given. Deregistration
|
||||||
|
is equivalent to stating that you
|
||||||
|
are no longer in control of the
|
||||||
|
session, and that something else is.
|
||||||
|
|
||||||
|
-- x.neo.pub.window @ sys-everest --
|
||||||
|
|
||||||
|
This API is the reference definition
|
||||||
|
of how the windowing system works in
|
||||||
|
KittenOS NEO.
|
||||||
|
|
||||||
-- x.neo.sys.manage @ sys-glacier --
|
-- x.neo.sys.manage @ sys-glacier --
|
||||||
|
|
||||||
|
This API is how settings and ST are
|
||||||
|
managed
|
||||||
|
|
||||||
-- x.neo.sys.screens @ sys-glacier --
|
-- x.neo.sys.screens @ sys-glacier --
|
||||||
|
|
||||||
|
This API is how screens are managed
|
||||||
|
|
||||||
-- x.neo.pub.globals @ sys-glacier --
|
-- x.neo.pub.globals @ sys-glacier --
|
||||||
|
|
||||||
|
This API is some public global stuff
|
||||||
|
and spooky screen control???
|
||||||
|
|
||||||
-- This is released into
|
-- This is released into
|
||||||
the public domain.
|
the public domain.
|
||||||
-- No warranty is provided,
|
-- No warranty is provided,
|
||||||
|
Loading…
Reference in New Issue
Block a user