Skip to content

Instantly share code, notes, and snippets.

@iamgreaser
Created February 2, 2016 20:56

Revisions

  1. iamgreaser created this gist Feb 2, 2016.
    200 changes: 200 additions & 0 deletions bootcore.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,200 @@
    local CR,P,SMT,k,v,i=component,computer,setmetatable
    local function cwrap(addr)return SMT({},{__index=function(t,k)
    return function(...)return CR.invoke(addr,k,...)end end,
    __call=function(t) return addr end})end
    local C=SMT({},{__index=function(t,k)return CR[k] or cwrap(CR.list(k)())end})
    for i=1,4 do P.beep(220*i,0.1)end
    local SR=P.pullSignal
    while SR(0.05) do end
    local G=C.gpu
    G.bind(C.screen())
    G.setBackground(0)
    G.setForeground(0xFFFFFF)
    G.setResolution(G.maxResolution())

    local E,Ec,gcpoll={},{}
    function E.ignore(e,f)local i
    if Ec[e]then for i=1,#Ec[e]do if f==Ec[e]then
    table.remove(Ec[e],i)return end end end end
    function E.listen(e,f)E.ignore(e,f)
    if not Ec[e]then Ec[e]={}end
    Ec[e][#Ec[e]+1]=f end
    function E.pull(t)gcpoll()local l={SR(t)}--TODO name filter
    local n,i=l[1]if n and Ec[n]then
    for i=1,#Ec[n]do Ec[n](table.unpack(l))end end
    return table.unpack(l)end
    local T={}
    do
    local tx,ty=1,1
    local tw,th
    local getr=function()tw,th=G.getResolution()end

    getr()
    function T.isAvailable()return true end
    function T.getCursor()return tx,ty end
    function T.setCursor(x,y)tx,ty=x,y end
    function T.clear()G.fill(1,1,tw,th," ")tx,ty=1,1 end
    function T.write(s,wrap)getr()local b,bx,i=""
    local function unbuf()if b~=""then
    if bx<tw then G.copy(bx,ty,tw-bx,1,#b,0)end
    G.set(bx,ty,b)bx=nil b=""end end
    for i=1,#s do
    local c=s:sub(i,i)
    if c=="\n"then unbuf()tx=1 ty=ty+1
    elseif c=="\r"then unbuf()tx=1
    elseif c=="\t"then unbuf()tx=((tx-1)-((tx-1)%8))+9
    elseif c=="\b"then unbuf()tx=math.max(1,tx-1)G.set(tx,ty," ")
    else bx=bx or tx b=b..c tx=tx+1
    end
    if tx>tw then unbuf()if wrap then tx=1 ty=ty+1 else tx=tw end end
    if ty>th then unbuf()ty=th G.copy(1,2,tw,th-1,0,-1) G.fill(1,th,tw,1," ") end
    end unbuf()
    end
    function T.read(hi,db,fh,pw)
    local b,a,c=""
    while true do
    a={E.pull()}
    if a[1]=="key_down"then
    if a[3]>=32 then c=utf8.char(a[3])T.write(c)b=b..c
    elseif a[3]==13 then T.write("\n")return b
    elseif a[3]==8 and#b>0 then T.write("\b")
    if 127<b:byte(#b)then
    while 192>b:byte(#b)and#b>0 do b=b:sub(1,#b-1)T.write("\b")end end
    b=b:sub(1,#b-1)
    else --print(a[3],a[4])
    end
    end
    end
    end
    end
    function print(...)
    local a,i={...}for i=1,#a do T.write(tostring(a[i]),true)
    if i<#a then T.write("\t",true)end end
    T.write("\n",true)end

    T.clear()
    print("Bootcore loading!")

    local G1,G2={},SMT({},{__mode="v"})
    function gcable(o,f)
    assert(o and f)
    local i=#G1+1
    G1[i]=f
    G2[i]=o
    return o
    end
    gcpoll=function()
    while #G1~=#G2 do
    local t,f=#G2+1,#G1
    assert(pcall(G1[t]))
    if t==f then G1[t],G2[t]=nil end
    G1[t],G2[t],G1[f],G2[f]=G1[f],G2[f]
    end
    end
    local dnt={}
    local D={byname={},ntyp=dnt}
    for k,v in C.list"filesystem" do
    local d,n,f={id=k},"dh",cwrap(k)
    d.fs=f
    if f.isReadOnly()then n="rom"
    elseif f.getLabel()=="tmpfs" then n="ram"
    elseif f.spaceTotal()==512*1024 then n="df"
    end
    dnt[n]=(dnt[n] or 0)+1
    n=n..(dnt[n]-1)
    d.name=n
    D.byname[n]=d
    end
    local iofs=((D.byname.dh0 and"dh0")
    or(D.byname.df0 and"df0")
    or(D.byname.rom0 and"rom0"))
    do local ba=D.byname[iofs].id function P.getBootAddress()return ba end end
    local iocd="/"
    local function Dfix(n)
    while n:find("//")do n=n:gsub("//","/")end
    --while n:find("..")do n end--TODO!
    return n
    end
    local function Dpath(n)
    local pc,ps,cfs
    cfs=iofs
    pc,ps=n:find(":"),n:find("/")
    if pc and((not ps) or pc<ps)then return n:sub(1,pc-1),Dfix("/"..n:sub(pc+1))
    elseif ps==1 then return iofs,Dfix(n)
    else return iofs,Dfix(iocd.."/"..n)
    end
    end

    io={
    stdin={read=function()return T.read()end},
    stdout={write=function(s)return T.write(s,true)end,
    setvbuf=function()end},
    input=function()return io.stdin end,
    output=function()return io.stdout end,
    open=function(n,m)
    local dn,pn,fs,fd=Dpath(n)
    fs=D.byname[dn].fs
    fd=fs.open(pn,m or"r")
    assert(fd,dn.."|"..pn)
    return gcable({
    read=function(t,a)
    local r,s=""
    if a=="*a" then repeat s=fs.read(fd,999)if s then r=r..s end until s=="" or not s return r
    elseif a=="*l"or a=="*L"or not a then while true do
    s=fs.read(fd,1) if s=="\n" or s==""or not s then
    if a=="*L"then r=r..(s or"")end
    if r==""then return nil else return r end end r=r..s end
    else return fs.read(fd,a)
    end
    end,
    close=function()fs.close(fd)fd=nil end
    },function()if fd then fs.close(fd)end end)
    end,
    write=function(s)return T.write(s,true)end,
    }
    io.stderr=io.stdout

    local env={}
    os.getenv=function(n)if n=="PWD"then return shell.getWorkingDirectory()end
    return env[n]end
    os.setenv=function(n,v)if n=="PWD"then return shell.setWorkingDirectory(v)end
    env[n]=v end
    os.execute=function(s)
    local p,i={}
    while true do i=s:find(" ")if i
    then p[#p+1],s=s:sub(1,i-1),s:sub(i+1) else p[#p+1]=s break end
    end
    local n=loadfile("/bin/"..p[1]..".lua")(table.unpack(p,2))
    return "exit",n or 0
    end
    shell={
    getWorkingDirectory=function()return iofs..":"..iocd end,
    setWorkingDirectory=function(w)iofs,iocd=Dpath(w)end,
    resolve=function(n,x)assert(not x,x)n,x=Dpath(n)return n..":"..x end,
    parse=function(...)local a,o,p,i,j,v,s={},{},{...}for i=1,#p do
    v=p[i]if v:sub(1,1)=="-"then for j=2,#v do o[v:sub(j,j)]=true end
    else a[#a+1]=v end
    end return a,o end
    }
    local text={
    trim=function(s)return s end,--TODO!
    }
    function loadfile(fn)local f,s
    f=io.open(fn,"r")s=f:read("*a")f:close()return load(s,fn)end
    function dofile(fn,...)return loadfile(fn)(...)end

    function Dinvoker(n,z)return function(p,...)
    local a,d=Dpath(p)d=D.byname[a]return(d and d.fs[n](...))or error(n) end end
    local fsm fsm=SMT({
    get=function(s)local a=(Dpath(s))return D.byname[a].fs,a..":"end,
    },{__index=function(t,k)return rawget(t,k)or Dinvoker(k)end})

    local MB={gpu=G,term=T,component=C,computer=P,event=E,shell=shell,
    text=text,filesystem=fsm}
    function require(n)return MB[n]end

    while true do
    k,v=pcall(dofile,"dh0:/bin/sh.lua")
    if not k then print(v or"nil",debug.traceback())end
    end
    print("HALTED")while true do E.pull(1.0)end