restructure for spm

This commit is contained in:
2026-01-18 22:14:15 -05:00
parent fd7ee1aa3b
commit 63bcc2df5c
68 changed files with 120 additions and 98 deletions

View File

@@ -0,0 +1,296 @@
--: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,
_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
}
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
function sleep(time)
local stoptime = apis.os.clock() + (time)
while stoptime > apis.os.clock() do end
end
apis.term.setPaletteColor(0x1, 0x000000) -- #000000
apis.term.setPaletteColor(0x2, 0xFFFFFF) -- #FFFFFF
apis.term.setPaletteColor(0x4, 0xFF0000) -- #FF0000
apis.term.setPaletteColor(0x8, 0x00FF00) -- #00FF00
apis.term.setPaletteColor(0x10, 0x0000FF) -- #0000FF
apis.term.setPaletteColor(0x20, 0x00FFFF) -- #00FFFF
apis.term.setPaletteColor(0x40, 0xFF00FF) -- #FF00FF
apis.term.setPaletteColor(0x80, 0xFFFF00) -- #FFFF00
apis.term.setPaletteColor(0x100, 0xFF6D00) -- #FF6D00
apis.term.setPaletteColor(0x200, 0x6DFF55) -- #6DFF55
apis.term.setPaletteColor(0x400, 0x24FFFF) -- #24FFFF
apis.term.setPaletteColor(0x800, 0x924900) -- #924900
apis.term.setPaletteColor(0x1000, 0x6D6D55) -- #6D6D55
apis.term.setPaletteColor(0x2000, 0xDBDBAA) -- #DBDBAA
apis.term.setPaletteColor(0x4000, 0x6D00FF) -- #6D00FF
apis.term.setPaletteColor(0x8000, 0xB6FF00) -- #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")()
local key = load(getFile(BOOT_DRIVE_PATH.."/boot/cct/keys.lua"),"@keyhelper")(apis)
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 key then
displaySuperBadError("Could not load key helper.")
end
local eventQueue = {}
local function queueEvent(event, ...)
table.insert(eventQueue, {event, ...})
end
local computer = {
time = function() return apis.os.epoch("utc") end,
clock = function() return apis.os.clock()/1000 end,
shutdown = apis.os.shutdown,
reboot = apis.os.reboot,
getMachineEvent = function()
if #eventQueue > 0 then
return table.unpack(table.remove(eventQueue, 1))
else
return nil
end
end,
getEEPROM = function()
return getFile("/startup.lua")
end,
setEEPROM = function(_,text)
local h = apis.fs.open("/startup.lua", "w")
h.write(text)
h.close()
end
}
local icolors={
[0x1] =0, -- #000000
[0x2] =1, -- #FFFFFF
[0x4] =2, -- #FF0000
[0x8] =3, -- #00FF00
[0x10] =4, -- #0000FF
[0x20] =5, -- #00FFFF
[0x40] =6, -- #FF00FF
[0x80] =7, -- #FFFF00
[0x100] =8, -- #FF6D00
[0x200] =9, -- #6DFF55
[0x400] =10, -- #24FFFF
[0x800] =11, -- #924900
[0x1000] =12, -- #6D6D55
[0x2000] =13, -- #DBDBAA
[0x4000] =14, -- #6D00FF
[0x8000] =15 -- #B6FF00
}
local colors={
[0]=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
}
apis.term.setBackgroundColor(0x1)
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, apis, initFs, "cct", "/sbin/init", {
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(colors[color]) end,
setTextColor=function(_,color) apis.term.setTextColor(colors[color]) end,
getBackgroundColor=function() return icolors[apis.term.getBackgroundColor()] end,
getTextColor=function() return icolors[apis.term.getTextColor()] end
}, computer, fs, "$")
if not ok then
displaySuperBadError(err)
end
end)
-- time is in milliseconds
function coroutine.resumeWithTimeout(co, timeout, ...)
local startTime = computer.time()
debug.sethook(co, function()
if computer.time() > 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 = 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("keyPressed", 1, event[2])
key(event, queueEvent)
elseif event[1] == "key_up" then
queueEvent("keyReleased", 1, event[2])
key(event, queueEvent)
elseif event[1] == "disk" then
queueEvent("componentAdded", "disk")
elseif event[1] == "disk_eject" then
queueEvent("componentRemoved", "disk")
elseif event[1] == "NoSleep" then
exit=true
end
end
if status == "error" or coroutine.status(kernelCoro)=="dead" then
displaySuperBadError("Kernel error: "..tostring(err))
coroutine.yield("key")
end
end
end, debug.traceback)
if not ok then
displaySuperBadError("Fatal error during boot: "..err)
end
while true do coroutine.yield() end

