Created
March 24, 2020 21:59
-
-
Save Ocawesome101/02e0bbba21db0b34ab99da630ccc1237 to your computer and use it in GitHub Desktop.
Bare-metal installer for the Proton hybrid kernel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Proton installer -- | |
---------------------------------- Graphics -------------------------------- | |
local gpu = component.proxy(component.list("gpu")()) | |
gpu.bind(component.list("screen")()) | |
gpu.setResolution(50, 16) | |
local background = 0x000000 | |
local boxbg = 0xFFFFFF | |
local boxtext = 0x000000 | |
local bgtext = 0xFFFFFF | |
local w, h = gpu.getResolution() | |
local function clear() | |
gpu.setForeground(bgtext) | |
gpu.setBackground(background) | |
gpu.fill(1, 1, w, h, " ") | |
end | |
local function bgset(x, y, text) | |
gpu.setForeground(bgtext) | |
gpu.setBackground(background) | |
gpu.set(x, y, text) | |
end | |
local function box(x1, y1, x2, y2) | |
gpu.setBackground(boxbg) | |
gpu.setForeground(boxtext) | |
gpu.fill(x1, y1, x2 - x1, y2 - y1, " ") | |
end | |
local function bxset(x, y, text) | |
gpu.setForeground(boxtext) | |
gpu.setBackground(boxbg) | |
gpu.set(x, y, text) | |
end | |
------------------------- Menu functions ----------------------------- | |
local function basicmenu(x, y, items) | |
local sel = 1 | |
local function redraw() | |
for i=1, #items, 1 do | |
bxset(x, y + i, items[i]:sub(1, w - x) .. (" "):rep(36 - #items[i])) -- cut off items if they're too long | |
end | |
bgset(x, y + sel, items[sel]:sub(1, w - x) .. (" "):rep(36 - #items[sel])) | |
end | |
repeat | |
redraw() | |
local e, _, id, code = computer.pullSignal() | |
if e == "key_down" then | |
if code == 200 then -- up arrow | |
if sel > 1 then | |
sel = sel - 1 | |
else | |
sel = #items | |
end | |
elseif code == 208 then | |
if sel < #items then | |
sel = sel + 1 | |
else | |
sel = 1 | |
end | |
end | |
end | |
until e == "key_down" and id == 13 | |
return sel | |
end | |
local function selectmenu(x, y, items, defaults) | |
local sel = 1 | |
local selected = {} | |
for k,v in pairs(defaults) do | |
selected[v] = true | |
end | |
local function redraw() | |
for i=1, #items, 1 do | |
local d = (sel == i and bxset) or bgset | |
if selected[ items[i] ] then | |
d(x, y + i, "[x] " .. items[i]) | |
else | |
d(x, y + i, "[ ] " .. items[i]) | |
end | |
end | |
end | |
repeat | |
redraw() | |
local e, _, id, code = computer.pullSignal() | |
if e == "key_down" then | |
if code == 200 then -- up | |
if sel > 1 then | |
sel = sel - 1 | |
else | |
sel = #items | |
end | |
elseif code == 208 then -- down | |
if sel < #items then | |
sel = sel + 1 | |
else | |
sel = 1 | |
end | |
elseif code == 57 then | |
selected[ items[sel] ] = (not selected[ items[sel] ]) | |
end | |
end | |
until e == "key_down" and id == 13 | |
return selected | |
end | |
--------------------------- Internet Card ----------------------------- | |
local inet = component.proxy(component.list("internet")()) | |
if not inet.isHttpEnabled() then | |
error("HTTP is required!") | |
end | |
---------------------------------------------------------------------- | |
-- non-optional packages | |
local packages = { | |
"proton-base", | |
"driver-fs", | |
"driver-component" | |
} | |
--------------------------- FS Selection ------------------------------ | |
local filesystem | |
local tmpfs | |
do | |
clear() | |
bgset(1, 1, "Detecting filesystems") | |
local fses = {} | |
for addr, _ in component.list("filesystem") do | |
fses[#fses + 1] = addr | |
if component.invoke(addr, "getLabel") == "tmpfs" then | |
tmpfs = component.proxy(addr) | |
end | |
end | |
clear() | |
bgset(1, 1, "Proton Installer: Select medium") | |
bgset(w - 3, h, "1/5") | |
box(3, 3, w - 3, h - 3) | |
bxset(4, 4, "Please choose an installation medium.") | |
fses[#fses + 1] = "Cancel" | |
local install = basicmenu(4, 6, fses) | |
if fses[install] == "Cancel" then | |
computer.shutdown() | |
end | |
filesystem = component.proxy(fses[install]) | |
end | |
------------------------- Driver Selection ------------------------- | |
local ppmrepo = "https://raw.githubusercontent.com/ocawesome101/proton-packages/master/" | |
do | |
local drivers = { | |
"internet", | |
"modem", | |
"sound", | |
"gpu", | |
"redstone", | |
-- These drivers will be added later | |
--[["3dprinter", | |
"data", | |
"eeprom", | |
"robot"]] | |
} | |
clear() | |
bgset(1, 1, "Proton Installer: Select drivers") | |
bgset(w - 3, h, "2/5") | |
box(3, 3, w - 3, h - 3) | |
bxset(4, 4, "Please select drivers to be installed.") | |
local selections = selectmenu(4, 6, drivers, {"gpu", "internet"}) | |
for k,v in pairs(selections) do | |
if v then | |
packages[#packages + 1] = "driver-" .. k | |
end | |
end | |
end | |
-------------------------- UI Selection --------------------------- | |
do | |
local ifaces = { | |
"proton-shell", | |
--"modularity" -- Does NOT work yet | |
} | |
clear() | |
bgset(1, 1, "Proton Installer: Select interface") | |
bgset(w - 3, h, "3/5") | |
box(3, 3, w - 3, h - 2) | |
bxset(4, 4, "Please select a user interface.") | |
local selections = selectmenu(4, 6, ifaces, {"proton-shell"}) | |
for k,v in pairs(selections) do | |
if v then | |
packages[#packages + 1] = k | |
end | |
end | |
end | |
--- semi-platform-independent port of AdorableCatgirl's uncpio.lua --- | |
local function uncpio(f) | |
local file = tmpfs.open(f, "r") | |
local written = {} | |
local dent = { | |
magic = 0, | |
dev = 0, | |
ino = 0, | |
mode = 0, | |
uid = 0, | |
gid = 0, | |
nlink = 0, | |
rdev = 0, | |
mtime = 0, | |
namesize = 0, | |
filesize = 0, | |
} | |
local function readint(amt, rev) | |
local tmp = 0 | |
for i=(rev and amt) or 1, (rev and 1) or amt, (rev and -1) or 1 do | |
tmp = tmp | (tmpfs.read(file, 1):byte() << ((i-1)*8)) | |
end | |
return tmp | |
end | |
local function fwrite() | |
local dir = dent.name:match("(.+)/.*%.?.+") | |
if (dir) then | |
filesystem.makeDirectory("/"..dir) | |
end | |
local hand = filesystem.open(dent.name, "w") | |
filesystem.write(hand, tmpfs.read(file, dent.filesize)) | |
filesystem.close(hand) | |
written[#written + 1] = dent.name | |
end | |
while true do | |
dent.magic = readint(2) | |
local rev = false | |
if (dent.magic ~= tonumber("070707", 8)) then rev = true end | |
dent.dev = readint(2) | |
dent.ino = readint(2) | |
dent.mode = readint(2) | |
dent.uid = readint(2) | |
dent.gid = readint(2) | |
dent.nlink = readint(2) | |
dent.rdev = readint(2) | |
dent.mtime = (readint(2) << 16) | readint(2) | |
dent.namesize = readint(2) | |
dent.filesize = (readint(2) << 16) | readint(2) | |
local name = tmpfs.read(file, dent.namesize):sub(1, dent.namesize-1) | |
if (name == "TRAILER!!!") then break end | |
--for k, v in pairs(dent) do | |
-- print(k, v) | |
--end | |
dent.name = name | |
-- print(name) | |
if (dent.namesize % 2 ~= 0) then | |
tmpfs.seek(file, "cur", 1) | |
end | |
if (dent.mode & 32768 ~= 0) then | |
fwrite() | |
end | |
if (dent.filesize % 2 ~= 0) then | |
tmpfs.seek(file, "cur", 1) | |
end | |
end | |
tmpfs.close(file) | |
return written | |
end | |
------------------ Do the actual installation ------------------ | |
do | |
clear() | |
bgset(1, 1, "Proton Installer: Installing packages") | |
bgset(w - 3, h, "4/5") | |
box(3, 3, w - 3, h - 3) | |
local installed = "NAME,AUTHOR,FILES\n" | |
for i=1, #packages, 1 do | |
if type(packages[i]) == "number" then | |
table.remove(packages, i) | |
end | |
end | |
for i=1, #packages, 1 do | |
local package = packages[i] | |
bxset(4, 4, "Downloading " .. package .. " ") | |
bgset(4, 6, (" "):rep(math.floor((i / #package) * (w - 3)))) | |
local raw, err = inet.request(ppmrepo .. package .. ".cpio") | |
if not raw or not raw.finishConnect() then | |
bxset(4, 4, "Error downloading " .. package) | |
else | |
local file = tmpfs.open(package .. ".cpio", "w") | |
repeat | |
local chunk = raw.read(math.huge) | |
tmpfs.write(file, (chunk or "")) | |
until not chunk | |
tmpfs.close(file) | |
local files = uncpio(package .. ".cpio") | |
installed = installed .. package .. ",Ocawesome101," .. table.concat(files, ";") | |
end | |
end | |
filesystem.makeDirectory("/sys/ppm/") | |
local handle = filesystem.open("/sys/ppm/installed.csv", "w") | |
filesystem.write(handle, installed) | |
filesystem.close(handle) | |
end | |
------------------------- Bye bye! -------------------------- | |
do | |
clear() | |
bgset(1, 1, "Proton Installer: Done") | |
bgset(w - 3, h, "5/5") | |
box(3, 3, w - 3, h - 3) | |
if computer.setBootAddress then | |
computer.setBootAddress(filesystem.address) | |
end | |
local lines = { | |
"The Proton hybrid kernel is now installed", | |
"on your computer. Additional packages can", | |
"be installed with the ppm utility.", | |
"", | |
"Your system will restart in 5 seconds, or", | |
"if ENTER is pressed. If present, please", | |
"remove any installation media now." | |
} | |
for i=1, #lines, 1 do | |
bxset(4, i + 3, lines[i]) | |
end | |
local dest = computer.uptime() + 5 | |
repeat | |
local e, _, id = computer.pullSignal(dest - computer.uptime()) | |
until computer.uptime() >= dest or (e == "key_down" and id == 13) | |
computer.shutdown(true) | |
end | |
while true do | |
computer.pullSignal() | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment