GFX update :D

This commit is contained in:
Astronand committed 2026-10-04 19:45:35 -04:00
1 parent 05ca0f10a2
commit c1b4ef2644
70 files changed
+1398 -5174

No files matched your search

@@ -0,0 +1,318 @@
--:Minify:--
local kernel=...
if not kernel.cct then return end
local plt={
[0]=0x000000,0x0b0b0b,0x222222,0x444444,0x555555,0x777777,0x888888,0xaaaaaa,
0xbbbbbb,0xdddddd,0xeeeeee,0x00000b,0x000022,0x000044,0x000055,0x000077,
0x000088,0x0000aa,0x0000bb,0x0000dd,0x0000ee,0x000b00,0x002200,0x004400,
0x005500,0x007700,0x008800,0x00aa00,0x00bb00,0x00dd00,0x00ee00,0x0b0000,
0x220000,0x440000,0x550000,0x770000,0x880000,0xaa0000,0xbb0000,0xdd0000,
0xee0000,0x000033,0x000066,0x000099,0x0000cc,0x0000ff,0x003300,0x003333,
0x003366,0x003399,0x0033cc,0x0033ff,0x006600,0x006633,0x006666,0x006699,
0x0066cc,0x0066ff,0x009900,0x009933,0x009966,0x009999,0x0099cc,0x0099ff,
0x00cc00,0x00cc33,0x00cc66,0x00cc99,0x00cccc,0x00ccff,0x00ff00,0x00ff33,
0x00ff66,0x00ff99,0x00ffcc,0x00ffff,0x330000,0x330033,0x330066,0x330099,
0x3300cc,0x3300ff,0x333300,0x333333,0x333366,0x333399,0x3333cc,0x3333ff,
0x336600,0x336633,0x336666,0x336699,0x3366cc,0x3366ff,0x339900,0x339933,
0x339966,0x339999,0x3399cc,0x3399ff,0x33cc00,0x33cc33,0x33cc66,0x33cc99,
0x33cccc,0x33ccff,0x33ff00,0x33ff33,0x33ff66,0x33ff99,0x33ffcc,0x33ffff,
0x660000,0x660033,0x660066,0x660099,0x6600cc,0x6600ff,0x663300,0x663333,
0x663366,0x663399,0x6633cc,0x6633ff,0x666600,0x666633,0x666666,0x666699,
0x6666cc,0x6666ff,0x669900,0x669933,0x669966,0x669999,0x6699cc,0x6699ff,
0x66cc00,0x66cc33,0x66cc66,0x66cc99,0x66cccc,0x66ccff,0x66ff00,0x66ff33,
0x66ff66,0x66ff99,0x66ffcc,0x66ffff,0x990000,0x990033,0x990066,0x990099,
0x9900cc,0x9900ff,0x993300,0x993333,0x993366,0x993399,0x9933cc,0x9933ff,
0x996600,0x996633,0x996666,0x996699,0x9966cc,0x9966ff,0x999900,0x999933,
0x999966,0x999999,0x9999cc,0x9999ff,0x99cc00,0x99cc33,0x99cc66,0x99cc99,
0x99cccc,0x99ccff,0x99ff00,0x99ff33,0x99ff66,0x99ff99,0x99ffcc,0x99ffff,
0xcc0000,0xcc0033,0xcc0066,0xcc0099,0xcc00cc,0xcc00ff,0xcc3300,0xcc3333,
0xcc3366,0xcc3399,0xcc33cc,0xcc33ff,0xcc6600,0xcc6633,0xcc6666,0xcc6699,
0xcc66cc,0xcc66ff,0xcc9900,0xcc9933,0xcc9966,0xcc9999,0xcc99cc,0xcc99ff,
0xcccc00,0xcccc33,0xcccc66,0xcccc99,0xcccccc,0xccccff,0xccff00,0xccff33,
0xccff66,0xccff99,0xccffcc,0xccffff,0xff0000,0xff0033,0xff0066,0xff0099,
0xff00cc,0xff00ff,0xff3300,0xff3333,0xff3366,0xff3399,0xff33cc,0xff33ff,
0xff6600,0xff6633,0xff6666,0xff6699,0xff66cc,0xff66ff,0xff9900,0xff9933,
0xff9966,0xff9999,0xff99cc,0xff99ff,0xffcc00,0xffcc33,0xffcc66,0xffcc99,
0xffcccc,0xffccff,0xffff00,0xffff33,0xffff66,0xffff99,0xffffcc,0xffffff,
}
local iplt={}
for i=0, #plt do
iplt[plt[i]]=i
end
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(iplt, c24)
if not closestKey then return nil end
local value = iplt[closestKey]
l1d[c24] = value
l1f[c24] = 1
return value
end
local function splitFramebufferToStrings(fb, w)
local rows = {}
for i = 1, #fb, w do
local row_chars = {}
for j = 0, w - 1 do
local val = fb[i + j]
if val ~= nil then
table.insert(row_chars, string.char(aprox(val)))
else
break
end
end
table.insert(rows, table.concat(row_chars))
end
return rows
end
local function creategfx(term, id)
local active=false
term.setGraphicsMode(2)
for i=0, #plt do
term.setPaletteColor(i,plt[i])
end
term.setGraphicsMode(false)
term.setPaletteColor(0x1, 0xFFFFFF)
term.setPaletteColor(0x2, 0xFF0000)
term.setPaletteColor(0x4, 0x00FF00)
term.setPaletteColor(0x8, 0x0000FF)
term.setPaletteColor(0x10, 0x00FFFF)
term.setPaletteColor(0x20, 0xFF00FF)
term.setPaletteColor(0x40, 0xFFFF00)
term.setPaletteColor(0x80, 0xFF6D00)
term.setPaletteColor(0x100, 0x6DFF55)
term.setPaletteColor(0x200, 0x24FFFF)
term.setPaletteColor(0x400, 0x924900)
term.setPaletteColor(0x800, 0x6D6D55)
term.setPaletteColor(0x1000, 0xDBDBAA)
term.setPaletteColor(0x2000, 0x6D00FF)
term.setPaletteColor(0x4000, 0xB6FF00)
term.setPaletteColor(0x8000, 0x000000)
local handle={
gplt=function()
return setmetatable({},{__index=plt,__usermeta=false,__pairs=function() return pairs(plt) end})
end,
spixel=function(x,y,c)
term.setPixel(x,y,aprox(c))
end,
gpixel=function(x,y)
return term.getPixel()
end,
drawFB=function(x,y,fb,w)
local f=splitFramebufferToStrings(fb,w)
term.drawPixels(x,y,f)
end,
box=function(x,y,w,h,c,fill)
c=aprox(c)
if not fill then
term.drawPixels(x,y,c,w,1)
term.drawPixels(x,y,c,1,h)
term.drawPixels(x+w-1,y,c,1,h)
term.drawPixels(x,y+h-1,c,w,1)
else
term.drawPixels(x,y,c,w,h)
end
end,
circle=function(xc,yc,r,c,fill)
c=aprox(c)
if not fill then
local x = 0
local y = r
local d = 3 - 2 * r
-- Helper function to plot all 8 symmetric points
local function plot8Points(x, y)
term.setPixel(xc + x, yc + y, c)
term.setPixel(xc - x, yc + y, c)
term.setPixel(xc + x, yc - y, c)
term.setPixel(xc - x, yc - y, c)
term.setPixel(xc + y, yc + x, c)
term.setPixel(xc - y, yc + x, c)
term.setPixel(xc + y, yc - x, c)
term.setPixel(xc - y, yc - x, c)
end
plot8Points(x, y)
while y >= x do
x = x + 1
if d > 0 then
y = y - 1
d = d + 4 * (x - y) + 10
else
d = d + 4 * x + 6
end
plot8Points(x, y)
end
else
local x = 0
local y = r
local d = 3 - 2 * r
-- Helper to fill rows using symmetry
local function fillRows(x, y)
-- Width is (2 * coordinate) + 1 to include the center column
local strX = string.rep(string.char(c), 2 * x + 1)
local strY = string.rep(string.char(c), 2 * y + 1)
-- Draw the horizontal spans
term.drawPixels(xc - x, yc + y, {strX})
term.drawPixels(xc - x, yc - y, {strX})
term.drawPixels(xc - y, yc + x, {strY})
term.drawPixels(xc - y, yc - x, {strY})
end
fillRows(x, y)
while y >= x do
x = x + 1
if d > 0 then
y = y - 1
d = d + 4 * (x - y) + 10
else
d = d + 4 * x + 6
end
fillRows(x, y)
end
end
end,
line=function(x1,y1,x2,y2,c)
x1=math.floor(x1+0.5)
y1=math.floor(y1+0.5)
x2=math.floor(x2+0.5)
y2=math.floor(y2+0.5)
c=aprox(c)
local w,h=term.getSize(2)
local dx=math.abs(x2-x1)
local dy=math.abs(y2-y1)
local sx=x1<x2 and 1 or -1
local sy=y1<y2 and 1 or -1
local err=dx-dy
while true do
if 0<x1 and x1<=w and 0<y1 and y1<=h then
term.setPixel(x1,y1,c)
end
if x1==x2 and y1==y2 then
break
end
local e2=2*err
if e2>-dy then
err=err-dy
x1=x1+sx
end
if e2<dx then
err=err+dx
y1=y1+sy
end
end
end,
setMode=function(state)
if state then
term.setGraphicsMode(2)
for i=0, #plt do
term.setPaletteColor(i,plt[i])
end
active=true
else
term.setGraphicsMode(false)
term.setPaletteColor(0x1, 0xFFFFFF)
term.setPaletteColor(0x2, 0xFF0000)
term.setPaletteColor(0x4, 0x00FF00)
term.setPaletteColor(0x8, 0x0000FF)
term.setPaletteColor(0x10, 0x00FFFF)
term.setPaletteColor(0x20, 0xFF00FF)
term.setPaletteColor(0x40, 0xFFFF00)
term.setPaletteColor(0x80, 0xFF6D00)
term.setPaletteColor(0x100, 0x6DFF55)
term.setPaletteColor(0x200, 0x24FFFF)
term.setPaletteColor(0x400, 0x924900)
term.setPaletteColor(0x800, 0x6D6D55)
term.setPaletteColor(0x1000, 0xDBDBAA)
term.setPaletteColor(0x2000, 0x6D00FF)
term.setPaletteColor(0x4000, 0xB6FF00)
term.setPaletteColor(0x8000, 0x000000)
active=false
end
end,
getMode=function()
return active
end,
size=function()
return term.getSize(2)
end,
drawRun=function(y,x1,x2,c)
term.drawPixels(x1,y,c,{string.rep(string.char(aprox(c)),x1-x2)})
end
}
return handle
end
for id,obj in pairs(kernel.cct.term) do
if obj.setGraphicsMode then
kernel.cct.gfx[id]=creategfx(obj, id)
end
end
+3 -121
View File
@@ -1,121 +1,3 @@
local cp,c=component,computer;local b_addr=c.getBootAddress();local b_fs=cp.proxy(b_addr)
local gpu=cp.list("gpu")() and cp.proxy(cp.list("gpu")())
local e_rom=cp.list("eeprom")() and cp.proxy(cp.list("eeprom")())
local screens={}
for addr in cp.list("screen") do
if gpu then
gpu.bind(addr)
local w,h=gpu.maxResolution()
gpu.setResolution(w,h)
gpu.fill(1,1,w,h," ")
cp.proxy(addr).turnOn()
screens[#screens+1] = {cx=1,cy=1,w=w,h=h,addr=addr}
end
end
local function scroll(scr) gpu.copy(1,2,scr.w,scr.h-1,0,-1);gpu.fill(1,scr.h,scr.w,1," ") end
local function write(t)
if not gpu then return end
for s=1, #screens do
local scr=screens[s]
gpu.bind(scr.addr)
for i=1,#t do
local char=t:sub(i,i)
if char=="\n" then scr.cx=1;scr.cy=scr.cy+1
elseif char=="\t" then scr.cx=scr.cx+(4-((scr.cx-1)%4))
elseif char=="\b" then if scr.cx>1 then scr.cx=scr.cx-1;gpu.set(scr.cx,scr.cy," ") end
else gpu.set(scr.cx,scr.cy,char);scr.cx=scr.cx+1 end
if scr.cx>scr.w then scr.cx=1;scr.cy=scr.cy+1 end
if scr.cy>scr.h then scroll(scr);scr.cy=scr.cy-1 end
end
end
end
local function throw(err)
if gpu then
gpu.setBackground(0x0000AA);
gpu.setForeground(0xFFFFFF);
for i=1, #screens do
gpu.fill(1,1,screens[i].w,screens[i].h," ");
screens[i].cx,screens[i].cy=1,1;
end
write("CRITICAL KERNEL ERROR:\n"..tostring(err))
end
while true do c.pullSignal() end
end
local ok,err=xpcall(function()
local apis={}
local _l={coroutine=1,debug=1,_VERSION=1,assert=1,collectgarbage=1,error=1,getmetatable=1,ipairs=1,load=1,math=1,next=1,pairs=1,pcall=1,rawequal=1,rawget=1,rawlen=1,rawset=1,select=1,setmetatable=1,string=1,table=1,tonumber=1,tostring=1,type=1,xpcall=1,_G=1}
for k,v in pairs(_G) do if not _l[k] then apis[k]=v;_G[k]=nil end end
function sleep(t) local s=c.uptime()+t;while c.uptime()<s do c.pullSignal(s-c.uptime()) end end
local function getFile(path)
local h,err=b_fs.open(path,"r")
if not h then throw("Cannot open: "..path) end
local buf,chk="",""
repeat chk=b_fs.read(h,math.huge);buf=buf..(chk or "") until not chk
b_fs.close(h)
return buf
end
local Kernel=load(getFile("/kernel.lua"),"@Kernel")
local initFs=load(getFile("/oc/initdisks"),"@Init_disks")
local fs=load(getFile("/initfs"),"@InitFs")
if not Kernel then throw("Kernel load failed.") end
if initFs then initFs=initFs(apis, b_fs, b_addr) end
if fs then fs=fs() end
local eQ={}
local function qEv(e,...) table.insert(eQ,{e,...}) end
local efi={
getEpochMs=function() return math.floor(c.uptime()*1000) end,
getUptime=function() return c.uptime()*1000 end,
date=function() return tostring(apis.os.date()) end,
getMachineEvent=function()
if #eQ > 0 then
return table.unpack(table.remove(eQ, 1))
else
return nil
end
end,
getEEPROM=function() return e_rom and e_rom.get() or "" end,
setEEPROM=function(_,t) if e_rom then e_rom.set(t) end end,
getNvram=function() return e_rom and e_rom.getData() or "" end,
setNvram=function(_,t) if e_rom then e_rom.setData(t) end end,
beep=function(freq, timeMs) c.beep(freq, timeMs / 1000) end,
initfs=fs,
disks=initFs,
architecture="oc",
firmware=apis,
reboot=false,
yield=function() coroutine.yield() end,
screenCtl={
print=function(_,t) write(tostring(t).."\n") end,
printInline=function(_,t) write(tostring(t)) end,
clear=function() if gpu then for i=1, #screens do local scr=screens[i];gpu.bind(scr.addr);gpu.fill(1,1,scr.w,scr.h," ");scr.cx,scr.cy=1,1 end end end,
resetCursor=function() for i=1, #screens do local scr=screens[i];scr.cx,scr.cy=1,1 end end,
setBackgroundColor=function(_,cl) if gpu then gpu.setBackground(cl) end end,
setTextColor=function(_,cl) if gpu then gpu.setForeground(cl) end end,
enable=function() end,
disable=function() end
}
}
local kCo=coroutine.create(function()
local s,e=xpcall(Kernel,debug.traceback,efi)
if not s and not efi.reboot then throw(e) end
if efi.reboot then c.shutdown(true) else c.shutdown() end
end)
efi.screenCtl:print("Loaded in "..tostring(c.uptime()).."s")
while true do
local st,e=coroutine.resume(kCo)
c.pushSignal("NoSleep")
local ex=false
while not ex do
local ev={c.pullSignal(0)}
if ev[1]=="key_down" then qEv("keyPressed",1,ev[3]);qEv("keyTyped",1,string.char(ev[3]))
elseif ev[1]=="key_up" then qEv("keyReleased",1,ev[3])
end
if ev[1]=="NoSleep" then ex=true else qEv(table.unpack(ev)) end
end
if st=="error" or coroutine.status(kCo)=="dead" then
if efi.reboot then c.shutdown(true) end
throw("Kernel fault: "..tostring(e))
end
end
end,debug.traceback)
if not ok then throw("Boot fault: "..err) end
---@diagnostic disable-next-line: undefined-global
local bootdrive=__UEFI.bootDrive
+142 -64
View File
@@ -1,68 +1,146 @@
local init
do
local component_invoke = component.invoke
local function boot_invoke(address, method, ...)
local result = table.pack(pcall(component_invoke, address, method, ...))
if not result[1] then
return nil, result[2]
else
return table.unpack(result, 2, result.n)
local comp,disks,autocomplete,ev,ent,data,path,exit,dirty,ls,eb,sb,bp=components,{},false,nil,true,"","",false,true,{},false
local c,gpu=comp:getFirst("computer"),comp:getFirst("gpu")
if gpu then sb=gpu:newBuffer(48,32) end
--c.nvram.data="1/ac/boot.lua"
local function resetScreens()
sb=gpu:newBuffer(64,48)
for typ, obj in comp:list() do
if typ=="screen" then gpu:assignBuffer(sb,obj) end
end
end
-- backwards compatibility, may remove later
local eeprom = component.list("eeprom")()
computer.getBootAddress = function()
return boot_invoke(eeprom, "getData")
end
computer.setBootAddress = function(address)
return boot_invoke(eeprom, "setData", address)
end
do
local screen = component.list("screen")()
local gpu = component.list("gpu")()
if gpu and screen then
boot_invoke(gpu, "bind", screen)
end
end
local function tryLoadFrom(address)
local handle, reason = boot_invoke(address, "open", "/oc/boot.lua")
if not handle then
return nil, reason
end
local buffer = ""
repeat
local data, reason = boot_invoke(address, "read", handle, math.maxinteger or math.huge)
if not data and reason then
return nil, reason
end
buffer = buffer .. (data or "")
until not data
boot_invoke(address, "close", handle)
return load(buffer, "=init")
end
local reason
if computer.getBootAddress() then
init, reason = tryLoadFrom(computer.getBootAddress())
end
if not init then
computer.setBootAddress()
for address in component.list("filesystem") do
init, reason = tryLoadFrom(address)
if init then
computer.setBootAddress(address)
break
end
end
end
if not init then
error("no bootable medium found" .. (reason and (": " .. tostring(reason)) or ""), 0)
end
end
local ok, err = xpcall(init,debug.traceback)
if not ok then
error(err)
resetScreens()
local function displayError(err)
if not gpu then return end
gpu:freeAllBuffers()
resetScreens()
sb:pasteText(0,0,"FILL_SPILL",err)
end
local function bootloader()
for typ, obj in comp:list() do
if typ~="massStorage" then goto skip end
disks[tostring(obj.diskId)]=obj
::skip::
end
local function display(text)
print(text)
if not sb then print("NO_SB") return end
sb:pasteText(0,0,"FILL_SPILL",text)
end
local function boot()
local pos = path:find("/", 1, true)
if not pos then displayError("EINVAL") sleep(5) return end
local id,p = path:sub(1,pos-1),path:sub(pos)
if not disks[id] then displayError("ENODEV") sleep(5) return end
local init,err=load(disks[id]:open(p):read(-1),"@init","t",_G)
if err then displayError(err) sleep(5) return end
local ret = {xpcall(init, debug.traceback)}
if not ret[1] then
displayError("EFI PROGRAM ERROR: "..err)
sleep(5)
return false
else
if ret[2]=="ENTER_BIOS" then
c.nvram.ENTER_BIOS=true
return true
end
return table.unpack(ret, 2)
end
end
if c.nvram then
path=c.nvram.data or ""
eb=c.nvram.ENTER_BIOS
c.nvram.ENTER_BIOS=false
end
local function drainev()
repeat
ev={c:getMachineEvent()}
if ev[1]=="charTyped" then ent=false end
until not ev[1]
end
if path=="" or eb then drainev() ent=false else
display("Press key to enter boot menu...")
sleep(3)
drainev()
if ent then return boot() end
end
local function proc(key)
if key=="\n" then exit=true
elseif key=="\b" then path=path:sub(1,#path-1) dirty=true
elseif key=="\t" then print("autocomplete")
else path=path..key dirty=true end
end
local function get()
data=""
local pos = path:find("/", 1, true)
local trailingslash=false
if path:sub(#path)=="/" then trailingslash=true end
if not pos then
for id in pairs(disks) do
if id:sub(1,#path)==path then
data=data..id.."\n"
end
end
else
if not trailingslash then
local n=""
for i=#path, 0, -1 do
if path:sub(i,i)~="/" then
n=path:sub(i,i)..n
else break end
end
local ok,ret=pcall(function()
return disks[path:sub(1,pos-1)]:list(path:sub(pos,#path-#n))
end)
if ok then
ls = ret
end
for _,p in ipairs(ls) do
if p:sub(1,#n) == n then
data=data..p.."\n"
end
end
else
local ok,ret=pcall(function()
return disks[path:sub(1,pos-1)]:list(path:sub(pos))
end)
if ok then
ls=ret
for _,p in ipairs(ls) do
data=data..p.."\n"
end
end
end
end
end
if not ent then
while true do
get()
if dirty then
for i=0,31 do sb:clearRow(i) end
display("Select boot file...\n"..path.."\n\n"..data)
dirty=false
end
ev={c:getMachineEvent()}
if ev[1]=="charTyped" then proc(ev[2]) end
if exit then return boot() end
end
end
end
local ret={xpcall(bootloader,debug.traceback)}
if not ret[1] then
displayError(ret[2])
error(ret[2])
else
return err
return table.unpack(ret, 2)
end
@@ -1,387 +0,0 @@
--:Minify:--
local BOOT_DRIVE_PATH = ({...})[1] or "/$"
---@diagnostic disable-next-line: undefined-global
local term = term
local os = os
local function write(text)
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)
term.setBackgroundColor(0x1)
term.setTextColor(0x4)
term.clear()
term.setCursorPos(1, 1)
term.write("A critical error occurred while loading the system:")
term.setCursorPos(1, 3)
write(err)
while true do end
end
term.setCursorBlink(false)
local ok, err = xpcall(function()
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
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 function getFile(path)
local file = apis.fs.open(path, "r")
if not file then
displaySuperBadError("Could not open file: " .. path)
end
local content = file.readAll()
file.close()
return content
end
local Kernel = load(getFile(BOOT_DRIVE_PATH .. "/boot/kernel.lua"),"@Kernel")
local initFs = load(getFile(BOOT_DRIVE_PATH .. "/boot/cct/initdisks"),"@Init_disks")(apis)
local fs = load(getFile(BOOT_DRIVE_PATH .. "/boot/initfs"), "@InitFs")()
if not Kernel then displaySuperBadError("Could not load kernel.") end
if not initFs then displaySuperBadError("Could not load initdisks.") end
if not fs then displaySuperBadError("Could not load initfs.") end
if not apis.fs.exists("/nvram.dat") then
local file = apis.fs.open("/nvram.dat", "w")
file.write("Hello, World!")
file.close()
end
local eeprom
if apis.fs.exists("/startup.lua") then
eeprom="/startup.lua"
elseif apis.fs.exists("/eeprom") then
eeprom="/eeprom"
end
local eventQueue = {}
local function queueEvent(event, ...)
table.insert(eventQueue, {event, ...})
end
local colors = {
[0x000000]=0x0001,
[0xFFFFFF]=0x0002,
[0xFF0000]=0x0004,
[0x00FF00]=0x0008,
[0x0000FF]=0x0010,
[0x00FFFF]=0x0020,
[0xFF00FF]=0x0040,
[0xFFFF00]=0x0080,
[0xFF6D00]=0x0100,
[0x6DFF55]=0x0200,
[0x24FFFF]=0x0400,
[0x924900]=0x0800,
[0x6D6D55]=0x1000,
[0xDBDBAA]=0x2000,
[0x6D00FF]=0x4000,
[0xB6FF00]=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
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
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) write(text .. "\n") end,
printInline = function(_, text) write(text) end,
clear = function()
apis.term.clear()
apis.term.setCursorPos(1, 1)
end,
setCursorPos = function(_, x, y)
apis.term.setCursorPos(x, y)
end,
getCursorPos = function() return apis.term.getCursorPos() end,
getSize = function() return apis.term.getSize() end,
setBackgroundColor = function(_, color)
apis.term.setBackgroundColor(aprox(color))
end,
setTextColor = function(_, color)
apis.term.setTextColor(aprox(color))
end,
getBackgroundColor = function()
return bg
end,
getTextColor = function()
return fg
end,
enable=function() end,
disable=function() end
},
architecture="cct",
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
}
apis.term.setBackgroundColor(0x8000)
apis.term.setTextColor(0x1000)
apis.term.clear()
apis.term.setCursorPos(1, 1)
local kernelCoro = coroutine.create(function()
---@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 EFI.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
write("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
while true do
local status, err = EFI.resumeWithTimeout(kernelCoro, 50)
apis.os.queueEvent("NoSleep")
local exit = false
while not exit do
local event = {coroutine.yield()}
if event[1] == "key" then
queueEvent("keyPressed", 1, event[2])
if acekeys[event[2]] then
queueEvent("keyTyped", 1, acekeys[event[2]])
end
elseif event[1] == "char" then
queueEvent("keyTyped", 1, event[2])
elseif event[1] == "key_up" then
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
exit = true
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")
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
@@ -1,119 +0,0 @@
--:Minify:--
local BOOT_DRIVE_PATH=({...})[1] or "/$"
-- UnBIOS by JackMacWindows
-- This will undo most of the changes/additions made in the BIOS, but some things may remain wrapped if `debug` is unavailable
-- To use, just place a `bios.lua` in the root of the drive, and run this program
-- Here's a list of things that are irreversibly changed:
-- * both `bit` and `bit32` are kept for compatibility
-- * string metatable blocking (on old versions of CC)
-- In addition, if `debug` is not available these things are also irreversibly changed:
-- * old Lua 5.1 `load` function (for loading from a function)
-- * `loadstring` prefixing (before CC:T 1.96.0)
-- * `http.request`
-- * `os.shutdown` and `os.reboot`
-- * `peripheral`
-- * `turtle.equip[Left|Right]`
-- Licensed under the MIT license
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
-- Set up TLCO
-- This functions by crashing `rednet.run` by removing `os.pullEventRaw`. Normally
-- this would cause `parallel` to throw an error, but we replace `error` with an
-- empty placeholder to let it continue and return without throwing. This results
-- in the `pcall` returning successfully, preventing the error-displaying code
-- from running - essentially making it so that `os.shutdown` is called immediately
-- after the new BIOS exits.
--
-- From there, the setup code is placed in `term.native` since it's the first
-- thing called after `parallel` exits. This loads the new BIOS and prepares it
-- for execution. Finally, it overwrites `os.shutdown` with the new function to
-- allow it to be the last function called in the original BIOS, and returns.
-- From there execution continues, calling the `term.redirect` dummy, skipping
-- over the error-handling code (since `pcall` returned ok), and calling
-- `os.shutdown()`. The real `os.shutdown` is re-added, and the new BIOS is tail
-- called, which effectively makes it run as the main chunk.
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 = fs.open(BOOT_DRIVE_PATH.."/boot/cct/boot.lua", "r")
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(BOOT_DRIVE_PATH)
end
end
if debug then
-- Restore functions that were overwritten in the BIOS
-- Apparently this has to be done *after* redefining term.native
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,272 +0,0 @@
--:Minify:--
local apis = ({...})[1]
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH
local fs = apis.fs
local native = apis.peripheral
local peripheral = {}
local sides = {"top", "bottom", "left", "right", "front", "back"}
function peripheral.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 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 disks = {}
local internal = {}
local function norm(path)
if not path or path == "" then return "/" end
return fs.combine("/", path)
end
local function createDisk(id, basePath, readonly, periph)
basePath = norm(basePath)
local disk = {address = id, isReadOnly = function() return readonly end}
function disk:spaceUsed()
return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
end
function disk:spaceTotal() return fs.getCapacity(basePath) end
function disk:list(path)
local p = fs.combine(basePath, path)
if not fs.exists(p) or not fs.isDir(p) then
return nil, "not directory"
end
return fs.list(p)
end
function disk:fileExists(path)
local p = fs.combine(basePath, path)
return fs.exists(p) and not fs.isDir(p)
end
function disk:directoryExists(path)
local p = fs.combine(basePath, path)
return fs.exists(p) and fs.isDir(p)
end
function disk:type(path)
local p = fs.combine(basePath, path)
if not fs.exists(p) then
return nil
elseif fs.isDir(p) then
return "directory"
else
return "file"
end
end
function disk:makeDirectory(path)
local p = fs.combine(basePath, path)
fs.makeDir(p)
return true
end
function disk:remove(path)
local p = fs.combine(basePath, path)
if fs.exists(p) then fs.delete(p) end
return true
end
function disk:setLabel(label) periph.setLabel(label) end
function disk:getLabel(label) return periph.getLabel() end
function disk:attributes(path)
local p = fs.combine(basePath, path)
return fs.attributes(p)
end
function disk:open(path, mode)
local p = fs.combine(basePath, path)
return fs.open(p, mode)
end
return disk
end
internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
setLabel = function(label)
local h = fs.open("/.label", "w")
h.write(label)
h.close()
end,
getLabel = function()
local h = fs.open("/.label", "r")
if not h then return "$" end
local label = h.readAll()
h.close()
return label
end
})
internal["rom"] = createDisk("rom", "/rom", true, {
setLabel = function(label)
error("Device is read-only")
end,
getLabel = function()
return "cctrom"
end
})
local function refresh()
disks={}
for _, disk in ipairs({peripheral.find("drive")}) do
if disk.isDiskPresent() then
disks[tostring(disk.getDiskID())]=createDisk("cctdisk"..tostring(disk.getDiskID()), disk.getMountPath(), false, fs)
end
end
end
local function iter()
refresh()
local combined = {}
for id, obj in pairs(internal) do combined[id] = obj end
for id, obj in pairs(disks) do combined[id] = obj end
return pairs(combined)
end
return {refresh = refresh, list = iter}
@@ -1,6 +0,0 @@
--:Minify:--
local kernel=...
if kernel.gfx then
end
@@ -494,7 +494,7 @@ local ok, err = xpcall(function()
h.close()
end,
firmware=apis,
reboot=false,
status="running",
beep=function() end
}
@@ -505,7 +505,7 @@ local ok, err = xpcall(function()
local kernelCoro = coroutine.create(function()
--pf
---@diagnostic disable-next-line: param-type-mismatch-
---@diagnostic disable-next-line: param-type-mismatch
local ok, err = xpcall(Kernel, debug.traceback, EFI)
if not ok then
error(err)
@@ -569,14 +569,18 @@ local ok, err = xpcall(function()
end
end
if status == "error" or coroutine.status(kernelCoro) == "dead" then
if EFI.reboot then
if EFI.status=="reboot" then
apis.os.reboot()
elseif EFI.status=="shutdown" then
apis.os.shutdown()
end
displaySuperBadError("Kernel error: " .. tostring(err))
coroutine.yield("key")
elseif status == "success" then
if EFI.reboot then
if EFI.status=="reboot" then
apis.os.reboot()
elseif EFI.status=="shutdown" then
apis.os.shutdown()
end
displaySuperBadError("Kernel error: Attempted to yield main thread\n"..debug.traceback(kernelCoro, "Attempted to yield main thread"))
coroutine.yield("key")
@@ -163,7 +163,7 @@ local function createDisk(id, basePath, readonly, periph)
local disk = {address = id, isReadOnly = function() return readonly end}
function disk:spaceUsed()
return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
return (fs.getCapacity(basePath) or 0) - (fs.getFreeSpace(basePath) or 0)
end
function disk:spaceTotal() return fs.getCapacity(basePath) end
@@ -0,0 +1,25 @@
--:Minify:--
local kernel=...
local fifo=kernel.newFifo()
kernel.devfs.data["input"]["mouse1"] = function(op, mode)
if op=="type" then
return "Mouse"
elseif op=="open" then
local h = {
read=function(amount)
local rv=""
for i=1, amount or 1 do
local event = {fifo.pop()}
if event[1] then
rv=rv..event[1]
end
end
---@diagnostic disable-next-line: cast-local-type
if rv=="" then rv=nil end
return rv
end
}
return h
end
end
kernel.cct.mouse={fifo=fifo}
@@ -1,6 +1,8 @@
--:Minify:--
local kernel = ...
local peripheral=kernel.cct.peripheral
kernel.cct.gfx={}
kernel.cct.term={}
local colors = {
[0xFFFFFF]=0x0001,
@@ -155,6 +157,7 @@ local function serializeBool(bool)
end
local function newtty(obj, id, ev)
kernel.cct.term[id]=obj
obj.setPaletteColor(0x1, 0xFFFFFF) -- #000000
obj.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
obj.setPaletteColor(0x4, 0x00FF00) -- #FF0000
@@ -176,17 +179,6 @@ local function newtty(obj, id, ev)
return "Terminal"
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,
@@ -221,18 +213,16 @@ local function newtty(obj, id, ev)
return false
end,
gplt=function()
return plt
return table.deepcopy(plt)
end,
gfx=function(...)
if kernel.cct.gfx[id] then return kernel.cct.gfx[id] else return false end
end,
id=function()
return id
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
return h
end
end
end
@@ -259,23 +249,14 @@ kernel.devfs.data["input"]["keyboard1"] = function(op, mode)
rv=rv..event[1]
end
end
---@diagnostic disable-next-line: cast-local-type
if rv=="" then rv=nil end
return rv
end,
write=function(content)
end,
gctrl=function()
return serializeBool(kernel.cct.ctrl)..";"..serializeBool(kernel.cct.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
return h
end
end
@@ -71,8 +71,10 @@ kernel.processes.cctdaemon = function()
elseif eventType == "mouse_scroll" then
if event[2] == 1 then
kernel.cct.fifo.push("S")
kernel.cct.mouse.fifo.push("S")
else
kernel.cct.fifo.push("T")
kernel.cct.mouse.fifo.push("T")
end
elseif eventType == "http_success" then
if kernel.cct.httpqueue[event[2]] then
@@ -85,6 +87,16 @@ kernel.processes.cctdaemon = function()
kernel.cct.httperror[event[2]]=event[3]
kernel.cct.httpresponse[event[2]]=event[4]
end
elseif eventType == "mouse_click" then
--";X;Y;C"
-- 1 = left
-- 2 = right
-- 3 = middle
kernel.cct.mouse.fifo.push(";"..tostring(event[3])..";"..tostring(event[4])..";"..tostring(event[2]))
elseif eventType == "mouse_drag" then
kernel.cct.mouse.fifo.push(";"..tostring(event[3])..";"..tostring(event[4])..";"..tostring(event[2]))
elseif eventType == "mouse_up" then
kernel.cct.mouse.fifo.push(";"..tostring(event[3])..";"..tostring(event[4])..";"..tostring(event[2]))
else
if kernel.cct.eventhooks[eventType] then
local ok,err = xpcall(kernel.cct.eventhooks[eventType], debug.traceback, table.unpack(event))
@@ -35,6 +35,14 @@ function kernel.main()
local totalTaskTime = 0
local taskTimes = {}
for id,hook in ipairs(kernel.mainHooks) do
local ok,err = xpcall(hook, debug.traceback)
if not ok then
kernel.log("[MAIN HOOK ERR]: "..err, "ERROR", 0xFF0000)
kernel.mainHooks[id]=nil
end
end
for pid, task in pairs(kernel.tasks) do
if kernel.exitMain then break end
@@ -42,7 +50,7 @@ function kernel.main()
for id,hook in ipairs(list) do
local ok,err = xpcall(hook, debug.traceback, task, pid)
if not ok then
kernel.log("[MAIN HOOK ERR]: "..err, "ERROR", 0xFF0000)
kernel.log("[TASK HOOK ERR]: "..err, "ERROR", 0xFF0000)
list[id]=nil
end
end
@@ -148,4 +156,6 @@ function kernel.main()
kernel.saveLog()
end
end
kernel.log("Exited main")
kernel.saveLog()
end
@@ -1,3 +1,4 @@
---@diagnostic disable-next-line: undefined-global
local cp,c=component,computer;local b_addr=c.getBootAddress();local b_fs=cp.proxy(b_addr)
local gpu=cp.list("gpu")() and cp.proxy(cp.list("gpu")())
local e_rom=cp.list("eeprom")() and cp.proxy(cp.list("eeprom")())
@@ -121,10 +121,7 @@ function kernel.main()
end
end
end
if kernel.EFI:getEpochMs()>=nextyield then
kernel.EFI:yield()
nextyield=kernel.EFI:getEpochMs()+5000
end
kernel.EFI:yield()
end
local T_prev_avg = (N > 0) and (totalTaskTime / N) or 0
+8 -5
View File
@@ -74,7 +74,7 @@ function kernel.PANIC(msg)
break
end
end
EFI.reboot=true
EFI.status="reboot"
error("KERNEL PANIC")
end
kernel.panic=kernel.PANIC
@@ -179,7 +179,6 @@ if not root then
if event[1]=="keyTyped" then
if tonumber(event[3]) then
if canadates[tonumber(event[3])] then
ifs.writeAllText("/boot/fstab", "U "..canadates[tonumber(event[3])]..";/\n"..fstab)
fstab="U "..canadates[tonumber(event[3])]..";/\n"..fstab
ifs.mount(canadates[tonumber(event[3])], "/")
break
@@ -359,7 +358,7 @@ kernel.perTaskHooks={}
kernel.mainHooks={}
kernel.runhooks={}
-- args {taskobj}
-- args {taskobj, pid}
function kernel.execPerTask(func, prior)
if not kernel.perTaskHooks[prior] then kernel.perTaskHooks[prior]={} end
kernel.perTaskHooks[prior][#kernel.perTaskHooks[prior]+1] = func
@@ -460,6 +459,7 @@ kernel.syscalls["saveLog"]=function()
end
end
ifs.writeAllText("/boot/fstab", fstab)
kernel.saveLog()
kernel.log("Running modules")
for _,p in ipairs(modules) do
@@ -471,7 +471,7 @@ for _,p in ipairs(modules) do
if not code then
kernel.panic("Failed to read module "..v)
end
local func,err=load(code,"@"..v)
local func,err=load(code,"@"..v,"t",_G)
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
@@ -502,10 +502,13 @@ if kernel.status=="panic" then
kernel.panic(kernel.reason)
end
if kernel.status=="reboot" then
EFI.reboot=true
EFI.status="reboot"
return true
elseif kernel.status=="halt" then
kernel.log("System halted.")
kernel.saveLog()
while true do end
else
EFI.status="shutdown"
return true
end
@@ -2,6 +2,16 @@
--- @diagnostic disable: duplicate-set-field
local kernel = ...
kernel.allowGlobalOverwrites = true
local oldtype = type
local oldgetmetatable = getmetatable
function math.round(x)
if x>=0 then
return math.floor(x+0.5)
else
return math.ceil(x-0.5)
end
end
function string.hasSuffix(str, suffix)
return string.sub(str, #suffix + 1) == suffix
@@ -70,6 +80,10 @@ function table.hasVal(tabl, query)
return false
end
function table.readOnly(tabl, typ)
return setmetatable({},{__index=tabl,__newindex=function()error("Table is read-only")end,__usermeta=false,__type=typ})
end
local function serialize(tbl, seen)
seen = seen or {}
@@ -100,6 +114,8 @@ local function serialize(tbl, seen)
output = output .. "\"" .. tostring(v) .. "\""
elseif type(v) == "thread" then
output = output .. "\"" .. tostring(v) .. "\""
elseif oldgetmetatable(v) and oldgetmetatable(v).__tostring then
output = output .. tostring(v)
else
error("serialization of type \"" .. type(v) .. "\" is not supported")
end
@@ -111,8 +127,6 @@ local function serialize(tbl, seen)
return output
end
local oldtype = type
local oldgetmetatable = getmetatable
function type(object, trueType)
if trueType then return oldtype(object) end
if oldtype(object) ~= "table" then
@@ -131,7 +145,7 @@ end
function getmetatable(object)
if oldtype(object) ~= "table" then return end
if oldtype(oldgetmetatable(object)) == "table" then
if oldgetmetatable(object).__isuserdata then
if oldgetmetatable(object).__usermeta then
if oldtype(oldgetmetatable(object).__usermeta) == "function" then
return oldgetmetatable(object).__usermeta()
else
@@ -251,8 +265,6 @@ local function makeSyscallProxy()
local backing = {}
return setmetatable(backing, {
__index = function(self, name)
local raw = rawget(self, name)
if raw ~= nil then return raw end
return function(...)
local res = table.pack(coroutine.yield("syscall", name, ...))
if res[1] then
@@ -263,7 +275,7 @@ local function makeSyscallProxy()
end
end,
__newindex = function(self, k, v)
rawset(self, k, v)
error("Table is read-only")
end,
__metatable=false
})
@@ -271,6 +283,5 @@ end
syscall = makeSyscallProxy()
_makeSyscallProxy = makeSyscallProxy
table.serialize = serialize
@@ -299,6 +299,7 @@ local function namei(path, noFollow, symDepth)
if not target or target == "" then
error("ENOENT: empty symlink target")
end
if kernel.config.logSymlinkTraverse then kernel.log(curPath .. " > " .. target) end
local symIsAbs, symTokens = tokenizePath(target)
@@ -1158,7 +1159,27 @@ function vfs.devlst(fd)
return table.keys(kernel.currentTask.fd[fd].handle)
end
function vfs.getOpenFds()
local out={}
for i,v in ipairs(kernel.currentTask.fd) do
out[i]=v.path
end
return out
end
function vfs.fsinfo()
local out={mounts={},disks={}}
for i,v in pairs(vfs.mounts) do
out.mounts[i]=v
end
for i,v in pairs(vfs.disks) do
out.disks[i]={size=vfs.disks[i].spaceTotal(),used=vfs.disks[i].spaceUsed(),label=vfs.disks[i].getLabel(),readOnly=vfs.disks[i].isReadOnly(),isVirt=vfs.disks[i].isvirt,address=vfs.disks[i].addressz}
end
return out
end
vfs.resolveMount = resolveMount
vfs.updateMeta = updateMeta
local sys = kernel.syscalls
sys["open"] = vfs.open
@@ -1198,5 +1219,7 @@ sys["fget_suid"] = function(fd)
local fobj = kernel.currentTask and kernel.currentTask.fd[fd]
return fobj and fobj.suid_owner or nil
end
sys["getOpenFds"]= vfs.getOpenFds
sys["fsinfo"] = vfs.fsinfo
kernel.log("VFS module loaded")
@@ -7,8 +7,12 @@ kernel.searchpaths = {
}
kernel.reqcache = cache
local function wrap(lib)
return setmetatable({},{__index=lib,__newindex=function()error("Table is read-only")end,__usermeta=false,__call=function(s,...) return lib.new(...) end})
end
local function require(module, ...)
if cache[module] then return cache[module].ret end
if cache[module] then return wrap(cache[module].ret) end
local args = {...}
for _, path in ipairs(kernel.searchpaths) do
local filepath = path:gsub("?", module)
@@ -36,8 +40,8 @@ local function require(module, ...)
if not ok then
error("Error running module "..module..": "..tostring(ret))
end
cache[module] = {ret = ret, expires = kernel.EFI:getEpochMs() + 120000}
return ret
cache[module] = {ret = ret}
return wrap(ret)
end
coroutine.yield()
end
@@ -0,0 +1,3 @@
--:Minify:--
local kernel = ...
@@ -0,0 +1,82 @@
--:Minify:--
local kernel = ...
local proxy = {}
local data = {}
proxy.address = "devfs0000"
proxy.isvirt = true
proxy.isReadOnly = function() return false end
proxy.spaceUsed = function() return 0 end
proxy.spaceTotal = function() return 0 end
proxy.makeDirectory = function() error("EACCES") end
proxy.remove = function() error("EACCES") end
proxy.setLabel = function() error("EACCES") end
proxy.getLabel = function() return "devfs" end
proxy.attributes = function(path) return {
size = 0,
modified = 0,
created = 0
} end
function proxy:open(path, mode)
local steps = kernel.vfs.splitPath(path)
local step = data
for i=1, #steps-1 do
local dat = step[steps[i]]
if type(dat) ~= "table" then error("ENFILE") end
step=dat
end
if type(step[steps[#steps]]) == "function" then
return step[steps[#steps]]("open", mode)
end
error("ENFILE")
end
function proxy:type(path, mode)
local steps = kernel.vfs.splitPath(path)
local step = data
if #steps == 0 then
return "directory"
end
for i=1, #steps-1 do
local dat = step[steps[i]]
if type(dat) ~= "table" then error("ENFILE") end
step=dat
end
if type(step[steps[#steps]]) == "function" then
return step[steps[#steps]]("type", mode)
end
if type(step[steps[#steps]]) == "table" then
return "directory"
end
error("ENOENT")
end
function proxy:list(path)
local steps = kernel.vfs.splitPath(path)
local step = data
if #steps == 0 then
return table.keys(data)
end
for i=1, #steps-1 do
local dat = step[steps[i]]
if type(dat) ~= "table" then error("ENOENT") end
step=dat
end
if type(step[steps[#steps]]) == "table" then
return table.keys(step[steps[#steps]])
end
error("ENOENT")
end
function proxy:fileExists(path)
local ok = pcall(function()
return self:type(path)
end)
return ok
end
kernel.sysfs={}
kernel.sysfs.proxy=proxy
kernel.disks["sysfs0000"]=proxy
@@ -37,7 +37,7 @@ kernel.execPerTask(function(task)
if task.sigq and #task.sigq ~= 0 and task.sigh then
local coro = coroutine.create(task.sigh)
local status,err=coroutine.resume(coro, table.remove(task.sigq, 1))
EFI:yeild()
kernel.EFI:yield()
if status=="error" or status==false then
task.sigd.error=err or "Unknown"
task.sigd.active=false
@@ -2,3 +2,5 @@
local kernel=...
kernel.unixSockets={}
local socket=kernel.socket
--socket.registerProtocal()
@@ -58,10 +58,12 @@ kernel._U.load = function(a,b,c,d) return origLoad(a,b,c,d or kernel._U) end
function kernel.freshUserEnv()
local locals = {}
locals.syscall = _makeSyscallProxy()
local env = setmetatable(locals, {
__index = kernel._U,
__pairs = function(self)
return pairs(kernel._U)
end,
__newindex = function(_, k, v) rawset(locals, k, v) end,
__metatable=false
})
@@ -33,7 +33,7 @@ local function createVt(id, width, height)
end
end
function vt.obj:write(content)
function vt.obj.write(content)
local x, y = vt.cursorX, vt.cursorY
if x>vt.width then return end
if y>vt.height then return end
@@ -79,36 +79,36 @@ local function createVt(id, width, height)
vt.cursorX, vt.cursorY = x, y
end
function vt.obj:spos(x, y)
function vt.obj.spos(x, y)
vt.cursorX = tonumber(x)
vt.cursorY = tonumber(y)
end
function vt.obj:gpos()
return tostring(vt.cursorX)..";"..tostring(vt.cursorY)
function vt.obj.gpos()
return vt.cursorX, vt.cursorY
end
function vt.obj:sfgc(color)
function vt.obj.sfgc(color)
vt.fgColor = tonumber(color)
end
function vt.obj:sbgc(color)
function vt.obj.sbgc(color)
vt.bgColor = tonumber(color)
end
function vt.obj:gfgc()
function vt.obj.gfgc()
return vt.fgColor
end
function vt.obj:gbgc()
function vt.obj.gbgc()
return vt.bgColor
end
function vt.obj:gplt()
function vt.obj.gplt()
return 24
end
function vt.obj:clear()
function vt.obj.clear()
for y = 1, vt.height do
for x = 1, vt.width do
vt.buffer[y][x] = {char = " ", fgColor = vt.fgColor, bgColor = vt.bgColor}
@@ -117,12 +117,12 @@ local function createVt(id, width, height)
vt.cursorX, vt.cursorY = 1, 1
end
function vt.obj:isvirt()
function vt.obj.isvirt()
return true
end
function vt.obj:gctrl()
return serializeBool(vt.ctrl)..";"..serializeBool(vt.alt)
function vt.obj.gfx()
end
return vt
@@ -108,7 +108,7 @@ function sys.spawn(func, name, envars, args, tgid, clearFds)
end
function sys.execspawn(path, name, envars, args, tgid, keepFds)
local func, euid, suid_active = loadExecutable(path, kernel._U)
local func, euid, suid_active = loadExecutable(path)
local caller = kernel.currentTask
local real_uid = caller and caller.uid or kernel.uid
@@ -124,16 +124,19 @@ function sys.execspawn(path, name, envars, args, tgid, keepFds)
return createTask(func, name or path, envars, args, tgid, real_uid, euid, not keepFds)
end
function sys.exec(path, args, envars)
function sys.exec(path, args, envars, clearFds)
local task = kernel.currentTask
local func, euid, _ = loadExecutable(path, kernel._U)
local func, euid, _ = loadExecutable(path)
-- no idea why this is here?
--if task.fd then
-- for fd, _ in pairs(task.fd) do
-- if fd > 2 then pcall(kernel.vfs.close, fd) end
-- end
--end
-- Figured it out it is to close fds on su
if clearFds then
if task.fd then
for fd, _ in pairs(task.fd) do
if fd > 2 then pcall(kernel.vfs.close, fd) end
end
end
end
task.euid = euid
task.args = args or {}
@@ -1,7 +1,7 @@
--:Minify:--
local kernel=...
local debug=debug
kernel.debug=debug
kernel._G.debug={
getinfo=debug.getinfo,
traceback=debug.traceback
getinfo=kernel.debug.getinfo,
traceback=kernel.debug.traceback
}
@@ -14,7 +14,7 @@ local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
if not handle then kernel.panic("Failed to read "..kernel.config.initPath) end
kernel.vfs.close(handle)
local initFunc, err = load(data, "@sysinit", "t", kernel._U)
local initFunc, err = load(data, "@init", "t", kernel._U)
if not initFunc then kernel.PANIC("Failed to load init system: " .. err) end
kernel.tasks["1"] = {
@@ -28,7 +28,7 @@ kernel.tasks["1"] = {
kernel.saveLog()
end),
name = "sysinit",
name = "init",
status = "R",
pid = 1,
tgid = 1,
@@ -2,11 +2,11 @@
local kernel = ...
kernel.processes.kgc = function()
while true do
for i,v in pairs(kernel.reqcache) do
if v.expires and kernel.EFI:getEpochMs() > v.expires then
kernel.reqcache[i] = nil
end
end
--for i,v in pairs(kernel.reqcache) do
-- if v.expires and kernel.EFI:getEpochMs() > v.expires then
-- kernel.reqcache[i] = nil
-- end
--end
sleep(5)
end
end
@@ -1,7 +1,10 @@
--:Minify:--
local kernel = ...
if kernel.firstBoot then
if kernel.firstBoot or kernel.config.resetPerms then
if kernel.config.resetPerms then
kernel.log("resetPerms is active, disable it in /boot/boot.cfg", "WARN", 0xFFFF00)
end
kernel.log("Seeding filesystem permissions...")
local P = kernel.vfs.P
@@ -18,20 +21,23 @@ if kernel.firstBoot then
local function seed(root, data)
for i=1,#data do
local entry=data[1]
kernel.vfs.chmod(root..entry[1],entry[2],entry[3])
kernel.vfs.chown(root..entry[1],entry[4])
local entry=data[i]
if kernel.vfs.exists(root..entry[1]) then
kernel.vfs.updateMeta(root..entry[1],function(e)
e.perms=entry[4]
e.group=entry[3]
e.owner=entry[2]
end)
end
end
end
seed("/", {
{"bin", 0, 0, RWX_RX_RX},
{"boot", 0, 0, RWX_RX_RX},
{"dev", 0, 0, RWXRWXRWX},
{"etc", 0, 0, RWX_RX_RX},
{"home", 0, 0, RWX_RX_RX},
{"lib", 0, 0, RWX_RX_RX},
{"proc", 0, 0, RWXRWXRWX},
{"root", 0, 0, RW____ },
{"sbin", 0, 0, RWX_RX_RX},
{"tmp", 0, 0, RWXRWXRWX},
+1 -1
View File
@@ -58,7 +58,7 @@ syscall.setEnviron("HOME", homedir)
syscall.setEnviron("USER", username)
syscall.setEnviron("SHELL", shell)
local ok, err = pcall(syscall.exec, shell)
local ok, err = pcall(syscall.exec, shell, nil, true)
if not ok then
print("su: cannot exec shell '" .. shell .. "': " .. tostring(err))
syscall.exit(1)
File renamed without changes.
File renamed without changes.
+1
View File
@@ -0,0 +1 @@
vector
File renamed without changes.
+19
View File
@@ -0,0 +1,19 @@
function lib.load(fd)
function handle.setPixel(x,y,color24)
function handle.getPixel(x,y)
function handle.setPixels(x,y,w,framebuffer)
function handle.getPixels(x,y,w,h)
function handle.frame(x,y,w,h,writeonly)
integer id
recurse lib.load
function handle.framectl(id)
function frame.move(x,y)
function frame.resize(w,h)
function frame.free()
function handle.sync()
function handle.line(x1,y1,x2,y2)
function handle.box(x,y,w,h,c,fill)
function handle.filledBox(x,y,w,h,c)
function handle.text(x,y,font,text)
function handle.free()
function handle.size()
View File
Whitespace-only changes.
File renamed without changes.
View File
Whitespace-only changes.
File renamed without changes.
-40
View File
@@ -1,40 +0,0 @@
--:Minify:--
local lib = {}
function lib.frame(frame)
local handle = {}
function handle.setPixel(x,y,color24)
end
function handle.getPixel(x,y)
end
function handle.setPixels(x,y,framebuffer)
end
function handle.getPixels(x,y,w,h)
end
function handle.frame(x,y,w,h,writeonly)
end
function handle.framectl(id,x,y,w,h,writeonly)
end
function handle.drawframe()
end
function handle.line()
end
return handle
end
-350
View File
@@ -1,350 +0,0 @@
term.setGraphicsMode(2)
local w,h = term.getSize(2)
local fb={}
for i=1, h do
fb[i]={}
for x=1, w do
fb[i][x]=0
end
end
local function setPixel(x,y,c)
--local old=fb[y]
--fb[y]=string.sub(old,1,x-1)..string.char(c)..string.sub(old,x+1)
fb[y][x]=c
end
local function setPixels(x,y,frame)
local w,h = #fb[1], #fb
for i=1, #frame do
for j=1, #frame[i] do
fb[y+i-1][x+j-1]=frame[i][j]
end
end
end
local function getPixel(x,y)
return fb[y][x]
end
local function getPixels(x,y,w,h)
local ret={}
for i=y, y+h do
ret[#ret+1] = {table.unpack(fb[i], x, x+w)}
end
return ret
end
local colors = {
[0]=0x000000,
0x0b0b0b,
0x222222,
0x444444,
0x555555,
0x777777,
0x888888,
0xaaaaaa,
0xbbbbbb,
0xdddddd,
0xeeeeee,
0x00000b,
0x000022,
0x000044,
0x000055,
0x000077,
0x000088,
0x0000aa,
0x0000bb,
0x0000dd,
0x0000ee,
0x000b00,
0x002200,
0x004400,
0x005500,
0x007700,
0x008800,
0x00aa00,
0x00bb00,
0x00dd00,
0x00ee00,
0x0b0000,
0x220000,
0x440000,
0x550000,
0x770000,
0x880000,
0xaa0000,
0xbb0000,
0xdd0000,
0xee0000,
0x000033,
0x000066,
0x000099,
0x0000cc,
0x0000ff,
0x003300,
0x003333,
0x003366,
0x003399,
0x0033cc,
0x0033ff,
0x006600,
0x006633,
0x006666,
0x006699,
0x0066cc,
0x0066ff,
0x009900,
0x009933,
0x009966,
0x009999,
0x0099cc,
0x0099ff,
0x00cc00,
0x00cc33,
0x00cc66,
0x00cc99,
0x00cccc,
0x00ccff,
0x00ff00,
0x00ff33,
0x00ff66,
0x00ff99,
0x00ffcc,
0x00ffff,
0x330000,
0x330033,
0x330066,
0x330099,
0x3300cc,
0x3300ff,
0x333300,
0x333333,
0x333366,
0x333399,
0x3333cc,
0x3333ff,
0x336600,
0x336633,
0x336666,
0x336699,
0x3366cc,
0x3366ff,
0x339900,
0x339933,
0x339966,
0x339999,
0x3399cc,
0x3399ff,
0x33cc00,
0x33cc33,
0x33cc66,
0x33cc99,
0x33cccc,
0x33ccff,
0x33ff00,
0x33ff33,
0x33ff66,
0x33ff99,
0x33ffcc,
0x33ffff,
0x660000,
0x660033,
0x660066,
0x660099,
0x6600cc,
0x6600ff,
0x663300,
0x663333,
0x663366,
0x663399,
0x6633cc,
0x6633ff,
0x666600,
0x666633,
0x666666,
0x666699,
0x6666cc,
0x6666ff,
0x669900,
0x669933,
0x669966,
0x669999,
0x6699cc,
0x6699ff,
0x66cc00,
0x66cc33,
0x66cc66,
0x66cc99,
0x66cccc,
0x66ccff,
0x66ff00,
0x66ff33,
0x66ff66,
0x66ff99,
0x66ffcc,
0x66ffff,
0x990000,
0x990033,
0x990066,
0x990099,
0x9900cc,
0x9900ff,
0x993300,
0x993333,
0x993366,
0x993399,
0x9933cc,
0x9933ff,
0x996600,
0x996633,
0x996666,
0x996699,
0x9966cc,
0x9966ff,
0x999900,
0x999933,
0x999966,
0x999999,
0x9999cc,
0x9999ff,
0x99cc00,
0x99cc33,
0x99cc66,
0x99cc99,
0x99cccc,
0x99ccff,
0x99ff00,
0x99ff33,
0x99ff66,
0x99ff99,
0x99ffcc,
0x99ffff,
0xcc0000,
0xcc0033,
0xcc0066,
0xcc0099,
0xcc00cc,
0xcc00ff,
0xcc3300,
0xcc3333,
0xcc3366,
0xcc3399,
0xcc33cc,
0xcc33ff,
0xcc6600,
0xcc6633,
0xcc6666,
0xcc6699,
0xcc66cc,
0xcc66ff,
0xcc9900,
0xcc9933,
0xcc9966,
0xcc9999,
0xcc99cc,
0xcc99ff,
0xcccc00,
0xcccc33,
0xcccc66,
0xcccc99,
0xcccccc,
0xccccff,
0xccff00,
0xccff33,
0xccff66,
0xccff99,
0xccffcc,
0xccffff,
0xff0000,
0xff0033,
0xff0066,
0xff0099,
0xff00cc,
0xff00ff,
0xff3300,
0xff3333,
0xff3366,
0xff3399,
0xff33cc,
0xff33ff,
0xff6600,
0xff6633,
0xff6666,
0xff6699,
0xff66cc,
0xff66ff,
0xff9900,
0xff9933,
0xff9966,
0xff9999,
0xff99cc,
0xff99ff,
0xffcc00,
0xffcc33,
0xffcc66,
0xffcc99,
0xffcccc,
0xffccff,
0xffff00,
0xffff33,
0xffff66,
0xffff99,
0xffffcc,
0xffffff,
}
for i=0,255 do
term.setPaletteColor(i,colors[i])
end
term.drawPixels(0,0,fb)
for i=0,255 do
for y=1+i, h-i do
for x=1+i, w-i do
setPixel(x,y,i)
end
end
term.drawPixels(1,1,fb)
os.queueEvent("nosleep")
os.pullEvent()
end
for i=1, 1000 do
pcall(function()
setPixels(math.random(1,w),math.random(1,h),getPixels(math.random(1,w),math.random(1,h),math.random(1,w),math.random(1,h)))
end)
term.drawPixels(1,1,fb)
os.queueEvent("nosleep")
os.pullEvent()
end
setPixels(1,1,getPixels(w-50,h-50,50,50))
term.drawPixels(0,0,fb)
local i=0
for x=1, 16*4, 4 do
for y=1, 16*4, 4 do
setPixel(x,y,i)
setPixel(x+1,y,i)
setPixel(x+2,y,i)
setPixel(x+3,y,i)
setPixel(x,y+1,i)
setPixel(x+1,y+1,i)
setPixel(x+2,y+1,i)
setPixel(x+3,y+1,i)
setPixel(x,y+2,i)
setPixel(x+1,y+2,i)
setPixel(x+2,y+2,i)
setPixel(x+3,y+2,i)
setPixel(x,y+3,i)
setPixel(x+1,y+3,i)
setPixel(x+2,y+3,i)
setPixel(x+3,y+3,i)
i=i+1
end
end
term.drawPixels(0,0,fb)
sleep(5)
term.setGraphicsMode(false)
+9 -4
View File
@@ -6,6 +6,7 @@ syscall.open("/dev/tty/1","w") --stdout (Device 1)
syscall.open("/dev/null","w") --stderr (device 2)
local fs = require("fs")
local gfx = syscall.devctl(1,"gfx")
syscall.devctl(1,"clear")
syscall.devctl(1,"sfgc",0xFFFFFF)
@@ -242,6 +243,7 @@ builtinCmds.clear = function()
syscall.devctl(1,"clear")
syscall.devctl(1,"sfgc",0xFFFFFF)
syscall.devctl(1,"spos",1,1)
if gfx then local w,h=gfx.size() gfx.box(0,0,w+5,h+5,0,true) end
end
builtinCmds.whoami = function()
@@ -820,10 +822,11 @@ builtinCmds.df = function(...)
end
local function fmt(n) return opts.h and hfmt(n) or tostring(n) end
print(string.format("%-20s %10s %10s %10s %6s %-s","Filesystem","Size","Used","Avail","Use%","Mounted on"))
local mounts = {{"$","/"}, {"devfs0000","/dev/"}, {"tmpfs0000","/tmp/"}}
for _, m in ipairs(mounts) do
local id, mp = m[1], m[2]
print(string.format("%-20s %10s %10s %10s %6s %-s", id, "?", "?", "?", "?%", mp))
local fsinfo = syscall.fsinfo()
for id, obj in pairs(fsinfo.disks) do
local use = ((obj.size/obj.used)-1)*100
local avail = obj.size-obj.used
print(string.format("%-20s %10s %10s %10s %6s %-s", id, tostring(obj.size), tostring(obj.used), avail, tostring(use).."%", fsinfo.mounts[id] or ""))
end
end
@@ -1218,12 +1221,14 @@ local function runCommand(command)
while true do
local exited, code = syscall.collect(proc)
if exited then
if gfx then gfx.setMode(false) end
if code then print("\nTask exited with code:\n"..tostring(code)) end
return
end
if terminate then
local ok2 = syscall.kill(proc, true)
if ok2 then
if gfx then gfx.setMode(false) end
syscall.devctl(1,"sbgc",16); syscall.devctl(1,"sfgc",0xFF0000)
print("\nProgram Terminated."); syscall.devctl(1,"sfgc",0xFFFFFF)
end
+6 -4
View File
@@ -173,6 +173,8 @@ end
local luaEnv = setmetatable({}, {__index = _ENV})
luaEnv._G = luaEnv
luaEnv._ENV = _ENV
luaEnv._G = _G
luaEnv.print = function(...)
local n = select("#", ...)
@@ -259,9 +261,9 @@ local function getUserInput(prompt, history)
local key = syscall.read(0)
if key and key ~= "" then
if key == "" then
if cursor > 1 then cursor = cursor - 1; dirty = true end
if cursor > 1 then cursor = cursor + 1; dirty = true end
elseif key == "" then
if cursor <= #input then cursor = cursor + 1; dirty = true end
if cursor <= #input then cursor = cursor - 1; dirty = true end
elseif key == "" then
if history and histIdx < #history then
histIdx = histIdx + 1
@@ -298,9 +300,9 @@ local function getUserInput(prompt, history)
end
c(C_PROMPT); w("HyperionOS " .. _VERSION .. "\n")
w("Type \"exit()\" to exit.")
w("Interactive Lua REPL. Type \"exit()\" to exit.\n")
c(C_NIL)
w("Interactive Lua REPL. exit() to quit.\n\n")
w("\n\n")
c(1)
local history = {}
+2
View File
@@ -0,0 +1,2 @@
Hyperion
Astronand
+217
View File
@@ -0,0 +1,217 @@
--:Minify:--
local lib={}
local function check(a,b,ignoreb)
if type(a)~="vector" then error("vector metatable is on non vector object") end
if not ignoreb and b~=nil then
if type(b)~="vector" then error("b must be vector") end
if #a~=#b then error("vectors must be same size") end
end
end
local vector={
add = function(a,b)
check(a,b)
local ret={}
for i=1, #a do
ret[i]=a[i]+b[i]
end
return lib.convert(ret)
end,
sub = function(a,b)
check(a,b)
if type(b)~="vector" then error("b must be vector") end
local ret={}
for i=1, #a do
ret[i]=a[i]-b[i]
end
return lib.convert(ret)
end,
unm = function(a)
local ret={}
for i=1, #a do
ret[i]=-a[i]
end
return lib.convert(ret)
end,
mul = function(a,b)
if type(a)=="number" and type(b)=="vector" then a,b=b,a end
check(a,b,true)
local ret={}
if type(b)=="vector" then
for i=1, #a do
ret[i]=a[i]*b[i]
end
elseif type(b)=="number" then
for i=1, #a do
ret[i]=a[i]*b
end
else
error("b must be vector or number")
end
return lib.convert(ret)
end,
div = function(a,b)
if type(a)=="number" and type(b)=="vector" then a,b=b,a end
check(a,b,true)
local ret={}
if type(b)=="vector" then
for i=1, #a do
ret[i]=a[i]/b[i]
end
elseif type(b)=="number" then
for i=1, #a do
ret[i]=a[i]/b
end
else
error("b must be vector or number")
end
return lib.convert(ret)
end,
dot = function(a,b)
check(a,b)
local out=a[1]*b[1]
for i=2, #a do
out=out+a[i]*b[i]
end
return out
end,
tostring = function(a)
check(a)
local out = "{"
for i=1, #a do
out=out..tostring(a[i])..", "
end
return out:sub(1,#out-2).."}"
end,
equals = function(a,b)
check(a,b)
for i=1, #a do
if a[i]~=b[i] then
return false
end
end
return true
end,
cross = function(a,b)
check(a,b)
if #a~=3 then error("Vectors must be of type 'vec3'") end
if #b~=3 then error("Vectors must be of type 'vec3'") end
return lib.convert({
a.y*b.z-a.z*b.y,
a.z*b.x-a.x*b.z,
a.x*b.y-a.y*b.x
})
end,
length = function(a)
check(a)
local out=a[1]*a[1]
for i=2, #a do
out=out+a[i]*a[i]
end
if type(out)=="vector" then
return out:sqrt()
else
return math.sqrt(out)
end
end,
len = function(a)
return a:length()
end,
normalize = function(a)
return a*(1/a:len())
end,
round = function(a, t)
check(a)
local ret={}
for i=1, #a do
ret[i]=math.floor((a[i]+t*0.5)/t)*t
end
return lib.convert(ret)
end,
exp = function(a, e)
check(a)
local ret={}
for i=1, #a do
ret[i]=a^e
end
return lib.convert(ret)
end,
sqrt = function(a)
check(a)
local ret={}
for i=1, #a do
if type(a[i])=="vector" then
ret[i]=a[i]:sqrt()
else
ret[i]=math.sqrt(a[i])
end
end
return lib.convert(ret)
end
}
local idxtable={
w=4,
x=1,
y=2,
z=3,
}
local function index(self, k)
if idxtable[k] then
return rawget(self,idxtable[k])
elseif vector[k] then
return vector[k]
else
return rawget(self,k)
end
end
local function newindex(self, k, v)
if idxtable[k] then
rawset(self, idxtable[k], v)
else
rawset(self, k, v)
end
end
local meta={
__name="vector",
__type="vector",
__usermeta=function() error("EACCES") end,
__index=index,
__newindex=newindex,
__unm=vector.unm,
__add=vector.add,
__sub=vector.sub,
__mul=vector.mul,
__div=vector.div,
__tostring=vector.tostring,
__eq=vector.equals
}
function lib.new(...)
local vars={...}
return setmetatable(vars,meta)
end
function lib.convert(vars)
return setmetatable(vars,meta)
end
return lib
+217
View File
@@ -0,0 +1,217 @@
--:Minify:--
local lib={}
local function check(a,b,ignoreb)
if type(a)~="vector" then error("a must be vector") end
if not ignoreb and b~=nil then
if type(b)~="vector" then error("b must be vector") end
if #a~=#b then error("vectors must be same size") end
end
end
local vector={
add = function(a,b)
check(a,b)
local ret={}
for i=1, #a do
ret[i]=a[i]+b[i]
end
return lib.convert(ret)
end,
sub = function(a,b)
check(a,b)
if type(b)~="vector" then error("b must be vector") end
local ret={}
for i=1, #a do
ret[i]=a[i]-b[i]
end
return lib.convert(ret)
end,
unm = function(a)
local ret={}
for i=1, #a do
ret[i]=-a[i]
end
return lib.convert(ret)
end,
mul = function(a,b)
if type(a)=="number" and type(b)=="vector" then a,b=b,a end
check(a,b,true)
local ret={}
if type(b)=="vector" then
for i=1, #a do
ret[i]=a[i]*b[i]
end
elseif type(b)=="number" then
for i=1, #a do
ret[i]=a[i]*b
end
else
error("b must be vector or number")
end
return lib.convert(ret)
end,
div = function(a,b)
if type(a)=="number" and type(b)=="vector" then a,b=b,a end
check(a,b,true)
local ret={}
if type(b)=="vector" then
for i=1, #a do
ret[i]=a[i]/b[i]
end
elseif type(b)=="number" then
for i=1, #a do
ret[i]=a[i]/b
end
else
error("b must be vector or number")
end
return lib.convert(ret)
end,
dot = function(a,b)
check(a,b)
local out=a[1]*b[1]
for i=2, #a do
out=out+a[i]*b[i]
end
return out
end,
tostring = function(a)
check(a)
local out = "{"
for i=1, #a do
out=out..tostring(a[i])..", "
end
return out:sub(1,#out-2).."}"
end,
equals = function(a,b)
check(a,b)
for i=1, #a do
if a[i]~=b[i] then
return false
end
end
return true
end,
cross = function(a,b)
check(a,b)
if #a~=3 then error("Vectors must be of type 'vec3'") end
if #b~=3 then error("Vectors must be of type 'vec3'") end
return lib.convert({
a.y*b.z-a.z*b.y,
a.z*b.x-a.x*b.z,
a.x*b.y-a.y*b.x
})
end,
length = function(a)
check(a)
local out=a[1]*a[1]
for i=2, #a do
out=out+a[i]*a[i]
end
if type(out)=="vector" then
return out:sqrt()
else
return math.sqrt(out)
end
end,
len = function(a)
return a:length()
end,
normalize = function(a)
return a*(1/a:len())
end,
round = function(a, t)
check(a)
local ret={}
for i=1, #a do
ret[i]=math.floor((a[i]+t*0.5)/t)*t
end
return lib.convert(ret)
end,
exp = function(a, e)
check(a)
local ret={}
for i=1, #a do
ret[i]=a^e
end
return lib.convert(ret)
end,
sqrt = function(a)
check(a)
local ret={}
for i=1, #a do
if type(a[i])=="vector" then
ret[i]=a[i]:sqrt()
else
ret[i]=math.sqrt(a[i])
end
end
return lib.convert(ret)
end
}
local idxtable={
w=4,
x=1,
y=2,
z=3,
}
local function index(self, k)
if idxtable[k] then
return rawget(self,idxtable[k])
elseif vector[k] then
return vector[k]
else
return rawget(self,k)
end
end
local function newindex(self, k, v)
if idxtable[k] then
rawset(self, idxtable[k], v)
else
rawset(self, k, v)
end
end
local meta={
__name="vector",
__type="vector",
__usermeta=function() error("EACCES") end,
__index=index,
__newindex=newindex,
__unm=vector.unm,
__add=vector.add,
__sub=vector.sub,
__mul=vector.mul,
__div=vector.div,
__tostring=vector.tostring,
__eq=vector.equals
}
function lib.new(...)
local vars={...}
return setmetatable(vars,meta)
end
function lib.convert(vars)
return setmetatable(vars,meta)
end
return lib
+3
View File
@@ -0,0 +1,3 @@
General advanced math libs
VectorX
Matrix
+1
View File
@@ -0,0 +1 @@
1.0.0
+124
View File
@@ -0,0 +1,124 @@
local args={...}
if #args<1 then print("Usage: render3d [file.obj]") end
local fs=require("fs")
local vec=require("vector")
local gfx=syscall.devctl(1,"gfx")
local file = fs.readAllText(args[1])
local obj={v={},f={}}
local lines=string.split(file, "\n")
for i=1, #lines do
local line=lines[i]
if line:sub(1,2)=="v " then
line=line:sub(3)
local s=string.split(line, " ")
obj.v[#obj.v+1]=vec(tonumber(s[1]),tonumber(s[2]),tonumber(s[3]))
elseif line:sub(1,2)=="f " then
line=line:sub(3)
local s=string.split(line, " ")
local vs={}
for c=1, #s do
local v=string.split(s[c], "/")
vs[#vs+1]=tonumber(v[1])
end
obj.f[#obj.f+1]=vec(table.unpack(vs))
end
end
print("Vertices")
for i=1, #obj.v do
print(obj.v[i])
end
print("Faces")
for i=1, #obj.f do
print(obj.f[i])
end
local function projectPoint(point, cameraPos, cameraRot, fov, width, height)
local p=point-cameraPos
local pitch=cameraRot.x
local yaw=cameraRot.y
local cp=math.cos(pitch)
local sp=math.sin(pitch)
local cy=math.cos(yaw)
local sy=math.sin(yaw)
local right=vec(
cy,
0,
-sy
)
local up=vec(
sy*sp,
cp,
cy*sp
)
local forward=vec(
-sy*cp,
sp,
-cy*cp
)
local x=p:dot(right)
local y=p:dot(up)
local z=p:dot(forward)
if z<=0 then
return nil
end
local aspect=width/height
local f=1/math.tan(fov*0.5)
local sx=(x*f/aspect)/z
local sy=(y*f)/z
return vec(
(sx+1)*0.5*width,
(1-sy)*0.5*height
),z
end
local proj={}
local camera=vec(0,0,3)
local rot=vec(0,0,0)
local w,h=gfx.size()
local fov=math.rad(90)
for i=1, #obj.v do
proj[i]={}
proj[i].p,proj[i].z=projectPoint(obj.v[i],camera,rot,fov,w,h)
end
print("Projected")
for i=1, #proj do
print(proj[i].p)
end
gfx.setMode(true)
for i=#obj.f, 1, -1 do
local f=obj.f[i]
local c=math.random(0,0xffffff)
for p=1, #f do
if p~=#f then
print(tostring(proj[f[p]].p.x)..","..tostring(proj[f[p]].p.y).." > "..tostring(proj[f[p+1]].p.x)..","..tostring(proj[f[p+1]].p.y))
gfx.line(proj[f[p]].p.x,proj[f[p]].p.y,proj[f[p+1]].p.x,proj[f[p+1]].p.y,c)
else
print(tostring(proj[f[p]].p.x)..","..tostring(proj[f[p]].p.y).." > "..tostring(proj[f[1]].p.x)..","..tostring(proj[f[1]].p.y))
gfx.line(proj[f[p]].p.x,proj[f[p]].p.y,proj[f[1]].p.x,proj[f[1]].p.y,c)
end
end
end
while true do
sleep(5)
end
@@ -0,0 +1,40 @@
# Blender 5.2.2 LTS
# www.blender.org
mtllib box.mtl
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vt 0.625000 0.500000
vt 0.875000 0.500000
vt 0.875000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.125000 0.500000
vt 0.375000 0.500000
vt 0.125000 0.750000
s 0
usemtl Material
f 1/1/1 5/2/1 7/3/1 3/4/1
f 4/5/2 3/4/2 7/6/2 8/7/2
f 8/8/3 7/9/3 5/10/3 6/11/3
f 6/12/4 2/13/4 4/5/4 8/14/4
f 2/13/5 1/1/5 3/4/5 4/5/5
f 6/11/6 5/10/6 1/1/6 2/13/6
+4
View File
@@ -0,0 +1,4 @@
--:Minify:--
local lib = {}
return lib