-- This is released into the public domain. -- No warranty is provided, implied or otherwise. -- confboot.lua : VM configuration program -- Authors: 20kdc -- _MMstartVM(name) -- _MMcomList(...) -- _MMserial(str) -- _MMdeserial(str) local screen = component.proxy(component.list("screen", true)()) local gpu = component.proxy(component.list("gpu", true)()) local fs = component.proxy("world") screen.turnOn() gpu.bind(screen.address) gpu.setResolution(50, 15) gpu.setForeground(0) gpu.setBackground(0xFFFFFF) local menu local currentY local currentVMId local currentVM local genMainMenu, genFSSelector, genEditor function genFSSelector(cb) local fsName = "" menu = { {" - Select VFS -", function () end}, {"Cancel", cb}, {"New FS: ", function () fs.makeDirectory("fs-" .. fsName) genFSSelector(cb) end, function (text) if text then fsName = text end return fsName end} } currentY = 2 local fsl = fs.list("") table.sort(fsl) for k, v in ipairs(fsl) do if v:sub(#v) == "/" and v:sub(1, 3) == "fs-" then local id = v:sub(4, #v - 1) table.insert(menu, {id, function () cb(id) end}) table.insert(menu, {" Delete", function () fs.remove("fs-" .. id) genFSSelector(cb) end}) end end end local function doVMSave() local f = fs.open("vm-" .. currentVMId, "wb") if not f then error("VM Save failed...") end fs.write(f, _MMserial(currentVM)) fs.close(f) end function genEditor() menu = { --01234567890123456789012345678901234567890123456789 {" - configuring VM: " .. currentVMId, function () end}, {"Save & Return", function () doVMSave() currentVM, currentVMId = nil genMainMenu() end}, {"Save & Launch", function () doVMSave() _MMstartVM(currentVMId) computer.shutdown() end}, {"Delete", function () fs.remove("vm-" .. currentVMId) currentVM, currentVMId = nil genMainMenu() end}, } currentY = 3 for k, v in pairs(currentVM) do local v1 = tostring(v) if type(v) ~= "string" then v1 = "virt. ".. v[1] end table.insert(menu, {"Del. " .. v1 .. " " .. k, function () currentVM[k] = nil genEditor() end}) end if not currentVM["k-eeprom"] then table.insert(menu, {"+ Virtual EEPROM (R/W, preloaded w/ LUCcABOOT)...", function () currentVM[currentVMId .. "-eeprom"] = {"eeprom", "/vc-" .. currentVMId .. ".lua", "/vd-" .. currentVMId .. ".bin", "VM BIOS", false} genEditor() -- do file copy now! local handleA = fs.open("/lucaboot.lua", "rb") local handleB = fs.open("/vc-" .. currentVMId .. ".lua", "wb") if not handleA then if handleB then fs.close(handleB) end return end if not handleB then fs.close(handleA) return end while true do local s = fs.read(handleA, 2048) if not s then break end fs.write(handleB, s) end fs.close(handleA) fs.close(handleB) end}) end table.insert(menu, {"+ Virtual FS (R/W)...", function () genFSSelector(function (fsa) if fsa then currentVM["fs-" .. fsa] = {"filesystem", "/fs-" .. fsa .. "/", false} end genEditor() end) end}) table.insert(menu, {"+ Virtual FS (R/O)...", function () genFSSelector(function (fsa) if fsa then currentVM[fsa .. "-fs"] = {"filesystem", fsa, true} end genEditor() end) end}) local tx = { "+ Screen 50x15:", "+ Screen 80x24:", "+ Screen 160x49:" } local txw = { 50, 80, 160 } local txh = { 15, 24, 49 } for i = 1, 3 do local cName = currentVMId .. "-screen" local nt = 0 while currentVM[cName] do nt = nt + 1 cName = currentVMId .. "-" .. nt end table.insert(menu, {tx[i], function () currentVM[cName] = {"screen", cName, txw[i], txh[i], 8} genEditor() end, function (text) if text then cName = text end return cName end}) end for address, ty in _MMcomList("") do if (not currentVM[address]) and ty ~= "gpu" then table.insert(menu, {"+ Host " .. ty .. " " .. address, function () currentVM[address] = ty genEditor() end}) end end end function genMainMenu() local vmName = "" menu = { --01234567890123456789012345678901234567890123456789 {" - metamachine configurator -- use keyboard - ", function () end}, {"Shutdown", computer.shutdown}, {"New VM: ", function () local f = fs.open("vm-" .. vmName, "wb") if not f then return end fs.write(f, _MMserial({ [vmName .. "-eeprom"] = {"eeprom", "/lucaboot.lua", "/vd-" .. vmName .. ".bin", "LUCcABOOT VM BIOS", true}, [vmName .. "-screen"] = {"screen", vmName, 50, 15, 8} })) fs.close(f) genMainMenu() end, function (text) if text then vmName = text end return vmName end} } currentY = 3 local fsl = fs.list("") table.sort(fsl) for k, v in ipairs(fsl) do if v:sub(#v) == "/" then elseif v:sub(1, 3) == "vm-" then local id = v:sub(4) table.insert(menu, #menu, {id, function () local f = fs.open("vm-" .. id, "rb") if not f then return end local str = "" while true do local sb = fs.read(f, 2048) if not sb then break end str = str .. sb end currentVM = _MMdeserial(str) or {} fs.close(f) currentVMId = id genEditor() end}) end end end ---- genMainMenu() local function draw() gpu.fill(1, 1, 50, 15, " ") local camera = math.max(0, math.min(math.floor(currentY - 7), #menu - 15)) for i = 1, #menu do local pfx = " " if currentY == i then pfx = "> " end local pox = "" if menu[i][3] then pox = menu[i][3]() end gpu.set(1, i - camera, pfx .. menu[i][1] .. pox) end end -- Final main loop. draw() while true do local t = {computer.pullSignal()} if t[1] == "key_down" then if t[4] == 200 then currentY = math.max(1, currentY - 1) draw() elseif t[4] == 208 then currentY = math.min(currentY + 1, #menu) draw() elseif t[3] == 13 then menu[currentY][2]() draw() elseif t[3] == 8 then local tx = menu[currentY][3]() menu[currentY][3](unicode.sub(tx, 1, unicode.len(tx) - 1)) draw() elseif t[3] >= 32 then if menu[currentY][3] then menu[currentY][3](menu[currentY][3]() .. unicode.char(t[3])) draw() end end end end