View File

@@ -0,0 +1,122 @@
--:Minify:--
sleep(1)
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 = {...}
if _HOST:find("UnBIOS") then return end
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
_G._HOST = _G._HOST .. " (UnBIOS)"
-- 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

View File

@@ -0,0 +1,192 @@
--:Minify:--
local apis = ({...})[1]
local BOOT_DRIVE_PATH=apis.BOOT_DRIVE_PATH or "/$"
local fs = apis.fs
local native = apis.peripheral
local peripheral = {}
local sides = {"top", "bottom", "left", "right", "front", "back"}
function peripheral.getType(name)
if native.isPresent(name) then
return native.getType(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, "getTypeRemote", name)
end
end
return nil
end
function peripheral.getNames()
local names = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(names, side)
end
if native.hasType(side, "peripheral_hub") then
local hubSides = native.call(side, "getConnectedSides")
for _, hubSide in ipairs(hubSides) do
table.insert(names, hubSide)
end
end
end
return names
end
---------------------------------------------------------
-- STORAGE
---------------------------------------------------------
local disks = {} -- real disks
local internal = {} -- "$" disk
---------------------------------------------------------
-- HELPERS
---------------------------------------------------------
local function norm(path)
if not path or path == "" then return "/" end
return fs.combine("/", path)
end
--- Creates a disk object given a base path
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 DISK "$" (mapped to "/")
---------------------------------------------------------
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")
local label = h.readAll()
h.close()
return label
end
})
---------------------------------------------------------
-- SCAN REAL DISK PERIPHERALS
---------------------------------------------------------
local function refresh()
-- remove disks that no longer exist
for id, _ in pairs(disks) do
if not peripheral.getType(id) then
disks[id] = nil
end
end
-- detect new disks
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "disk" then
if not disks[name] then
local mount = disk.getMountPath(name)
if mount then
disks[name] = createDisk(name, mount, false, disk)
end
end
end
end
end
---------------------------------------------------------
-- ITERATOR
---------------------------------------------------------
local function iter()
refresh()
-- first internal
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
---------------------------------------------------------
-- MODULE RETURN
---------------------------------------------------------
return {
refresh = refresh,
list = iter
}

View File

@@ -0,0 +1,203 @@
--:Minify:--
local apis=...
local keys=apis.keys
local tKeys = {}
tKeys[keys.space] = ' '
tKeys[keys.grave] = '`'
tKeys[keys.comma] = ','
tKeys[keys.minus] = '-'
tKeys[keys.period] = '.'
tKeys[keys.slash] = '/'
tKeys[keys.zero] = '0'
tKeys[keys.one] = '1'
tKeys[keys.two] = '2'
tKeys[keys.three] = '3'
tKeys[keys.four] = '4'
tKeys[keys.five] = '5'
tKeys[keys.six] = '6'
tKeys[keys.seven] = '7'
tKeys[keys.eight] = '8'
tKeys[keys.nine] = '9'
tKeys[keys.semicolon or keys.semiColon] = ';'
tKeys[keys.equals] = '='
tKeys[keys.a] = 'a'
tKeys[keys.b] = 'b'
tKeys[keys.c] = 'c'
tKeys[keys.d] = 'd'
tKeys[keys.e] = 'e'
tKeys[keys.f] = 'f'
tKeys[keys.g] = 'g'
tKeys[keys.h] = 'h'
tKeys[keys.i] = 'i'
tKeys[keys.j] = 'j'
tKeys[keys.k] = 'k'
tKeys[keys.l] = 'l'
tKeys[keys.m] = 'm'
tKeys[keys.n] = 'n'
tKeys[keys.o] = 'o'
tKeys[keys.p] = 'p'
tKeys[keys.q] = 'q'
tKeys[keys.r] = 'r'
tKeys[keys.s] = 's'
tKeys[keys.t] = 't'
tKeys[keys.u] = 'u'
tKeys[keys.v] = 'v'
tKeys[keys.w] = 'w'
tKeys[keys.x] = 'x'
tKeys[keys.y] = 'y'
tKeys[keys.z] = 'z'
tKeys[keys.leftBracket] = '['
tKeys[keys.backslash] = '\\'
tKeys[keys.rightBracket] = ']'
tKeys[keys.apostrophe] = "'"
tKeys[keys.enter] = '\n'
tKeys[keys.tab] = '\t'
tKeys[keys.backspace] = '\b'
tKeys[keys.insert] = '\x1b[2~'
tKeys[keys.delete] = '\x1b[3~'
tKeys[keys.right] = '\x1b[C'
tKeys[keys.left] = '\x1b[D'
tKeys[keys.down] = '\x1b[B'
tKeys[keys.up] = '\x1b[A'
tKeys[keys.pageUp] = '\x1b[5~'
tKeys[keys.pageDown] = '\x1b[6~'
tKeys[keys.home] = '\x1b[1~'
tKeys[keys["end"]] = '\x1b[4~'
tKeys[keys.capsLock] = '\x1b[capsLock'
tKeys[keys.scrollLock] = '\x1b[scrollLock'
tKeys[keys.numLock] = '\x1b[numLock'
if keys.printScreen then
tKeys[keys.printScreen] = '\x1b[printScreen'
end
tKeys[keys.pause] = '\x1b[pause'
tKeys[keys.f1] = '\x1b[11~'
tKeys[keys.f2] = '\x1b[12~'
tKeys[keys.f3] = '\x1b[13~'
tKeys[keys.f4] = '\x1b[14~'
tKeys[keys.f5] = '\x1b[15~'
tKeys[keys.f6] = '\x1b[17~'
tKeys[keys.f7] = '\x1b[18~'
tKeys[keys.f8] = '\x1b[19~'
tKeys[keys.f9] = '\x1b[20~'
tKeys[keys.f10] = '\x1b[21~'
tKeys[keys.f11] = '\x1b[23~'
tKeys[keys.f12] = '\x1b[24~'
--tKeys[keys.f13] = '\x1b[25~'
--tKeys[keys.f14] = '\x1b[26~'
--tKeys[keys.f15] = '\x1b[28~'
--tKeys[keys.f16] = '\x1b[29~'
--tKeys[keys.f17] = '\x1b[31~'
--tKeys[keys.f18] = '\x1b[32~'
--tKeys[keys.f19] = '\x1b[33~'
--tKeys[keys.f20] = '\x1b[34~'
--tKeys[keys.f21] = '\x1b[42~'
--tKeys[keys.f22] = '\x1b[43~'
--tKeys[keys.f23] = '\x1b[44~'
--tKeys[keys.f24] = '\x1b[45~'
--tKeys[keys.f25] = '\x1b[46~'
-- Numpad
tKeys[keys.numPad0] = '0'
tKeys[keys.numPad1] = '1'
tKeys[keys.numPad2] = '2'
tKeys[keys.numPad3] = '3'
tKeys[keys.numPad4] = '4'
tKeys[keys.numPad5] = '5'
tKeys[keys.numPad6] = '6'
tKeys[keys.numPad7] = '7'
tKeys[keys.numPad8] = '8'
tKeys[keys.numPad9] = '9'
--tKeys[340] = 'leftShift'
--tKeys[341] = 'leftCtrl'
--tKeys[342] = 'leftAlt'
--tKeys[343] = 'leftSuper'
--tKeys[344] = 'rightShift'
--tKeys[345] = 'rightCtrl'
--tKeys[346] = 'rightAlt'
--tKeys[347] = 'rightSuper'
--tKeys[348] = 'menu'
local shift = false
local ctrl = false
local alt = false
local function s(char)
if not shift then return char end
-- Letters
if char == "a" then return "A" end
if char == "b" then return "B" end
if char == "c" then return "C" end
if char == "d" then return "D" end
if char == "e" then return "E" end
if char == "f" then return "F" end
if char == "g" then return "G" end
if char == "h" then return "H" end
if char == "i" then return "I" end
if char == "j" then return "J" end
if char == "k" then return "K" end
if char == "l" then return "L" end
if char == "m" then return "M" end
if char == "n" then return "N" end
if char == "o" then return "O" end
if char == "p" then return "P" end
if char == "q" then return "Q" end
if char == "r" then return "R" end
if char == "s" then return "S" end
if char == "t" then return "T" end
if char == "u" then return "U" end
if char == "v" then return "V" end
if char == "w" then return "W" end
if char == "x" then return "X" end
if char == "y" then return "Y" end
if char == "z" then return "Z" end
-- Symbols
if char == "`" then return "~" end
if char == "1" then return "!" end
if char == "2" then return "@" end
if char == "3" then return "#" end
if char == "4" then return "$" end
if char == "5" then return "%" end
if char == "6" then return "^" end
if char == "7" then return "&" end
if char == "8" then return "*" end
if char == "9" then return "(" end
if char == "0" then return ")" end
if char == "-" then return "_" end
if char == "=" then return "+" end
if char == "[" then return "{" end
if char == "]" then return "}" end
if char == "\\" then return "|" end
if char == ";" then return ":" end
if char == "'" then return '"' end
if char == "," then return "<" end
if char == "." then return ">" end
if char == "/" then return "?" end
return char or ""
end
local function p()
local str = ""
if alt then
str=str.."\x1b"
end
if ctrl then
str=str.."^"
end
return str
end
return function(event, q)
if event[1] == "key" then
if event[2]==keys.leftCtrl or event[2]==keys.rightCtrl then ctrl=true return
elseif event[2]==keys.leftAlt or event[2]==keys.rightAlt then alt=true return
elseif event[2]==keys.leftShift or event[2]==keys.rightCtrl then shift=true return
end
q("keyTyped", 1, p()..s(tKeys[event[2]]))
elseif event[1] == "key_up" then
if event[2]==keys.leftCtrl or event[2]==keys.rightCtrl then ctrl=false return
elseif event[2]==keys.leftAlt or event[2]==keys.rightAlt then alt=false return
elseif event[2]==keys.leftShift or event[2]==keys.rightCtrl then shift=false return
end
end
end

