spm works maybe?

This commit is contained in:
2026-08-14 20:44:11 -04:00
parent 56646625c0
commit 10aa0c62ff
82 changed files with 1706 additions and 535 deletions
+3
View File
@@ -8,5 +8,8 @@
"toHex", "toHex",
"loadcstr", "loadcstr",
"userinput" "userinput"
],
"Lua.diagnostics.disable": [
"need-check-nil"
] ]
} }
@@ -0,0 +1,9 @@
--:Minify:--
local kernel=...
local kbs = {kernel.cct.peripheral.find("tm_keyboard")}
kernel.cct.eventhooks["tm_keyboard_char"]=function(...)
end
@@ -1,394 +1,6 @@
--:Minify:-- --:Minify:--
local kernel = ... local kernel=...
local apis = kernel.apis
local native = apis.peripheral
local sides = {"top", "bottom", "left", "right", "front", "back"}
local peripheral={}
function peripheral.getNames() if kernel.gfx then
local results = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(results, side)
if native.hasType(side, "peripheral_hub") then
local remote = native.call(side, "getNamesRemote")
for _, name in ipairs(remote) do
table.insert(results, name)
end
end
end
end
return results
end
function peripheral.isPresent(name)
if native.isPresent(name) then
return true
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return true
end
end
return false
end
function peripheral.getType(peripheral)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.getType(peripheral)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "getTypeRemote", peripheral)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return table.unpack(mt.types)
end
end
function peripheral.hasType(peripheral, peripheral_type)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.hasType(peripheral, peripheral_type)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.types[peripheral_type] ~= nil
end
end
function peripheral.getMethods(name)
if native.isPresent(name) then
return native.getMethods(name)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "getMethodsRemote", name)
end
end
return nil
end
function peripheral.getName(peripheral)
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.name
end
function peripheral.call(name, method, ...)
if native.isPresent(name) then
return native.call(name, method, ...)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "callRemote", name, method, ...)
end
end
return nil
end
function peripheral.wrap(name)
local methods = peripheral.getMethods(name)
if not methods then
return nil
end
local types = { peripheral.getType(name) }
for i = 1, #types do types[types[i]] = true end
local result = setmetatable({}, {
__name = "peripheral",
name = name,
type = types[1],
types = types,
})
for _, method in ipairs(methods) do
result[method] = function(...)
return peripheral.call(name, method, ...)
end
end
return result
end
function peripheral.find(ty, filter)
local results = {}
for _, name in ipairs(peripheral.getNames()) do
if peripheral.hasType(name, ty) then
local wrapped = peripheral.wrap(name)
if filter == nil or filter(name, wrapped) then
table.insert(results, wrapped)
end
end
end
return table.unpack(results)
end
local icolors = {
[0x1] = 1, -- #000000
[0x2] = 2, -- #FFFFFF
[0x4] = 3, -- #FF0000
[0x8] = 4, -- #00FF00
[0x10] = 5, -- #0000FF
[0x20] = 6, -- #00FFFF
[0x40] = 7, -- #FF00FF
[0x80] = 8, -- #FFFF00
[0x100] = 9, -- #FF6D00
[0x200] = 10, -- #6DFF55
[0x400] = 11, -- #24FFFF
[0x800] = 12, -- #924900
[0x1000] = 13, -- #6D6D55
[0x2000] = 14, -- #DBDBAA
[0x4000] = 15, -- #6D00FF
[0x8000] = 16 -- #B6FF00
}
local colors = {
0x0001, -- #000000
0x0002, -- #FFFFFF
0x0004, -- #FF0000
0x0008, -- #00FF00
0x0010, -- #0000FF
0x0020, -- #00FFFF
0x0040, -- #FF00FF
0x0080, -- #FFFF00
0x0100, -- #FF6D00
0x0200, -- #6DFF55
0x0400, -- #24FFFF
0x0800, -- #924900
0x1000, -- #6D6D55
0x2000, -- #DBDBAA
0x4000, -- #6D00FF
0x8000 -- #B6FF00
}
local function write(text, term)
local x, y = term.getCursorPos()
local w, h = term.getSize()
for i = 1, #text do
local c = text:sub(i, i)
if c == "\n" then
y = y + 1
x = 1
elseif c == "\t" then
local tabSize = 4
local spaces = tabSize - ((x - 1) % tabSize)
term.write(string.rep(" ", spaces))
x = x + spaces
elseif c == "\b" then
if x > 1 then
x = x - 1
term.setCursorPos(x, y)
term.write(" ")
term.setCursorPos(x, y)
end
else
if x <= w and y <= h then
term.setCursorPos(x, y)
term.write(c)
x = x + 1
end
end
if x > w then
x = 1
y = y + 1
end
if y - 1 >= h then
term.scroll(1)
y = h
term.setCursorPos(x, y)
end
end
term.setCursorPos(x, y)
end
kernel.devfs.data.tty={}
local ctrl,alt = false, false
local function serializeBool(bool)
if bool then
return "T"
else
return "F"
end
end
local function newtty(obj, id, ev)
kernel.devfs.data["tty"][id] = function(op, mode)
if op=="type" then
return "character device"
elseif op=="open" then
local h = {
read=function(amount)
local rv=""
for i=1, amount or 1 do
local event = {ev()}
if event[1] then
rv=rv..event[1]
end
end
if rv=="" then rv=nil end
return rv
end,
write=function(content)
write(content, obj)
end,
size=function()
local s={obj.getSize()}
return table.concat(s,";")
end,
clear=function()
obj.clear()
obj.setCursorPos(1,1)
end,
gpos=function()
local s={obj.getCursorPos()}
return table.concat(s,";")
end,
spos=function(x,y)
return obj.setCursorPos(x,y)
end,
sfgc=function(c)
return obj.setTextColor(colors[c])
end,
sbgc=function(c)
return obj.setBackgroundColor(colors[c])
end,
gfgc=function()
return icolors[obj.getTextColor()]
end,
gbgc=function()
return icolors[obj.getBackgroundColor()]
end,
gctrl=function()
return serializeBool(ctrl)..";"..serializeBool(alt)
end
}
if mode=="rw" then
return h
elseif mode=="r" then
h["write"]=nil
return h
elseif mode=="w" then
h["read"]=nil
return h
end
end
end
end
local fifo = kernel.newFifo()
kernel.processes.cctmond = function()
local timeout = false
while true do
local event = {kernel.EFI:getMachineEvent()}
if event[1] then
local eventType = event[1]
local charOrKey = event[3]
local ctrlKeyMap = {
[apis.keys.a]=1, [apis.keys.b]=2, [apis.keys.c]=3,
[apis.keys.d]=4, [apis.keys.e]=5, [apis.keys.f]=6,
[apis.keys.g]=7, [apis.keys.h]=8, [apis.keys.i]=9,
[apis.keys.j]=10, [apis.keys.k]=11, [apis.keys.l]=12,
[apis.keys.m]=13, [apis.keys.n]=14, [apis.keys.o]=15,
[apis.keys.p]=16, [apis.keys.q]=17, [apis.keys.r]=18,
[apis.keys.s]=19, [apis.keys.t]=20, [apis.keys.u]=21,
[apis.keys.v]=22, [apis.keys.w]=23, [apis.keys.x]=24,
[apis.keys.y]=25, [apis.keys.z]=26,
}
if eventType == "keyPressed" then
if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then
ctrl = true
elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then
alt = true
end
if ctrl then
local ctrlByte = ctrlKeyMap[charOrKey]
if ctrlByte then
if ctrlByte == 3 then
for _, task in ipairs(syscall.getTasks()) do
syscall.sigsend(task, 1)
end
else
fifo.push(string.char(ctrlByte))
end
end
else
local specialKeyMap = {
[apis.keys.up] = "",
[apis.keys.down] = "",
[apis.keys.right] = "",
[apis.keys.left] = "",
[apis.keys.home] = "",
[apis.keys["end"]] = "",
[apis.keys.pageUp] = "[5~",
[apis.keys.pageDown] = "[6~",
[apis.keys.delete] = "[3~",
}
local special = specialKeyMap[charOrKey]
if special then fifo.push(special) end
end
elseif eventType == "keyReleased" then
if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then
ctrl = false
elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then
alt = false
end
elseif eventType == "keyTyped" then
if charOrKey then fifo.push(charOrKey) end
end
timeout = false
else
timeout = true
end
if timeout then
sleep(0.05)
end
end
end
newtty(apis.term, "1", fifo.pop)
for i,v in ipairs({peripheral.find("monitor")}) do
v.setTextScale(.5)
v.write("Initializing...")
newtty(v,tostring(i+1),function () end)
end end
@@ -55,11 +55,12 @@ local function displaySuperBadError(err)
lterm.write("A critical error occurred while loading the system:") lterm.write("A critical error occurred while loading the system:")
lterm.setCursorPos(1, 3) lterm.setCursorPos(1, 3)
write(err, lterm) write(err, lterm)
while true do end coroutine.yield("key")
end end
term.setCursorBlink(false) term.setCursorBlink(false)
local ok, err = xpcall(function() local ok, err = xpcall(function()
--p
local apis = {BOOT_DRIVE_PATH = BOOT_DRIVE_PATH} local apis = {BOOT_DRIVE_PATH = BOOT_DRIVE_PATH}
local lua = { local lua = {
@@ -100,6 +101,7 @@ local ok, err = xpcall(function()
_G[i] = nil _G[i] = nil
end end
end end
--p
local acekeys={ local acekeys={
[apis.keys.enter]="\n", [apis.keys.enter]="\n",
@@ -248,11 +250,12 @@ local ok, err = xpcall(function()
return value return value
end end
local peripheral={} --p
local p={}
local native = apis.peripheral local native = apis.peripheral
local sides = {"top", "bottom", "left", "right", "front", "back"} local sides = {"top", "bottom", "left", "right", "front", "back"}
function peripheral.getNames() function p.getNames()
local results = {} local results = {}
for n = 1, #sides do for n = 1, #sides do
local side = sides[n] local side = sides[n]
@@ -269,7 +272,7 @@ local ok, err = xpcall(function()
return results return results
end end
function peripheral.isPresent(name) function p.isPresent(name)
if native.isPresent(name) then if native.isPresent(name) then
return true return true
end end
@@ -283,7 +286,7 @@ local ok, err = xpcall(function()
return false return false
end end
function peripheral.getType(peripheral) function p.getType(peripheral)
if type(peripheral) == "string" then if type(peripheral) == "string" then
if native.isPresent(peripheral) then if native.isPresent(peripheral) then
return native.getType(peripheral) return native.getType(peripheral)
@@ -304,7 +307,7 @@ local ok, err = xpcall(function()
end end
end end
function peripheral.hasType(peripheral, peripheral_type) function p.hasType(peripheral, peripheral_type)
if type(peripheral) == "string" then if type(peripheral) == "string" then
if native.isPresent(peripheral) then if native.isPresent(peripheral) then
return native.hasType(peripheral, peripheral_type) return native.hasType(peripheral, peripheral_type)
@@ -325,7 +328,7 @@ local ok, err = xpcall(function()
end end
end end
function peripheral.getMethods(name) function p.getMethods(name)
if native.isPresent(name) then if native.isPresent(name) then
return native.getMethods(name) return native.getMethods(name)
end end
@@ -338,7 +341,7 @@ local ok, err = xpcall(function()
return nil return nil
end end
function peripheral.getName(peripheral) function p.getName(peripheral)
local mt = getmetatable(peripheral) local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
error("bad argument #1 (table is not a peripheral)", 2) error("bad argument #1 (table is not a peripheral)", 2)
@@ -346,7 +349,7 @@ local ok, err = xpcall(function()
return mt.name return mt.name
end end
function peripheral.call(name, method, ...) function p.call(name, method, ...)
if native.isPresent(name) then if native.isPresent(name) then
return native.call(name, method, ...) return native.call(name, method, ...)
end end
@@ -360,13 +363,13 @@ local ok, err = xpcall(function()
return nil return nil
end end
function peripheral.wrap(name) function p.wrap(name)
local methods = peripheral.getMethods(name) local methods = p.getMethods(name)
if not methods then if not methods then
return nil return nil
end end
local types = { peripheral.getType(name) } local types = { p.getType(name) }
for i = 1, #types do types[types[i]] = true end for i = 1, #types do types[types[i]] = true end
local result = setmetatable({}, { local result = setmetatable({}, {
__name = "peripheral", __name = "peripheral",
@@ -376,17 +379,17 @@ local ok, err = xpcall(function()
}) })
for _, method in ipairs(methods) do for _, method in ipairs(methods) do
result[method] = function(...) result[method] = function(...)
return peripheral.call(name, method, ...) return p.call(name, method, ...)
end end
end end
return result return result
end end
function peripheral.find(ty, filter) function p.find(ty, filter)
local results = {} local results = {}
for _, name in ipairs(peripheral.getNames()) do for _, name in ipairs(p.getNames()) do
if peripheral.hasType(name, ty) then if p.hasType(name, ty) then
local wrapped = peripheral.wrap(name) local wrapped = p.wrap(name)
if filter == nil or filter(name, wrapped) then if filter == nil or filter(name, wrapped) then
table.insert(results, wrapped) table.insert(results, wrapped)
end end
@@ -394,8 +397,8 @@ local ok, err = xpcall(function()
end end
return table.unpack(results) return table.unpack(results)
end end
--p
local allscreens = {peripheral.find("monitor")} local allscreens = {p.find("monitor")}
for i=1, #allscreens do for i=1, #allscreens do
allscreens[i].setTextScale(.5) allscreens[i].setTextScale(.5)
allscreens[i].clear() allscreens[i].clear()
@@ -404,6 +407,17 @@ local ok, err = xpcall(function()
allscreens[#allscreens+1] = apis.term allscreens[#allscreens+1] = apis.term
local callAsyncQueue = {}
local callAsyncReturn = {}
apis.callAsyncReturn = callAsyncReturn
local callidx=0
function apis.callAsync(func, ...)
callidx=callidx+1
callAsyncQueue[#callAsyncQueue+1] = {callidx, func, ...}
return callidx
end
local EFI = { local EFI = {
getEpochMs = function() return apis.os.epoch("utc") end, getEpochMs = function() return apis.os.epoch("utc") end,
getUptime = function() return apis.os.clock() * 1000 end, getUptime = function() return apis.os.clock() * 1000 end,
@@ -489,7 +503,8 @@ local ok, err = xpcall(function()
apis.term.setCursorPos(1, 1) apis.term.setCursorPos(1, 1)
local kernelCoro = coroutine.create(function() local kernelCoro = coroutine.create(function()
---@diagnostic disable-next-line: param-type-mismatch --pf
---@diagnostic disable-next-line: param-type-mismatch-
local ok, err = xpcall(Kernel, debug.traceback, EFI) local ok, err = xpcall(Kernel, debug.traceback, EFI)
if not ok and not EFI.reboot then displaySuperBadError(err) end if not ok and not EFI.reboot then displaySuperBadError(err) end
if err then if err then
@@ -518,6 +533,7 @@ local ok, err = xpcall(function()
end end
EFI.screenCtl:print("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n") EFI.screenCtl:print("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
--p
while true do while true do
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50) local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
@@ -526,28 +542,30 @@ local ok, err = xpcall(function()
while not exit do while not exit do
local event = {coroutine.yield()} local event = {coroutine.yield()}
if event[1] == "key" then if event[1] == "key" then
queueEvent(table.unpack(event))
queueEvent("keyPressed", 1, event[2]) queueEvent("keyPressed", 1, event[2])
if acekeys[event[2]] then if acekeys[event[2]] then
queueEvent("keyTyped", 1, acekeys[event[2]]) queueEvent("keyTyped", 1, acekeys[event[2]])
end end
elseif event[1] == "char" then elseif event[1] == "char" then
queueEvent(table.unpack(event))
queueEvent("keyTyped", 1, event[2]) queueEvent("keyTyped", 1, event[2])
elseif event[1] == "key_up" then elseif event[1] == "key_up" then
queueEvent(table.unpack(event))
queueEvent("keyReleased", 1, event[2]) queueEvent("keyReleased", 1, event[2])
elseif event[1] == "disk" then
queueEvent("componentAdded", "disk")
elseif event[1] == "disk_eject" then
queueEvent("componentRemoved", "disk")
elseif event[1] == "modem_message" then
queueEvent("modem_message", table.unpack(event, 2))
elseif event[1] == "rednet_message" then
queueEvent("rednet_message", table.unpack(event, 2))
elseif event[1] == "http_success" then
queueEvent("http_success", table.unpack(event, 2))
elseif event[1] == "http_failure" then
queueEvent("http_failure", table.unpack(event, 2))
elseif event[1] == "NoSleep" then elseif event[1] == "NoSleep" then
exit = true exit = true
else
queueEvent(table.unpack(event))
end
end
while #callAsyncQueue>0 do
local bundle = table.remove(callAsyncQueue, 1)
local ret = {xpcall(bundle[2], debug.traceback, table.unpack(bundle, 3))}
if not ret[1] then
callAsyncReturn[bundle[1]]={false, ret[2]}
else
callAsyncReturn[bundle[1]]={true, table.unpack(ret,2)}
end end
end end
if status == "error" or coroutine.status(kernelCoro) == "dead" then if status == "error" or coroutine.status(kernelCoro) == "dead" then
@@ -556,6 +574,12 @@ local ok, err = xpcall(function()
end end
displaySuperBadError("Kernel error: " .. tostring(err)) displaySuperBadError("Kernel error: " .. tostring(err))
coroutine.yield("key") coroutine.yield("key")
elseif status == "success" then
if EFI.reboot then
apis.os.reboot()
end
displaySuperBadError("Kernel error: Attempted to yield main thread\n"..debug.traceback(kernelCoro, "Attempted to yield main thread"))
coroutine.yield("key")
end end
initFs:refresh() initFs:refresh()
end end
@@ -3,6 +3,7 @@
local kernel=... local kernel=...
kernel.cct={} kernel.cct={}
kernel.cct.peripheral={} kernel.cct.peripheral={}
kernel.cct.callAsync=kernel.apis.callAsync
local peripheral=kernel.cct.peripheral local peripheral=kernel.cct.peripheral
local apis = kernel.apis local apis = kernel.apis
local native = apis.peripheral local native = apis.peripheral
@@ -103,6 +104,40 @@ function peripheral.getName(peripheral)
end end
function peripheral.call(name, method, ...) function peripheral.call(name, method, ...)
if native.isPresent(name) then
local id = kernel.cct.callAsync(native.call, name, method, ...)
kernel.currentTask.io=function()
if kernel.apis.callAsyncReturn[id] then
local r=kernel.apis.callAsyncReturn[id]
if not r[1] then error(r[2]) end
kernel.apis.callAsyncReturn[id]=nil
return table.unpack(r,2)
end
end
kernel.currentTask.status="D"
return
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
local id = kernel.cct.callAsync(native.call, side, "callRemote", name, method, ...)
kernel.currentTask.io=function()
if kernel.apis.callAsyncReturn[id] then
local r=kernel.apis.callAsyncReturn[id]
if not r[1] then error(r[2]) end
kernel.apis.callAsyncReturn[id]=nil
return table.unpack(r,2)
end
end
kernel.currentTask.status="D"
return
end
end
return nil
end
function peripheral.callnative(name, method, ...)
if native.isPresent(name) then if native.isPresent(name) then
return native.call(name, method, ...) return native.call(name, method, ...)
end end
@@ -116,7 +151,7 @@ function peripheral.call(name, method, ...)
return nil return nil
end end
function peripheral.wrap(name) function peripheral.wrap(name, wrap)
local methods = peripheral.getMethods(name) local methods = peripheral.getMethods(name)
if not methods then if not methods then
return nil return nil
@@ -130,9 +165,17 @@ function peripheral.wrap(name)
type = types[1], type = types[1],
types = types, types = types,
}) })
for _, method in ipairs(methods) do if wrap then
result[method] = function(...) for _, method in ipairs(methods) do
return peripheral.call(name, method, ...) result[method] = function(...)
return peripheral.call(name, method, ...)
end
end
else
for _, method in ipairs(methods) do
result[method] = function(...)
return peripheral.callnative(name, method, ...)
end
end end
end end
return result return result
@@ -149,4 +192,4 @@ function peripheral.find(ty, filter)
end end
end end
return table.unpack(results) return table.unpack(results)
end end
@@ -0,0 +1,26 @@
--:Minify:--
local kernel=...
local peripheral=kernel.cct.peripheral
local function wrap(p)
return function(op, mode)
if op=="type" then
return "device"
elseif op=="open" then
if kernel.uid~=0 then error("EACCES") end
return peripheral.wrap(p, true)
end
end
end
local peripherals=peripheral.getNames()
for i=1, #peripherals do
local p=peripherals[i]
local typ=peripheral.getType(p)
local file=wrap(p)
kernel.devfs.data["raw"][p]=file
local typefolder=kernel.devfs.data["raw"]["by-type"][typ]
if not typefolder then typefolder={} end
typefolder[tostring(#table.keys(typefolder)+1)] = file
kernel.devfs.data["raw"]["by-type"][typ]=typefolder
end
@@ -120,6 +120,7 @@ function handler.connect(fd, address)
end end
fdo.socket.active=true fdo.socket.active=true
fdo.socket.url=url fdo.socket.url=url
fdo.socket.loaded=false
return true return true
end end
@@ -129,10 +130,11 @@ function handler.connect(fd, address)
return return
end end
if not kernel.cct.httpqueue[fdo.socket.url] then if not kernel.cct.httpqueue[fdo.socket.url] and not fdo.socket.loaded then
fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url])) fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url]))
kernel.cct.httpqueue[fdo.socket.url]=nil kernel.cct.httpqueue[fdo.socket.url]=nil
kernel.cct.httpresponse[fdo.socket.url]=nil kernel.cct.httpresponse[fdo.socket.url]=nil
fdo.socket.loaded=true
end end
if not fdo.socket.file then if not fdo.socket.file then
@@ -141,6 +143,7 @@ function handler.connect(fd, address)
fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url])) fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url]))
kernel.cct.httpqueue[fdo.socket.url]=nil kernel.cct.httpqueue[fdo.socket.url]=nil
kernel.cct.httpresponse[fdo.socket.url]=nil kernel.cct.httpresponse[fdo.socket.url]=nil
fdo.socket.loaded=true
return fdo.socket.file.read(count) return fdo.socket.file.read(count)
end end
end end
@@ -156,10 +159,11 @@ function handler.connect(fd, address)
return return
end end
if not kernel.cct.httpqueue[fdo.socket.url] then if not kernel.cct.httpqueue[fdo.socket.url] and not fdo.socket.loaded then
fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url])) fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url]))
kernel.cct.httpqueue[fdo.socket.url]=nil kernel.cct.httpqueue[fdo.socket.url]=nil
kernel.cct.httpresponse[fdo.socket.url]=nil kernel.cct.httpresponse[fdo.socket.url]=nil
fdo.socket.loaded=true
end end
if not fdo.socket.file then if not fdo.socket.file then
@@ -168,6 +172,7 @@ function handler.connect(fd, address)
fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url])) fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url]))
kernel.cct.httpqueue[fdo.socket.url]=nil kernel.cct.httpqueue[fdo.socket.url]=nil
kernel.cct.httpresponse[fdo.socket.url]=nil kernel.cct.httpresponse[fdo.socket.url]=nil
fdo.socket.loaded=true
return fdo.socket.file.seek(whence, offset) return fdo.socket.file.seek(whence, offset)
end end
end end
@@ -144,7 +144,6 @@ local function write(text, term)
term.setCursorPos(x, y) term.setCursorPos(x, y)
end end
kernel.devfs.data.tty={}
kernel.cct.ctrl,kernel.cct.alt = false, false kernel.cct.ctrl,kernel.cct.alt = false, false
local function serializeBool(bool) local function serializeBool(bool)
@@ -1,10 +1,11 @@
--:Minify:-- --:Minify:--
local kernel=... local kernel=...
local keys=kernel.apis.keys local keys=kernel.apis.keys
kernel.cct.eventhooks={}
kernel.processes.cctdeamon = function() kernel.processes.cctdaemon = function()
local timeout = false local timeout = false
kernel.log("CCT deamon started") kernel.log("CCT daemon started")
while true do while true do
local event = {kernel.EFI:getMachineEvent()} local event = {kernel.EFI:getMachineEvent()}
@@ -84,6 +85,13 @@ kernel.processes.cctdeamon = function()
kernel.cct.httperror[event[2]]=event[3] kernel.cct.httperror[event[2]]=event[3]
kernel.cct.httpresponse[event[2]]=event[4] kernel.cct.httpresponse[event[2]]=event[4]
end end
else
if kernel.cct.eventhooks[eventType] then
local ok,err = xpcall(kernel.cct.eventhooks[eventType], debug.traceback, table.unpack(event))
if not ok then
kernel.log("Error on eventhook "..eventType.."\n"..err)
end
end
end end
timeout = false timeout = false
@@ -97,4 +105,4 @@ kernel.processes.cctdeamon = function()
end end
end end
kernel.log("CCT deamon queued for execution") kernel.log("CCT daemon queued for execution")
+32 -11
View File
@@ -1,5 +1,6 @@
--:Minify:-- --:Minify:--
local EFI=... local EFI=...
--pf
EFI.beep(440, 500) EFI.beep(440, 500)
local screen=EFI.screenCtl local screen=EFI.screenCtl
local ifs=EFI.initfs local ifs=EFI.initfs
@@ -302,20 +303,24 @@ for _, i in ipairs(ifs.list("/lib/modules")) do
for _,v in ipairs(modlist) do for _,v in ipairs(modlist) do
local prior=tonumber(v:sub(1,2)) local prior=tonumber(v:sub(1,2))
if prior then if prior then
modules[prior+1][#modules[prior+1]+1]="/lib/modules/"..i.."/"..v modules[prior+1][#modules[prior+1]+1]=i.."/"..v
end end
end end
end end
end end
kernel.ifs=ifs kernel.ifs=ifs
--pf
kernel.apis=EFI.firmware kernel.apis=EFI.firmware
--pf
kernel.EFI=EFI kernel.EFI=EFI
kernel.arch=arch kernel.arch=arch
kernel.initdisks=disks kernel.initdisks=disks
kernel.screen=screen kernel.screen=screen
kernel.processes={} kernel.processes={}
kernel.fstab=fstab kernel.fstab=fstab
kernel.denied={}
kernel.loadingModule="kernel"
kernel.kernelTask = { kernel.kernelTask = {
name="kernel", name="kernel",
@@ -357,6 +362,11 @@ function kernel.asyncReturn(...)
kernel.currentTask.syscallReturn = {...} kernel.currentTask.syscallReturn = {...}
end end
function kernel.deny(moduleid)
kernel.denied[moduleid]=true
if kernel.config.showModLoad then kernel.log("Module "..kernel.loadingModule.." denied "..moduleid, "DBUG", 0xFF0000) end
end
kernel.syscalls["time"]=function() return kernel.EFI:getEpochMs() end kernel.syscalls["time"]=function() return kernel.EFI:getEpochMs() end
kernel.syscalls["date"]=function() return kernel.EFI:date() end kernel.syscalls["date"]=function() return kernel.EFI:date() end
kernel.syscalls["log"]=kernel.log kernel.syscalls["log"]=kernel.log
@@ -390,28 +400,39 @@ kernel.syscalls["halt"]=function()
kernel.halt() kernel.halt()
end end
end end
kernel.syscalls["saveLog"]=function()
if kernel.uid==0 or kernel.groups.wheel then
kernel.saveLog()
end
end
kernel.saveLog() kernel.saveLog()
kernel.log("Running modules") kernel.log("Running modules")
for _,p in ipairs(modules) do for _,p in ipairs(modules) do
for _,v in ipairs(p) do for _,v in ipairs(p) do
if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG", 0x00FFFF) end kernel.loadingModule=v
local code=ifs.readAllText(v) if not kernel.denied[v] then
if not code then if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG", 0x00FFFF) end
kernel.panic("Failed to read module "..v) local code=ifs.readAllText("/lib/modules/"..v)
if not code then
kernel.panic("Failed to read module "..v)
end
local func,err=load(code,"@"..v)
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) end
local status, err = xpcall(func,debug.traceback, kernel)
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 0x00FFFF) end
if kernel.config.moreLogsaves then kernel.saveLog() end
else
if kernel.config.showModLoad then kernel.log("Denied module "..v, "DBUG", 0xFF0000) end
end end
local func,err=load(code,"@"..v)
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) end
local status, err = xpcall(func,debug.traceback, kernel)
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 0x00FFFF) end
if kernel.config.moreLogsaves then kernel.saveLog() end
end end
end end
kernel.log("Kernel initialized successfully.") kernel.log("Kernel initialized successfully.")
kernel.saveLog() kernel.saveLog()
kernel.status="running" kernel.status="running"
kernel.loadingModule=nil
screen:disable() screen:disable()
local ok,err = xpcall(kernel.main, debug.traceback) local ok,err = xpcall(kernel.main, debug.traceback)
if not ok then if not ok then
@@ -690,7 +690,9 @@ function vfs.open(path, mode)
local handle local handle
if disk:type(diskPath) ~= "directory" then if disk:type(diskPath) ~= "directory" then
handle = disk:open(diskPath, mode) handle = disk:open(diskPath, mode)
if type(handle) ~= "table" then error("ENFILE") end if type(handle, true) ~= "table" then
error("ENFILE")
end
end end
if isNew then if isNew then
@@ -761,7 +763,7 @@ function vfs.close(fd)
local task = kernel.currentTask local task = kernel.currentTask
local file = task.fd[fd] local file = task.fd[fd]
if not file then error("EBADF") end if not file then error("EBADF") end
if not task.fd[fd].isvirt then if not task.fd[fd].isvirt then
total = total - 1 total = total - 1
end end
task.fd[fd] = nil task.fd[fd] = nil
@@ -1147,6 +1149,12 @@ function vfs.devctl(fd, method, ...)
return kernel.currentTask.fd[fd].handle[method](...) return kernel.currentTask.fd[fd].handle[method](...)
end end
function vfs.devlst(fd)
if not kernel.currentTask.fd[fd] then error("EBADF") end
if not kernel.currentTask.fd[fd] then error("EINVAL") end
return table.keys(kernel.currentTask.fd[fd].handle)
end
vfs.resolveMount = resolveMount vfs.resolveMount = resolveMount
local sys = kernel.syscalls local sys = kernel.syscalls
@@ -1179,6 +1187,7 @@ sys["chroot"] = vfs.chroot
sys["dup"] = vfs.dup sys["dup"] = vfs.dup
sys["dup2"] = vfs.dup2 sys["dup2"] = vfs.dup2
sys["devctl"] = vfs.devctl sys["devctl"] = vfs.devctl
sys["devlst"] = vfs.devlst
sys["symlink"] = vfs.symlink sys["symlink"] = vfs.symlink
sys["readlink"] = vfs.readlink sys["readlink"] = vfs.readlink
sys["access"] = vfs.access sys["access"] = vfs.access
@@ -214,6 +214,8 @@ end
data[".meta"]=strFile(buildMeta({ data[".meta"]=strFile(buildMeta({
stdin="/proc/self/fd/0", stdin="/proc/self/fd/0",
stdout="/proc/self/fd/1", stdout="/proc/self/fd/1",
stderr="/proc/self/2",
fd="/proc/self/fd",
log="/var/log/syslog.log" log="/var/log/syslog.log"
})) }))
@@ -222,6 +224,7 @@ if kernel.EFI.getEEPROM then
if op=="type" then if op=="type" then
return "character device" return "character device"
elseif op=="open" then elseif op=="open" then
if kernel.uid~=0 then error("EACCES") end
if mode=="r" then if mode=="r" then
local ptr,eeprom=1,kernel.EFI:getEEPROM() local ptr,eeprom=1,kernel.EFI:getEEPROM()
return { return {
@@ -231,7 +234,6 @@ if kernel.EFI.getEEPROM then
end end
} }
elseif mode=="w" then elseif mode=="w" then
if kernel.uid~=0 then error("EACCES") end
local firstwrite=true local firstwrite=true
return { return {
write=function(data) write=function(data)
@@ -243,7 +245,6 @@ if kernel.EFI.getEEPROM then
end end
} }
elseif mode=="a" then elseif mode=="a" then
if kernel.uid~=0 then error("EACCES") end
return { return {
write=function(data) write=function(data)
kernel.EFI:setEEPROM(kernel.EFI:getEEPROM()..data) kernel.EFI:setEEPROM(kernel.EFI:getEEPROM()..data)
@@ -260,6 +261,7 @@ if kernel.EFI.getNvram then
if op=="type" then if op=="type" then
return "character device" return "character device"
elseif op=="open" then elseif op=="open" then
if kernel.uid~=0 then error("EACCES") end
if mode=="r" then if mode=="r" then
local ptr,nvram=1,kernel.EFI:getNvram() local ptr,nvram=1,kernel.EFI:getNvram()
return { return {
@@ -269,7 +271,6 @@ if kernel.EFI.getNvram then
end end
} }
elseif mode=="w" then elseif mode=="w" then
if kernel.uid~=0 then error("EACCES") end
local firstwrite=true local firstwrite=true
return { return {
write=function(data) write=function(data)
@@ -281,7 +282,6 @@ if kernel.EFI.getNvram then
end end
} }
elseif mode=="a" then elseif mode=="a" then
if kernel.uid~=0 then error("EACCES") end
return { return {
write=function(data) write=function(data)
kernel.EFI:setNvram(kernel.EFI:getNvram()..data) kernel.EFI:setNvram(kernel.EFI:getNvram()..data)
@@ -294,7 +294,15 @@ if kernel.EFI.getNvram then
end end
data["disk"]={["by-id"]={}, ["by-path"]={}, ["by-label"]={}} data["disk"]={["by-id"]={}, ["by-path"]={}, ["by-label"]={}}
-- disks
for i,v in pairs(kernel.vfs.mounts) do
end
data["raw"]={["by-type"]={}}
data["gfx"]={}
data["input"]={} data["input"]={}
data["tty"]={}
kernel.devfs={} kernel.devfs={}
kernel.devfs.data=data kernel.devfs.data=data
kernel.devfs.proxy=proxy kernel.devfs.proxy=proxy
@@ -150,7 +150,6 @@ function sys.exec(path, args, envars)
tasks[tostring(task.pid)].status = "Z" tasks[tostring(task.pid)].status = "Z"
end) end)
task.syscallReturn = {} task.syscallReturn = {}
coroutine.yield()
end end
function sys.sleep(s) function sys.sleep(s)
@@ -1,3 +1,4 @@
--:Minify:--
local kernel = ... local kernel = ...
kernel.processes.kgc = function() kernel.processes.kgc = function()
while true do while true do
@@ -6,6 +7,6 @@ kernel.processes.kgc = function()
kernel.reqcache[i] = nil kernel.reqcache[i] = nil
end end
end end
kernel.sleep(5000) sleep(5)
end end
end end
+84
View File
@@ -0,0 +1,84 @@
--:Minify:--
local lib = {}
--[[
Example framebuffer object
fb = {
r={
"","" -- repeat for # of rows length of string is the # of collums
},
g = {
"",""
},
b = {
"",""
}
}
Example font object
font = {
width=int,
hight=int,
data={
A={
"Ga","gs","Gk" -- length of string is byte alligned with the string being a binary bitmap
}
}
}
]]
function lib.newFbObj(fb)
local handle = {}
function handle.setPixel(x,y,color24)
end
function handle.line(x1,y1,x2,y2,color24)
end
function handle.box(x1,y1,x2,y2,color24)
end
function handle.filledBox(x1,y1,x2,y2,color24)
end
function handle.tri(x1,y1,x2,y2,x3,y3,color24)
end
function handle.filledTri(x1,y1,x2,y2,x3,y3,color24)
end
function handle.window(id,x,y,w,h,writeonly)
end
function handle.editWindow(id,x,y,w,h)
end
function handle.text(x,y,font,color24)
end
function handle.draw()
end
function handle.getPixel(x,y)
end
function handle.getPixels(x1y1,x2,y2)
end
return handle
end
+232
View File
@@ -0,0 +1,232 @@
-- psf.lua
-- NeetComputers PSF1 & PSF2 font renderer
-- Copyright 2026 SpartanSoftware
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- MODULE API
-- psf.open(path, disk = 0) Returns a Font object, or nil + errmsg
--
-- FONT OBJECT API
-- font:print(x, y, text) Draw text in white
-- font:print(x, y, text, r, g, b) Draw text in given color
-- font:measure(text) Width of string in pixels
-- font:lineHeight() Font height in pixels
-- font:setSpacing(w) Set px width of glyph spacing
-- font:close() Free all layers
local psf = {}
local function readUInt(header, n)
local bytes = header.read(n)
if not bytes or #bytes < n then return nil end
local value = 0
for i = 1, n do
value = value + string.byte(bytes, i) * (256 ^ (i - 1))
end
return math.floor(value)
end
local function parseGlyph(bytes, w, h)
local bytesPerRow = math.floor((w + 7) / 8)
local pixels = {}
for y = 1, h do
pixels[y] = {}
for x = 1, w do
local byteIdx = (y - 1) * bytesPerRow + math.floor((x - 1) / 8) + 1
local bitPos = 7 - ((x - 1) % 8)
local b = string.byte(bytes, byteIdx) or 0
pixels[y][x] = (math.floor(b / (2 ^ bitPos)) % 2 == 1)
end
end
return pixels
end
local OFF_PIXEL = "\0\0\0\0"
local function getGlyphBuffer(glyph, r, g, b)
local cache = glyph._bufCache
if not cache then
cache = {}
glyph._bufCache = cache
end
local key = r * 65536 + g * 256 + b
local buf = cache[key]
if buf then return buf end
local onPixel = string.char(r, g, b, 255)
local pixels = glyph.pixels
local chunks = {}
local n = 0
for y = 1, glyph.height do
local row = pixels[y]
for x = 1, glyph.width do
n = n + 1
chunks[n] = row[x] and onPixel or OFF_PIXEL
end
end
buf = table.concat(chunks)
cache[key] = buf
return buf
end
local function parsePSF1(header, glyphs)
local mode = readUInt(header, 1)
local charsize = readUInt(header, 1)
if not charsize then return false, "truncated PSF1 header" end
local count = (mode and (mode % 4 >= 2)) and 512 or 256
for i = 0, count - 1 do
local raw = header.read(charsize)
if not raw or #raw < charsize then break end
glyphs[i] = { width = 8, height = charsize,
pixels = parseGlyph(raw, 8, charsize) }
end
return true, 8, charsize
end
local function parsePSF2(header, glyphs)
readUInt(header, 4)
local headersize = readUInt(header, 4)
readUInt(header, 4)
local numglyph = readUInt(header, 4)
local bytesperglyph = readUInt(header, 4)
local h = readUInt(header, 4)
local w = readUInt(header, 4)
if not w or not h then return false, "truncated PSF2 header" end
local consumed = 32
if headersize > consumed then
header.seek('cur', headersize - consumed)
end
for i = 0, numglyph - 1 do
local raw = header.read(bytesperglyph)
if not raw or #raw < bytesperglyph then break end
glyphs[i] = { width = w, height = h,
pixels = parseGlyph(raw, w, h) }
end
return true, w, h
end
local Font = {}
Font.__index = Font
function Font:print(x, y, text, r, g, b)
assert(not self._closed, "psf: font has been closed")
r = r or 255
g = g or 255
b = b or 255
local sw = screen.getSize()
local cur = x
local spacing = self._spacing
for i = 1, #text do
if cur >= sw then break end
local code = string.byte(text, i)
local glyph = self._glyphs[code]
if glyph then
local buf = getGlyphBuffer(glyph, r, g, b)
screen.drawPixels(cur, y, buf, glyph.width, glyph.height)
cur = cur + glyph.width + spacing
end
end
end
function Font:measure(text)
local w = 0
local count = 0
for i = 1, #text do
local g = self._glyphs[string.byte(text, i)]
if g then
w = w + g.width
count = count + 1
end
end
if count > 1 then
w = w + self._spacing * (count - 1)
end
return w
end
function Font:lineHeight()
return self._height
end
function Font:close()
if self._closed then return end
for _, glyph in pairs(self._glyphs) do
glyph._bufCache = nil
end
self._glyphs = {}
self._closed = true
end
function Font:setSpacing(px)
self._spacing = px
end
function psf.open(path, disk)
disk = disk or 0
if not files.exists(path, disk) then
return nil, "file not found: " .. path
end
local ok, header = pcall(files.open, path, 'rb', disk)
if not ok or not header then
return nil, "could not open: " .. path
end
local magic = header.read(2)
if not magic or #magic < 2 then
header.close()
return nil, "could not read magic bytes"
end
local b1, b2 = string.byte(magic, 1), string.byte(magic, 2)
local glyphs = {}
local ok, w, h
if b1 == 0x36 and b2 == 0x04 then
ok, w, h = parsePSF1(header, glyphs)
elseif b1 == 0x72 and b2 == 0xb5 then
header.read(2)
ok, w, h = parsePSF2(header, glyphs)
else
header.close()
return nil, string.format("not a PSF file (magic: %02x %02x)", b1, b2)
end
header.close()
if not ok then
return nil, w
end
return setmetatable({
_glyphs = glyphs,
_width = w,
_height = h,
_spacing = 0,
_closed = false,
}, Font)
end
return psf
+6 -2
View File
@@ -833,14 +833,18 @@ builtinCmds.ops = function()
end end
end end
builtinCmds.reboot = function () builtinCmds.reboot = function()
syscall.reboot() syscall.reboot()
end end
builtinCmds.shutdown = function () builtinCmds.shutdown = function()
syscall.shutdown() syscall.shutdown()
end end
builtinCmds.kill = function(id)
syscall.kill(tonumber(id))
end
local function listDir(dir, prefix) local function listDir(dir, prefix)
local ok, entries = pcall(syscall.listdir, dir) local ok, entries = pcall(syscall.listdir, dir)
if not ok or not entries then return {} end if not ok or not entries then return {} end
+14
View File
@@ -0,0 +1,14 @@
--:Minify:--
local args = {...}
local list = syscall.listdir("/proc/self/fd")
for i=1, #list do
syscall.close(tonumber(list[i]))
end
if #args>=2 then
for i=2, #args do
syscall.open(args[i], "rw")
end
end
syscall.exec(args[1])
+15 -9
View File
@@ -1,3 +1,4 @@
--:Minify:--
--[[ --[[
MIT License MIT License
@@ -89,7 +90,11 @@ local WhiteChars = lookupify { ' ', '\n', '\t', '\r' }
local EscapeForCharacter = { ['\r'] = '\\r', ['\n'] = '\\n', ['\t'] = '\\t', ['"'] = '\\"', ["'"] = "\\'", ['\\'] = '\\' } local EscapeForCharacter = { ['\r'] = '\\r', ['\n'] = '\\n', ['\t'] = '\\t', ['"'] = '\\"', ["'"] = "\\'", ['\\'] = '\\' }
local CharacterForEscape = { ['r'] = '\r', ['n'] = '\n', ['t'] = '\t', ['"'] = '"', ["'"] = "'", ['\\'] = '\\' } local CharacterForEscape = { ['r'] = '\r', ['n'] = '\n', ['t'] = '\t', ['"'] = '"', ["'"] = "'", ['\\'] = '\\', ['b'] = '\b', ['f'] = '\f' }
for i=0,255 do
CharacterForEscape[tostring(i)]=string.char(i)
end
local AllIdentStartChars = lookupify { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', local AllIdentStartChars = lookupify { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
@@ -201,9 +206,9 @@ local function CreateLuaTokenStream(text)
end end
q = q + 1 q = q + 1
end end
for _, token in pairs(tokenBuffer) do --for _, token in pairs(tokenBuffer) do
print(token.Type .. "<" .. token.Source .. ">") -- print(token.Type .. "<" .. token.Source .. ">")
end --end
olderr("file<" .. line .. ":" .. char .. ">: " .. str) olderr("file<" .. line .. ":" .. char .. ">: " .. str)
end end
@@ -485,9 +490,9 @@ local function CreateLuaParser(text)
if tk.Type == type and (source == nil or tk.Source == source) then if tk.Type == type and (source == nil or tk.Source == source) then
return get() return get()
else else
for i = -3, 3 do --for i = -3, 3 do
print("Tokens[" .. i .. "] = `" .. peek(i).Source .. "`") -- print("Tokens[" .. i .. "] = `" .. peek(i).Source .. "`")
end --end
if source then if source then
error(getTokenStartPosition(tk) .. ": `" .. source .. "` expected.") error(getTokenStartPosition(tk) .. ": `" .. source .. "` expected.")
else else
@@ -666,7 +671,7 @@ local function CreateLuaParser(text)
get() get()
return body, after return body, after
else else
print(after.Type, after.Source) --print(after.Type, after.Source)
error(getTokenStartPosition(after) .. ": " .. terminator .. " expected.") error(getTokenStartPosition(after) .. ": " .. terminator .. " expected.")
end end
end end
@@ -2802,6 +2807,7 @@ local function StripAst(ast)
stript(sep) stript(sep)
end end
end end
stript(stat.Token_OpenParen) stript(stat.Token_OpenParen)
for index, arg in pairs(stat.ArgList) do for index, arg in pairs(stat.ArgList) do
stript(arg) stript(arg)
@@ -3074,7 +3080,7 @@ end
local function validateCode(code, validate) local function validateCode(code, validate)
if validate then if validate then
local func,err = load(code, "@minifyvalidation", "t", {}) local func,err = load(code, "@minifyvalidation", "t", _G)
if not func then if not func then
error(err) error(err)
end end
+426 -22
View File
@@ -16,10 +16,11 @@ local spm = function(...)
i = false, i = false,
e = false, e = false,
t = false, t = false,
s = false,
sysroot = "", sysroot = "",
init = false, init = false,
help = false, help = false,
source = false overwrite = false
} }
local i = 1 local i = 1
@@ -27,7 +28,9 @@ local spm = function(...)
local http = require("http") local http = require("http")
local json = require("json") local json = require("json")
local tar = require("tar") local tar = require("tar")
local minify = require("minify")
local deflate = require("deflate") local deflate = require("deflate")
local bit32 = require("bit32")
local httpcache = {} local httpcache = {}
local function get(url) local function get(url)
@@ -93,6 +96,82 @@ local spm = function(...)
i = i + 1 i = i + 1
end end
i=nil
if cloptions.help or cloptions.h then
if cloptions.S then
print("spm -S - Synchronize Packages")
print("")
print("Usage:")
print(" spm -S [options] <packages>")
print("")
print("Options:")
print(" -y Refresh package databases")
print(" -u Upgrade installed packages")
print(" -i Show remote package information")
print(" -s Download source")
print("")
print("Examples:")
print(" spm -Sy")
print(" spm -S package")
print(" spm -Syu")
return
elseif cloptions.Q then
print("spm -Q - Query Package Database")
print("")
print("Usage:")
print(" spm -Q [options] [package]")
print("")
print("Options:")
print(" -i Show installed package information")
print(" -l List files owned by a package")
print(" -o Find which package owns a file")
print(" -e List explicitly installed packages")
print(" -t List orphan packages")
print("")
print("Examples:")
print(" spm -Q")
print(" spm -Qi lua")
print(" spm -Ql lua")
print(" spm -Qo /bin/lua")
return
elseif cloptions.R then
print("spm -R - Remove Packages")
print("")
print("Usage:")
print(" spm -R [options] <packages>")
print("")
print("Currently no remove-specific options are implemented.")
print("")
print("Example:")
print(" spm -R package")
return
else
print("spm - HyperionOS Package Manager")
print("")
print("Usage:")
print(" spm <operation> [options] [targets]")
print("")
print("Operations:")
print(" -S Synchronize packages")
print(" -Q Query package database")
print(" -R Remove packages")
print("")
print("General Options:")
print(" -h, --help Show help")
print(" --init Initialize spm")
print(" --sysroot DIR Operate on alternate root")
print("")
print("For operation-specific help:")
print(" spm -Sh")
print(" spm -Qh")
print(" spm -Rh")
return
end
end
if cloptions.sysroot=="" then if cloptions.sysroot=="" then
syscall.chdir("/") syscall.chdir("/")
@@ -113,6 +192,17 @@ local spm = function(...)
print("spm not initialized run \"spm --init\"") print("spm not initialized run \"spm --init\"")
return return
end end
local log = fs.open("var/log/spm.log", "w")
local function w(...)
local args = {...}
local output = ""
for i = 1, #args do output = output .. tostring(args[i]) .. "\t" end
output = output:sub(1, -2)
syscall.write(1, output.."\n")
log.write(output.."\n")
log.flush()
end
local repodb = string.split(fs.readAllText("var/spm/db/repos.list"), "\n") local repodb = string.split(fs.readAllText("var/spm/db/repos.list"), "\n")
local sourcelist = string.split(fs.readAllText("etc/spm/sources.list"), "\n") local sourcelist = string.split(fs.readAllText("etc/spm/sources.list"), "\n")
@@ -192,29 +282,29 @@ local spm = function(...)
for _, url in ipairs(repodb) do for _, url in ipairs(repodb) do
local ok, repo = checkRepo(url) local ok, repo = checkRepo(url)
if not ok then if not ok then
print("Failed to contact repository:") w("Failed to contact repository:")
print(url) w(url)
print("Consider running 'spm -Sy' to remove broken repositories.") w("Consider running 'spm -Sy' to remove broken repositories.")
else else
if repo.packages then if repo.packages then
if repo.packages[name] then if repo.packages[name] then
local pkgurl = repo.packages[name] local pkgurl = repo.packages[name]
local resp = get(pkgurl) local resp = get(pkgurl)
if not resp then if not resp then
print("Repository: "..url) w("Repository: "..url)
print("Has broken package: "..name) w("Has broken package: "..name)
print("Ignoring") w("Ignoring")
else else
if resp.code ~= 200 then if resp.code ~= 200 then
print("Repository: "..url) w("Repository: "..url)
print("Has broken package: "..name) w("Has broken package: "..name)
print("Ignoring") w("Ignoring")
else else
local pkgjson = json.decode(resp.body) local pkgjson = json.decode(resp.body)
if not pkgjson then if not pkgjson then
print("Repository: "..url) w("Repository: "..url)
print("Has broken package: "..name) w("Has broken package: "..name)
print("Ignoring") w("Ignoring")
else else
return { return {
url=pkgurl, url=pkgurl,
@@ -236,14 +326,207 @@ local spm = function(...)
return false, "target not found: "..name return false, "target not found: "..name
end end
local function flatten(t)
local ret={}
for _,v in ipairs(t.content) do
if v.type == "dir" then
local f=flatten(v)
for i,c in pairs(f) do
ret[i]=c
end
elseif v.type == "file" then
ret[v.name]=v.content
end
end
return ret
end
local function ptar(t, pkg)
t=t.content[1]
if t.name~=pkg.id then w("Tar contains "..t.name.." not "..pkg.id) return false end
local ret={}
for i=1, #t.content do
if t.content[i].name == "data" then
local data=flatten(t.content[i])
local new={}
for p,v in pairs(data) do
new[p:sub(#pkg.id+7)]=v
end
ret.data=new
elseif t.content[i].name == "control" then
local data=flatten(t.content[i])
local new={}
for p,v in pairs(data) do
new[p:sub(#pkg.id+10)]=v
end
ret.control=new
end
end
return ret
end
local function mini(tabl)
local ret={}
for i,v in pairs(tabl) do
if v:sub(1,12)=="--:Minify:--" then
local ok, code = pcall(minify.minify,v)
if not ok then w("Failed to minify "..i..":\n"..code) ret[i]=v
else ret[i]=code end
else
ret[i]=v
end
end
return ret
end
local function md5(msg)
local bit = bit32
local function rol(x, n)
return bit.lrotate(x, n)
end
local function F(x, y, z)
return bit.bor(bit.band(x, y), bit.band(bit.bnot(x), z))
end
local function G(x, y, z)
return bit.bor(bit.band(x, z), bit.band(y, bit.bnot(z)))
end
local function H(x, y, z)
return bit.bxor(x, y, z)
end
local function I(x, y, z)
return bit.bxor(y, bit.bor(x, bit.bnot(z)))
end
local function u32le(s, i)
return s:byte(i)
+ s:byte(i + 1) * 0x100
+ s:byte(i + 2) * 0x10000
+ s:byte(i + 3) * 0x1000000
end
local function le32(x)
return string.char(
bit.band(x, 0xff),
bit.band(bit.rshift(x, 8), 0xff),
bit.band(bit.rshift(x, 16), 0xff),
bit.band(bit.rshift(x, 24), 0xff)
)
end
-- MD5 padding
local bitlen = #msg * 8
msg = msg .. "\128"
while #msg % 64 ~= 56 do
msg = msg .. "\0"
end
-- Append 64-bit little-endian length
local lo = bitlen % 0x100000000
local hi = math.floor(bitlen / 0x100000000)
msg = msg .. le32(lo) .. le32(hi)
local a0 = 0x67452301
local b0 = 0xefcdab89
local c0 = 0x98badcfe
local d0 = 0x10325476
local S = {
7,12,17,22, 7,12,17,22, 7,12,17,22, 7,12,17,22,
5, 9,14,20, 5, 9,14,20, 5, 9,14,20, 5, 9,14,20,
4,11,16,23, 4,11,16,23, 4,11,16,23, 4,11,16,23,
6,10,15,21, 6,10,15,21, 6,10,15,21, 6,10,15,21
}
local K = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
}
for chunk = 1, #msg, 64 do
local M = {}
for i = 0, 15 do
M[i] = u32le(msg, chunk + i * 4)
end
local A = a0
local B = b0
local C = c0
local D = d0
for i = 0, 63 do
local f
local g
if i < 16 then
f = F(B, C, D)
g = i
elseif i < 32 then
f = G(B, C, D)
g = (5 * i + 1) % 16
elseif i < 48 then
f = H(B, C, D)
g = (3 * i + 5) % 16
else
f = I(B, C, D)
g = (7 * i) % 16
end
local tmp = D
D = C
C = B
local x = A + f + K[i + 1] + M[g]
x = x % 0x100000000
B = (B + rol(x, S[i + 1])) % 0x100000000
A = tmp
end
a0 = (a0 + A) % 0x100000000
b0 = (b0 + B) % 0x100000000
c0 = (c0 + C) % 0x100000000
d0 = (d0 + D) % 0x100000000
end
local digest = le32(a0) .. le32(b0) .. le32(c0) .. le32(d0)
return (digest:gsub(".", function(c)
return string.format("%02x", c:byte())
end))
end
if cloptions.S then if cloptions.S then
if cloptions.y then if cloptions.y then
print("Updating repositories...") w("Updating repositories...")
repodb={} repodb={}
for _,v in ipairs(getRepos(sourcelist)) do for _,v in ipairs(getRepos(sourcelist)) do
repodb[#repodb+1]=v repodb[#repodb+1]=v
end end
print("Writing new data...") w("Writing new data...")
local str = "" local str = ""
for _,v in ipairs(repodb) do for _,v in ipairs(repodb) do
str=str..v.."\n" str=str..v.."\n"
@@ -257,7 +540,7 @@ local spm = function(...)
local found = {} local found = {}
for i,v in ipairs(args) do for i,v in ipairs(args) do
local pkg, err = getPkg(v) local pkg, err = getPkg(v)
if not pkg then print(err) syscall.exit(1) end if not pkg then w(err) syscall.exit(1) end
needed[#needed+1] = pkg needed[#needed+1] = pkg
found[v]=true found[v]=true
end end
@@ -286,10 +569,10 @@ local spm = function(...)
if #needed==0 then if #needed==0 then
syscall.exit() syscall.exit()
end end
print("") w("")
print("Packages("..tostring(#needed).."):") w("Packages("..tostring(#needed).."):")
printpkgs(needed) printpkgs(needed)
print("") w("")
while true do while true do
local text = userinput(0, "Proceed with download [Y/n]", nil, 1) local text = userinput(0, "Proceed with download [Y/n]", nil, 1)
if text=="" then if text=="" then
@@ -303,10 +586,131 @@ local spm = function(...)
local files = {} local files = {}
for _,v in ipairs(needed) do for _,v in ipairs(needed) do
local file = http.get(v.tar) if not pkgdb[v.id] or not pkgdb[v.id].hash==v.hash then
w("Downloading "..v.id)
local resp = get(v.tar)
if not resp then
w("Package "..v.id.." failed GET")
syscall.exit()
end
if resp.code ~= 200 then
w("Package "..v.id.." returned code "..tostring(resp.code))
syscall.exit()
end
local ok, repotar = pcall(tar.unpack, resp.body)
if not ok or not repotar then
w("Package "..v.id.." failed tar parsing")
syscall.exit()
end
local f=ptar(repotar, v)
if not f or not f.data then syscall.exit() end
if not cloptions.s then
f.data=mini(f.data)
end
f.hash=v.hash
files[v.id]=f
else
w("Package "..v.id.." hash already installed")
end
end end
w("Checking for conflicts...")
local seen={}
for i,v in pairs(files) do
for f,c in pairs(v.data) do
if seen[f] then
w(i.." and "..seen[f].." have conflicting file "..f)
v.data[f]=nil
else
seen[f]=i
end
end
end
seen=nil
w("Checking for modified files...")
local block={}
for i, v in pairs(files) do
if pkgdb[i] then
if not cloptions.overwrite then
for f,h in pairs(v.data) do
if pkgdb[i].files[f]~=md5(fs.readAllText(f)) then
w(f.." was modified on disk, specify --overwrite to overwrite")
block[f]=true
end
end
end
else
if not cloptions.overwrite then
for f,h in pairs(v.data) do
if fs.exists(f) then
w(f.." already exists, specify --overwrite to overwrite or remove the file")
syscall.exit()
end
end
end
end
end
w("Adding delete calls...")
local delete={}
for i,v in pairs(files) do
if pkgdb[i] then
for f,c in pairs(pkgdb[i].files) do
if not v.data[f] then
if c~=md5(fs.readAllText(f)) then
w(f.." was modified on disk, specify --overwrite to overwrite")
else
delete[f]=true
end
end
end
end
end
w("Calculating useage...")
local net=0
for i,v in pairs(files) do
for f,c in pairs(v.data) do
if not block[f] then
net=net+#c
end
end
for f,c in pairs(delete) do
net=net-#fs.readAllText(f)
end
end
w("")
w("Net Upgrade Size: "..tostring(net))
w("")
while true do
local text = userinput(0, "Proceed with Installation [Y/n]", nil, 1)
if text=="" then
break
elseif text:lower()=="y" then
break
elseif text:lower()=="n" then
syscall.exit()
end
end
w("Updatating db...")
for i,v in pairs(files) do
local content={}
content.files={}
for f,c in pairs(v.data) do
content.files[f]=md5(c)
end
content.hash=v.hash
fs.writeAllText("var/spm/db/installed/"..i, json.encode(content))
end
w("Writing changes...")
for i,v in pairs(files) do
w("Writing "..i)
for f,c in pairs(v.data) do
if not block[f] then
fs.writeAllText(f,c)
end
end
end
w("Install complete")
log.close()
elseif cloptions.R then elseif cloptions.R then
-- remove tree -- remove tree
elseif cloptions.Q then elseif cloptions.Q then
+3 -1
View File
@@ -1,4 +1,6 @@
tar tar
deflate deflate
json json
minify minify
bit32
Hyperion-core
+1
View File
@@ -1,3 +1,4 @@
--:Minify:--
local LibDeflate = require("LibDeflate") local LibDeflate = require("LibDeflate")
local tar = {} local tar = {}
+609
View File
@@ -0,0 +1,609 @@
print("Running CC:Tweaked vm bootstrap")
local bootloader=[=[
---@diagnostic disable-next-line: undefined-global
local lterm = term
local function write(text, term)
local x, y = term.getCursorPos()
local w, h = term.getSize()
for i = 1, #text do
local c = text:sub(i, i)
if c == "\n" then
y = y + 1
x = 1
elseif c == "\t" then
local tabSize = 4
local spaces = tabSize - ((x - 1) % tabSize)
term.write(string.rep(" ", spaces))
x = x + spaces
elseif c == "\b" then
if x > 1 then
x = x - 1
term.setCursorPos(x, y)
term.write(" ")
term.setCursorPos(x, y)
end
else
if x <= w and y <= h then
term.setCursorPos(x, y)
term.write(c)
x = x + 1
end
end
if x > w then
x = 1
y = y + 1
end
if y - 1 >= h then
term.scroll(1)
y = h
term.setCursorPos(x, y)
end
end
term.setCursorPos(x, y)
end
local function displaySuperBadError(err)
lterm.setBackgroundColor(0x1)
lterm.setTextColor(0x4)
lterm.clear()
lterm.setCursorPos(1, 1)
lterm.write("A critical error occurred while loading the system:")
lterm.setCursorPos(1, 3)
write(err, lterm)
while true do end
end
term.setCursorBlink(false)
local ok, err = xpcall(function()
--p
local apis = {BOOT_DRIVE_PATH = BOOT_DRIVE_PATH}
local lua = {
coroutine = true,
debug = true,
_VERSION = true,
assert = true,
collectgarbage = true,
error = true,
gcinfo = true,
getmetatable = true,
ipairs = true,
__inext = true,
load = true,
math = true,
next = true,
pairs = true,
pcall = true,
rawequal = true,
rawget = true,
rawlen = true,
rawset = true,
select = true,
setmetatable = true,
string = true,
table = true,
tonumber = true,
tostring = true,
type = true,
xpcall = true,
_G = true
}
local debug = debug
for i, v in pairs(_G) do
if not lua[i] or lua[i] == nil then
apis[i] = v
_G[i] = nil
end
end
--p
local acekeys={
[apis.keys.enter]="\n",
[apis.keys.tab]="\t",
[apis.keys.backspace]="\b",
[apis.keys.up]="\17",
[apis.keys.down]="\18",
[apis.keys.left]="\19",
[apis.keys.right]="\20",
}
function sleep(time)
local stoptime = apis.os.clock() + (time)
while stoptime > apis.os.clock() do end
end
apis.term.setPaletteColor(0x1, 0xFFFFFF) -- #000000
apis.term.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
apis.term.setPaletteColor(0x4, 0x00FF00) -- #FF0000
apis.term.setPaletteColor(0x8, 0x0000FF) -- #00FF00
apis.term.setPaletteColor(0x10, 0x00FFFF) -- #0000FF
apis.term.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF
apis.term.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF
apis.term.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00
apis.term.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00
apis.term.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55
apis.term.setPaletteColor(0x400, 0x924900) -- #24FFFF
apis.term.setPaletteColor(0x800, 0x6D6D55) -- #924900
apis.term.setPaletteColor(0x1000, 0xDBDBAA) -- #6D6D55
apis.term.setPaletteColor(0x2000, 0x6D00FF) -- #DBDBAA
apis.term.setPaletteColor(0x4000, 0xB6FF00) -- #6D00FF
apis.term.setPaletteColor(0x8000, 0x000000) -- #B6FF00
local eventQueue = {}
local function queueEvent(event, ...)
table.insert(eventQueue, {event, ...})
end
local colors = {
[0xFFFFFF]=0x0001,
[0x000000]=0x8000
}
local fg,bg=0x6D6D55,0x000000
local l1f,l1d,l2,ops={},{},{},0
local function findClosest(tbl, target)
local closest = nil
local smallestDiff = math.huge
for k, _ in pairs(tbl) do
if k==target then return k end
local diff = math.abs(k - target)
if diff < smallestDiff then
smallestDiff = diff
closest = k
end
end
return closest
end
local function aprox(c24)
ops = ops + 1
if ops % 1024 == 0 then
l1d = {}
l1f = {}
end
if ops % 8192 == 0 then
l2 = {}
end
if l2[c24] ~= nil then
return l2[c24]
end
if l1d[c24] ~= nil then
l1f[c24] = l1f[c24] + 1
if l1f[c24] >= 16 then
l2[c24] = l1d[c24]
l1d[c24] = nil
l1f[c24] = nil
return l2[c24]
end
return l1d[c24]
end
local closestKey = findClosest(colors, c24)
if not closestKey then return nil end
local value = colors[closestKey]
l1d[c24] = value
l1f[c24] = 1
return value
end
--p
local p={}
local native = apis.peripheral
local sides = {"top", "bottom", "left", "right", "front", "back"}
function p.getNames()
local results = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(results, side)
if native.hasType(side, "peripheral_hub") then
local remote = native.call(side, "getNamesRemote")
for _, name in ipairs(remote) do
table.insert(results, name)
end
end
end
end
return results
end
function p.isPresent(name)
if native.isPresent(name) then
return true
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return true
end
end
return false
end
function p.getType(peripheral)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.getType(peripheral)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "getTypeRemote", peripheral)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return table.unpack(mt.types)
end
end
function p.hasType(peripheral, peripheral_type)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.hasType(peripheral, peripheral_type)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.types[peripheral_type] ~= nil
end
end
function p.getMethods(name)
if native.isPresent(name) then
return native.getMethods(name)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "getMethodsRemote", name)
end
end
return nil
end
function p.getName(peripheral)
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.name
end
function p.call(name, method, ...)
if native.isPresent(name) then
return native.call(name, method, ...)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "callRemote", name, method, ...)
end
end
return nil
end
function p.wrap(name)
local methods = p.getMethods(name)
if not methods then
return nil
end
local types = { p.getType(name) }
for i = 1, #types do types[types[i]] = true end
local result = setmetatable({}, {
__name = "peripheral",
name = name,
type = types[1],
types = types,
})
for _, method in ipairs(methods) do
result[method] = function(...)
return p.call(name, method, ...)
end
end
return result
end
function p.find(ty, filter)
local results = {}
for _, name in ipairs(p.getNames()) do
if p.hasType(name, ty) then
local wrapped = p.wrap(name)
if filter == nil or filter(name, wrapped) then
table.insert(results, wrapped)
end
end
end
return table.unpack(results)
end
--p
local allscreens = {p.find("monitor")}
for i=1, #allscreens do
allscreens[i].setTextScale(.5)
allscreens[i].clear()
allscreens[i].setCursorPos(1,1)
end
allscreens[#allscreens+1] = apis.term
local EFI = {
getEpochMs = function() return apis.os.epoch("utc") end,
getUptime = function() return apis.os.clock() * 1000 end,
date = function() return apis.os.date("!%Y-%m-%dT%H:%M:%SZ", apis.os.epoch("utc") / 1000) end,
getMachineEvent = function()
if #eventQueue > 0 then
return table.unpack(table.remove(eventQueue, 1))
else
return nil
end
end,
getEEPROM = function() return getFile(eeprom) end,
setEEPROM = function(_, text)
local h = apis.fs.open(eeprom, "w")
h.write(text)
h.close()
end,
initfs=fs,
disks=initFs,
screenCtl={
print = function(_, text)
for i=1, #allscreens do
write(text.."\n", allscreens[i])
end
end,
printInline = function(_, text)
for i=1, #allscreens do
write(text, allscreens[i])
end
end,
clear = function()
for i=1, #allscreens do
allscreens[i].clear()
allscreens[i].setCursorPos(1, 1)
end
end,
resetCursor = function()
for i=1, #allscreens do
allscreens[i].setCursorPos(1, 1)
end
end,
setBackgroundColor = function(_, color)
bg=color
for i=1, #allscreens do
allscreens[i].setBackgroundColor(aprox(color))
end
end,
setTextColor = function(_, color)
fg=color
for i=1, #allscreens do
allscreens[i].setTextColor(aprox(color))
end
end,
getBackgroundColor = function()
return bg
end,
getTextColor = function()
return fg
end,
enable=function()
for i=1, #allscreens do
allscreens[i].clear()
allscreens[i].setCursorPos(1, 1)
end
end,
disable=function() end
},
architecture="vm",
getNvram = function() return getFile("/nvram.dat") end,
setNvram = function(_, text)
local h = apis.fs.open("/nvram.dat", "w")
h.write(text)
h.close()
end,
firmware=apis,
reboot=false,
beep=function() end
}
apis.term.setBackgroundColor(0x8000)
apis.term.setTextColor(0x1000)
apis.term.clear()
apis.term.setCursorPos(1, 1)
local kernelCoro = coroutine.create(function()
--pf
---@diagnostic disable-next-line: param-type-mismatch
local ok, err = xpcall(Kernel, debug.traceback, EFI)
if not ok and not EFI.reboot then displaySuperBadError(err) end
if err then
apis.os.reboot()
else
apis.os.shutdown()
end
end)
function coroutine.resumeWithTimeout(co, timeout, ...)
local startTime = EFI.getEpochMs()
debug.sethook(co, function()
if EFI.getEpochMs() > startTime + timeout then
return coroutine.yield("timeout")
end
end, "", 1000)
local ret = {coroutine.resume(co, ...)}
if ret[1] and ret[2] == "timeout" then
return "timeout"
elseif ret[1] == false then
return "error", ret[2]
else
debug.sethook(co)
return "success", table.unpack(ret, 2)
end
end
EFI.screenCtl:print("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
--p
while true do
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
apis.os.queueEvent("NoSleep")
local exit = false
while not exit do
local event = {coroutine.yield()}
if event[1] == "key" then
queueEvent(table.unpack(event))
queueEvent("keyPressed", 1, event[2])
if acekeys[event[2]] then
queueEvent("keyTyped", 1, acekeys[event[2]])
end
elseif event[1] == "char" then
queueEvent(table.unpack(event))
queueEvent("keyTyped", 1, event[2])
elseif event[1] == "key_up" then
queueEvent(table.unpack(event))
queueEvent("keyReleased", 1, event[2])
elseif event[1] == "NoSleep" then
exit = true
else
queueEvent(table.unpack(event))
end
end
if status == "error" or coroutine.status(kernelCoro) == "dead" then
if EFI.reboot then
apis.os.reboot()
end
displaySuperBadError("Kernel error: " .. tostring(err))
coroutine.yield("key")
elseif status == "success" then
if EFI.reboot then
apis.os.reboot()
end
displaySuperBadError("Kernel error: Attempted to yield main thread")
coroutine.yield("key")
end
initFs:refresh()
end
end, debug.traceback)
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
while true do coroutine.yield("key") end
]=]
local args = {}
local keptAPIs = {keys=true, bit32 = true, bit = true, ccemux = true, config = true, coroutine = true, debug = true, fs = true, http = true, mounter = true, os = true, periphemu = true, peripheral = true, redstone = true, rs = true, term = true, utf8 = true, _HOST = true, _CC_DEFAULT_SETTINGS = true, _CC_DISABLE_LUA51_FEATURES = true, _VERSION = true, assert = true, collectgarbage = true, error = true, gcinfo = true, getfenv = true, getmetatable = true, ipairs = true, __inext = true,load = true, loadstring = true, math = true, newproxy = true, next = true, pairs = true, pcall = true, rawequal = true, rawget = true, rawlen = true, rawset = true, select = true, setfenv = true, setmetatable = true, string = true, table = true, tonumber = true, tostring = true, type = true, unpack = true, xpcall = true, turtle = true, pocket = true, commands = true, _G = true}
local t = {}
for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end
for _,k in ipairs(t) do _G[k] = nil end
local native = _G.term.native()
for _, method in ipairs {"nativePaletteColor", "nativePaletteColour", "screenshot"} do native[method] = _G.term[method] end
_G.term = native
if _G.http then
_G.http.checkURL = _G.http.checkURLAsync
_G.http.websocket = _G.http.websocketAsync
end
if _G.commands then _G.commands = _G.commands.native end
if _G.turtle then _G.turtle.native, _G.turtle.craft = nil end
local delete = {os = {"version", "pullEventRaw", "pullEvent", "run", "loadAPI", "unloadAPI", "sleep"}, http = _G.http and {"get", "post", "put", "delete", "patch", "options", "head", "trace", "listen", "checkURLAsync", "websocketAsync"}, fs = {"complete", "isDriveRoot"}}
for k,v in pairs(delete) do for _,a in ipairs(v) do _G[k][a] = nil end end
local olderror = error
_G.error = function() end
_G.term.redirect = function() end
function _G.term.native()
_G.term.native = nil
_G.term.redirect = nil
_G.error = olderror
term.setBackgroundColor(32768)
term.setTextColor(1)
term.setCursorPos(1, 1)
term.setCursorBlink(true)
term.clear()
local file = bootloader
if file == nil then
term.setCursorBlink(false)
term.setTextColor(16384)
term.write("Could not find /boot/cct/boot.lua. UnBIOS cannot continue.")
term.setCursorPos(1, 2)
term.write("Press any key to continue")
coroutine.yield("key")
os.shutdown()
end
local fn, err = loadstring(file.readAll(), "@bootloader")
file.close()
if fn == nil then
term.setCursorBlink(false)
term.setTextColor(16384)
term.write("Could not load /boot/cc/boot.lua. UnBIOS cannot continue.")
term.setCursorPos(1, 2)
term.write(err)
term.setCursorPos(1, 3)
term.write("Press any key to continue")
coroutine.yield("key")
os.shutdown()
end
setfenv(fn, _G)
local oldshutdown = os.shutdown
os.shutdown = function()
os.shutdown = oldshutdown
return fn()
end
end
if debug then
local function restoreValue(tab, idx, name, hint)
local i, key, value = 1, debug.getupvalue(tab[idx], hint)
while key ~= name and key ~= nil do
key, value = debug.getupvalue(tab[idx], i)
i=i+1
end
tab[idx] = value or tab[idx]
end
restoreValue(_G, "loadstring", "nativeloadstring", 1)
restoreValue(_G, "load", "nativeload", 5)
if http then restoreValue(http, "request", "nativeHTTPRequest", 3) end
restoreValue(os, "shutdown", "nativeShutdown", 1)
restoreValue(os, "reboot", "nativeReboot", 1)
if turtle then
restoreValue(turtle, "equipLeft", "v", 1)
restoreValue(turtle, "equipRight", "v", 1)
end
do
local i, key, value = 1, debug.getupvalue(peripheral.isPresent, 2)
while key ~= "native" and key ~= nil do
key, value = debug.getupvalue(peripheral.isPresent, i)
i=i+1
end
_G.peripheral = value or peripheral
end
end
+1 -1
View File
@@ -28,7 +28,7 @@ def debug(message):
def sha256(path): def sha256(path):
hasher = hashlib.sha256() hasher = hashlib.md5()
with open(path, "rb") as file: with open(path, "rb") as file:
while chunk := file.read(1024 * 1024): while chunk := file.read(1024 * 1024):
+15
View File
@@ -0,0 +1,15 @@
local args={...}
local bootstrap=""
if args[1]=="cct" then
print("installing cct")
local function get(url)
local resp=http.get(url)
return resp.readAll()
end
bootstrap=get("https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/bootstrap/cct-bootstrap.lua")
else
error("Unsupported architecture")
end
local func=load(bootstrap,"@Bootstrap", "t", _G)
func()
BIN
View File
Binary file not shown.
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "e70a3cff68a821b6d1641553c2b1495e07930bcd5808db63e8768608a928339e", "hash": "e4de9d3d66a1a13e65b502ebd1404739",
"tarball": "http://localhost:8000/packages/raw/Hyperion-core.tar.xz" "tarball": "http://localhost:8000/packages/raw/Hyperion-core.tar.gz"
} }
+2 -2
View File
@@ -8,6 +8,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "771fd62d79ff857a1ea1cf3caae340a40b08bc2330fcc6b012b9e07d001ddb45", "hash": "79e9de8d0e639f1f7183d380f93082c3",
"tarball": "http://localhost:8000/packages/raw/Hyperion-firmware-ac.tar.xz" "tarball": "http://localhost:8000/packages/raw/Hyperion-firmware-ac.tar.gz"
} }
+9
View File
@@ -0,0 +1,9 @@
{
"id": "Hyperion-firmware-addon-cct",
"description": "No description provided",
"authors": [],
"dependencies": [],
"version": "0.0.0",
"hash": "5ee70c898fb350c5b0a40a0b8cfc4a97",
"tarball": "http://localhost:8000/packages/raw/Hyperion-firmware-addon-cct.tar.gz"
}
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "f79a5a9f657acc72bb97c7731c06e366f4118c8d5d5324f8e35a958f95be2796", "hash": "282807ec0aefa87c7077b0b848a491b0",
"tarball": "http://localhost:8000/packages/raw/Hyperion-firmware-ccpc.tar.xz" "tarball": "http://localhost:8000/packages/raw/Hyperion-firmware-ccpc.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.3.0", "version": "1.3.0",
"hash": "c2b234005baa8bee1b753b96808f0b326a7f035d65e52295cb93320d5a397886", "hash": "4139f847ee8c2095dc2d561c794e5a3f",
"tarball": "http://localhost:8000/packages/raw/Hyperion-firmware-cct.tar.xz" "tarball": "http://localhost:8000/packages/raw/Hyperion-firmware-cct.tar.gz"
} }
+9
View File
@@ -0,0 +1,9 @@
{
"id": "Hyperion-firmware-lua",
"description": "No description provided",
"authors": [],
"dependencies": [],
"version": "0.0.0",
"hash": "122ff4566fe42c48335b198567938c17",
"tarball": "http://localhost:8000/packages/raw/Hyperion-firmware-lua.tar.gz"
}
+2 -2
View File
@@ -6,6 +6,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "0.1.0", "version": "0.1.0",
"hash": "f7805a3934a09cc3384d82a20ade2adc81afa3e403055cda191bf5cdc31bcc2b", "hash": "4a3445e77b744698734dde9a03e0f5b7",
"tarball": "http://localhost:8000/packages/raw/Hyperion-firmware-oc.tar.xz" "tarball": "http://localhost:8000/packages/raw/Hyperion-firmware-oc.tar.gz"
} }
+9
View File
@@ -0,0 +1,9 @@
{
"id": "Hyperion-firmware-vm",
"description": "No description provided",
"authors": [],
"dependencies": [],
"version": "0.0.0",
"hash": "cd6e3d268d9f7789e766bf8311bd755f",
"tarball": "http://localhost:8000/packages/raw/Hyperion-firmware-vm.tar.gz"
}
+2 -2
View File
@@ -8,6 +8,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.5.0", "version": "1.5.0",
"hash": "68b8f1ae21a62e627bad1187b828c959c93454d1b75a29db00a1a31b187796d0", "hash": "2e0d256069112c59e69f7f4b2bf42a0e",
"tarball": "http://localhost:8000/packages/raw/Hyperion-kernel.tar.xz" "tarball": "http://localhost:8000/packages/raw/Hyperion-kernel.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "a92fbf2d886c1ee965b1d34aed8bcf5294d97fd0f55a981e82ba5d17171e99e9", "hash": "e142c639ebae6ce8b346ff241cbce0b9",
"tarball": "http://localhost:8000/packages/raw/bit32.tar.xz" "tarball": "http://localhost:8000/packages/raw/bit32.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "2ee62a46d32e3d302453d4cb04ac8af72771645b8120e1d827eeb47b599eb192", "hash": "0cd816ee2dbc61f93aa129a32407e962",
"tarball": "http://localhost:8000/packages/raw/blake2s.tar.xz" "tarball": "http://localhost:8000/packages/raw/blake2s.tar.gz"
} }
+2 -2
View File
@@ -8,6 +8,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "dc2b541f3b9eaf8f0fd41afdaef95d2a2c37a05c01e1e6143dd0d17380f75340", "hash": "69f888fabb92d8e736200f949160e632",
"tarball": "http://localhost:8000/packages/raw/coreutils.tar.xz" "tarball": "http://localhost:8000/packages/raw/coreutils.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0-release", "version": "1.0.0-release",
"hash": "e35f29c486d4a002e46b5c4e85676c480310829b606fc72d093ed86e7daab91d", "hash": "2c6544d7c8e72522f84b5d88ba30e7e7",
"tarball": "http://localhost:8000/packages/raw/deflate.tar.xz" "tarball": "http://localhost:8000/packages/raw/deflate.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "73515e60e945b7dc9e5adb34db499e52cec9a44ff688d30ce7600025572a3e4c", "hash": "63a3b040d50c915bb60db7948109953d",
"tarball": "http://localhost:8000/packages/raw/gfxterm.tar.xz" "tarball": "http://localhost:8000/packages/raw/gfxterm.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.3.0", "version": "1.3.0",
"hash": "f01bd72d19c57a3a12c940fb2fd8d09b53a47eb857e09ecbca6464199dba35ae", "hash": "80514eb2984bb8fa249b49bd0aae7847",
"tarball": "http://localhost:8000/packages/raw/hysh.tar.xz" "tarball": "http://localhost:8000/packages/raw/hysh.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "6a883872f8f1db19617b99aae58358dc603f54801b7cde035b603773f03c7ca1", "hash": "386a212dee133206759c17809dced5d9",
"tarball": "http://localhost:8000/packages/raw/iniparse.tar.xz" "tarball": "http://localhost:8000/packages/raw/iniparse.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "3d57052898dfbfcb645cc407523702d4df91675a17bd04754b6494c3e9d2a53b", "hash": "11d7d6211673eb000c2fa59cc62e1e88",
"tarball": "http://localhost:8000/packages/raw/installer.tar.xz" "tarball": "http://localhost:8000/packages/raw/installer.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "f27f343ab85bb4dc8bd0ee6882a01aaaceeb38c791f672b54c2f1d6e80d4287e", "hash": "0ced136c9ac9324fe869515283839a23",
"tarball": "http://localhost:8000/packages/raw/json.tar.xz" "tarball": "http://localhost:8000/packages/raw/json.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.2.0", "version": "1.2.0",
"hash": "0ce3793bcef753f01ced1d5db88f39840ffbbd15eb485e32ebfc9191f0f67360", "hash": "8523c88be2eeaf3a437fe455581df80c",
"tarball": "http://localhost:8000/packages/raw/lua.tar.xz" "tarball": "http://localhost:8000/packages/raw/lua.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "cb53fe713bb74dc76f66bac0d856525ab4aeb9ab9ac1c09ca1a674ad646378fd", "hash": "d2ddcba471746b54e55ce44eec8fcff6",
"tarball": "http://localhost:8000/packages/raw/micro.tar.xz" "tarball": "http://localhost:8000/packages/raw/micro.tar.gz"
} }
+2 -2
View File
@@ -8,6 +8,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "47f8e1658373657131d514af623e7cf74fdc3165e8d4c05634fd064eb1217ef8", "hash": "d728bd2e85437a8a96d668cd731c5a22",
"tarball": "http://localhost:8000/packages/raw/minify.tar.xz" "tarball": "http://localhost:8000/packages/raw/minify.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "6736ecf743bbe3a09c223c7f73d5247056a103ec334813ada62f9bd50720f412", "hash": "a0f49db23415afc4d75f87aab12ece00",
"tarball": "http://localhost:8000/packages/raw/pid.tar.xz" "tarball": "http://localhost:8000/packages/raw/pid.tar.gz"
} }
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+6 -3
View File
@@ -8,9 +8,12 @@
"dependencies": [ "dependencies": [
"tar", "tar",
"deflate", "deflate",
"json" "json",
"minify",
"bit32",
"Hyperion-core"
], ],
"version": "1.0.0", "version": "1.0.0",
"hash": "26d7cf304ad0bc36fbfa80af1b7af957de29a6c233e6d8a302b2b562f78326db", "hash": "c2df5d0028987d76b9321ed403bcb370",
"tarball": "http://localhost:8000/packages/raw/spm.tar.xz" "tarball": "http://localhost:8000/packages/raw/spm.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.1.0", "version": "1.1.0",
"hash": "379cae7a2c42b5b0c30476c7660148c60ac426664627c649060c8feca01aa33f", "hash": "69efe854e597e8f53caaa2d0c03d0d6f",
"tarball": "http://localhost:8000/packages/raw/sysinit.tar.xz" "tarball": "http://localhost:8000/packages/raw/sysinit.tar.gz"
} }
+2 -2
View File
@@ -7,6 +7,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "", "version": "",
"hash": "2549429f0686c88354b091cbbd0cd7f80148115178cb3e5198924de28c7da6f4", "hash": "328ad76df75b9a0bc55f4fed0e31d7dd",
"tarball": "http://localhost:8000/packages/raw/tar.tar.xz" "tarball": "http://localhost:8000/packages/raw/tar.tar.gz"
} }
+2 -2
View File
@@ -10,6 +10,6 @@
], ],
"dependencies": [], "dependencies": [],
"version": "1.0.0", "version": "1.0.0",
"hash": "38422b0eb99cef1122d4aeb3472e705ba304f58713280449bd3a6a492bacd521", "hash": "32b0bcfa6c57158a00e2cb75b9f2f023",
"tarball": "http://localhost:8000/packages/raw/xz.tar.xz" "tarball": "http://localhost:8000/packages/raw/xz.tar.gz"
} }
+3
View File
@@ -2,9 +2,12 @@
"packages": { "packages": {
"Hyperion-core": "http://localhost:8000/packages/Hyperion-core.pkg", "Hyperion-core": "http://localhost:8000/packages/Hyperion-core.pkg",
"Hyperion-firmware-ac": "http://localhost:8000/packages/Hyperion-firmware-ac.pkg", "Hyperion-firmware-ac": "http://localhost:8000/packages/Hyperion-firmware-ac.pkg",
"Hyperion-firmware-addon-cct": "http://localhost:8000/packages/Hyperion-firmware-addon-cct.pkg",
"Hyperion-firmware-ccpc": "http://localhost:8000/packages/Hyperion-firmware-ccpc.pkg", "Hyperion-firmware-ccpc": "http://localhost:8000/packages/Hyperion-firmware-ccpc.pkg",
"Hyperion-firmware-cct": "http://localhost:8000/packages/Hyperion-firmware-cct.pkg", "Hyperion-firmware-cct": "http://localhost:8000/packages/Hyperion-firmware-cct.pkg",
"Hyperion-firmware-lua": "http://localhost:8000/packages/Hyperion-firmware-lua.pkg",
"Hyperion-firmware-oc": "http://localhost:8000/packages/Hyperion-firmware-oc.pkg", "Hyperion-firmware-oc": "http://localhost:8000/packages/Hyperion-firmware-oc.pkg",
"Hyperion-firmware-vm": "http://localhost:8000/packages/Hyperion-firmware-vm.pkg",
"Hyperion-kernel": "http://localhost:8000/packages/Hyperion-kernel.pkg", "Hyperion-kernel": "http://localhost:8000/packages/Hyperion-kernel.pkg",
"bit32": "http://localhost:8000/packages/bit32.pkg", "bit32": "http://localhost:8000/packages/bit32.pkg",
"blake2s": "http://localhost:8000/packages/blake2s.pkg", "blake2s": "http://localhost:8000/packages/blake2s.pkg",
BIN
View File
Binary file not shown.