Advertisement
nonogamer9

NextDOS : An Multitasking Operating System For OpenComputers

Sep 24th, 2024 (edited)
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 22.54 KB | Software | 0 0
  1. local component = require("component")
  2. local computer = require("computer")
  3. local event = require("event")
  4. local filesystem = require("filesystem")
  5. local term = require("term")
  6. local shell = require("shell")
  7. local unicode = require("unicode")
  8. local thread = require("thread")
  9. local internet = component.internet
  10.  
  11. local VERSION, OS_NAME = "3.2", "NextDOS"
  12. local PRIMARY_WIDTH, PRIMARY_HEIGHT, SECONDARY_WIDTH, SECONDARY_HEIGHT = 0, 0, 0, 0
  13. local gpus, screens, tasks, command_history = {}, {}, {}, {}
  14. local current_dir, history_index = "/", 0
  15. local primary_gpu, secondary_gpu, primary_screen, secondary_screen
  16. local secondary_program_running = false
  17.  
  18. local floor, max, concat = math.floor, math.max, table.concat
  19. local yield = coroutine.yield
  20. local push_signal = computer.pushSignal
  21. local pull_signal = computer.pullSignal
  22.  
  23. for address in component.list("gpu") do gpus[#gpus + 1] = component.proxy(address) end
  24. for address in component.list("screen") do screens[#screens + 1] = component.proxy(address) end
  25. assert(#gpus > 0 and #screens > 0, "No GPU or screen found")
  26.  
  27. primary_gpu, secondary_gpu = gpus[1], gpus[2] or gpus[1]
  28. primary_screen, secondary_screen = screens[1], screens[2] or screens[1]
  29.  
  30. primary_gpu.bind(primary_screen.address)
  31. if secondary_gpu ~= primary_gpu then secondary_gpu.bind(secondary_screen.address) end
  32.  
  33. PRIMARY_WIDTH, PRIMARY_HEIGHT = primary_gpu.getResolution()
  34. SECONDARY_WIDTH, SECONDARY_HEIGHT = secondary_gpu.getResolution()
  35.  
  36. local screensaver = {
  37.     running = false,
  38.     thread = nil,
  39.     start = function(self)
  40.         if not self.running and secondary_gpu ~= primary_gpu and not secondary_program_running then
  41.             self.running = true
  42.             self.thread = thread.create(function()
  43.                 local x, y = SECONDARY_WIDTH / 2, SECONDARY_HEIGHT / 2
  44.                 local dx, dy = 1, 1
  45.                 local color = 0xFFFFFF
  46.                 local buffer1, buffer2 = 1, 2
  47.                
  48.                 secondary_gpu.setBackground(0x000000)
  49.                 secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ", buffer1)
  50.                 secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ", buffer2)
  51.  
  52.                 while self.running do
  53.                     local active_buffer = buffer1
  54.                     local back_buffer = buffer2
  55.  
  56.                     secondary_gpu.setActiveBuffer(back_buffer)
  57.                     secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ")
  58.                     secondary_gpu.setForeground(color)
  59.                     secondary_gpu.set(floor(x), floor(y), "O")
  60.                    
  61.                     x = x + dx
  62.                     y = y + dy
  63.                    
  64.                     if x <= 1 or x >= SECONDARY_WIDTH then dx = -dx end
  65.                     if y <= 1 or y >= SECONDARY_HEIGHT then dy = -dy end
  66.                    
  67.                     secondary_gpu.setActiveBuffer(active_buffer)
  68.                     secondary_gpu.bitblt(active_buffer, 1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, back_buffer, 1, 1)
  69.                    
  70.                     buffer1, buffer2 = buffer2, buffer1
  71.                     os.sleep(0.05)
  72.                 end
  73.             end)
  74.         end
  75.     end,
  76.     stop = function(self)
  77.         self.running = false
  78.         if self.thread then
  79.             self.thread:kill()
  80.             self.thread = nil
  81.         end
  82.         if secondary_gpu ~= primary_gpu then
  83.             secondary_gpu.setBackground(0x000000)
  84.             secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ")
  85.         end
  86.     end
  87. }
  88.  
  89. local function setup_secondary_buffers(task)
  90.     if task.gpu_index == 2 then
  91.         task.buffer1 = 1
  92.         task.buffer2 = 2
  93.         task.active_buffer = task.buffer1
  94.         secondary_gpu.setBackground(0x000000)
  95.         secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ", task.buffer1)
  96.         secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ", task.buffer2)
  97.     end
  98. end
  99.  
  100. local function run_task(task)
  101.     if task.gpu_index == 2 then
  102.         secondary_gpu.setActiveBuffer(task.active_buffer)
  103.     end
  104.     term.bind(task.gpu)
  105.     local start_time = computer.uptime()
  106.     task.state = "running"
  107.     local success, result = coroutine.resume(task.coroutine, table.unpack(task.args))
  108.     task.run_time = task.run_time + (computer.uptime() - start_time)
  109.     task.last_run = computer.uptime()
  110.     term.bind(primary_gpu)
  111.     if task.gpu_index == 2 and success then
  112.         secondary_gpu.bitblt(task.active_buffer, 1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, task.active_buffer == task.buffer1 and task.buffer2 or task.buffer1, 1, 1)
  113.         task.active_buffer = task.active_buffer == task.buffer1 and task.buffer2 or task.buffer1
  114.     end
  115.     task.state = coroutine.status(task.coroutine) == "dead" and "finished" or "ready"
  116.     if task.state == "finished" and task.gpu_index == 2 then
  117.         secondary_program_running = false
  118.         screensaver:start()
  119.     end
  120.     return success, result
  121. end
  122.  
  123. local function create_task(func, priority, gpu_index, ...)
  124.     local task = {
  125.         coroutine = coroutine.create(func),
  126.         gpu = gpu_index == 2 and secondary_gpu or gpus[gpu_index],
  127.         args = {...},
  128.         start_time = computer.uptime(),
  129.         run_time = 0,
  130.         priority = priority or 1,
  131.         last_run = 0,
  132.         state = "ready",
  133.         gpu_index = gpu_index
  134.     }
  135.     setup_secondary_buffers(task)
  136.     tasks[#tasks + 1] = task
  137.     return task
  138. end
  139.  
  140. local function cmd_cd(args)
  141.     if #args == 0 then
  142.         current_dir = "/"
  143.     else
  144.         local new_dir = shell.resolve(args[1])
  145.         if filesystem.isDirectory(new_dir) then
  146.             current_dir = new_dir
  147.         else
  148.             print("Directory not found: " .. args[1])
  149.         end
  150.     end
  151. end
  152.  
  153. local function cmd_ls(args)
  154.     local path = args[1] and shell.resolve(args[1]) or current_dir
  155.     if filesystem.isDirectory(path) then
  156.         for file in filesystem.list(path) do
  157.             local full_path = filesystem.concat(path, file)
  158.             if filesystem.isDirectory(full_path) then
  159.                 print("\27[34m" .. file .. "/\27[0m")
  160.             else
  161.                 print(file)
  162.             end
  163.         end
  164.     else
  165.         print("Not a directory: " .. path)
  166.     end
  167. end
  168.  
  169. local function cmd_run(args)
  170.     if #args < 1 then
  171.         print("Usage: run <program> [gpu_index] [priority] [args...]")
  172.     else
  173.         local program_path = shell.resolve(args[1])
  174.         local gpu_index = tonumber(args[2]) or 1
  175.         local priority = tonumber(args[3]) or 1
  176.         if filesystem.exists(program_path) then
  177.             if gpu_index == 2 then
  178.                 secondary_program_running = true
  179.                 screensaver:stop()
  180.                 secondary_gpu.setBackground(0x000000)
  181.                 secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ")
  182.             end
  183.             create_task(function(...)
  184.                 local program = assert(loadfile(program_path), "Failed to load program")
  185.                 program(...)
  186.                 if gpu_index == 2 then
  187.                     secondary_program_running = false
  188.                     screensaver:start()
  189.                 end
  190.             end, priority, gpu_index, table.unpack(args, 4))
  191.         else
  192.             print("Program not found: " .. args[1])
  193.         end
  194.     end
  195. end
  196.  
  197. local function cmd_kill(args)
  198.     if #args < 1 then
  199.         print("Usage: kill <task_id>")
  200.     else
  201.         local task_id = tonumber(args[1])
  202.         if task_id and tasks[task_id] then
  203.             if tasks[task_id].gpu_index == 2 then
  204.                 secondary_program_running = false
  205.                 screensaver:start()
  206.             end
  207.             tasks[task_id].state = "finished"
  208.             print("Task " .. task_id .. " killed")
  209.         else
  210.             print("Invalid task ID")
  211.         end
  212.     end
  213. end
  214.  
  215. local function cmd_neofetch()
  216.     local info = {
  217.         OS = OS_NAME .. " v" .. VERSION,
  218.         Host = computer.address(),
  219.         Uptime = string.format("%.2f hours", computer.uptime() / 3600),
  220.         RAM = string.format("%.2f MB / %.2f MB", computer.freeMemory() / 1024 / 1024, computer.totalMemory() / 1024 / 1024),
  221.         GPUs = tostring(#gpus),
  222.         Screens = tostring(#screens),
  223.         Primary = string.format("%dx%d", PRIMARY_WIDTH, PRIMARY_HEIGHT),
  224.         Secondary = secondary_gpu ~= primary_gpu and string.format("%dx%d", SECONDARY_WIDTH, SECONDARY_HEIGHT) or "N/A"
  225.     }
  226.     local ascii_art = {
  227.         "    _   __          __  ____  ____  _____",
  228.         "   / | / /__  _  __/ /_/ __ \\/ __ \\/ ___/",
  229.         "  /  |/ / _ \\| |/_/ __/ / / / / / /\\__ \\ ",
  230.         " / /|  /  __/>  </ /_/ /_/ / /_/ /___/ / ",
  231.         "/_/ |_/\\___/_/|_|\\__/_____/\\____//____/  "
  232.     }
  233.     local max_length = 0
  234.     for i = 1, #ascii_art do
  235.         max_length = max(max_length, unicode.len(ascii_art[i]))
  236.     end
  237.     local info_keys = {}
  238.     for k in pairs(info) do
  239.         table.insert(info_keys, k)
  240.     end
  241.     table.sort(info_keys)
  242.     for i = 1, #ascii_art do
  243.         local info_key = info_keys[i]
  244.         if info_key then
  245.             print(string.format("\27[36m%-"..max_length.."s\27[0m  %s: %s", ascii_art[i], info_key, info[info_key]))
  246.         else
  247.             print(string.format("\27[36m%-"..max_length.."s\27[0m", ascii_art[i]))
  248.         end
  249.     end
  250.     print(string.format("\27[36m%-"..max_length.."s\27[0m  %s", "", "NextDOS made by nonogamer9"))
  251. end
  252.  
  253. local function cmd_wget(args)
  254.     if #args < 2 then
  255.         print("Usage: wget <url> <filename>")
  256.         return
  257.     end
  258.     local url = args[1]
  259.     local filename = args[2]
  260.  
  261.     print("Downloading " .. url .. " to " .. filename)
  262.  
  263.     local result, response = pcall(function()
  264.         local request, requestReason = internet.request(url)
  265.         if not request then
  266.             error("HTTP request failed: " .. (requestReason or "unknown error"))
  267.         end
  268.  
  269.         local result = ""
  270.         local data = request.read(1024)
  271.         while data do
  272.             result = result .. data
  273.             data = request.read(1024)
  274.         end
  275.         request.close()
  276.         return result
  277.     end)
  278.  
  279.     if result then
  280.         local file, fileReason = io.open(filename, "wb")
  281.         if not file then
  282.             print("Failed to open file for writing: " .. (fileReason or "unknown error"))
  283.             return
  284.         end
  285.         file:write(response)
  286.         file:close()
  287.         print("Download complete: " .. filename)
  288.     else
  289.         print("Download failed: " .. tostring(response))
  290.     end
  291. end
  292.  
  293. local function cmd_edit(args)
  294.     if #args < 1 then
  295.         print("Usage: edit <filename>")
  296.         return
  297.     end
  298.     local filename = shell.resolve(args[1])
  299.     local content = ""
  300.     if filesystem.exists(filename) then
  301.         local file = io.open(filename, "r")
  302.         content = file:read("*a")
  303.         file:close()
  304.     end
  305.    
  306.     local lines = {}
  307.     for line in content:gmatch("[^\r\n]+") do
  308.         table.insert(lines, line)
  309.     end
  310.    
  311.     local cursor_x, cursor_y = 1, 1
  312.     local scroll_y = 0
  313.    
  314.     local function redraw()
  315.         term.clear()
  316.         for i = 1, PRIMARY_HEIGHT - 1 do
  317.             local line = lines[i + scroll_y] or ""
  318.             term.setCursor(1, i)
  319.             term.write(line)
  320.         end
  321.         term.setCursor(1, PRIMARY_HEIGHT)
  322.         term.write("ESC to save and exit, Ctrl+C to exit without saving")
  323.         term.setCursor(cursor_x, cursor_y - scroll_y)
  324.     end
  325.    
  326.     while true do
  327.         redraw()
  328.         local event, _, char, code = event.pull()
  329.         if event == "key_down" then
  330.             if code == 28 then
  331.                 table.insert(lines, cursor_y, "")
  332.                 cursor_y = cursor_y + 1
  333.                 cursor_x = 1
  334.             elseif code == 14 then
  335.                 if cursor_x > 1 then
  336.                     lines[cursor_y] = lines[cursor_y]:sub(1, cursor_x - 2) .. lines[cursor_y]:sub(cursor_x)
  337.                     cursor_x = cursor_x - 1
  338.                 elseif cursor_y > 1 then
  339.                     local current_line = lines[cursor_y]
  340.                     table.remove(lines, cursor_y)
  341.                     cursor_y = cursor_y - 1
  342.                     cursor_x = #lines[cursor_y] + 1
  343.                     lines[cursor_y] = lines[cursor_y] .. current_line
  344.                 end
  345.             elseif code == 203 then
  346.                 if cursor_x > 1 then
  347.                     cursor_x = cursor_x - 1
  348.                 elseif cursor_y > 1 then
  349.                     cursor_y = cursor_y - 1
  350.                     cursor_x = #lines[cursor_y] + 1
  351.                 end
  352.             elseif code == 205 then
  353.                 if cursor_x <= #lines[cursor_y] then
  354.                     cursor_x = cursor_x + 1
  355.                 elseif cursor_y < #lines then
  356.                     cursor_y = cursor_y + 1
  357.                     cursor_x = 1
  358.                 end
  359.             elseif code == 200 then
  360.                 if cursor_y > 1 then
  361.                     cursor_y = cursor_y - 1
  362.                     cursor_x = math.min(cursor_x, #lines[cursor_y] + 1)
  363.                 end
  364.             elseif code == 208 then
  365.                 if cursor_y < #lines then
  366.                     cursor_y = cursor_y + 1
  367.                     cursor_x = math.min(cursor_x, #lines[cursor_y] + 1)
  368.                 end
  369.             elseif code == 1 then
  370.                 local file = io.open(filename, "w")
  371.                 file:write(table.concat(lines, "\n"))
  372.                 file:close()
  373.                 break
  374.             elseif char == 3 then
  375.                 break
  376.             elseif char >= 32 and char <= 126 then
  377.                 local line = lines[cursor_y]
  378.                 lines[cursor_y] = line:sub(1, cursor_x - 1) .. unicode.char(char) .. line:sub(cursor_x)
  379.                 cursor_x = cursor_x + 1
  380.             end
  381.         end
  382.        
  383.         if cursor_y - scroll_y > PRIMARY_HEIGHT - 1 then
  384.             scroll_y = cursor_y - (PRIMARY_HEIGHT - 1)
  385.         elseif cursor_y - scroll_y < 1 then
  386.             scroll_y = cursor_y - 1
  387.         end
  388.     end
  389. end
  390.  
  391. local function cmd_ping(args)
  392.     if #args < 1 then
  393.         print("Usage: ping <hostname>")
  394.         return
  395.     end
  396.    
  397.     local hostname = args[1]
  398.     print("Pinging " .. hostname .. "...")
  399.    
  400.     for i = 1, 4 do
  401.         local start_time = computer.uptime()
  402.         local success, response = pcall(function()
  403.             return internet.request("http://" .. hostname)
  404.         end)
  405.         local end_time = computer.uptime()
  406.        
  407.         if success then
  408.             print(string.format("Reply from %s: time=%.2fms", hostname, (end_time - start_time) * 1000))
  409.         else
  410.             print("Request timed out.")
  411.         end
  412.        
  413.         os.sleep(1)
  414.     end
  415. end
  416.  
  417. local function cmd_copy(args)
  418.     if #args < 2 then
  419.         print("Usage: copy <source> <destination>")
  420.         return
  421.     end
  422.     local source = shell.resolve(args[1])
  423.     local destination = shell.resolve(args[2])
  424.    
  425.     if not filesystem.exists(source) then
  426.         print("Source file not found: " .. source)
  427.         return
  428.     end
  429.    
  430.     local sourceHandle = io.open(source, "rb")
  431.     if not sourceHandle then
  432.         print("Failed to open source file: " .. source)
  433.         return
  434.     end
  435.    
  436.     local destHandle = io.open(destination, "wb")
  437.     if not destHandle then
  438.         sourceHandle:close()
  439.         print("Failed to create destination file: " .. destination)
  440.         return
  441.     end
  442.    
  443.     local data = sourceHandle:read("*a")
  444.     destHandle:write(data)
  445.    
  446.     sourceHandle:close()
  447.     destHandle:close()
  448.    
  449.     print("File copied successfully")
  450. end
  451.  
  452. local function cmd_mkdir(args)
  453.     if #args < 1 then
  454.         print("Usage: mkdir <directory>")
  455.         return
  456.     end
  457.     local path = shell.resolve(args[1])
  458.    
  459.     if filesystem.exists(path) then
  460.         print("Path already exists: " .. path)
  461.         return
  462.     end
  463.    
  464.     local success, reason = filesystem.makeDirectory(path)
  465.     if success then
  466.         print("Directory created: " .. path)
  467.     else
  468.         print("Failed to create directory: " .. reason)
  469.     end
  470. end
  471.  
  472. local commands = {
  473.     cd = cmd_cd,
  474.     ls = cmd_ls,
  475.     dir = cmd_ls,
  476.     run = cmd_run,
  477.     kill = cmd_kill,
  478.     neofetch = cmd_neofetch,
  479.     wget = cmd_wget,
  480.     edit = cmd_edit,
  481.     ping = cmd_ping,
  482.     copy = cmd_copy,
  483.     mkdir = cmd_mkdir,
  484.     clear = function() term.clear() end,
  485.     reboot = function() computer.shutdown(true) end,
  486.     shutdown = function() computer.shutdown() end,
  487.     gpus = function()
  488.         for i, gpu in ipairs(gpus) do
  489.             local width, height = gpu.getResolution()
  490.             print(string.format("GPU %d: %dx%d, %d-bit color", i, width, height, gpu.getDepth()))
  491.         end
  492.     end,
  493.     tasks = function()
  494.         print("Running tasks:")
  495.         for i, task in ipairs(tasks) do
  496.             print(string.format("Task %d: Priority %d, Runtime %.2fs, State: %s, GPU: %d", i, task.priority, task.run_time, task.state, task.gpu_index))
  497.         end
  498.     end,
  499.     mem = function()
  500.         local free, total = computer.freeMemory(), computer.totalMemory()
  501.         print(string.format("Memory: %.2f MB / %.2f MB (%.2f%% used)", free / 1024 / 1024, total / 1024 / 1024, (1 - free / total) * 100))
  502.     end,
  503.     ps = function()
  504.         for i, task in ipairs(tasks) do
  505.             print(string.format("PID %d: State: %s, GPU: %d, Priority: %d", i, task.state, task.gpu_index, task.priority))
  506.         end
  507.     end,
  508.     del = function(args)
  509.         if #args < 1 then
  510.             print("Usage: del <file>")
  511.         else
  512.             local file_path = shell.resolve(args[1])
  513.             if filesystem.exists(file_path) then
  514.                 if filesystem.remove(file_path) then
  515.                     print("File deleted: " .. file_path)
  516.                 else
  517.                     print("Failed to delete file: " .. file_path)
  518.                 end
  519.             else
  520.                 print("File not found: " .. file_path)
  521.             end
  522.         end
  523.     end,
  524.     help = function()
  525.         local help_cmds = {
  526.             {"cd <dir>", "Change directory"},
  527.             {"ls/dir", "List files"},
  528.             {"run <program> [gpu_index] [priority] [args...]", "Run a program"},
  529.             {"kill <task_id>", "Kill a task"},
  530.             {"neofetch", "Display system info"},
  531.             {"wget <url> <filename>", "Download file"},
  532.             {"edit <filename>", "Edit a file"},
  533.             {"ping <hostname>", "Ping a host"},
  534.             {"copy <source> <destination>", "Copy a file"},
  535.             {"mkdir <directory>", "Create a directory"},
  536.             {"gpus", "List GPUs"},
  537.             {"tasks", "List running tasks"},
  538.             {"clear", "Clear the screen"},
  539.             {"reboot", "Reboot the system"},
  540.             {"shutdown", "Shutdown the system"},
  541.             {"mem", "Display memory usage"},
  542.             {"ps", "List all processes"},
  543.             {"del <file>", "Delete a file"}
  544.         }
  545.         print(string.format("%s v%s Help", OS_NAME, VERSION))
  546.         for _, cmd in ipairs(help_cmds) do print(string.format("  %-40s - %s", cmd[1], cmd[2])) end
  547.     end
  548. }
  549.  
  550. local function execute_command(input)
  551.     local args = {}
  552.     for arg in input:gmatch("%S+") do args[#args + 1] = arg end
  553.     local cmd = table.remove(args, 1)
  554.    
  555.     local cmd_func = commands[cmd]
  556.     if cmd_func then
  557.         return cmd_func(args) ~= false
  558.     else
  559.         print("Unknown command: " .. cmd)
  560.         return true
  561.     end
  562. end
  563.  
  564. local function display_prompt()
  565.     term.write(string.format("\27[32m%s \27[34m%s\27[0m> ", OS_NAME, current_dir))
  566. end
  567.  
  568. local function reset_secondary_screen()
  569.     if secondary_gpu ~= primary_gpu then
  570.         secondary_gpu.setBackground(0x000000)
  571.         secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ")
  572.         secondary_program_running = false
  573.         screensaver:start()
  574.     end
  575. end
  576.  
  577. local function main_loop()
  578.     screensaver:start()
  579.     local last_yield = computer.uptime()
  580.     local prompt_displayed = false
  581.  
  582.     while true do
  583.         if not prompt_displayed then
  584.             display_prompt()
  585.             prompt_displayed = true
  586.         end
  587.  
  588.         local active_tasks = {}
  589.         for i = 1, #tasks do
  590.             local task = tasks[i]
  591.             if task.state ~= "finished" then
  592.                 local success, result = run_task(task)
  593.                 if not success then
  594.                     push_signal("task_error", tostring(result))
  595.                     task.state = "finished"
  596.                 else
  597.                     active_tasks[#active_tasks + 1] = task
  598.                 end
  599.             end
  600.         end
  601.         tasks = active_tasks
  602.  
  603.         if secondary_program_running then
  604.             screensaver:stop()
  605.         elseif #tasks == 0 and not secondary_program_running then
  606.             screensaver:start()
  607.         end
  608.  
  609.         local event_data = {pull_signal(0)}
  610.         if event_data[1] then
  611.             if event_data[1] == "key_down" then
  612.                 local input = term.read(nil, command_history)
  613.                 if input then
  614.                     command_history[#command_history + 1] = input
  615.                     if #command_history > 50 then table.remove(command_history, 1) end
  616.                     history_index = #command_history + 1
  617.                     execute_command(input)
  618.                     prompt_displayed = false
  619.                 end
  620.             elseif event_data[1] == "task_error" then
  621.                 print("Task error: " .. event_data[2])
  622.                 prompt_displayed = false
  623.             end
  624.         end
  625.  
  626.         if computer.uptime() - last_yield > 0.05 then
  627.             os.sleep(0)
  628.             last_yield = computer.uptime()
  629.         end
  630.     end
  631. end
  632.  
  633. local function error_handler(err)
  634.     io.stderr:write("Error: " .. tostring(err) .. "\n")
  635.     io.stderr:write(debug.traceback(nil, 2) .. "\n")
  636.     return err
  637. end
  638.  
  639. local function init_system()
  640.     primary_gpu.setResolution(PRIMARY_WIDTH, PRIMARY_HEIGHT)
  641.     if secondary_gpu ~= primary_gpu then
  642.         secondary_gpu.setResolution(SECONDARY_WIDTH, SECONDARY_HEIGHT)
  643.         secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ")
  644.         secondary_gpu.set(1, 1, "Secondary Display - No program running")
  645.     end
  646. end
  647.  
  648. local function start_system()
  649.     init_system()
  650.     term.clear()
  651.     print(string.format("%s v%s - Type 'help' for commands", OS_NAME, VERSION))
  652.    
  653.     local success, err = xpcall(main_loop, error_handler)
  654.     if not success then
  655.         io.stderr:write("NextDOS crashed: " .. tostring(err) .. "\n")
  656.         io.stderr:write("Rebooting in 5 seconds...\n")
  657.         os.sleep(5)
  658.         computer.shutdown(true)
  659.     end
  660. end
  661.  
  662. start_system()
  663.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement