mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2025-12-20 02:59:20 +01:00
322 lines
8.4 KiB
Lua
322 lines
8.4 KiB
Lua
|
|
local stringsMain, stringsChangeLabel, stringKeyDown, stringsFilesystem, colorsTitle, colorsBackground, colorsText, colorsSelectionBackground, colorsSelectionText, componentProxy, componentList, pullSignal, uptime, tableInsert, mathMax, mathMin, mathHuge, mathFloor = "MineOS EFI", "Change label", "key_down", "filesystem", 0x2D2D2D, 0xE1E1E1, 0x878787, 0x878787, 0xE1E1E1, component.proxy, component.list, computer.pullSignal, computer.uptime, table.insert, math.max, math.min, math.huge, math.floor
|
|
|
|
local eeprom, gpu, internetAddress = componentProxy(componentList("eeprom")()), componentProxy(componentList("gpu")()), componentList("internet")()
|
|
|
|
gpu.bind(componentList("screen")(), true)
|
|
|
|
local shutdown, gpuSet, gpuSetBackground, gpuSetForeground, gpuFill, eepromSetData, eepromGetData, screenWidth, screenHeight = computer.shutdown, gpu.set, gpu.setBackground, gpu.setForeground, gpu.fill, eeprom.setData, eeprom.getData, gpu.getResolution()
|
|
|
|
local OSList, rectangle, centrizedText, menuElement =
|
|
{
|
|
{
|
|
"/OS.lua",
|
|
function()
|
|
end
|
|
},
|
|
{
|
|
"/init.lua",
|
|
function()
|
|
computer.getBootAddress, computer.setBootAddress = eepromGetData, eepromSetData
|
|
end
|
|
}
|
|
},
|
|
function(x, y, width, height, color)
|
|
gpuSetBackground(color)
|
|
gpuFill(x, y, width, height, " ")
|
|
end,
|
|
function(y, foreground, text)
|
|
local x = mathFloor(screenWidth / 2 - #text / 2)
|
|
gpuSetForeground(foreground)
|
|
gpuSet(x, y, text)
|
|
end,
|
|
function(text, callback, breakLoop)
|
|
return {
|
|
s = text,
|
|
c = callback,
|
|
b = breakLoop
|
|
}
|
|
end
|
|
|
|
local function title(y, titleText)
|
|
y = mathFloor(screenHeight / 2 - y / 2)
|
|
rectangle(1, 1, screenWidth, screenHeight, colorsBackground)
|
|
centrizedText(y, colorsTitle, titleText)
|
|
|
|
return y + 2
|
|
end
|
|
|
|
local function status(titleText, statusText, needWait)
|
|
local lines = {}
|
|
for line in statusText:gmatch("[^\r\n]+") do
|
|
lines[#lines + 1] = line:gsub("\t", " ")
|
|
end
|
|
|
|
local y = title(#lines, titleText)
|
|
|
|
for i = 1, #lines do
|
|
centrizedText(y, colorsText, lines[i])
|
|
y = y + 1
|
|
end
|
|
|
|
if needWait then
|
|
repeat
|
|
needWait = pullSignal()
|
|
until needWait == stringKeyDown or needWait == "touch"
|
|
end
|
|
end
|
|
|
|
local function executeString(...)
|
|
local result, reason = load(...)
|
|
if result then
|
|
result, reason = xpcall(result, debug.traceback)
|
|
if result then
|
|
return
|
|
end
|
|
end
|
|
|
|
status(stringsMain, reason, 1)
|
|
end
|
|
|
|
local boot, menuBack, menu, input =
|
|
function(proxy)
|
|
for i = 1, #OSList do
|
|
if proxy.exists(OSList[i][1]) then
|
|
status(stringsMain, "Booting from " .. (proxy.getLabel() or proxy.address))
|
|
|
|
-- Updating current EEPROM boot address if it's differs from given proxy address
|
|
if eepromGetData() ~= proxy.address then
|
|
eepromSetData(proxy.address)
|
|
end
|
|
|
|
-- Running OS pre-boot function
|
|
OSList[i][2]()
|
|
|
|
-- Reading boot file
|
|
local handle, data, chunk, success, reason = proxy.open(OSList[i][1], "rb"), ""
|
|
repeat
|
|
chunk = proxy.read(handle, mathHuge)
|
|
data = data .. (chunk or "")
|
|
until not chunk
|
|
|
|
proxy.close(handle)
|
|
|
|
-- Running boot file
|
|
executeString(data, "=" .. OSList[i][1])
|
|
|
|
return 1
|
|
end
|
|
end
|
|
end,
|
|
function(f)
|
|
return menuElement("Back", f, 1)
|
|
end,
|
|
function(titleText, elements)
|
|
local selectedElement, maxLength = 1, 0
|
|
for i = 1, #elements do
|
|
maxLength = math.max(maxLength, #elements[i].s)
|
|
end
|
|
|
|
while 1 do
|
|
local y, x, eventData = title(#elements + 2, titleText)
|
|
|
|
for i = 1, #elements do
|
|
x = mathFloor(screenWidth / 2 - #elements[i].s / 2)
|
|
|
|
if i == selectedElement then
|
|
rectangle(mathFloor(screenWidth / 2 - maxLength / 2) - 2, y, maxLength + 4, 1, colorsSelectionBackground)
|
|
gpuSetForeground(colorsSelectionText)
|
|
gpuSet(x, y, elements[i].s)
|
|
gpuSetBackground(colorsBackground)
|
|
else
|
|
gpuSetForeground(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, " ")
|
|
gpuSetForeground(colorsText)
|
|
gpuSet(mathFloor(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
|
|
|
|
status(stringsMain, "Hold Alt to show boot options")
|
|
|
|
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 restrict, filesystems, filesystemOptions =
|
|
function(text, limit)
|
|
if #text < limit then
|
|
text = text .. string.rep(" ", limit - #text)
|
|
else
|
|
text = text:sub(1, limit)
|
|
end
|
|
|
|
return text .. " "
|
|
end,
|
|
{menuBack()}
|
|
|
|
local function updateFilesystems()
|
|
for i = 2, #filesystems do
|
|
table.remove(filesystems, 1)
|
|
end
|
|
|
|
for address in componentList(stringsFilesystem) do
|
|
local proxy = componentProxy(address)
|
|
local label, isReadOnly, filesystemOptions =
|
|
proxy.getLabel() or "Unnamed",
|
|
proxy.isReadOnly(),
|
|
{
|
|
menuElement("Set as bootable", function()
|
|
eepromSetData(address)
|
|
updateFilesystems()
|
|
end, 1)
|
|
}
|
|
|
|
if not isReadOnly then
|
|
tableInsert(filesystemOptions, menuElement(stringsChangeLabel, function()
|
|
proxy.setLabel(input(title(2, stringsChangeLabel), "Enter new name: "))
|
|
updateFilesystems()
|
|
end, 1))
|
|
|
|
tableInsert(filesystemOptions, menuElement("Format", function()
|
|
status(stringsMain, "Formatting filesystem " .. address)
|
|
|
|
for _, file in ipairs(proxy.list("/")) do
|
|
proxy.remove(file)
|
|
end
|
|
|
|
updateFilesystems()
|
|
end, 1))
|
|
end
|
|
|
|
tableInsert(filesystemOptions, menuBack())
|
|
|
|
tableInsert(filesystems, 1,
|
|
menuElement(
|
|
(address == eepromGetData() and "> " or " ") ..
|
|
restrict(label, 12) ..
|
|
restrict(proxy.spaceTotal() > 1048576 and "HDD" or proxy.spaceTotal() > 65536 and "FDD" or "SYS", 3) ..
|
|
restrict(isReadOnly and "R" or "R/W", 3) ..
|
|
restrict(string.format("%.1f", proxy.spaceUsed() / proxy.spaceTotal() * 100) .. "%", 6) ..
|
|
address:sub(1, 7) .. "…",
|
|
function()
|
|
menu(label .. " (" .. address .. ")", filesystemOptions)
|
|
end
|
|
)
|
|
)
|
|
end
|
|
end
|
|
|
|
updateFilesystems()
|
|
menu("Select filesystem", filesystems)
|
|
end),
|
|
|
|
menuElement("Shutdown", function()
|
|
shutdown()
|
|
end),
|
|
|
|
menuBack()
|
|
}
|
|
|
|
if internetAddress then
|
|
tableInsert(utilities, 2, menuElement("Internet recovery", function()
|
|
local handle, data, result, reason = componentProxy(internetAddress).request("https://raw.githubusercontent.com/IgorTimofeev/MineOS/master/Installer/Main.lua"), ""
|
|
|
|
if handle then
|
|
status(stringsMain, "Downloading recovery script")
|
|
|
|
while 1 do
|
|
result, reason = handle.read(mathHuge)
|
|
|
|
if result then
|
|
data = data .. result
|
|
else
|
|
handle.close()
|
|
|
|
if reason then
|
|
status(stringsMain, reason, 1)
|
|
else
|
|
executeString(data, "=string")
|
|
end
|
|
|
|
break
|
|
end
|
|
end
|
|
else
|
|
status(stringsMain, "invalid URL-address", 1)
|
|
end
|
|
end))
|
|
end
|
|
|
|
menu(stringsMain, utilities)
|
|
end
|
|
end
|
|
|
|
local proxy = componentProxy(eepromGetData())
|
|
if not (proxy and boot(proxy)) then
|
|
for address in componentList(stringsFilesystem) do
|
|
proxy = componentProxy(address)
|
|
|
|
if boot(proxy) then
|
|
break
|
|
else
|
|
proxy = nil
|
|
end
|
|
end
|
|
|
|
if not proxy then
|
|
status(stringsMain, "No bootable mediums found", 1)
|
|
end
|
|
end
|
|
|
|
shutdown()
|