Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = require("component")
- local computer = require("computer")
- local event = require("event")
- local filesystem = require("filesystem")
- local term = require("term")
- local shell = require("shell")
- local unicode = require("unicode")
- local thread = require("thread")
- local internet = component.internet
- local VERSION, OS_NAME = "3.2", "NextDOS"
- local PRIMARY_WIDTH, PRIMARY_HEIGHT, SECONDARY_WIDTH, SECONDARY_HEIGHT = 0, 0, 0, 0
- local gpus, screens, tasks, command_history = {}, {}, {}, {}
- local current_dir, history_index = "/", 0
- local primary_gpu, secondary_gpu, primary_screen, secondary_screen
- local secondary_program_running = false
- local floor, max, concat = math.floor, math.max, table.concat
- local yield = coroutine.yield
- local push_signal = computer.pushSignal
- local pull_signal = computer.pullSignal
- for address in component.list("gpu") do gpus[#gpus + 1] = component.proxy(address) end
- for address in component.list("screen") do screens[#screens + 1] = component.proxy(address) end
- assert(#gpus > 0 and #screens > 0, "No GPU or screen found")
- primary_gpu, secondary_gpu = gpus[1], gpus[2] or gpus[1]
- primary_screen, secondary_screen = screens[1], screens[2] or screens[1]
- primary_gpu.bind(primary_screen.address)
- if secondary_gpu ~= primary_gpu then secondary_gpu.bind(secondary_screen.address) end
- PRIMARY_WIDTH, PRIMARY_HEIGHT = primary_gpu.getResolution()
- SECONDARY_WIDTH, SECONDARY_HEIGHT = secondary_gpu.getResolution()
- local screensaver = {
- running = false,
- thread = nil,
- start = function(self)
- if not self.running and secondary_gpu ~= primary_gpu and not secondary_program_running then
- self.running = true
- self.thread = thread.create(function()
- local x, y = SECONDARY_WIDTH / 2, SECONDARY_HEIGHT / 2
- local dx, dy = 1, 1
- local color = 0xFFFFFF
- local buffer1, buffer2 = 1, 2
- secondary_gpu.setBackground(0x000000)
- secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ", buffer1)
- secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ", buffer2)
- while self.running do
- local active_buffer = buffer1
- local back_buffer = buffer2
- secondary_gpu.setActiveBuffer(back_buffer)
- secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ")
- secondary_gpu.setForeground(color)
- secondary_gpu.set(floor(x), floor(y), "O")
- x = x + dx
- y = y + dy
- if x <= 1 or x >= SECONDARY_WIDTH then dx = -dx end
- if y <= 1 or y >= SECONDARY_HEIGHT then dy = -dy end
- secondary_gpu.setActiveBuffer(active_buffer)
- secondary_gpu.bitblt(active_buffer, 1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, back_buffer, 1, 1)
- buffer1, buffer2 = buffer2, buffer1
- os.sleep(0.05)
- end
- end)
- end
- end,
- stop = function(self)
- self.running = false
- if self.thread then
- self.thread:kill()
- self.thread = nil
- end
- if secondary_gpu ~= primary_gpu then
- secondary_gpu.setBackground(0x000000)
- secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ")
- end
- end
- }
- local function setup_secondary_buffers(task)
- if task.gpu_index == 2 then
- task.buffer1 = 1
- task.buffer2 = 2
- task.active_buffer = task.buffer1
- secondary_gpu.setBackground(0x000000)
- secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ", task.buffer1)
- secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ", task.buffer2)
- end
- end
- local function run_task(task)
- if task.gpu_index == 2 then
- secondary_gpu.setActiveBuffer(task.active_buffer)
- end
- term.bind(task.gpu)
- local start_time = computer.uptime()
- task.state = "running"
- local success, result = coroutine.resume(task.coroutine, table.unpack(task.args))
- task.run_time = task.run_time + (computer.uptime() - start_time)
- task.last_run = computer.uptime()
- term.bind(primary_gpu)
- if task.gpu_index == 2 and success then
- 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)
- task.active_buffer = task.active_buffer == task.buffer1 and task.buffer2 or task.buffer1
- end
- task.state = coroutine.status(task.coroutine) == "dead" and "finished" or "ready"
- if task.state == "finished" and task.gpu_index == 2 then
- secondary_program_running = false
- screensaver:start()
- end
- return success, result
- end
- local function create_task(func, priority, gpu_index, ...)
- local task = {
- coroutine = coroutine.create(func),
- gpu = gpu_index == 2 and secondary_gpu or gpus[gpu_index],
- args = {...},
- start_time = computer.uptime(),
- run_time = 0,
- priority = priority or 1,
- last_run = 0,
- state = "ready",
- gpu_index = gpu_index
- }
- setup_secondary_buffers(task)
- tasks[#tasks + 1] = task
- return task
- end
- local function cmd_cd(args)
- if #args == 0 then
- current_dir = "/"
- else
- local new_dir = shell.resolve(args[1])
- if filesystem.isDirectory(new_dir) then
- current_dir = new_dir
- else
- print("Directory not found: " .. args[1])
- end
- end
- end
- local function cmd_ls(args)
- local path = args[1] and shell.resolve(args[1]) or current_dir
- if filesystem.isDirectory(path) then
- for file in filesystem.list(path) do
- local full_path = filesystem.concat(path, file)
- if filesystem.isDirectory(full_path) then
- print("\27[34m" .. file .. "/\27[0m")
- else
- print(file)
- end
- end
- else
- print("Not a directory: " .. path)
- end
- end
- local function cmd_run(args)
- if #args < 1 then
- print("Usage: run <program> [gpu_index] [priority] [args...]")
- else
- local program_path = shell.resolve(args[1])
- local gpu_index = tonumber(args[2]) or 1
- local priority = tonumber(args[3]) or 1
- if filesystem.exists(program_path) then
- if gpu_index == 2 then
- secondary_program_running = true
- screensaver:stop()
- secondary_gpu.setBackground(0x000000)
- secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ")
- end
- create_task(function(...)
- local program = assert(loadfile(program_path), "Failed to load program")
- program(...)
- if gpu_index == 2 then
- secondary_program_running = false
- screensaver:start()
- end
- end, priority, gpu_index, table.unpack(args, 4))
- else
- print("Program not found: " .. args[1])
- end
- end
- end
- local function cmd_kill(args)
- if #args < 1 then
- print("Usage: kill <task_id>")
- else
- local task_id = tonumber(args[1])
- if task_id and tasks[task_id] then
- if tasks[task_id].gpu_index == 2 then
- secondary_program_running = false
- screensaver:start()
- end
- tasks[task_id].state = "finished"
- print("Task " .. task_id .. " killed")
- else
- print("Invalid task ID")
- end
- end
- end
- local function cmd_neofetch()
- local info = {
- OS = OS_NAME .. " v" .. VERSION,
- Host = computer.address(),
- Uptime = string.format("%.2f hours", computer.uptime() / 3600),
- RAM = string.format("%.2f MB / %.2f MB", computer.freeMemory() / 1024 / 1024, computer.totalMemory() / 1024 / 1024),
- GPUs = tostring(#gpus),
- Screens = tostring(#screens),
- Primary = string.format("%dx%d", PRIMARY_WIDTH, PRIMARY_HEIGHT),
- Secondary = secondary_gpu ~= primary_gpu and string.format("%dx%d", SECONDARY_WIDTH, SECONDARY_HEIGHT) or "N/A"
- }
- local ascii_art = {
- " _ __ __ ____ ____ _____",
- " / | / /__ _ __/ /_/ __ \\/ __ \\/ ___/",
- " / |/ / _ \\| |/_/ __/ / / / / / /\\__ \\ ",
- " / /| / __/> </ /_/ /_/ / /_/ /___/ / ",
- "/_/ |_/\\___/_/|_|\\__/_____/\\____//____/ "
- }
- local max_length = 0
- for i = 1, #ascii_art do
- max_length = max(max_length, unicode.len(ascii_art[i]))
- end
- local info_keys = {}
- for k in pairs(info) do
- table.insert(info_keys, k)
- end
- table.sort(info_keys)
- for i = 1, #ascii_art do
- local info_key = info_keys[i]
- if info_key then
- print(string.format("\27[36m%-"..max_length.."s\27[0m %s: %s", ascii_art[i], info_key, info[info_key]))
- else
- print(string.format("\27[36m%-"..max_length.."s\27[0m", ascii_art[i]))
- end
- end
- print(string.format("\27[36m%-"..max_length.."s\27[0m %s", "", "NextDOS made by nonogamer9"))
- end
- local function cmd_wget(args)
- if #args < 2 then
- print("Usage: wget <url> <filename>")
- return
- end
- local url = args[1]
- local filename = args[2]
- print("Downloading " .. url .. " to " .. filename)
- local result, response = pcall(function()
- local request, requestReason = internet.request(url)
- if not request then
- error("HTTP request failed: " .. (requestReason or "unknown error"))
- end
- local result = ""
- local data = request.read(1024)
- while data do
- result = result .. data
- data = request.read(1024)
- end
- request.close()
- return result
- end)
- if result then
- local file, fileReason = io.open(filename, "wb")
- if not file then
- print("Failed to open file for writing: " .. (fileReason or "unknown error"))
- return
- end
- file:write(response)
- file:close()
- print("Download complete: " .. filename)
- else
- print("Download failed: " .. tostring(response))
- end
- end
- local function cmd_edit(args)
- if #args < 1 then
- print("Usage: edit <filename>")
- return
- end
- local filename = shell.resolve(args[1])
- local content = ""
- if filesystem.exists(filename) then
- local file = io.open(filename, "r")
- content = file:read("*a")
- file:close()
- end
- local lines = {}
- for line in content:gmatch("[^\r\n]+") do
- table.insert(lines, line)
- end
- local cursor_x, cursor_y = 1, 1
- local scroll_y = 0
- local function redraw()
- term.clear()
- for i = 1, PRIMARY_HEIGHT - 1 do
- local line = lines[i + scroll_y] or ""
- term.setCursor(1, i)
- term.write(line)
- end
- term.setCursor(1, PRIMARY_HEIGHT)
- term.write("ESC to save and exit, Ctrl+C to exit without saving")
- term.setCursor(cursor_x, cursor_y - scroll_y)
- end
- while true do
- redraw()
- local event, _, char, code = event.pull()
- if event == "key_down" then
- if code == 28 then
- table.insert(lines, cursor_y, "")
- cursor_y = cursor_y + 1
- cursor_x = 1
- elseif code == 14 then
- if cursor_x > 1 then
- lines[cursor_y] = lines[cursor_y]:sub(1, cursor_x - 2) .. lines[cursor_y]:sub(cursor_x)
- cursor_x = cursor_x - 1
- elseif cursor_y > 1 then
- local current_line = lines[cursor_y]
- table.remove(lines, cursor_y)
- cursor_y = cursor_y - 1
- cursor_x = #lines[cursor_y] + 1
- lines[cursor_y] = lines[cursor_y] .. current_line
- end
- elseif code == 203 then
- if cursor_x > 1 then
- cursor_x = cursor_x - 1
- elseif cursor_y > 1 then
- cursor_y = cursor_y - 1
- cursor_x = #lines[cursor_y] + 1
- end
- elseif code == 205 then
- if cursor_x <= #lines[cursor_y] then
- cursor_x = cursor_x + 1
- elseif cursor_y < #lines then
- cursor_y = cursor_y + 1
- cursor_x = 1
- end
- elseif code == 200 then
- if cursor_y > 1 then
- cursor_y = cursor_y - 1
- cursor_x = math.min(cursor_x, #lines[cursor_y] + 1)
- end
- elseif code == 208 then
- if cursor_y < #lines then
- cursor_y = cursor_y + 1
- cursor_x = math.min(cursor_x, #lines[cursor_y] + 1)
- end
- elseif code == 1 then
- local file = io.open(filename, "w")
- file:write(table.concat(lines, "\n"))
- file:close()
- break
- elseif char == 3 then
- break
- elseif char >= 32 and char <= 126 then
- local line = lines[cursor_y]
- lines[cursor_y] = line:sub(1, cursor_x - 1) .. unicode.char(char) .. line:sub(cursor_x)
- cursor_x = cursor_x + 1
- end
- end
- if cursor_y - scroll_y > PRIMARY_HEIGHT - 1 then
- scroll_y = cursor_y - (PRIMARY_HEIGHT - 1)
- elseif cursor_y - scroll_y < 1 then
- scroll_y = cursor_y - 1
- end
- end
- end
- local function cmd_ping(args)
- if #args < 1 then
- print("Usage: ping <hostname>")
- return
- end
- local hostname = args[1]
- print("Pinging " .. hostname .. "...")
- for i = 1, 4 do
- local start_time = computer.uptime()
- local success, response = pcall(function()
- return internet.request("http://" .. hostname)
- end)
- local end_time = computer.uptime()
- if success then
- print(string.format("Reply from %s: time=%.2fms", hostname, (end_time - start_time) * 1000))
- else
- print("Request timed out.")
- end
- os.sleep(1)
- end
- end
- local function cmd_copy(args)
- if #args < 2 then
- print("Usage: copy <source> <destination>")
- return
- end
- local source = shell.resolve(args[1])
- local destination = shell.resolve(args[2])
- if not filesystem.exists(source) then
- print("Source file not found: " .. source)
- return
- end
- local sourceHandle = io.open(source, "rb")
- if not sourceHandle then
- print("Failed to open source file: " .. source)
- return
- end
- local destHandle = io.open(destination, "wb")
- if not destHandle then
- sourceHandle:close()
- print("Failed to create destination file: " .. destination)
- return
- end
- local data = sourceHandle:read("*a")
- destHandle:write(data)
- sourceHandle:close()
- destHandle:close()
- print("File copied successfully")
- end
- local function cmd_mkdir(args)
- if #args < 1 then
- print("Usage: mkdir <directory>")
- return
- end
- local path = shell.resolve(args[1])
- if filesystem.exists(path) then
- print("Path already exists: " .. path)
- return
- end
- local success, reason = filesystem.makeDirectory(path)
- if success then
- print("Directory created: " .. path)
- else
- print("Failed to create directory: " .. reason)
- end
- end
- local commands = {
- cd = cmd_cd,
- ls = cmd_ls,
- dir = cmd_ls,
- run = cmd_run,
- kill = cmd_kill,
- neofetch = cmd_neofetch,
- wget = cmd_wget,
- edit = cmd_edit,
- ping = cmd_ping,
- copy = cmd_copy,
- mkdir = cmd_mkdir,
- clear = function() term.clear() end,
- reboot = function() computer.shutdown(true) end,
- shutdown = function() computer.shutdown() end,
- gpus = function()
- for i, gpu in ipairs(gpus) do
- local width, height = gpu.getResolution()
- print(string.format("GPU %d: %dx%d, %d-bit color", i, width, height, gpu.getDepth()))
- end
- end,
- tasks = function()
- print("Running tasks:")
- for i, task in ipairs(tasks) do
- print(string.format("Task %d: Priority %d, Runtime %.2fs, State: %s, GPU: %d", i, task.priority, task.run_time, task.state, task.gpu_index))
- end
- end,
- mem = function()
- local free, total = computer.freeMemory(), computer.totalMemory()
- print(string.format("Memory: %.2f MB / %.2f MB (%.2f%% used)", free / 1024 / 1024, total / 1024 / 1024, (1 - free / total) * 100))
- end,
- ps = function()
- for i, task in ipairs(tasks) do
- print(string.format("PID %d: State: %s, GPU: %d, Priority: %d", i, task.state, task.gpu_index, task.priority))
- end
- end,
- del = function(args)
- if #args < 1 then
- print("Usage: del <file>")
- else
- local file_path = shell.resolve(args[1])
- if filesystem.exists(file_path) then
- if filesystem.remove(file_path) then
- print("File deleted: " .. file_path)
- else
- print("Failed to delete file: " .. file_path)
- end
- else
- print("File not found: " .. file_path)
- end
- end
- end,
- help = function()
- local help_cmds = {
- {"cd <dir>", "Change directory"},
- {"ls/dir", "List files"},
- {"run <program> [gpu_index] [priority] [args...]", "Run a program"},
- {"kill <task_id>", "Kill a task"},
- {"neofetch", "Display system info"},
- {"wget <url> <filename>", "Download file"},
- {"edit <filename>", "Edit a file"},
- {"ping <hostname>", "Ping a host"},
- {"copy <source> <destination>", "Copy a file"},
- {"mkdir <directory>", "Create a directory"},
- {"gpus", "List GPUs"},
- {"tasks", "List running tasks"},
- {"clear", "Clear the screen"},
- {"reboot", "Reboot the system"},
- {"shutdown", "Shutdown the system"},
- {"mem", "Display memory usage"},
- {"ps", "List all processes"},
- {"del <file>", "Delete a file"}
- }
- print(string.format("%s v%s Help", OS_NAME, VERSION))
- for _, cmd in ipairs(help_cmds) do print(string.format(" %-40s - %s", cmd[1], cmd[2])) end
- end
- }
- local function execute_command(input)
- local args = {}
- for arg in input:gmatch("%S+") do args[#args + 1] = arg end
- local cmd = table.remove(args, 1)
- local cmd_func = commands[cmd]
- if cmd_func then
- return cmd_func(args) ~= false
- else
- print("Unknown command: " .. cmd)
- return true
- end
- end
- local function display_prompt()
- term.write(string.format("\27[32m%s \27[34m%s\27[0m> ", OS_NAME, current_dir))
- end
- local function reset_secondary_screen()
- if secondary_gpu ~= primary_gpu then
- secondary_gpu.setBackground(0x000000)
- secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ")
- secondary_program_running = false
- screensaver:start()
- end
- end
- local function main_loop()
- screensaver:start()
- local last_yield = computer.uptime()
- local prompt_displayed = false
- while true do
- if not prompt_displayed then
- display_prompt()
- prompt_displayed = true
- end
- local active_tasks = {}
- for i = 1, #tasks do
- local task = tasks[i]
- if task.state ~= "finished" then
- local success, result = run_task(task)
- if not success then
- push_signal("task_error", tostring(result))
- task.state = "finished"
- else
- active_tasks[#active_tasks + 1] = task
- end
- end
- end
- tasks = active_tasks
- if secondary_program_running then
- screensaver:stop()
- elseif #tasks == 0 and not secondary_program_running then
- screensaver:start()
- end
- local event_data = {pull_signal(0)}
- if event_data[1] then
- if event_data[1] == "key_down" then
- local input = term.read(nil, command_history)
- if input then
- command_history[#command_history + 1] = input
- if #command_history > 50 then table.remove(command_history, 1) end
- history_index = #command_history + 1
- execute_command(input)
- prompt_displayed = false
- end
- elseif event_data[1] == "task_error" then
- print("Task error: " .. event_data[2])
- prompt_displayed = false
- end
- end
- if computer.uptime() - last_yield > 0.05 then
- os.sleep(0)
- last_yield = computer.uptime()
- end
- end
- end
- local function error_handler(err)
- io.stderr:write("Error: " .. tostring(err) .. "\n")
- io.stderr:write(debug.traceback(nil, 2) .. "\n")
- return err
- end
- local function init_system()
- primary_gpu.setResolution(PRIMARY_WIDTH, PRIMARY_HEIGHT)
- if secondary_gpu ~= primary_gpu then
- secondary_gpu.setResolution(SECONDARY_WIDTH, SECONDARY_HEIGHT)
- secondary_gpu.fill(1, 1, SECONDARY_WIDTH, SECONDARY_HEIGHT, " ")
- secondary_gpu.set(1, 1, "Secondary Display - No program running")
- end
- end
- local function start_system()
- init_system()
- term.clear()
- print(string.format("%s v%s - Type 'help' for commands", OS_NAME, VERSION))
- local success, err = xpcall(main_loop, error_handler)
- if not success then
- io.stderr:write("NextDOS crashed: " .. tostring(err) .. "\n")
- io.stderr:write("Rebooting in 5 seconds...\n")
- os.sleep(5)
- computer.shutdown(true)
- end
- end
- start_system()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement