forked from Hyperion/HyperionOS
236 lines
5.9 KiB
C++
236 lines
5.9 KiB
C++
local apis={}
|
|
|
|
local lua = {
|
|
coroutine = true,
|
|
debug = true,
|
|
_HOST = true,
|
|
_VERSION = true,
|
|
assert = true,
|
|
collectgarbage = true,
|
|
error = true,
|
|
gcinfo = true,
|
|
getfenv = 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,
|
|
setfenv = true,
|
|
setmetatable = true,
|
|
string = true,
|
|
table = true,
|
|
tonumber = true,
|
|
tostring = true,
|
|
type = true,
|
|
xpcall = true,
|
|
_G=true
|
|
}
|
|
|
|
for i,v in pairs(_G) do
|
|
if not lua[i] or lua[i]==nil then
|
|
apis[i]=v
|
|
_G[i]=nil
|
|
end
|
|
end
|
|
|
|
function sleep(time)
|
|
coroutine.yield("CC_TIMER", time)
|
|
end
|
|
|
|
local function catErr(text)
|
|
apis.term.setCursorPos(1,1)
|
|
apis.term.write(text)
|
|
while true do
|
|
coroutine.yield()
|
|
end
|
|
end
|
|
|
|
local function getFile(path)
|
|
if path:sub(1,1) ~= "/" then
|
|
path="/"..path
|
|
end
|
|
path="/disk"..path
|
|
if not apis.fs.exists(path) then error("File does not exist") end
|
|
if apis.fs.isDir(path) then error("Cannot open a directory") end
|
|
return {
|
|
readAllText=function()
|
|
local file = apis.fs.open(path, "r")
|
|
local text = file.readAll()
|
|
file.close()
|
|
return text
|
|
end,
|
|
writeAllText=function(text)
|
|
local file = apis.fs.open(path, "w")
|
|
file.write(text)
|
|
file.close()
|
|
end
|
|
}
|
|
end
|
|
|
|
-- Prints text handling \n, \t, and \b with scrolling (no wrapping)
|
|
local function write(text)
|
|
local x, y = apis.term.getCursorPos()
|
|
local w, h = apis.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)
|
|
apis.term.write(string.rep(" ", spaces))
|
|
x = x + spaces
|
|
elseif c == "\b" then
|
|
if x > 1 then
|
|
x = x - 1
|
|
apis.term.setCursorPos(x, y)
|
|
apis.term.write(" ")
|
|
apis.term.setCursorPos(x, y)
|
|
end
|
|
else
|
|
if x <= w and y <= h then
|
|
apis.term.setCursorPos(x, y)
|
|
apis.term.write(c)
|
|
x = x + 1
|
|
end
|
|
end
|
|
|
|
-- Handle scrolling if we go past bottom
|
|
if y > h then
|
|
apis.term.scroll(1)
|
|
y = h
|
|
apis.term.setCursorPos(x, y)
|
|
end
|
|
end
|
|
|
|
apis.term.setCursorPos(x, y)
|
|
end
|
|
|
|
|
|
local event_queue = {}
|
|
local function addEventRaw(...)
|
|
event_queue[#event_queue+1] = {...}
|
|
end
|
|
|
|
local function getEvent()
|
|
local event = event_queue[1]
|
|
event_queue = {table.unpack(event_queue, 2)}
|
|
return table.unpack(event or {})
|
|
end
|
|
|
|
local lkeys={}
|
|
lkeys[apis.keys.enter]="\n"
|
|
lkeys[apis.keys.backspace]="\b"
|
|
lkeys[apis.keys.tab]="\t"
|
|
|
|
local computer={}
|
|
computer.beep=function() end
|
|
computer.shutdown=apis.os.shutdown
|
|
computer.reboot=apis.os.reboot
|
|
computer.time=function()
|
|
return apis.os.epoch("utc")
|
|
end
|
|
computer.getMachineEvent=getEvent
|
|
computer.date=apis.os.date
|
|
|
|
local function list(path)
|
|
if path:sub(1,1) ~= "/" then
|
|
path="/"..path
|
|
end
|
|
path="/disk"..path
|
|
if not apis.fs.isDir(path) then return {} end
|
|
return apis.fs.list(path)
|
|
end
|
|
|
|
function coroutine.resumeWithTimeout(CORO, LINES, ...)
|
|
local yeildKey = {}
|
|
debug.sethook(CORO, function()
|
|
coroutine.yield(yeildKey)
|
|
end, "l", LINES)
|
|
local ret = {coroutine.resume(CORO, ...)}
|
|
debug.sethook(CORO)
|
|
if ret[2]==yeildKey then return false else return true, table.unpack(ret, 2) end
|
|
end
|
|
|
|
local kernel = load(getFile("/boot/HBoot.sys").readAllText(), "@kernel", "t", _G)
|
|
if not kernel then
|
|
catErr("BOOT COMPILE ERR")
|
|
end
|
|
local kernel_coro = coroutine.create(function()
|
|
local ok,err = pcall(function()
|
|
local ok, err=xpcall(kernel, debug.traceback, "cc", apis, "disk", {
|
|
print=function(text)
|
|
write(text.."\n")
|
|
end,
|
|
printInline=function(text)
|
|
write(text)
|
|
end,
|
|
clear=function()
|
|
apis.term.clear()
|
|
apis.term.setCursorPos(1,1)
|
|
end,
|
|
getSize=function ()
|
|
return apis.term.getSize()
|
|
end
|
|
}, getFile, list, computer)
|
|
if not ok then
|
|
write(err)
|
|
while true do
|
|
coroutine.yield()
|
|
end
|
|
end
|
|
end)
|
|
if not ok then
|
|
catErr(err)
|
|
end
|
|
end)
|
|
|
|
apis.term.setCursorBlink(false)
|
|
while true do
|
|
local ret = {coroutine.resumeWithTimeout(kernel_coro, 200)}
|
|
if coroutine.status(kernel_coro) == "dead" then
|
|
catErr("KERNEL EXITED")
|
|
end
|
|
if ret[1] then
|
|
if ret[2]=="CC_TIMER" and ret[3]~=nil and type(ret[3])=="number" then
|
|
local timer = apis.os.startTimer(ret[3])
|
|
repeat
|
|
local _, param = coroutine.yield("timer")
|
|
until param == timer
|
|
end
|
|
end
|
|
apis.os.queueEvent("nosleep")
|
|
local exit = false
|
|
repeat
|
|
local event = {coroutine.yield()}
|
|
if event[1] == "nosleep" then
|
|
exit=true
|
|
elseif event[1]==nil then
|
|
elseif event[1]=="key" then
|
|
addEventRaw("keyPressed", 1, event[2])
|
|
if lkeys[event[2]] then
|
|
addEventRaw("keyTyped", 1, lkeys[event[2]])
|
|
end
|
|
elseif event[1]=="char" then
|
|
addEventRaw("keyTyped", 1, event[2])
|
|
elseif event[1]=="key_up" then
|
|
addEventRaw("keyReleased", 1, event[2])
|
|
elseif event[1]=="disk" then
|
|
addEventRaw("componentAdded", "disk")
|
|
elseif event[1]=="disk_eject" then
|
|
addEventRaw("componentRemoved", "disk")
|
|
end
|
|
until exit
|
|
end
|
|
apis.os.reboot() |