mirror of
https://github.com/Ale32bit/Capy64.git
synced 2025-01-18 18:46:43 +00:00
Rewrite everything
This commit is contained in:
parent
bcb358ed9d
commit
8b5fa96a74
38 changed files with 469 additions and 4154 deletions
|
@ -1,17 +0,0 @@
|
||||||
local args = {...}
|
|
||||||
local fs = require("fs")
|
|
||||||
|
|
||||||
local dir = args[1]
|
|
||||||
|
|
||||||
if not dir then
|
|
||||||
dir = shell.homePath
|
|
||||||
end
|
|
||||||
|
|
||||||
dir = shell.resolve(dir)
|
|
||||||
|
|
||||||
if not fs.isDir(dir) then
|
|
||||||
error("No such directory: " .. dir, 0)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
shell.setDir(dir)
|
|
|
@ -1,5 +0,0 @@
|
||||||
local term = require("term")
|
|
||||||
local colors = require("colors")
|
|
||||||
term.setBackground(colors.black)
|
|
||||||
term.clear()
|
|
||||||
term.setPos(1, 1)
|
|
|
@ -1 +0,0 @@
|
||||||
shell.exit()
|
|
|
@ -1,94 +0,0 @@
|
||||||
-- Mandelbrot in Capy64
|
|
||||||
|
|
||||||
local gpu = require("gpu")
|
|
||||||
local timer = require("timer")
|
|
||||||
local event = require("event")
|
|
||||||
local term = require("term")
|
|
||||||
|
|
||||||
-- lower = closer = slower
|
|
||||||
local scale = 4
|
|
||||||
|
|
||||||
-- higher = more detailed = slower
|
|
||||||
local iterations = 100
|
|
||||||
|
|
||||||
local pscale = scale
|
|
||||||
local w, h = gpu.getSize()
|
|
||||||
local px = pscale / w
|
|
||||||
local colorUnit = math.floor(0xffffff / iterations)
|
|
||||||
-- todo: make it interactive
|
|
||||||
local dx, dy = 0, 0
|
|
||||||
local cx, cy = math.floor(w / 2), math.floor(h / 2)
|
|
||||||
|
|
||||||
-- z = z^2 + c
|
|
||||||
local function mandelbrot(zr, zi, cr, ci)
|
|
||||||
return zr ^ 2 - zi ^ 2 + cr,
|
|
||||||
2 * zr * zi + ci
|
|
||||||
end
|
|
||||||
|
|
||||||
local function iter(cr, ci)
|
|
||||||
local zr, zi = 0, 0
|
|
||||||
for i = 1, iterations do
|
|
||||||
zr, zi = mandelbrot(zr, zi, cr, ci)
|
|
||||||
if math.abs(zr) >= (pscale >= 2 and pscale or 2) or math.abs(zi) >= (pscale >= 2 and pscale or 2) then
|
|
||||||
return false, colorUnit, i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return true, 0, iterations
|
|
||||||
end
|
|
||||||
|
|
||||||
local function draw()
|
|
||||||
local buffer <close> = gpu.newBuffer()
|
|
||||||
|
|
||||||
for y = 0, h - 1 do
|
|
||||||
for x = 0, w - 1 do
|
|
||||||
local _, _, i = iter((x - cx + dx * pscale) * px, (y - cy + dy * pscale) * px)
|
|
||||||
buffer[y * w + x] = colorUnit * (iterations - i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
gpu.setBuffer(buffer)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- no idea why it's needed
|
|
||||||
timer.sleep(1)
|
|
||||||
|
|
||||||
draw()
|
|
||||||
|
|
||||||
local tw, th = term.getSize()
|
|
||||||
|
|
||||||
while true do
|
|
||||||
term.setPos(1, th)
|
|
||||||
term.setBackground(0)
|
|
||||||
term.setForeground(0xffffff)
|
|
||||||
term.write("X: " .. dx .. "; Y: " .. dy .. "; S: " .. pscale .. "; " .. px .. "!")
|
|
||||||
local ev = { event.pull("key_down") }
|
|
||||||
if ev[1] == "key_down" then
|
|
||||||
local key = ev[3]
|
|
||||||
if key == "up" then
|
|
||||||
dy = dy - 10 / pscale
|
|
||||||
elseif key == "down" then
|
|
||||||
dy = dy + 10 / pscale
|
|
||||||
elseif key == "right" then
|
|
||||||
dx = dx + 10 / pscale
|
|
||||||
elseif key == "left" then
|
|
||||||
dx = dx - 10 / pscale
|
|
||||||
elseif key == "enter" then
|
|
||||||
draw()
|
|
||||||
elseif key == "page_down" then
|
|
||||||
pscale = pscale * 1.25
|
|
||||||
dx = dx * pscale
|
|
||||||
dy = dy * pscale
|
|
||||||
elseif key == "page_up" then
|
|
||||||
pscale = pscale / 1.25
|
|
||||||
dx = dx / pscale
|
|
||||||
dy = dy / pscale
|
|
||||||
elseif key == "r" then
|
|
||||||
pscale = scale
|
|
||||||
dx = 0
|
|
||||||
dy = 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
px = pscale / w
|
|
||||||
end
|
|
|
@ -1,73 +0,0 @@
|
||||||
local gpu = require("gpu")
|
|
||||||
local timer = require("timer")
|
|
||||||
local event = require("event")
|
|
||||||
local colors = require("colors")
|
|
||||||
local parallel = require("parallel")
|
|
||||||
|
|
||||||
local melts = 2 ^ 12
|
|
||||||
|
|
||||||
local function contains(arr, val)
|
|
||||||
for k, v in ipairs(arr) do
|
|
||||||
if v == val then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function melt()
|
|
||||||
local w, h = gpu.getSize()
|
|
||||||
local x, y = 0, 0
|
|
||||||
|
|
||||||
while true do
|
|
||||||
local buffer <close> = gpu.getBuffer()
|
|
||||||
for i = 1, melts do
|
|
||||||
local nx = math.random(x, w)
|
|
||||||
local ny = math.random(y, h)
|
|
||||||
|
|
||||||
local c = buffer[ny * w + nx]
|
|
||||||
buffer[(ny + 1) * w + nx] = c
|
|
||||||
end
|
|
||||||
gpu.setBuffer(buffer)
|
|
||||||
|
|
||||||
timer.sleep(10)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function draw()
|
|
||||||
local ox, oy
|
|
||||||
while true do
|
|
||||||
local ev, b, x, y = event.pull("mouse_move", "mouse_down")
|
|
||||||
|
|
||||||
if ev == "mouse_down" then
|
|
||||||
if b == 1 then
|
|
||||||
ox = x
|
|
||||||
oy = y
|
|
||||||
end
|
|
||||||
elseif ev == "mouse_move" then
|
|
||||||
if contains(b, 1) then
|
|
||||||
gpu.plot(x, y, colors.red)
|
|
||||||
gpu.drawLine(x, y, ox, oy, colors.red)
|
|
||||||
ox, oy = x, y
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function random()
|
|
||||||
local w, h = gpu.getSize()
|
|
||||||
while true do
|
|
||||||
for i = 1, 24 do
|
|
||||||
gpu.drawString(
|
|
||||||
math.random(-7, w),
|
|
||||||
math.random(-13, h),
|
|
||||||
math.random(0, 0xffffff),
|
|
||||||
string.char(math.random(32, 127))
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
timer.sleep(100)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
parallel.waitForAny(draw, melt, random)
|
|
|
@ -1,17 +0,0 @@
|
||||||
local timer = require("timer")
|
|
||||||
local colors = require("colors")
|
|
||||||
local term = require("term")
|
|
||||||
|
|
||||||
local function slowPrint(text, delay)
|
|
||||||
for i = 1, #text do
|
|
||||||
local ch = text:sub(i, i)
|
|
||||||
io.write(ch)
|
|
||||||
timer.sleep(delay)
|
|
||||||
end
|
|
||||||
print()
|
|
||||||
end
|
|
||||||
|
|
||||||
local color = colors[math.random(1, #colors)]
|
|
||||||
|
|
||||||
term.setForeground(color)
|
|
||||||
slowPrint("Hello, World!", 50)
|
|
|
@ -1,25 +0,0 @@
|
||||||
local args = { ... }
|
|
||||||
local fs = require("fs")
|
|
||||||
local term = require("term")
|
|
||||||
local colors = require("colors")
|
|
||||||
local dir = shell.getDir()
|
|
||||||
|
|
||||||
if args[1] then
|
|
||||||
dir = shell.resolve(args[1])
|
|
||||||
end
|
|
||||||
|
|
||||||
if not fs.isDir(dir) then
|
|
||||||
error("No such directory: " .. dir, 0)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local files = fs.list(dir)
|
|
||||||
for k, v in ipairs(files) do
|
|
||||||
if fs.isDir(fs.combine(dir, v)) then
|
|
||||||
term.setForeground(colors.lightBlue)
|
|
||||||
print(v .. "/")
|
|
||||||
else
|
|
||||||
term.setForeground(colors.white)
|
|
||||||
print(v)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,75 +0,0 @@
|
||||||
local term = require("term")
|
|
||||||
local io = require("io")
|
|
||||||
local colors = require("colors")
|
|
||||||
local colours = colors
|
|
||||||
|
|
||||||
local tArgs = { ... }
|
|
||||||
if #tArgs > 0 then
|
|
||||||
print("This is an interactive Lua prompt.")
|
|
||||||
print("To run a lua program, just type its name.")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
--local pretty = require "cc.pretty"
|
|
||||||
|
|
||||||
local bRunning = true
|
|
||||||
local tCommandHistory = {}
|
|
||||||
local tEnv = {
|
|
||||||
["exit"] = setmetatable({}, {
|
|
||||||
__tostring = function() return "Call exit() to exit." end,
|
|
||||||
__call = function() bRunning = false end,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
setmetatable(tEnv, { __index = _ENV })
|
|
||||||
|
|
||||||
for k, v in pairs(package.loaded) do
|
|
||||||
tEnv[k] = v
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setForeground(colours.yellow)
|
|
||||||
print(_VERSION .. " interactive prompt")
|
|
||||||
print("Call exit() to exit.")
|
|
||||||
term.setForeground(colours.white)
|
|
||||||
|
|
||||||
while bRunning do
|
|
||||||
term.setForeground(colours.yellow)
|
|
||||||
io.write("> ")
|
|
||||||
term.setForeground(colours.white)
|
|
||||||
|
|
||||||
local s = io.read(nil, tCommandHistory)
|
|
||||||
if s:match("%S") and tCommandHistory[#tCommandHistory] ~= s then
|
|
||||||
table.insert(tCommandHistory, s)
|
|
||||||
end
|
|
||||||
|
|
||||||
local nForcePrint = 0
|
|
||||||
local func, e = load(s, "=lua", "t", tEnv)
|
|
||||||
local func2 = load("return " .. s, "=lua", "t", tEnv)
|
|
||||||
if not func then
|
|
||||||
if func2 then
|
|
||||||
func = func2
|
|
||||||
e = nil
|
|
||||||
nForcePrint = 1
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if func2 then
|
|
||||||
func = func2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if func then
|
|
||||||
local tResults = table.pack(pcall(func))
|
|
||||||
if tResults[1] then
|
|
||||||
local n = 1
|
|
||||||
while n < tResults.n or n <= nForcePrint do
|
|
||||||
local value = tResults[n + 1]
|
|
||||||
print(tostring(value))
|
|
||||||
n = n + 1
|
|
||||||
end
|
|
||||||
else
|
|
||||||
io.stderr.print(tResults[2])
|
|
||||||
end
|
|
||||||
else
|
|
||||||
io.stderr.print(e)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,14 +0,0 @@
|
||||||
local fs = require("fs")
|
|
||||||
local args = { ... }
|
|
||||||
|
|
||||||
if #args == 0 then
|
|
||||||
print("Usage: mkdir <directory>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local dir = shell.resolve(args[1])
|
|
||||||
if fs.exists(dir) then
|
|
||||||
error("Path already exists", 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
fs.makeDir(dir)
|
|
|
@ -1 +0,0 @@
|
||||||
print(shell.getDir())
|
|
|
@ -1,8 +0,0 @@
|
||||||
local timer = require("timer")
|
|
||||||
local machine = require("machine")
|
|
||||||
|
|
||||||
print("Goodbye!")
|
|
||||||
|
|
||||||
timer.sleep(1000)
|
|
||||||
|
|
||||||
machine.reboot()
|
|
|
@ -1,10 +0,0 @@
|
||||||
local fs = require("fs")
|
|
||||||
|
|
||||||
local args = { ... }
|
|
||||||
if #args == 0 then
|
|
||||||
print("Usage: rm <file>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local file = shell.resolve(args[1])
|
|
||||||
fs.delete(file, true)
|
|
|
@ -1,143 +0,0 @@
|
||||||
local term = require("term")
|
|
||||||
local colors = require("colors")
|
|
||||||
local fs = require("fs")
|
|
||||||
local machine = require("machine")
|
|
||||||
|
|
||||||
local exit = false
|
|
||||||
local shell = {}
|
|
||||||
|
|
||||||
shell.path = "./?;./?.lua;/bin/?.lua"
|
|
||||||
shell.homePath = "/home"
|
|
||||||
|
|
||||||
local currentDir = shell.homePath
|
|
||||||
|
|
||||||
local function buildEnvironment(path, args)
|
|
||||||
local arg = { table.unpack(args, 2) }
|
|
||||||
arg[0] = path
|
|
||||||
|
|
||||||
return setmetatable({
|
|
||||||
shell = shell,
|
|
||||||
arg = arg
|
|
||||||
}, { __index = _G })
|
|
||||||
end
|
|
||||||
|
|
||||||
local function tokenise(...)
|
|
||||||
local sLine = table.concat({ ... }, " ")
|
|
||||||
local tWords = {}
|
|
||||||
local bQuoted = false
|
|
||||||
for match in string.gmatch(sLine .. "\"", "(.-)\"") do
|
|
||||||
if bQuoted then
|
|
||||||
table.insert(tWords, match)
|
|
||||||
else
|
|
||||||
for m in string.gmatch(match, "[^ \t]+") do
|
|
||||||
table.insert(tWords, m)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
bQuoted = not bQuoted
|
|
||||||
end
|
|
||||||
return tWords
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.getDir()
|
|
||||||
return currentDir
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.setDir(path)
|
|
||||||
currentDir = path
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.resolve(path)
|
|
||||||
if path:sub(1, 1) == "/" then
|
|
||||||
return fs.combine("", path)
|
|
||||||
end
|
|
||||||
|
|
||||||
if path:sub(1, 1) == "~" then
|
|
||||||
return fs.combine(shell.homePath, path)
|
|
||||||
end
|
|
||||||
|
|
||||||
return fs.combine(currentDir, path)
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.resolveProgram(path)
|
|
||||||
if path:sub(1, 1) == "/" then
|
|
||||||
return shell.resolve(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
for seg in shell.path:gmatch("[^;]+") do
|
|
||||||
local resolved = shell.resolve(seg:gsub("%?", path))
|
|
||||||
if fs.exists(resolved) and not fs.isDir(resolved) then
|
|
||||||
return resolved
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.run(...)
|
|
||||||
local args = tokenise(...)
|
|
||||||
local command = args[1]
|
|
||||||
local path = shell.resolveProgram(command)
|
|
||||||
|
|
||||||
if not path then
|
|
||||||
io.stderr.print("Command not found: " .. command)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local env = buildEnvironment(command, args)
|
|
||||||
|
|
||||||
local func, err = loadfile(path, "t", env)
|
|
||||||
|
|
||||||
if not func then
|
|
||||||
io.stderr.print(err)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local ok, err = pcall(func, table.unpack(args, 2))
|
|
||||||
if not ok then
|
|
||||||
io.stderr.print(err)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.exit()
|
|
||||||
exit = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if not fs.exists(shell.homePath) then
|
|
||||||
fs.makeDir(shell.homePath)
|
|
||||||
end
|
|
||||||
|
|
||||||
local history = {}
|
|
||||||
local lastExecSuccess = true
|
|
||||||
while not exit do
|
|
||||||
machine.setRPC(os.version(), "On shell")
|
|
||||||
|
|
||||||
term.setBackground(colors.black)
|
|
||||||
term.setForeground(colors.white)
|
|
||||||
io.write(":")
|
|
||||||
term.setForeground(colors.lightBlue)
|
|
||||||
if currentDir == shell.homePath then
|
|
||||||
io.write("~")
|
|
||||||
else
|
|
||||||
io.write(currentDir)
|
|
||||||
end
|
|
||||||
|
|
||||||
if lastExecSuccess then
|
|
||||||
term.setForeground(colors.yellow)
|
|
||||||
else
|
|
||||||
term.setForeground(colors.red)
|
|
||||||
end
|
|
||||||
io.write("$ ")
|
|
||||||
|
|
||||||
term.setForeground(colors.white)
|
|
||||||
local line = io.read(nil, history)
|
|
||||||
|
|
||||||
if line:match("%S") and history[#history] ~= line then
|
|
||||||
table.insert(history, line)
|
|
||||||
end
|
|
||||||
|
|
||||||
if line:match("%S") then
|
|
||||||
machine.setRPC(os.version(), "Running: " .. line)
|
|
||||||
lastExecSuccess = shell.run(line)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
local timer = require("timer")
|
|
||||||
local machine = require("machine")
|
|
||||||
|
|
||||||
print("Goodbye!")
|
|
||||||
|
|
||||||
timer.sleep(1000)
|
|
||||||
|
|
||||||
machine.shutdown()
|
|
|
@ -1 +0,0 @@
|
||||||
print(string.format("%s @ %s - %s", os.version(), _HOST, _VERSION))
|
|
|
@ -1,34 +0,0 @@
|
||||||
local http = require("http")
|
|
||||||
local fs = require("fs")
|
|
||||||
|
|
||||||
local args = { ... }
|
|
||||||
|
|
||||||
if not http then
|
|
||||||
error("HTTP is not enabled", 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
if #args == 0 then
|
|
||||||
print("Usage: wget <url> [outputPath]")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local outputName = args[2] or fs.getName(args[1])
|
|
||||||
local outputPath = shell.resolve(outputName)
|
|
||||||
|
|
||||||
if not http.checkURL(args[1]) then
|
|
||||||
error("Invalid URL", 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
local response <close>, err = http.get(args[1], nil, {
|
|
||||||
binary = true,
|
|
||||||
})
|
|
||||||
if not response then
|
|
||||||
error(err, 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
local file <close> = fs.open(outputPath, "wb")
|
|
||||||
file:write(response:readAll())
|
|
||||||
file:close()
|
|
||||||
response:close()
|
|
||||||
|
|
||||||
print("File written to " .. outputPath)
|
|
|
@ -1,3 +0,0 @@
|
||||||
package.path = "/lib/?.lua;/lib/?/init.lua;" .. package.path
|
|
||||||
|
|
||||||
_G.io = require("io")
|
|
|
@ -1,15 +0,0 @@
|
||||||
function _G.print(...)
|
|
||||||
local args = { ... }
|
|
||||||
local size = #args
|
|
||||||
local lines = 0
|
|
||||||
for n, v in ipairs(args) do
|
|
||||||
local s = tostring(v)
|
|
||||||
if n < size then
|
|
||||||
s = s .. "\t"
|
|
||||||
end
|
|
||||||
lines = lines + io.write(s)
|
|
||||||
end
|
|
||||||
lines = lines + io.write("\n")
|
|
||||||
|
|
||||||
return lines
|
|
||||||
end
|
|
|
@ -1,90 +0,0 @@
|
||||||
local http = require("http")
|
|
||||||
local event = require("event")
|
|
||||||
local expect = require("expect").expect
|
|
||||||
|
|
||||||
|
|
||||||
function http.request(url, body, headers, options)
|
|
||||||
expect(1, url, "string")
|
|
||||||
expect(2, body, "string", "nil")
|
|
||||||
expect(3, headers, "table", "nil")
|
|
||||||
expect(4, options, "table", "nil")
|
|
||||||
|
|
||||||
if not http.checkURL(url) then
|
|
||||||
return nil, "Invalid URL"
|
|
||||||
end
|
|
||||||
|
|
||||||
local requestId = http.requestAsync(url, body, headers, options)
|
|
||||||
local ev, id, data, info
|
|
||||||
repeat
|
|
||||||
ev, id, data, info = event.pull("http_response", "http_failure")
|
|
||||||
until id == requestId
|
|
||||||
|
|
||||||
if ev == "http_failure" then
|
|
||||||
return nil, data
|
|
||||||
end
|
|
||||||
|
|
||||||
return data, info
|
|
||||||
end
|
|
||||||
|
|
||||||
function http.get(url, headers, options)
|
|
||||||
expect(1, url, "string")
|
|
||||||
expect(2, headers, "table", "nil")
|
|
||||||
expect(3, options, "table", "nil")
|
|
||||||
|
|
||||||
return http.request(url, nil, headers, options)
|
|
||||||
end
|
|
||||||
|
|
||||||
function http.post(url, body, headers, options)
|
|
||||||
expect(1, url, "string")
|
|
||||||
expect(2, body, "string", "nil")
|
|
||||||
expect(3, headers, "table", "nil")
|
|
||||||
expect(4, options, "table", "nil")
|
|
||||||
|
|
||||||
return http.request(url, body, headers, options)
|
|
||||||
end
|
|
||||||
|
|
||||||
local WebSocketHandle
|
|
||||||
local function buildWebsocketHandle(handle)
|
|
||||||
if not WebSocketHandle then
|
|
||||||
WebSocketHandle = getmetatable(handle) or { __index = {} }
|
|
||||||
function WebSocketHandle.__index:close()
|
|
||||||
self:closeAsync()
|
|
||||||
local _, id
|
|
||||||
repeat
|
|
||||||
_, id = event.pull("websocket_close")
|
|
||||||
until id == self:getRequestID()
|
|
||||||
end
|
|
||||||
|
|
||||||
function WebSocketHandle.__index:receive()
|
|
||||||
local _, id, par
|
|
||||||
repeat
|
|
||||||
_, id, par = event.pull("websocket_message")
|
|
||||||
until id == self:getRequestID()
|
|
||||||
|
|
||||||
return par
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return handle
|
|
||||||
end
|
|
||||||
|
|
||||||
function http.websocket(url, headers)
|
|
||||||
expect(1, url, "string")
|
|
||||||
expect(2, headers, "table", "nil")
|
|
||||||
|
|
||||||
if not http.checkURL(url) then
|
|
||||||
return nil, "Invalid URL"
|
|
||||||
end
|
|
||||||
|
|
||||||
local requestId = http.websocketAsync(url, headers)
|
|
||||||
local ev, id, par
|
|
||||||
repeat
|
|
||||||
ev, id, par = event.pull("websocket_connect", "websocket_failure")
|
|
||||||
until id == requestId
|
|
||||||
|
|
||||||
if ev == "http_failure" then
|
|
||||||
return nil, par
|
|
||||||
end
|
|
||||||
|
|
||||||
return buildWebsocketHandle(par)
|
|
||||||
end
|
|
|
@ -1,14 +0,0 @@
|
||||||
local timer = require("timer")
|
|
||||||
local event = require("event")
|
|
||||||
local expect = require("expect").expect
|
|
||||||
local range = require("expect").range
|
|
||||||
|
|
||||||
function timer.sleep(n)
|
|
||||||
expect(1, n, "number")
|
|
||||||
range(1, 1)
|
|
||||||
|
|
||||||
local timerId = timer.start(n)
|
|
||||||
repeat
|
|
||||||
local _, par = event.pull("timer")
|
|
||||||
until par == timerId
|
|
||||||
end
|
|
|
@ -1,15 +0,0 @@
|
||||||
local term = require("term")
|
|
||||||
local colors = require("colors")
|
|
||||||
local machine = require("machine")
|
|
||||||
|
|
||||||
term.setForeground(0x59c9ff)
|
|
||||||
term.setBackground(colors.black)
|
|
||||||
term.clear()
|
|
||||||
term.setPos(1, 1)
|
|
||||||
|
|
||||||
term.write(os.version())
|
|
||||||
term.setPos(1, 2)
|
|
||||||
|
|
||||||
dofile("/bin/shell.lua")
|
|
||||||
|
|
||||||
machine.shutdown()
|
|
Binary file not shown.
Before Width: | Height: | Size: 48 KiB |
|
@ -1,47 +0,0 @@
|
||||||
local version = "0.0.2"
|
|
||||||
|
|
||||||
print("Starting CapyOS")
|
|
||||||
|
|
||||||
local term = require("term")
|
|
||||||
local fs = require("fs")
|
|
||||||
local gpu = require("gpu")
|
|
||||||
|
|
||||||
local nPrint = print
|
|
||||||
local function showError(err)
|
|
||||||
nPrint(err)
|
|
||||||
local x, y = term.getPos()
|
|
||||||
term.setForeground(0xff0000)
|
|
||||||
term.setPos(1, y)
|
|
||||||
term.write(err)
|
|
||||||
|
|
||||||
term.setPos(1, y + 1)
|
|
||||||
term.setForeground(0xffffff)
|
|
||||||
term.write("Press any key to continue")
|
|
||||||
|
|
||||||
coroutine.yield("key_down")
|
|
||||||
end
|
|
||||||
|
|
||||||
function os.version()
|
|
||||||
return "CapyOS " .. version
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setSize(51, 19)
|
|
||||||
gpu.setScale(2)
|
|
||||||
|
|
||||||
term.setPos(1, 1)
|
|
||||||
term.write(_HOST)
|
|
||||||
|
|
||||||
local files = fs.list("/boot/autorun")
|
|
||||||
for i = 1, #files do
|
|
||||||
local func, err = loadfile("/boot/autorun/" .. files[i])
|
|
||||||
if not func then
|
|
||||||
showError(err)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
local ok, err = pcall(func)
|
|
||||||
if not ok then
|
|
||||||
showError(debug.traceback(err))
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,94 +0,0 @@
|
||||||
local expect = require("expect")
|
|
||||||
|
|
||||||
local palette = {
|
|
||||||
{
|
|
||||||
"white",
|
|
||||||
0xf0f0f0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"orange",
|
|
||||||
0xf2b233
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magenta",
|
|
||||||
0xe57fd8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"lightBlue",
|
|
||||||
0x99b2f2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"yellow",
|
|
||||||
0xdede6c
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"lime",
|
|
||||||
0x7fcc19
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pink",
|
|
||||||
0xf2b2cc
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"gray",
|
|
||||||
0x4c4c4c
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"lightGray",
|
|
||||||
0x999999
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cyan",
|
|
||||||
0x4c99b2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"purple",
|
|
||||||
0xb266e5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"blue",
|
|
||||||
0x3366cc
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"brown",
|
|
||||||
0x7f664c
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"green",
|
|
||||||
0x57a64e
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"red",
|
|
||||||
0xcc4c4c
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"black",
|
|
||||||
0x111111
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
local colors = {}
|
|
||||||
for k, v in ipairs(palette) do
|
|
||||||
colors[v[1]] = v[2]
|
|
||||||
colors[k] = v[2]
|
|
||||||
end
|
|
||||||
|
|
||||||
function colors.packRGB(r, g, b)
|
|
||||||
expect(1, r, "number")
|
|
||||||
expect(2, g, "number")
|
|
||||||
expect(3, b, "number")
|
|
||||||
|
|
||||||
return (r << 16) +
|
|
||||||
(g << 8) +
|
|
||||||
b
|
|
||||||
end
|
|
||||||
|
|
||||||
function colors.unpackRGB(rgb)
|
|
||||||
expect(1, rgb, "number")
|
|
||||||
|
|
||||||
return (rgb >> 16) & 0xff,
|
|
||||||
(rgb >> 8) & 0xff,
|
|
||||||
rgb & 0xff
|
|
||||||
end
|
|
||||||
|
|
||||||
return colors;
|
|
|
@ -1,52 +0,0 @@
|
||||||
-- Credits: https://github.com/Ocawesome101/recrafted
|
|
||||||
|
|
||||||
-- cc.expect
|
|
||||||
|
|
||||||
local _expect = {}
|
|
||||||
|
|
||||||
local function checkType(index, valueType, value, ...)
|
|
||||||
local expected = table.pack(...)
|
|
||||||
local isType = false
|
|
||||||
|
|
||||||
for i = 1, expected.n, 1 do
|
|
||||||
if type(value) == expected[i] then
|
|
||||||
isType = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not isType then
|
|
||||||
error(string.format("bad %s %s (%s expected, got %s)", valueType,
|
|
||||||
index, table.concat(expected, " or "), type(value)), 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
|
|
||||||
function _expect.expect(index, value, ...)
|
|
||||||
return checkType(("#%d"):format(index), "argument", value, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function _expect.field(tbl, index, ...)
|
|
||||||
_expect.expect(1, tbl, "table")
|
|
||||||
_expect.expect(2, index, "string")
|
|
||||||
return checkType(("%q"):format(index), "field", tbl[index], ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function _expect.range(num, min, max)
|
|
||||||
_expect.expect(1, num, "number")
|
|
||||||
_expect.expect(2, min, "number", "nil")
|
|
||||||
_expect.expect(3, max, "number", "nil")
|
|
||||||
min = min or -math.huge
|
|
||||||
max = max or math.huge
|
|
||||||
if num < min or num > max then
|
|
||||||
error(("number outside of range (expected %d to be within %d and %d")
|
|
||||||
:format(num, min, max), 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
setmetatable(_expect, { __call = function(_, ...)
|
|
||||||
return _expect.expect(...)
|
|
||||||
end })
|
|
||||||
|
|
||||||
return _expect
|
|
|
@ -1,282 +0,0 @@
|
||||||
local expect = require("expect").expect
|
|
||||||
local event = require("event")
|
|
||||||
local term = require("term")
|
|
||||||
|
|
||||||
local io = {}
|
|
||||||
|
|
||||||
function io.write(text)
|
|
||||||
text = tostring(text)
|
|
||||||
|
|
||||||
local lines = 0
|
|
||||||
local w, h = term.getSize()
|
|
||||||
|
|
||||||
local function inc_cy(cy)
|
|
||||||
lines = lines + 1
|
|
||||||
|
|
||||||
if cy > h - 1 then
|
|
||||||
term.scroll(1)
|
|
||||||
return cy
|
|
||||||
else
|
|
||||||
return cy + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
while #text > 0 do
|
|
||||||
local nl = text:find("\n") or #text
|
|
||||||
local chunk = text:sub(1, nl)
|
|
||||||
text = text:sub(#chunk + 1)
|
|
||||||
|
|
||||||
local has_nl = chunk:sub(-1) == "\n"
|
|
||||||
if has_nl then chunk = chunk:sub(1, -2) end
|
|
||||||
|
|
||||||
local cx, cy = term.getPos()
|
|
||||||
while #chunk > 0 do
|
|
||||||
if cx > w then
|
|
||||||
term.setPos(1, inc_cy(cy))
|
|
||||||
cx, cy = term.getPos()
|
|
||||||
end
|
|
||||||
|
|
||||||
local to_write = chunk:sub(1, w - cx + 1)
|
|
||||||
term.write(to_write)
|
|
||||||
|
|
||||||
chunk = chunk:sub(#to_write + 1)
|
|
||||||
cx, cy = term.getPos()
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_nl then
|
|
||||||
term.setPos(1, inc_cy(cy))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return lines
|
|
||||||
end
|
|
||||||
|
|
||||||
local empty = {}
|
|
||||||
function io.read(replace, history, complete, default)
|
|
||||||
expect(1, replace, "string", "nil")
|
|
||||||
expect(2, history, "table", "nil")
|
|
||||||
expect(3, complete, "function", "nil")
|
|
||||||
expect(4, default, "string", "nil")
|
|
||||||
|
|
||||||
if replace then replace = replace:sub(1, 1) end
|
|
||||||
local hist = history or {}
|
|
||||||
history = {}
|
|
||||||
for i = 1, #hist, 1 do
|
|
||||||
history[i] = hist[i]
|
|
||||||
end
|
|
||||||
|
|
||||||
local buffer = default or ""
|
|
||||||
local prev_buf = buffer
|
|
||||||
history[#history + 1] = buffer
|
|
||||||
|
|
||||||
local hist_pos = #history
|
|
||||||
local cursor_pos = 0
|
|
||||||
|
|
||||||
local stx, sty = term.getPos()
|
|
||||||
local w, h = term.getSize()
|
|
||||||
|
|
||||||
local dirty = false
|
|
||||||
local completions = {}
|
|
||||||
local comp_id = 0
|
|
||||||
|
|
||||||
local function clearCompletion()
|
|
||||||
if completions[comp_id] then
|
|
||||||
write((" "):rep(#completions[comp_id]))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function full_redraw(force)
|
|
||||||
if force or dirty then
|
|
||||||
if complete and buffer ~= prev_buf then
|
|
||||||
completions = complete(buffer) or empty
|
|
||||||
comp_id = math.min(1, #completions)
|
|
||||||
end
|
|
||||||
prev_buf = buffer
|
|
||||||
|
|
||||||
term.setPos(stx, sty)
|
|
||||||
local text = buffer
|
|
||||||
if replace then text = replace:rep(#text) end
|
|
||||||
local ln = io.write(text)
|
|
||||||
|
|
||||||
if completions[comp_id] then
|
|
||||||
local oldfg = term.getForeground()
|
|
||||||
local oldbg = term.getBackground()
|
|
||||||
term.setForeground(colors.white)
|
|
||||||
term.setBackground(colors.gray)
|
|
||||||
ln = ln + write(completions[comp_id])
|
|
||||||
term.setForeground(oldfg)
|
|
||||||
term.setBackground(oldbg)
|
|
||||||
else
|
|
||||||
ln = ln + io.write(" ")
|
|
||||||
end
|
|
||||||
|
|
||||||
if sty + ln > h then
|
|
||||||
sty = sty - (sty + ln - h)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- set cursor to the appropriate spot
|
|
||||||
local cx, cy = stx, sty
|
|
||||||
cx = cx + #buffer - cursor_pos -- + #(completions[comp_id] or "")
|
|
||||||
while cx > w do
|
|
||||||
cx = cx - w
|
|
||||||
cy = cy + 1
|
|
||||||
end
|
|
||||||
term.setPos(cx, cy)
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setBlink(true)
|
|
||||||
|
|
||||||
while true do
|
|
||||||
full_redraw()
|
|
||||||
-- get input
|
|
||||||
local evt, par1, par2 = event.pull()
|
|
||||||
|
|
||||||
if evt == "char" then
|
|
||||||
dirty = true
|
|
||||||
clearCompletion()
|
|
||||||
if cursor_pos == 0 then
|
|
||||||
buffer = buffer .. par1
|
|
||||||
elseif cursor_pos == #buffer then
|
|
||||||
buffer = par1 .. buffer
|
|
||||||
else
|
|
||||||
buffer = buffer:sub(0, -cursor_pos - 1) .. par1 .. buffer:sub(-cursor_pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif evt == "paste" then
|
|
||||||
dirty = true
|
|
||||||
clearCompletion()
|
|
||||||
if cursor_pos == 0 then
|
|
||||||
buffer = buffer .. par1
|
|
||||||
elseif cursor_pos == #buffer then
|
|
||||||
buffer = par1 .. buffer
|
|
||||||
else
|
|
||||||
buffer = buffer:sub(0, -cursor_pos - 1) .. par1 ..
|
|
||||||
buffer:sub(-cursor_pos + (#par1 - 1))
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif evt == "key_down" then
|
|
||||||
if par2 == "back" and #buffer > 0 then
|
|
||||||
dirty = true
|
|
||||||
if cursor_pos == 0 then
|
|
||||||
buffer = buffer:sub(1, -2)
|
|
||||||
clearCompletion()
|
|
||||||
elseif cursor_pos < #buffer then
|
|
||||||
buffer = buffer:sub(0, -cursor_pos - 2) .. buffer:sub(-cursor_pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif par2 == "delete" and cursor_pos > 0 then
|
|
||||||
dirty = true
|
|
||||||
|
|
||||||
if cursor_pos == #buffer then
|
|
||||||
buffer = buffer:sub(2)
|
|
||||||
elseif cursor_pos == 1 then
|
|
||||||
buffer = buffer:sub(1, -2)
|
|
||||||
else
|
|
||||||
buffer = buffer:sub(0, -cursor_pos - 1) .. buffer:sub(-cursor_pos + 1)
|
|
||||||
end
|
|
||||||
cursor_pos = cursor_pos - 1
|
|
||||||
|
|
||||||
elseif par2 == "up" then
|
|
||||||
if #completions > 1 then
|
|
||||||
dirty = true
|
|
||||||
clearCompletion()
|
|
||||||
if comp_id > 1 then
|
|
||||||
comp_id = comp_id - 1
|
|
||||||
else
|
|
||||||
comp_id = #completions
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif hist_pos > 1 then
|
|
||||||
cursor_pos = 0
|
|
||||||
|
|
||||||
history[hist_pos] = buffer
|
|
||||||
hist_pos = hist_pos - 1
|
|
||||||
|
|
||||||
buffer = (" "):rep(#buffer)
|
|
||||||
full_redraw(true)
|
|
||||||
|
|
||||||
buffer = history[hist_pos]
|
|
||||||
dirty = true
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif par2 == "down" then
|
|
||||||
if #completions > 1 then
|
|
||||||
dirty = true
|
|
||||||
clearCompletion()
|
|
||||||
if comp_id < #completions then
|
|
||||||
comp_id = comp_id + 1
|
|
||||||
else
|
|
||||||
comp_id = 1
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif hist_pos < #history then
|
|
||||||
cursor_pos = 0
|
|
||||||
|
|
||||||
history[hist_pos] = buffer
|
|
||||||
hist_pos = hist_pos + 1
|
|
||||||
|
|
||||||
buffer = (" "):rep(#buffer)
|
|
||||||
full_redraw(true)
|
|
||||||
|
|
||||||
buffer = history[hist_pos]
|
|
||||||
dirty = true
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif par2 == "left" then
|
|
||||||
if cursor_pos < #buffer then
|
|
||||||
clearCompletion()
|
|
||||||
cursor_pos = cursor_pos + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif par2 == "right" then
|
|
||||||
if cursor_pos > 0 then
|
|
||||||
cursor_pos = cursor_pos - 1
|
|
||||||
|
|
||||||
elseif comp_id > 0 then
|
|
||||||
dirty = true
|
|
||||||
buffer = buffer .. completions[comp_id]
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif par2 == "tab" then
|
|
||||||
if comp_id > 0 then
|
|
||||||
dirty = true
|
|
||||||
buffer = buffer .. completions[comp_id]
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif par2 == "home" then
|
|
||||||
cursor_pos = #buffer
|
|
||||||
|
|
||||||
elseif par2 == "end" then
|
|
||||||
cursor_pos = 0
|
|
||||||
|
|
||||||
elseif par2 == "enter" then
|
|
||||||
clearCompletion()
|
|
||||||
print()
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setBlink(false)
|
|
||||||
|
|
||||||
return buffer
|
|
||||||
end
|
|
||||||
|
|
||||||
io.stderr = {}
|
|
||||||
|
|
||||||
function io.stderr.write(text)
|
|
||||||
local fg = term.getForeground()
|
|
||||||
term.setForeground(0xff0000)
|
|
||||||
io.write(text)
|
|
||||||
term.setForeground(fg)
|
|
||||||
end
|
|
||||||
|
|
||||||
function io.stderr.print(...)
|
|
||||||
local fg = term.getForeground()
|
|
||||||
term.setForeground(0xff0000)
|
|
||||||
print(...)
|
|
||||||
term.setForeground(fg)
|
|
||||||
end
|
|
||||||
|
|
||||||
return io
|
|
|
@ -1,61 +0,0 @@
|
||||||
local expect = require("expect")
|
|
||||||
|
|
||||||
local parallel = {}
|
|
||||||
|
|
||||||
local function contains(array, value)
|
|
||||||
for k, v in pairs(array) do
|
|
||||||
if v == value then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function run(threads, exitOnAny)
|
|
||||||
local alive = #threads
|
|
||||||
local filters = {}
|
|
||||||
local ev = {}
|
|
||||||
while true do
|
|
||||||
for i, thread in pairs(threads) do
|
|
||||||
if not filters[i] or #filters[i] == 0 or contains(filters[i], ev[1]) or ev[1] == "interrupt" then
|
|
||||||
local pars = table.pack(coroutine.resume(thread, table.unpack(ev)))
|
|
||||||
if pars[1] then
|
|
||||||
filters[i] = table.pack(table.unpack(pars, 2))
|
|
||||||
else
|
|
||||||
error(pars[2], 0)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if coroutine.status(thread) == "dead" then
|
|
||||||
alive = alive - 1
|
|
||||||
if exitOnAny or alive <= 0 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
ev = table.pack(coroutine.yield())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function parallel.waitForAll(...)
|
|
||||||
local threads = {}
|
|
||||||
for k, v in ipairs({ ... }) do
|
|
||||||
expect(k, v, "function")
|
|
||||||
table.insert(threads, coroutine.create(v))
|
|
||||||
end
|
|
||||||
|
|
||||||
return run(threads, false)
|
|
||||||
end
|
|
||||||
|
|
||||||
function parallel.waitForAny(...)
|
|
||||||
local threads = {}
|
|
||||||
for k, v in ipairs({ ... }) do
|
|
||||||
expect(k, v, "function")
|
|
||||||
table.insert(threads, coroutine.create(v))
|
|
||||||
end
|
|
||||||
|
|
||||||
return run(threads, true)
|
|
||||||
end
|
|
||||||
|
|
||||||
return parallel
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,14 @@ local gpu = require("gpu")
|
||||||
local fs = require("fs")
|
local fs = require("fs")
|
||||||
local machine = require("machine")
|
local machine = require("machine")
|
||||||
local audio = require("audio")
|
local audio = require("audio")
|
||||||
|
local http = require("http")
|
||||||
|
local event = require("event")
|
||||||
|
|
||||||
|
local BASE_URL = "https://api.github.com/repos/%s/contents/%s"
|
||||||
|
local REPOSITORY = "Capy64/CapyOS"
|
||||||
|
local JSON_URL = "https://raw.githubusercontent.com/Capy64/CapyOS/main/lib/json.lua"
|
||||||
|
-- This token only has read-only access to repository files
|
||||||
|
local GITHUB_TOKEN = "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"
|
||||||
|
|
||||||
local bootSleep = 2000
|
local bootSleep = 2000
|
||||||
local bg = 0x0
|
local bg = 0x0
|
||||||
|
@ -16,6 +24,8 @@ term.clear()
|
||||||
term.setSize(51, 19)
|
term.setSize(51, 19)
|
||||||
gpu.setScale(2)
|
gpu.setScale(2)
|
||||||
|
|
||||||
|
local w, h = term.getSize()
|
||||||
|
|
||||||
local function sleep(n)
|
local function sleep(n)
|
||||||
local timerId = timer.start(n)
|
local timerId = timer.start(n)
|
||||||
repeat
|
repeat
|
||||||
|
@ -54,7 +64,96 @@ local function drawVendorImage()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local w, h = term.getSize()
|
local nPrint = print
|
||||||
|
local function print( text )
|
||||||
|
local x, y = term.getPos()
|
||||||
|
term.write(tostring(text))
|
||||||
|
if y == h then
|
||||||
|
term.scroll(1)
|
||||||
|
term.setPos(1, y)
|
||||||
|
else
|
||||||
|
term.setPos(1, y + 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function printError( text )
|
||||||
|
term.setForeground(0xff0000)
|
||||||
|
print(text)
|
||||||
|
term.setForeground(0xffffff)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function hget(url, headers)
|
||||||
|
local requestId = http.requestAsync(url, nil, headers, {binary = true})
|
||||||
|
|
||||||
|
local ev, rId, par, info
|
||||||
|
repeat
|
||||||
|
ev, rId, par, info = event.pull("http_response", "http_failure")
|
||||||
|
until rId == requestId
|
||||||
|
|
||||||
|
if ev == "http_failure" then
|
||||||
|
return nil, par
|
||||||
|
end
|
||||||
|
local content = par:read("a")
|
||||||
|
par:close()
|
||||||
|
return content, info
|
||||||
|
end
|
||||||
|
|
||||||
|
local function promptKey()
|
||||||
|
print("Press any key to continue")
|
||||||
|
event.pull("key_down")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function repo(path)
|
||||||
|
return string.format(BASE_URL, REPOSITORY, path or "")
|
||||||
|
end
|
||||||
|
|
||||||
|
local json
|
||||||
|
local function recursiveDownload(path)
|
||||||
|
path = path or ""
|
||||||
|
local index = json.decode(hget(repo(path), {
|
||||||
|
Authorization = "Bearer " .. GITHUB_TOKEN
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
for i, v in ipairs(index) do
|
||||||
|
if v.type == "dir" then
|
||||||
|
if not fs.exists(v.path) then
|
||||||
|
fs.makeDir(v.path)
|
||||||
|
end
|
||||||
|
recursiveDownload(v.path)
|
||||||
|
elseif v.type == "file" then
|
||||||
|
print("Downloading " .. v.path)
|
||||||
|
local fileContent = hget(v.download_url)
|
||||||
|
local f = fs.open(v.path, "wb")
|
||||||
|
f:write(fileContent)
|
||||||
|
f:close()
|
||||||
|
print("Written to " .. v.path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function installOS()
|
||||||
|
term.clear()
|
||||||
|
term.setPos(1, 1)
|
||||||
|
|
||||||
|
print("Installing CapyOS...")
|
||||||
|
|
||||||
|
local jsonLib, par = hget(JSON_URL)
|
||||||
|
if not jsonLib then
|
||||||
|
printError(par)
|
||||||
|
promptKey()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
json = load(jsonLib)()
|
||||||
|
|
||||||
|
recursiveDownload()
|
||||||
|
|
||||||
|
flagInstalled()
|
||||||
|
|
||||||
|
print("CapyOS installed!")
|
||||||
|
promptKey()
|
||||||
|
end
|
||||||
|
|
||||||
term.setBlink(false)
|
term.setBlink(false)
|
||||||
|
|
||||||
|
@ -148,6 +247,10 @@ end
|
||||||
|
|
||||||
audio.beep(1000, 0.4, 0.2)
|
audio.beep(1000, 0.4, 0.2)
|
||||||
|
|
||||||
|
if shouldInstallOS() then
|
||||||
|
installOS()
|
||||||
|
end
|
||||||
|
|
||||||
bootScreen()
|
bootScreen()
|
||||||
|
|
||||||
term.clear()
|
term.clear()
|
|
@ -1,11 +1,12 @@
|
||||||
using Capy64.API;
|
using Capy64.API;
|
||||||
using Capy64.Runtime.Objects.Handlers;
|
|
||||||
using Capy64.Runtime.Extensions;
|
using Capy64.Runtime.Extensions;
|
||||||
using KeraLua;
|
using KeraLua;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Capy64.Runtime.Objects;
|
||||||
|
|
||||||
namespace Capy64.Runtime.Libraries;
|
namespace Capy64.Runtime.Libraries;
|
||||||
|
|
||||||
|
@ -491,8 +492,7 @@ public class FileSystem : IPlugin
|
||||||
{
|
{
|
||||||
var L = Lua.FromIntPtr(state);
|
var L = Lua.FromIntPtr(state);
|
||||||
var path = Resolve(L.CheckString(1));
|
var path = Resolve(L.CheckString(1));
|
||||||
var mode = L.CheckString(2);
|
var mode = L.OptString(2, "r");
|
||||||
|
|
||||||
|
|
||||||
var errorMessage = "invalid file mode";
|
var errorMessage = "invalid file mode";
|
||||||
if (mode.Length < 1 && mode.Length > 2)
|
if (mode.Length < 1 && mode.Length > 2)
|
||||||
|
@ -542,25 +542,8 @@ public class FileSystem : IPlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileStream = File.Open(path, fileMode, fileAccess, FileShare.ReadWrite);
|
var fileStream = File.Open(path, fileMode, fileAccess, FileShare.ReadWrite);
|
||||||
|
L.PushObject(fileStream);
|
||||||
if (fileAccess == FileAccess.Read)
|
L.SetMetaTable(FileHandle.ObjectType);
|
||||||
{
|
|
||||||
if (binaryMode)
|
|
||||||
BinaryReadHandle.Push(L, new(fileStream));
|
|
||||||
else
|
|
||||||
ReadHandle.Push(L, new(fileStream));
|
|
||||||
}
|
|
||||||
else if (fileAccess == FileAccess.Write)
|
|
||||||
{
|
|
||||||
if (binaryMode)
|
|
||||||
BinaryWriteHandle.Push(L, new(fileStream));
|
|
||||||
else
|
|
||||||
WriteHandle.Push(L, new(fileStream));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
using Capy64.API;
|
using Capy64.API;
|
||||||
using Capy64.Runtime.Extensions;
|
using Capy64.Runtime.Extensions;
|
||||||
using Capy64.Runtime.Objects.Handlers;
|
using Capy64.Runtime.Objects;
|
||||||
using KeraLua;
|
using KeraLua;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
|
@ -209,10 +210,12 @@ public class HTTP : IPlugin
|
||||||
LK.PushInteger(requestId);
|
LK.PushInteger(requestId);
|
||||||
|
|
||||||
// arg 2, response data
|
// arg 2, response data
|
||||||
if ((bool)options["binary"])
|
L.PushObject(stream);
|
||||||
|
L.SetMetaTable(FileHandle.ObjectType);
|
||||||
|
/*if ((bool)options["binary"])
|
||||||
BinaryReadHandle.Push(LK, new(stream));
|
BinaryReadHandle.Push(LK, new(stream));
|
||||||
else
|
else
|
||||||
ReadHandle.Push(LK, new(stream));
|
ReadHandle.Push(LK, new(stream));*/
|
||||||
|
|
||||||
// arg 3, response info
|
// arg 3, response info
|
||||||
LK.NewTable();
|
LK.NewTable();
|
||||||
|
|
333
Capy64/Runtime/Objects/FileHandle.cs
Normal file
333
Capy64/Runtime/Objects/FileHandle.cs
Normal file
|
@ -0,0 +1,333 @@
|
||||||
|
using Capy64.API;
|
||||||
|
using KeraLua;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Capy64.Runtime.Objects;
|
||||||
|
|
||||||
|
public class FileHandle : IPlugin
|
||||||
|
{
|
||||||
|
public const string ObjectType = "file";
|
||||||
|
|
||||||
|
private static LuaRegister[] Methods = new LuaRegister[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "read",
|
||||||
|
function = L_Read,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "write",
|
||||||
|
function = L_Write,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "lines",
|
||||||
|
function = L_Lines,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "flush",
|
||||||
|
function = L_Flush,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "seek",
|
||||||
|
function = L_Seek,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "close",
|
||||||
|
function = L_Close,
|
||||||
|
},
|
||||||
|
new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static LuaRegister[] MetaMethods = new LuaRegister[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "__index",
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "__gc",
|
||||||
|
function = F_GC,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "__close",
|
||||||
|
function = F_GC,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "__tostring",
|
||||||
|
function = F_ToString,
|
||||||
|
},
|
||||||
|
|
||||||
|
new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
public void LuaInit(Lua L)
|
||||||
|
{
|
||||||
|
CreateMeta(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateMeta(Lua L)
|
||||||
|
{
|
||||||
|
L.NewMetaTable(ObjectType);
|
||||||
|
L.SetFuncs(MetaMethods, 0);
|
||||||
|
L.NewLibTable(Methods);
|
||||||
|
L.SetFuncs(Methods, 0);
|
||||||
|
L.SetField(-2, "__index");
|
||||||
|
L.Pop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char CheckMode(string mode)
|
||||||
|
{
|
||||||
|
var modes = "nlLa";
|
||||||
|
var i = modes.IndexOf(mode.TrimStart('*')[0]);
|
||||||
|
return modes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream ToStream(Lua L, bool gc = false)
|
||||||
|
{
|
||||||
|
return L.CheckObject<Stream>(1, ObjectType, gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream CheckStream(Lua L, bool gc = false)
|
||||||
|
{
|
||||||
|
var obj = L.CheckObject<Stream>(1, ObjectType, gc);
|
||||||
|
if (obj is null)
|
||||||
|
{
|
||||||
|
L.Error("attempt to use a closed file");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool ReadNumber(Lua L, Stream stream)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool ReadLine(Lua L, Stream stream, bool chop)
|
||||||
|
{
|
||||||
|
var buffer = new byte[stream.Length];
|
||||||
|
int i = 0;
|
||||||
|
int c = 0;
|
||||||
|
for (; i < stream.Length; i++)
|
||||||
|
{
|
||||||
|
c = stream.ReadByte();
|
||||||
|
if (c == -1 || c == '\n')
|
||||||
|
break;
|
||||||
|
buffer[i] = (byte)c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!chop && c == '\n')
|
||||||
|
buffer[i++] = (byte)c;
|
||||||
|
|
||||||
|
Array.Resize(ref buffer, i);
|
||||||
|
L.PushBuffer(buffer);
|
||||||
|
|
||||||
|
return c == '\n' || L.RawLen(-1) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ReadAll(Lua L, Stream stream)
|
||||||
|
{
|
||||||
|
var buffer = new byte[stream.Length];
|
||||||
|
var read = stream.Read(buffer, 0, buffer.Length);
|
||||||
|
Array.Resize(ref buffer, read);
|
||||||
|
L.PushBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool ReadChars(Lua L, Stream stream, int n)
|
||||||
|
{
|
||||||
|
var buffer = new byte[n];
|
||||||
|
var read = stream.Read(buffer, 0, n);
|
||||||
|
Array.Resize(ref buffer, read);
|
||||||
|
L.PushBuffer(buffer);
|
||||||
|
return read != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_Read(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
var stream = CheckStream(L);
|
||||||
|
|
||||||
|
if (!stream.CanRead)
|
||||||
|
{
|
||||||
|
L.PushNil();
|
||||||
|
L.PushString("Attempt to read from a write-only stream");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nargs = L.GetTop() - 1;
|
||||||
|
if (nargs == 0)
|
||||||
|
{
|
||||||
|
L.PushString("l");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (L.Type(2) == LuaType.Number)
|
||||||
|
{
|
||||||
|
success = ReadChars(L, stream, (int)L.ToNumber(2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var p = L.CheckString(2);
|
||||||
|
var mode = CheckMode(p);
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case 'n':
|
||||||
|
success = ReadNumber(L, stream);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
success = ReadLine(L, stream, true);
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
success = ReadLine(L, stream, false);
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
ReadAll(L, stream);
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return L.ArgumentError(2, "invalid format");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
L.Pop(1);
|
||||||
|
L.PushNil();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_Write(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var nargs = L.GetTop();
|
||||||
|
|
||||||
|
var stream = CheckStream(L);
|
||||||
|
if (!stream.CanWrite)
|
||||||
|
{
|
||||||
|
L.PushNil();
|
||||||
|
L.PushString("Attempt to write to a read-only stream");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int arg = 2; arg <= nargs; arg++)
|
||||||
|
{
|
||||||
|
if (L.Type(arg) == LuaType.Number)
|
||||||
|
{
|
||||||
|
stream.WriteByte((byte)L.ToNumber(arg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var buffer = L.CheckBuffer(arg);
|
||||||
|
stream.Write(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return L.FileResult(1, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_Lines(IntPtr state)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
var maxargn = 250;
|
||||||
|
|
||||||
|
var n = L.GetTop() - 1;
|
||||||
|
var stream = CheckStream(L, false);
|
||||||
|
L.ArgumentCheck(n <= maxargn, maxargn + 2, "too many arguments");
|
||||||
|
L.PushCopy(1);
|
||||||
|
L.PushInteger(n);
|
||||||
|
L.PushBoolean(false);
|
||||||
|
L.Rotate(2, 3);
|
||||||
|
L.PushCClosure(null, 3 + n); // todo
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_Flush(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var stream = CheckStream(L, false);
|
||||||
|
|
||||||
|
stream.Flush();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_Seek(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var stream = CheckStream(L, false);
|
||||||
|
|
||||||
|
var whence = L.CheckOption(2, "cur", new[]
|
||||||
|
{
|
||||||
|
"set", // begin 0
|
||||||
|
"cur", // current 1
|
||||||
|
"end", // end 2
|
||||||
|
null,
|
||||||
|
});
|
||||||
|
|
||||||
|
var offset = L.OptInteger(3, 0);
|
||||||
|
|
||||||
|
var newPosition = stream.Seek(offset, (SeekOrigin)whence);
|
||||||
|
|
||||||
|
L.PushInteger(newPosition);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_Close(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var stream = CheckStream(L, true);
|
||||||
|
stream.Close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static unsafe int F_ToString(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
var stream = ToStream(L);
|
||||||
|
if (stream is not null)
|
||||||
|
{
|
||||||
|
L.PushString("file ({0:X})", (ulong)&stream);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
L.PushString("file (closed)");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int F_GC(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var stream = ToStream(L, true);
|
||||||
|
if (stream is not null)
|
||||||
|
stream.Close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,508 +0,0 @@
|
||||||
using KeraLua;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Capy64.Runtime.Objects.Handlers;
|
|
||||||
|
|
||||||
public class BinaryReadHandle
|
|
||||||
{
|
|
||||||
public const string ObjectType = "BinaryReadHandle";
|
|
||||||
|
|
||||||
private static readonly Dictionary<string, LuaFunction> functions = new()
|
|
||||||
{
|
|
||||||
["readAll"] = L_ReadAll,
|
|
||||||
["seek"] = L_Seek,
|
|
||||||
["readByte"] = L_ReadByte,
|
|
||||||
["readShort"] = L_ReadShort,
|
|
||||||
["readInt"] = L_ReadInt,
|
|
||||||
["readLong"] = L_ReadLong,
|
|
||||||
["readSByte"] = L_ReadSByte,
|
|
||||||
["readUShort"] = L_ReadUShort,
|
|
||||||
["readUInt"] = L_ReadUInt,
|
|
||||||
["readULong"] = L_ReadULong,
|
|
||||||
["readHalf"] = L_ReadHalf,
|
|
||||||
["readFloat"] = L_ReadFloat,
|
|
||||||
["readDouble"] = L_ReadDouble,
|
|
||||||
["readChar"] = L_ReadChar,
|
|
||||||
["readString"] = L_ReadString,
|
|
||||||
["readBoolean"] = L_ReadBoolean,
|
|
||||||
["close"] = L_Close,
|
|
||||||
};
|
|
||||||
|
|
||||||
public static void Push(Lua L, BinaryReader stream)
|
|
||||||
{
|
|
||||||
L.PushObject(stream);
|
|
||||||
|
|
||||||
if (L.NewMetaTable(ObjectType))
|
|
||||||
{
|
|
||||||
L.PushString("__index");
|
|
||||||
L.NewTable();
|
|
||||||
foreach (var pair in functions)
|
|
||||||
{
|
|
||||||
L.PushString(pair.Key);
|
|
||||||
L.PushCFunction(pair.Value);
|
|
||||||
L.SetTable(-3);
|
|
||||||
}
|
|
||||||
L.SetTable(-3);
|
|
||||||
|
|
||||||
L.PushString("__close");
|
|
||||||
L.PushCFunction(L_Close);
|
|
||||||
L.SetTable(-3);
|
|
||||||
L.PushString("__gc");
|
|
||||||
L.PushCFunction(L_Close);
|
|
||||||
L.SetTable(-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
L.SetMetaTable(-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_Read(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (L.IsInteger(2))
|
|
||||||
{
|
|
||||||
if (stream.BaseStream.Position >= stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
stream.ReadChars((int)L.ToInteger(2));
|
|
||||||
}
|
|
||||||
else if (L.IsString(2))
|
|
||||||
{
|
|
||||||
var option = L.ToString(2);
|
|
||||||
option = option.TrimStart('*');
|
|
||||||
if (option.Length == 0)
|
|
||||||
{
|
|
||||||
L.ArgumentError(2, "invalid option");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position >= stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var reader = new StreamReader(stream.BaseStream);
|
|
||||||
|
|
||||||
switch (option[0])
|
|
||||||
{
|
|
||||||
case 'a':
|
|
||||||
L.PushString(reader.ReadToEnd());
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
L.PushString(reader.ReadLine());
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
L.Error("Not yet implemented!");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
L.ArgumentError(2, "invalid option");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
L.ArgumentError(2, "number or string expected");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadAll(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position >= stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var chars = stream.ReadChars((int)stream.BaseStream.Length);
|
|
||||||
var buffer = Encoding.ASCII.GetBytes(chars);
|
|
||||||
|
|
||||||
L.PushBuffer(buffer);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_Seek(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
var whence = L.CheckOption(2, "cur", new[]
|
|
||||||
{
|
|
||||||
"set", // begin 0
|
|
||||||
"cur", // current 1
|
|
||||||
"end", // end 2
|
|
||||||
null,
|
|
||||||
});
|
|
||||||
|
|
||||||
var offset = L.OptInteger(3, 0);
|
|
||||||
|
|
||||||
var newPosition = stream.BaseStream.Seek(offset, (SeekOrigin)whence);
|
|
||||||
|
|
||||||
L.PushInteger(newPosition);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadByte(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var count = (int)L.OptNumber(2, 1);
|
|
||||||
L.ArgumentCheck(count >= 1, 2, "count must be a positive integer");
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position >= stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 1)
|
|
||||||
{
|
|
||||||
var b = stream.ReadByte();
|
|
||||||
L.PushInteger(b);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var bs = stream.ReadBytes(count);
|
|
||||||
foreach (var b in bs)
|
|
||||||
{
|
|
||||||
L.PushInteger(b);
|
|
||||||
}
|
|
||||||
return bs.Length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadShort(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position >= stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var b = stream.ReadInt16();
|
|
||||||
L.PushInteger(b);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadInt(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position > stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var b = stream.ReadInt32();
|
|
||||||
L.PushInteger(b);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadLong(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position > stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var b = stream.ReadInt64();
|
|
||||||
L.PushInteger(b);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadSByte(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position > stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var b = stream.ReadSByte();
|
|
||||||
L.PushInteger(b);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadUShort(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position > stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var b = stream.ReadUInt16();
|
|
||||||
L.PushInteger(b);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadUInt(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position > stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var b = stream.ReadUInt32();
|
|
||||||
L.PushInteger(b);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadULong(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position > stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var b = stream.ReadUInt64();
|
|
||||||
L.PushInteger((long)b);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadHalf(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position > stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var b = stream.ReadHalf();
|
|
||||||
L.PushNumber((double)b);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadFloat(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position > stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var b = stream.ReadSingle();
|
|
||||||
L.PushNumber((double)b);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadDouble(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position > stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var b = stream.ReadDouble();
|
|
||||||
L.PushNumber((double)b);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadChar(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
var count = (int)L.OptNumber(2, 1);
|
|
||||||
L.ArgumentCheck(count >= 1, 2, "count must be a positive integer");
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position >= stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 1)
|
|
||||||
{
|
|
||||||
var b = stream.ReadChar();
|
|
||||||
L.PushString(b.ToString());
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var bs = stream.ReadChars(count);
|
|
||||||
foreach (var b in bs)
|
|
||||||
{
|
|
||||||
L.PushString(b.ToString());
|
|
||||||
}
|
|
||||||
return bs.Length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadString(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
var count = (int)L.OptNumber(2, 1);
|
|
||||||
L.ArgumentCheck(count >= 1, 2, "count must be a positive integer");
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position >= stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 1)
|
|
||||||
{
|
|
||||||
var b = stream.ReadChar();
|
|
||||||
L.PushString(b.ToString());
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var bs = stream.ReadBytes(count);
|
|
||||||
L.PushBuffer(bs);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadBoolean(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (stream.BaseStream.Position > stream.BaseStream.Length)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var b = stream.ReadBoolean();
|
|
||||||
L.PushBoolean(b);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_Close(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryReader>(1, ObjectType, true);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
stream.Dispose();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,395 +0,0 @@
|
||||||
using KeraLua;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Capy64.Runtime.Objects.Handlers;
|
|
||||||
|
|
||||||
public class BinaryWriteHandle
|
|
||||||
{
|
|
||||||
public const string ObjectType = "BinaryWriteHandle";
|
|
||||||
|
|
||||||
private static readonly Dictionary<string, LuaFunction> functions = new()
|
|
||||||
{
|
|
||||||
["seek"] = L_Seek,
|
|
||||||
["writeByte"] = L_WriteByte,
|
|
||||||
["writeShort"] = L_WriteShort,
|
|
||||||
["writeInt"] = L_WriteInt,
|
|
||||||
["writeLong"] = L_WriteLong,
|
|
||||||
["writeSByte"] = L_WriteSByte,
|
|
||||||
["writeUShort"] = L_WriteUShort,
|
|
||||||
["writeUInt"] = L_WriteUInt,
|
|
||||||
["writeULong"] = L_WriteULong,
|
|
||||||
["writeHalf"] = L_WriteHalf,
|
|
||||||
["writeFloat"] = L_WriteFloat,
|
|
||||||
["writeDouble"] = L_WriteDouble,
|
|
||||||
["writeChar"] = L_WriteChar,
|
|
||||||
["writeString"] = L_WriteString,
|
|
||||||
["writeBoolean"] = L_WriteBoolean,
|
|
||||||
["flush"] = L_Flush,
|
|
||||||
["close"] = L_Close,
|
|
||||||
};
|
|
||||||
|
|
||||||
public static void Push(Lua L, BinaryWriter stream)
|
|
||||||
{
|
|
||||||
L.PushObject(stream);
|
|
||||||
|
|
||||||
if (L.NewMetaTable(ObjectType))
|
|
||||||
{
|
|
||||||
L.PushString("__index");
|
|
||||||
L.NewTable();
|
|
||||||
foreach (var pair in functions)
|
|
||||||
{
|
|
||||||
L.PushString(pair.Key);
|
|
||||||
L.PushCFunction(pair.Value);
|
|
||||||
L.SetTable(-3);
|
|
||||||
}
|
|
||||||
L.SetTable(-3);
|
|
||||||
|
|
||||||
L.PushString("__close");
|
|
||||||
L.PushCFunction(L_Close);
|
|
||||||
L.SetTable(-3);
|
|
||||||
L.PushString("__gc");
|
|
||||||
L.PushCFunction(L_Close);
|
|
||||||
L.SetTable(-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
L.SetMetaTable(-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_Seek(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
var whence = L.CheckOption(2, "cur", new[]
|
|
||||||
{
|
|
||||||
"set", // begin 0
|
|
||||||
"cur", // current 1
|
|
||||||
"end", // end 2
|
|
||||||
null,
|
|
||||||
});
|
|
||||||
|
|
||||||
var offset = L.OptInteger(3, 0);
|
|
||||||
|
|
||||||
var newPosition = stream.BaseStream.Seek(offset, (SeekOrigin)whence);
|
|
||||||
|
|
||||||
L.PushInteger(newPosition);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteByte(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
byte[] buffer;
|
|
||||||
if (L.IsInteger(2))
|
|
||||||
{
|
|
||||||
buffer = new[]
|
|
||||||
{
|
|
||||||
(byte)L.ToInteger(2),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (L.IsTable(2))
|
|
||||||
{
|
|
||||||
var len = L.RawLen(2);
|
|
||||||
buffer = new byte[len];
|
|
||||||
|
|
||||||
for (int i = 1; i <= len; i++)
|
|
||||||
{
|
|
||||||
L.PushInteger(i);
|
|
||||||
L.GetTable(2);
|
|
||||||
var b = L.CheckInteger(-1);
|
|
||||||
L.Pop(1);
|
|
||||||
buffer[i - 1] = (byte)b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
L.ArgumentError(2, "integer or table expected, got " + L.Type(2));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write(buffer);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteShort(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var b = L.CheckInteger(2);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write((short)b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteInt(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var b = L.CheckInteger(2);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write((int)b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteLong(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var b = L.CheckInteger(2);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write(b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteSByte(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var b = L.CheckInteger(2);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write((sbyte)b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteUShort(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var b = L.CheckInteger(2);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write((ushort)b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteUInt(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var b = L.CheckInteger(2);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write((uint)b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteULong(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var b = L.CheckInteger(2);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write((ulong)b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteHalf(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var b = L.CheckNumber(2);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write((Half)b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteFloat(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var b = L.CheckNumber(2);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write((float)b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteDouble(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var b = L.CheckNumber(2);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write((double)b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteChar(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
byte[] buffer;
|
|
||||||
if (L.IsString(2))
|
|
||||||
{
|
|
||||||
var str = L.ToString(2);
|
|
||||||
buffer = Encoding.ASCII.GetBytes(str);
|
|
||||||
}
|
|
||||||
else if (L.IsTable(2))
|
|
||||||
{
|
|
||||||
var len = L.RawLen(2);
|
|
||||||
var tmpBuffer = new List<byte>();
|
|
||||||
|
|
||||||
for (int i = 1; i <= len; i++)
|
|
||||||
{
|
|
||||||
L.PushInteger(i);
|
|
||||||
L.GetTable(2);
|
|
||||||
var b = L.CheckString(-1);
|
|
||||||
L.Pop(1);
|
|
||||||
var chunk = Encoding.ASCII.GetBytes(b);
|
|
||||||
foreach (var c in chunk)
|
|
||||||
{
|
|
||||||
tmpBuffer.Add(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = tmpBuffer.ToArray();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
L.ArgumentError(2, "integer or table expected, got " + L.Type(2));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write(buffer);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteString(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var b = L.CheckString(2);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write(b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteBoolean(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
L.CheckType(2, LuaType.Boolean);
|
|
||||||
var b = L.ToBoolean(2);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Write(b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_Flush(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Flush();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_Close(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var stream = L.CheckObject<BinaryWriter>(1, ObjectType, true);
|
|
||||||
|
|
||||||
if (stream is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
stream.Dispose();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,127 +0,0 @@
|
||||||
using KeraLua;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Capy64.Runtime.Objects.Handlers;
|
|
||||||
|
|
||||||
public class ReadHandle
|
|
||||||
{
|
|
||||||
public const string ObjectType = "ReadHandle";
|
|
||||||
|
|
||||||
private static readonly Dictionary<string, LuaFunction> functions = new()
|
|
||||||
{
|
|
||||||
["readAll"] = L_ReadAll,
|
|
||||||
["readLine"] = L_ReadLine,
|
|
||||||
["read"] = L_Read,
|
|
||||||
["close"] = L_Close,
|
|
||||||
};
|
|
||||||
|
|
||||||
public static void Push(Lua L, StreamReader stream)
|
|
||||||
{
|
|
||||||
L.PushObject(stream);
|
|
||||||
|
|
||||||
if (L.NewMetaTable(ObjectType))
|
|
||||||
{
|
|
||||||
L.PushString("__index");
|
|
||||||
L.NewTable();
|
|
||||||
foreach (var pair in functions)
|
|
||||||
{
|
|
||||||
L.PushString(pair.Key);
|
|
||||||
L.PushCFunction(pair.Value);
|
|
||||||
L.SetTable(-3);
|
|
||||||
}
|
|
||||||
L.SetTable(-3);
|
|
||||||
|
|
||||||
L.PushString("__close");
|
|
||||||
L.PushCFunction(L_Close);
|
|
||||||
L.SetTable(-3);
|
|
||||||
L.PushString("__gc");
|
|
||||||
L.PushCFunction(L_Close);
|
|
||||||
L.SetTable(-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
L.SetMetaTable(-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadAll(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var handle = L.CheckObject<StreamReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (handle is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (handle.EndOfStream)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var content = handle.ReadToEnd();
|
|
||||||
L.PushString(content);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_ReadLine(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var handle = L.CheckObject<StreamReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (handle is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
var line = handle.ReadLine();
|
|
||||||
|
|
||||||
if (line is null)
|
|
||||||
L.PushNil();
|
|
||||||
else
|
|
||||||
L.PushString(line);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_Read(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var count = (int)L.OptNumber(2, 1);
|
|
||||||
L.ArgumentCheck(count >= 1, 2, "count must be a positive integer");
|
|
||||||
|
|
||||||
var handle = L.CheckObject<StreamReader>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (handle is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
if (handle.EndOfStream)
|
|
||||||
{
|
|
||||||
L.PushNil();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var chunk = new char[count];
|
|
||||||
|
|
||||||
handle.Read(chunk, 0, count);
|
|
||||||
|
|
||||||
L.PushString(new string(chunk));
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_Close(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var handle = L.CheckObject<StreamReader>(1, ObjectType, true);
|
|
||||||
|
|
||||||
if (handle is null)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
handle.Dispose();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,106 +0,0 @@
|
||||||
using KeraLua;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Capy64.Runtime.Objects.Handlers;
|
|
||||||
|
|
||||||
public class WriteHandle
|
|
||||||
{
|
|
||||||
public const string ObjectType = "WriteHandle";
|
|
||||||
|
|
||||||
private static readonly Dictionary<string, LuaFunction> functions = new()
|
|
||||||
{
|
|
||||||
["write"] = L_Write,
|
|
||||||
["writeLine"] = L_WriteLine,
|
|
||||||
["flush"] = L_Flush,
|
|
||||||
["close"] = L_Close,
|
|
||||||
};
|
|
||||||
|
|
||||||
public static void Push(Lua L, StreamWriter stream)
|
|
||||||
{
|
|
||||||
L.PushObject(stream);
|
|
||||||
|
|
||||||
if (L.NewMetaTable(ObjectType))
|
|
||||||
{
|
|
||||||
L.PushString("__index");
|
|
||||||
L.NewTable();
|
|
||||||
foreach (var pair in functions)
|
|
||||||
{
|
|
||||||
L.PushString(pair.Key);
|
|
||||||
L.PushCFunction(pair.Value);
|
|
||||||
L.SetTable(-3);
|
|
||||||
}
|
|
||||||
L.SetTable(-3);
|
|
||||||
|
|
||||||
L.PushString("__close");
|
|
||||||
L.PushCFunction(L_Close);
|
|
||||||
L.SetTable(-3);
|
|
||||||
L.PushString("__gc");
|
|
||||||
L.PushCFunction(L_Close);
|
|
||||||
L.SetTable(-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
L.SetMetaTable(-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_Write(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var handle = L.CheckObject<StreamWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
var content = L.CheckString(2);
|
|
||||||
|
|
||||||
if (handle is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
handle.Write(content);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_WriteLine(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var handle = L.CheckObject<StreamWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
var content = L.CheckString(2);
|
|
||||||
|
|
||||||
if (handle is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
handle.WriteLine(content);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_Flush(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var handle = L.CheckObject<StreamWriter>(1, ObjectType, false);
|
|
||||||
|
|
||||||
if (handle is null)
|
|
||||||
L.Error("handle is closed");
|
|
||||||
|
|
||||||
handle.Flush();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_Close(IntPtr state)
|
|
||||||
{
|
|
||||||
var L = Lua.FromIntPtr(state);
|
|
||||||
|
|
||||||
var handle = L.CheckObject<StreamWriter>(1, ObjectType, true);
|
|
||||||
|
|
||||||
if (handle is null)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
handle.Dispose();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Capy64.Runtime.Objects.Handlers;
|
namespace Capy64.Runtime.Objects;
|
||||||
|
|
||||||
public class WebSocketClient
|
public class WebSocketClient
|
||||||
{
|
{
|
|
@ -84,8 +84,6 @@ internal class RuntimeManager : IPlugin
|
||||||
|
|
||||||
private void InitBIOS()
|
private void InitBIOS()
|
||||||
{
|
{
|
||||||
InstallOS(false);
|
|
||||||
|
|
||||||
_game.Discord.SetPresence("Booting up...");
|
_game.Discord.SetPresence("Booting up...");
|
||||||
|
|
||||||
luaState = new LuaState();
|
luaState = new LuaState();
|
||||||
|
@ -104,8 +102,11 @@ internal class RuntimeManager : IPlugin
|
||||||
luaState.Thread.PushCFunction(L_OpenDataFolder);
|
luaState.Thread.PushCFunction(L_OpenDataFolder);
|
||||||
luaState.Thread.SetGlobal("openDataFolder");
|
luaState.Thread.SetGlobal("openDataFolder");
|
||||||
|
|
||||||
luaState.Thread.PushCFunction(L_InstallOS);
|
luaState.Thread.PushCFunction(L_ShouldInstallOS);
|
||||||
luaState.Thread.SetGlobal("installOS");
|
luaState.Thread.SetGlobal("shouldInstallOS");
|
||||||
|
|
||||||
|
luaState.Thread.PushCFunction(L_FlagInstalled);
|
||||||
|
luaState.Thread.SetGlobal("flagInstalled");
|
||||||
|
|
||||||
luaState.Thread.PushCFunction(L_Exit);
|
luaState.Thread.PushCFunction(L_Exit);
|
||||||
luaState.Thread.SetGlobal("exit");
|
luaState.Thread.SetGlobal("exit");
|
||||||
|
@ -153,16 +154,6 @@ internal class RuntimeManager : IPlugin
|
||||||
_game.Exit();
|
_game.Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InstallOS(bool force = false)
|
|
||||||
{
|
|
||||||
var installedFilePath = Path.Combine(Capy64.AppDataPath, ".installed");
|
|
||||||
if (!File.Exists(installedFilePath) || force)
|
|
||||||
{
|
|
||||||
FileSystem.CopyDirectory("Assets/Lua", FileSystem.DataPath, true, true);
|
|
||||||
File.Create(installedFilePath).Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int L_OpenDataFolder(IntPtr state)
|
private static int L_OpenDataFolder(IntPtr state)
|
||||||
{
|
{
|
||||||
var path = FileSystem.DataPath;
|
var path = FileSystem.DataPath;
|
||||||
|
@ -179,9 +170,22 @@ internal class RuntimeManager : IPlugin
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int L_InstallOS(IntPtr state)
|
private static int L_ShouldInstallOS(IntPtr state)
|
||||||
{
|
{
|
||||||
InstallOS(true);
|
var L = Lua.FromIntPtr(state);
|
||||||
|
var installedFilePath = Path.Combine(Capy64.AppDataPath, ".installed");
|
||||||
|
|
||||||
|
L.PushBoolean(!File.Exists(installedFilePath));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_FlagInstalled(IntPtr state)
|
||||||
|
{
|
||||||
|
var installedFilePath = Path.Combine(Capy64.AppDataPath, ".installed");
|
||||||
|
if (!File.Exists(installedFilePath))
|
||||||
|
File.Create(installedFilePath).Dispose();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue