-- local component, computer, unicode = require("component"), require("computer"), require("unicode") local stringsMain, stringsBootFromURL, stringsChangeLabel, stringKeyDown, stringsInit, stringsFilesystem, componentProxy, componentList, pullSignal, uptime, tableInsert, mathMax, mathMin, mathHuge = "MineOS EFI", "Internet boot", "Change label", "key_down", "/init.lua", "filesystem", component.proxy, component.list, computer.pullSignal, computer.uptime, table.insert, math.max, math.min, math.huge local colorsTitle, colorsBackground, colorsText, colorsSelectionBackground, colorsSelectionText, eeprom, gpu, internetAddress = 1, 0, 1, 1, 0, componentProxy(componentList("eeprom")()), componentProxy(componentList("gpu")()), componentList("internet")() gpu.bind(componentList("screen")(), true) local shutdown, gpuSet, gpuFill, eepromSetData, eepromGetData, depth, screenWidth, screenHeight, curentBackground, currentForeground, NIL = computer.shutdown, gpu.set, gpu.fill, eeprom.setData, eeprom.getData, gpu.getDepth(), gpu.getResolution() computer.getBootAddress, computer.setBootAddress = eepromGetData, eepromSetData if depth == 4 then colorsTitle, colorsBackground, colorsText, colorsSelectionBackground, colorsSelectionText = 0x333333, 0xFFFFFF, 0x333333, 0x333333, 0xFFFFFF elseif depth == 8 then colorsTitle, colorsBackground, colorsText, colorsSelectionBackground, colorsSelectionText = 0x2D2D2D, 0xE1E1E1, 0x878787, 0x878787, 0xE1E1E1 end local setBackground, setForeground, round, restrict = function(color) if color ~= curentBackground then gpu.setBackground(color) curentBackground = color end end, function(color) if color ~= currentForeground then gpu.setForeground(color) currentForeground = color end end, function(n) return math.floor(n + 0.5) end, function(text, limit, skip) if #text < limit then text = text .. string.rep(" ", limit - #text) else text = text:sub(1, limit) end return text .. (skip and "" or " ") end local rectangle, centrizedText, menuElement = function(x, y, width, height, color) setBackground(color) gpuFill(x, y, width, height, " ") end, function(y, foreground, text) local x = round(screenWidth / 2 - #text / 2) setForeground(foreground) gpuSet(x, y, text) end, function(text, callback, breakLoop) return { s = text, c = callback, b = breakLoop } end local function status(y, titleText, statusText, needWait) y = y or round(screenHeight / 2 - 1) rectangle(1, 1, screenWidth, screenHeight, colorsBackground) centrizedText(y, colorsTitle, titleText) centrizedText(y + 2, colorsText, statusText or "") if needWait then repeat local event = pullSignal() until event == stringKeyDown or event == "touch" end return y end local loadInit, menuBack, menu, input, netboot = function(proxy) status(NIL, stringsMain, "Booting from " .. proxy.address) local data, chunk, handle, success, reason = "", "", proxy.open(stringsInit, "r") while chunk do data, chunk = data .. chunk, proxy.read(handle, mathHuge) end proxy.close(handle) success, reason = load(data) if success then success, reason = pcall(success) if success then return end end status(NIL, stringsMain, "Failed to run init file: " .. reason, 1) end, function() return menuElement("Back", NIL, 1) end, function(titleText, elements) local spacing, selectedElement, maxLength = 2, 1, 0 for i = 1, #elements do maxLength = math.max(maxLength, #elements[i].s) end while 1 do local y, x, eventData = status(round(screenHeight / 2 - (#elements + 2) / 2), titleText) + 2 for i = 1, #elements do x = round(screenWidth / 2 - #elements[i].s / 2) if i == selectedElement then rectangle(round(screenWidth / 2 - maxLength / 2) - 2, y, maxLength + 4, 1, colorsSelectionBackground) setForeground(colorsSelectionText) gpuSet(x, y, elements[i].s) else setBackground(colorsBackground) setForeground(colorsText) gpuSet(x, y, elements[i].s) end y = y + 1 end eventData = {pullSignal()} if eventData[1] == stringKeyDown then if eventData[4] == 200 and selectedElement > 1 then selectedElement = selectedElement - 1 elseif eventData[4] == 208 and selectedElement < #elements then selectedElement = selectedElement + 1 elseif eventData[4] == 28 then if elements[selectedElement].c then elements[selectedElement].c() end if elements[selectedElement].b then return end end end end end, function(y, prefix) local text, state, eblo, eventData, char = "", true while 1 do eblo = prefix .. text gpuFill(1, y, screenWidth, 1, " ") gpuSet(round(screenWidth / 2 - #eblo / 2), y, eblo .. (state and "█" or "")) eventData = {pullSignal(0.5)} if eventData[1] == stringKeyDown then if eventData[4] == 28 then return text elseif eventData[4] == 14 then text = text:sub(1, -2) else char = unicode.char(eventData[3]) if char:match("^[%w%d%p%s]+") then text = text .. char end end state = true elseif eventData[1] == "clipboard" then text = text .. eventData[3] elseif not eventData[1] then state = not state end end end, function(url) local runReason, data, handle, result, reason = function(text) status(NIL, stringsBootFromURL, "Internet boot failed: " .. text, 1) end, "", componentProxy(internetAddress).request(url) if handle then status(NIL, stringsBootFromURL, "Downloading script...") while 1 do result, reason = handle.read(mathHuge) if result then data = data .. result else handle:close() if reason then runReason(reason) else result, reason = load(data) if result then eepromSetData("#" .. url) result, reason = pcall(result) if result then return else runReason(reason) end else runReason(reason) end end break end end else runReason("invalid URL-address") end end status(NIL, stringsMain, "Hold Alt to show boot options menu") local deadline, eventData = uptime() + 1 while uptime() < deadline do eventData = {pullSignal(deadline - uptime())} if eventData[1] == stringKeyDown and eventData[4] == 56 then local utilities = { menuElement("Disk management", function() local filesystems, bootAddress = {menuBack()}, eepromGetData() for address in componentList(stringsFilesystem) do local proxy = componentProxy(address) local label, isReadOnly = proxy.getLabel() or "Unnamed", proxy.isReadOnly() tableInsert(filesystems, 1, menuElement( (address == bootAddress and "> " or " ") .. restrict(label, 10) .. restrict(proxy.spaceTotal() > 1048576 and "HDD" or proxy.spaceTotal() > 65536 and "FDD" or "SYS", 3) .. restrict(isReadOnly and "R" or "R/W", 3) .. address:sub(1, 8) .. " " .. restrict(string.format("%.2f", proxy.spaceUsed() / proxy.spaceTotal() * 100) .. "%", 6, 1), function() local filesystemOptions = {menuBack()} if not isReadOnly then tableInsert(filesystemOptions, 1, menuElement(stringsChangeLabel, function() proxy.setLabel(input(status(NIL, stringsChangeLabel) + 2, "Enter new name: ")) end, 1)) tableInsert(filesystemOptions, 2, menuElement("Format", function() status(NIL, stringsMain, "Formatting filesystem " .. address) for _, file in ipairs(proxy.list("/")) do proxy.remove(file) end status(NIL, stringsMain, "Formatting finished", 1) end, 1)) end if proxy.exists(stringsInit) then tableInsert(filesystemOptions, 1, menuElement("Set as startup", function() eepromSetData(address) end, 1)) end menu(label .. " (" .. address .. ")", filesystemOptions) end , 1) ) end menu("Select filesystem to show options", filesystems) end), menuElement("Shutdown", function() shutdown() end), menuBack() } if internetAddress then tableInsert(utilities, 2, menuElement(stringsBootFromURL, function() netboot(input(status(NIL, stringsBootFromURL) + 2, "Enter URL: ")) end)) end menu(stringsMain, utilities) end end local data, proxy = eepromGetData() if data:sub(1, 1) == "#" then netboot(data:sub(2, -1)) else proxy = componentProxy(data) if proxy and proxy.exists(stringsInit) then loadInit(proxy) else for address in componentList(stringsFilesystem) do proxy = componentProxy(address) if proxy.exists(stringsInit) then eepromSetData(address) loadInit(proxy) break else proxy = nil end end if not proxy then status(NIL, stringsMain, "No bootable mediums found", 1) end end end shutdown()