View File

@@ -0,0 +1,26 @@
local args={...}
local kernel=args[1]
local driver={}
driver.name="CCT Term Module"
driver.version="0.1.0"
driver.type="gpio"
driver.description="CCT redstone Module Kernel Module"
driver.arch="cct"
driver.author="HyperionOS Dev Team"
driver.license="MIT"
driver.api={}
function driver.load()
-- will
end
function driver.unload()
-- Nothing to unload
end
function driver.main()
-- Nothing to run
end
-- kernel.drivers.register(driver)

View File

@@ -0,0 +1,182 @@
--:Minify:--
local kernel=...
local apis=kernel.apis
local main=apis.term
local native=apis.peripheral
local sides = {"top", "bottom", "left", "right", "front", "back"}
local function getType(name)
if native.isPresent(name) then
return native.getType(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, "getTypeRemote", name)
end
end
return nil
end
local function getNames()
local names = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(names, side)
end
if native.hasType(side, "peripheral_hub") then
local hubSides = native.call(side, "getConnectedSides")
for _, hubSide in ipairs(hubSides) do
table.insert(names, hubSide)
end
end
end
return names
end
local function wrapPeripheral(name)
if native.isPresent(name) then
return wrapPeripheral(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, "wrapRemote", name)
end
end
return nil
end
local colors={
[0]=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 icolors={
[0x1] =0, -- #000000
[0x2] =1, -- #FFFFFF
[0x4] =2, -- #FF0000
[0x8] =3, -- #00FF00
[0x10] =4, -- #0000FF
[0x20] =5, -- #00FFFF
[0x40] =6, -- #FF00FF
[0x80] =7, -- #FFFF00
[0x100] =8, -- #FF6D00
[0x200] =9, -- #6DFF55
[0x400] =10, -- #24FFFF
[0x800] =11, -- #924900
[0x1000] =12, -- #6D6D55
[0x2000] =13, -- #DBDBAA
[0x4000] =14, -- #6D00FF
[0x8000] =15 -- #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
-- Handle wrapping if we go past right edge
if x > w then
x = 1
y = y + 1
end
-- Handle scrolling if we go past bottom
if y-1 > h then
term.scroll(1)
y = h
term.setCursorPos(x, y)
end
end
term.setCursorPos(x, y)
end
local function newTTY(term)
local ret={}
function ret.print(text)
write(text.."\n", term)
end
function ret.printInline(text)
write(text, term)
end
function ret.clear()
term.clear()
term.setCursorPos(1,1)
end
function ret.setCursorPos(x,y)
term.setCursorPos(x,y)
end
function ret.getCursorPos()
return term.getCursorPos()
end
function ret.getSize()
return term.getSize()
end
function ret.setBackgroundColor(color)
term.setBackgroundColor(colors[color])
end
function ret.setTextColor(color)
term.setTextColor(colors[color])
end
function ret.getBackgroundColor()
return icolors[term.getBackgroundColor()]
end
function ret.getTextColor()
return icolors[term.getTextColor()]
end
return ret
end
kernel.tty.register("tty0", newTTY(main))
for _, name in ipairs(getNames()) do
local t = getType(name)
if t == "monitor" then
local monitorTerm = wrapPeripheral(name)
monitorTerm.setTextScale(0.5)
kernel.tty.register(name, newTTY(monitorTerm))
end
end