diff --git a/src/apis/component.lua b/src/apis/component.lua index 8ebc8ee..2e6b070 100644 --- a/src/apis/component.lua +++ b/src/apis/component.lua @@ -27,18 +27,41 @@ function component.connect(...) math.randomseed(info[2]) address = gen_uuid() end + if proxylist[address] ~= nil then + return nil, "component already at address" + end info[2] = address local fn, err = elsa.filesystem.load("component/" .. info[1] .. ".lua") if not fn then - error(err,0) + return nil, err end local proxy, cec, doc = fn(table.unpack(info,2)) + if not proxy then + return nil, cec or "no component added" + end proxy.address = address proxy.type = proxy.type or info[1] proxylist[address] = proxy emuicc[address] = cec doclist[address] = doc slotlist[address] = info[3] + if boot_machine then + table.insert(machine.signals,{"component_added",address,proxy.type}) + end + return true +end +function component.disconnect(address) + checkArg(1,address,"string") + if proxylist[address] == nil then + return nil, "no component at address" + end + local thetype = proxylist[address].type + proxylist[address] = nil + emuicc[address] = nil + doclist[address] = nil + slotlist[address] = nil + table.insert(machine.signals,{"component_removed",address,thetype}) + return true end function component.exists(address) checkArg(1,address,"string") diff --git a/src/component/eeprom.lua b/src/component/eeprom.lua index 80cc4ab..47a684b 100644 --- a/src/component/eeprom.lua +++ b/src/component/eeprom.lua @@ -1,4 +1,8 @@ -local address, slot, filename = ... +local address, _, filename = ... +compCheckArg(1,filename,"string") +if not elsa.filesystem.exists(filename) then + error("no such file",3) +end local crc32 = require("support.crc32") diff --git a/src/component/filesystem.lua b/src/component/filesystem.lua index 38c0d81..f0e9693 100644 --- a/src/component/filesystem.lua +++ b/src/component/filesystem.lua @@ -1,4 +1,6 @@ -local address, slot, directory, readonly = ... +local address, _, directory, readonly = ... +compCheckArg(1,directory,"string","nil") +compCheckArg(2,readonly,"boolean") if directory == nil then directory = elsa.filesystem.getSaveDirectory() .. "/" .. address diff --git a/src/component/gpu.lua b/src/component/gpu.lua index 325d2ed..00ce2cc 100644 --- a/src/component/gpu.lua +++ b/src/component/gpu.lua @@ -1,4 +1,7 @@ -local address, slot, maxwidth, maxheight, maxtier = ... +local address, _, maxwidth, maxheight, maxtier = ... +compCheckArg(1,maxwidth,"number") +compCheckArg(2,maxheight,"number") +compCheckArg(3,maxtier,"number") local lua_utf8 = require("utf8") diff --git a/src/component/internet.lua b/src/component/internet.lua index b60a7b7..07eb9c7 100644 --- a/src/component/internet.lua +++ b/src/component/internet.lua @@ -3,7 +3,7 @@ local okay, socket = pcall(require, "socket") if not okay then cprint("Cannot use internet component: " .. socket) - return + return nil, "missing socket library" end require("support.http_patch") local url = require("socket.url") @@ -145,9 +145,18 @@ function obj.request(url, postData) -- Starts an HTTP request. If this returns t end end local procotol, code, message + local bad = false if status then protocol, code, message = status:match("(.-) (.-) (.*)") code = tonumber(code) + if code >= 400 then + bad = true + if code == 404 or code == 410 then + page = url + else + page = "Server returned HTTP response code: " .. code .. " for URL: " .. url + end + end end local closed = false local fakesocket = { @@ -160,6 +169,8 @@ function obj.request(url, postData) -- Starts an HTTP request. If this returns t return nil, "Connection refused" elseif page == "" then return nil + elseif bad then + return nil, page else -- Return up to 8192 bytes local data = page:sub(1,8192) @@ -169,7 +180,7 @@ function obj.request(url, postData) -- Starts an HTTP request. If this returns t end, response = function() cprint("(socket) response") - if headers == nil then + if headers == nil or bad then return nil end return code, message, headers @@ -185,6 +196,8 @@ function obj.request(url, postData) -- Starts an HTTP request. If this returns t return nil, "connection lost" elseif headers == nil then return nil, "Connection refused" + elseif bad then + return nil, page end return true end diff --git a/src/component/ocemu.lua b/src/component/ocemu.lua new file mode 100644 index 0000000..68c6eaf --- /dev/null +++ b/src/component/ocemu.lua @@ -0,0 +1,31 @@ +-- ocemu component + +component.connect("filesystem",gen_uuid(),nil,"customlua/ocemu",true) + +local obj = {} + +function obj.connect(kind, address, slot, ...) + cprint("screen.isTouchModeInverted") + compCheckArg(1,kind,"string") + compCheckArg(2,address,"string","number","nil") + compCheckArg(3,slot,"number","nil") + if address == nil then + if elsa.SDL then + math.randomseed(elsa.SDL.getTicks()) + else + math.randomseed(os.clock()*1000000) + end + address=gen_uuid() + end + return component.connect(kind, address, slot, ...) +end +function obj.disconnect(address) + checkArg(1,address,"string") + return component.disconnect(address) +end + +local cec = {} + +local doc = {} + +return obj,cec,doc diff --git a/src/component/screen_sdl2.lua b/src/component/screen_sdl2.lua index a51e075..ac7c06c 100644 --- a/src/component/screen_sdl2.lua +++ b/src/component/screen_sdl2.lua @@ -1,4 +1,7 @@ -local address, slot, maxwidth, maxheight, maxtier = ... +local address, _, maxwidth, maxheight, maxtier = ... +compCheckArg(1,maxwidth,"number") +compCheckArg(2,maxheight,"number") +compCheckArg(3,maxtier,"number") local ffi = require("ffi") local utf8 = require("utf8") @@ -106,8 +109,6 @@ SDL.renderFillRect(renderer, ffi.C.NULL) SDL.setRenderTarget(renderer, ffi.C.NULL); function elsa.draw() - -- TODO: This causes issues in linux, test if it's necessary in windows or not - SDL.showWindow(window) SDL.renderCopy(renderer, texture, ffi.C.NULL, ffi.C.NULL) SDL.renderPresent(renderer) end @@ -359,7 +360,6 @@ function cec.copy(x1, y1, w, h, tx, ty) -- Copies a portion of the screen from t end for y = math.max(math.min(y1+ty, height), 1), math.max(math.min(y2+ty, height), 1) do for x = math.max(math.min(x1+tx, width), 1), math.max(math.min(x2+tx, width), 1) do - local renderchange = screen.txt[y][x] ~= copy.txt[y-y1-ty][x-x1-tx] or screen.bg[y][x] ~= copy.bg[y-y1-ty][x-x1-tx] or (screen.txt[y][x] ~= " " and screen.fg[y][x] ~= copy.fg[y-y1-ty][x-x1-tx]) screen.txt[y][x] = copy.txt[y-y1-ty][x-x1-tx] screen.fg[y][x] = copy.fg[y-y1-ty][x-x1-tx] screen.bg[y][x] = copy.bg[y-y1-ty][x-x1-tx] diff --git a/src/customlua/ocemu/.autorun.lua b/src/customlua/ocemu/.autorun.lua new file mode 100644 index 0000000..8cbee59 --- /dev/null +++ b/src/customlua/ocemu/.autorun.lua @@ -0,0 +1,29 @@ +local event = require("event") +local fs = require("filesystem") +local process = require("process") + +local proxy = ... + +-- Install symlinks if they don't already exist. +local links = {} +local fsroot = fs.path(process.running()) +local function inject(path) + for file in fs.list(fs.concat(fsroot, path)) do + local source = fs.concat(fsroot, path, file) + local target = fs.concat(path, file) + if fs.link(source, target) then + table.insert(links, target) + end + end +end +inject("bin") + +-- Delete symlinks on removal. +event.listen("component_removed", function(_, address) + if address == proxy.address then + for _, link in ipairs(links) do + fs.remove(link) + end + return false -- remove listener + end +end) diff --git a/src/customlua/ocemu/bin/cfgemu.lua b/src/customlua/ocemu/bin/cfgemu.lua new file mode 100644 index 0000000..34ea8d1 --- /dev/null +++ b/src/customlua/ocemu/bin/cfgemu.lua @@ -0,0 +1,169 @@ +local component = require("component") +local kbd = require("keyboard") +local event = require("event") +local term = require("term") + +if not component.isAvailable("ocemu") then + io.stderr:write("This program requires OCEmu to run.") + return +end + +local ocemu = component.ocemu +local gpu = component.gpu +local keys = kbd.keys + +local gpuW,gpuH = gpu.getResolution() + +gpu.setForeground(0xFFFFFF) +gpu.setBackground(0x000000) + +local function setTitle(title) + gpu.set((gpuW-#title)/2,1,title) +end + +local function setStatus(status) + gpu.fill(1,gpuH,gpuW,1," ") + gpu.set((gpuW-#status)/2,gpuH,status) +end + +local function componentConfig() + setTitle("Component Configuration Utility") + local list = {} + for address, kind in component.list() do + list[#list+1] = {address, kind} + end + table.sort(list, function(a, b) return a[1] < b[1] end) + local listX = 1 + + local function drawList() + gpu.fill(1,3,gpuW,gpuH-3," ") + for i = 1,#list do + gpu.set(4,i+2,string.format("%s - %s",list[i][1],list[i][2])) + end + gpu.set(2,listX+2,"▶") + end + local function prompt(msg) + gpu.fill(1,gpuH-3,gpuW,1," ") + term.setCursor(1,gpuH-3) + io.stdout:write(msg) + return term.read(nil, false):gsub("[\r\n]","") + end + drawList() + + while true do + local evnt = table.pack(event.pull()) + if evnt[1] == "key_down" then + if evnt[4] == keys.up and listX > 1 then + gpu.set(2,listX+2," ") + listX = listX - 1 + gpu.set(2,listX+2,"▶") + elseif evnt[4] == keys.down and listX < #list then + gpu.set(2,listX+2," ") + listX = listX + 1 + gpu.set(2,listX+2,"▶") + elseif evnt[4] == keys.delete then + local ok, err = ocemu.disconnect(list[listX][1]) + if ok then + table.remove(list, listX) + listX = math.min(listX,#list) + drawList() + else + setStatus(err or "unknown error") + end + elseif evnt[4] == keys.insert then + setStatus("") + local kind = prompt("Component type: ") + local address = prompt("Component address: ") + local slot = prompt("Component slot: ") + local args = prompt("Component arguments: ") + + local bad = false + if kind == "" or kind == nil then + bad = true + setStatus("Invalid type") + end + if address == "" or address == nil then + address = nil + elseif tonumber(address) ~= nil then + address = tonumber(address) + elseif address ~= address:gsub("[^%x-]","") or address:match("........%-....%-4...%-[89abAB]...%-............") == nil then + bad = true + setStatus("Invalid address") + end + if slot == "" or slot == nil then + slot = nil + elseif tonumber(slot) ~= nil then + slot = tonumber(slot) + else + bad = true + setStatus("Invalid slot") + end + if not bad then + local fn, err = load("return " .. args,"=arguments","t",{}) + if not fn then + setStatus(err) + else + local args = table.pack(pcall(fn)) + if not args[1] then + setStatus(args[2]) + else + local rok, ok, err = pcall(ocemu.connect, kind, address, slot, table.unpack(args, 2)) + if not rok then + if ok:match("^.-:.-: .*") then + ok = ok:match("^.-:.-: (.*)") + end + setStatus(ok) + elseif not ok then + setStatus(err) + else + list = {} + for address, kind in component.list() do + list[#list+1] = {address, kind} + end + table.sort(list, function(a, b) return a[1] < b[1] end) + end + end + end + end + drawList() + elseif evnt[3] == string.byte("q") then + return + end + end + end +end + +local menu = { + {"Configure Components",componentConfig}, + {"Exit",os.exit} +} +local menuX = 1 + +local function drawMenu() + gpu.fill(1,1,gpuW,gpuH," ") + setTitle("OCEmu Setup Utility") + for i = 1,#menu do + gpu.set(4,i+2,menu[i][1]) + end + gpu.set(2,menuX+2,"▶") +end +drawMenu() + +while true do + local evnt = table.pack(event.pull()) + if evnt[1] == "key_down" then + if evnt[4] == keys.up and menuX > 1 then + gpu.set(2,menuX+2," ") + menuX = menuX - 1 + gpu.set(2,menuX+2,"▶") + elseif evnt[4] == keys.down and menuX < #menu then + gpu.set(2,menuX+2," ") + menuX = menuX + 1 + gpu.set(2,menuX+2,"▶") + elseif evnt[4] == keys.enter then + gpu.fill(1,1,gpuW,gpuH," ") + menu[menuX][2]() + drawMenu() + end + end +end diff --git a/src/main.lua b/src/main.lua index d50339a..dbc588d 100644 --- a/src/main.lua +++ b/src/main.lua @@ -30,6 +30,7 @@ conf = { {"filesystem",nil,5,nil,false}, {"internet"}, {"computer"}, + {"ocemu"}, } } if elsa.SDL then