Implement filesystem component
This commit is contained in:
parent
54631f1e79
commit
03f4203fa2
2
Makefile
2
Makefile
@ -1,5 +1,5 @@
|
||||
CC=gcc
|
||||
CFLAGS=-g -std=c99 -Isrc/lib/lua -Iinclude
|
||||
CFLAGS=-g -std=gnu99 -Isrc/lib/lua -Iinclude
|
||||
|
||||
BUILD = bin/
|
||||
SOURCE = src/c/
|
||||
|
@ -5,6 +5,7 @@ extern char lua_component[];
|
||||
extern char lua_computer[];
|
||||
extern char lua_eepromDefault[];
|
||||
extern char lua_eeprom[];
|
||||
extern char lua_filesystem[];
|
||||
extern char lua_init[];
|
||||
extern char lua_sandbox[];
|
||||
extern char lua_textgpu[];
|
||||
|
264
src/c/lnative.c
264
src/c/lnative.c
@ -1,19 +1,279 @@
|
||||
#define _XOPEN_SOURCE 500
|
||||
|
||||
#include "lupi.h"
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <ftw.h>
|
||||
#include <limits.h>
|
||||
#include <linux/kd.h>
|
||||
|
||||
static int l_sleep (lua_State *L) {
|
||||
int t = lua_tonumber(L, 1);
|
||||
unsigned int t = lua_tonumber(L, 1);
|
||||
usleep(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Filesystem methods
|
||||
static int l_fs_exists (lua_State *L) {
|
||||
const char* fname = lua_tostring(L, 1);
|
||||
if( access( fname, F_OK ) != -1 ) {
|
||||
lua_pushboolean(L, 1);
|
||||
} else {
|
||||
lua_pushboolean(L, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_mkdir (lua_State *L) {
|
||||
const char* fname = lua_tostring(L, 1);
|
||||
if( mkdir( fname, 0755 ) != -1 ) {
|
||||
lua_pushboolean(L, 1);
|
||||
} else {
|
||||
lua_pushboolean(L, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_isdir (lua_State *L) {
|
||||
const char* fname = lua_tostring(L, 1);
|
||||
struct stat s;
|
||||
int err = stat(fname, &s);
|
||||
if(-1 == err) {
|
||||
lua_pushboolean(L, 0);
|
||||
} else {
|
||||
if(S_ISDIR(s.st_mode)) {
|
||||
lua_pushboolean(L, 1);
|
||||
} else {
|
||||
lua_pushboolean(L, 0);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_spaceUsed (lua_State *L) {
|
||||
const char* fname = lua_tostring(L, 1);
|
||||
struct statvfs s;
|
||||
if( statvfs(fname, &s) != -1 ) {
|
||||
lua_pushnumber(L, s.f_bsize * s.f_bfree);
|
||||
} else {
|
||||
lua_pushnumber(L, -1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_open (lua_State *L) {
|
||||
const char* fname = lua_tostring(L, 1);
|
||||
const char* mode = lua_tostring(L, 2);
|
||||
int m = 0;
|
||||
if(mode[0] == 'r') m = O_RDONLY;
|
||||
else if(mode[0] == 'w') m = O_WRONLY | O_CREAT /*| O_DIRECT*/;
|
||||
else if(mode[0] == 'a') m = O_WRONLY | O_APPEND | O_CREAT /*| O_DIRECT*/;
|
||||
else return 0;
|
||||
int fd = open(fname, m, 644);
|
||||
if(fd == -1) return 0;
|
||||
|
||||
lua_pushnumber(L, fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_seek (lua_State *L) {
|
||||
int fd = lua_tonumber(L, 1);
|
||||
int whence = lua_tonumber(L, 2);
|
||||
long offset = lua_tonumber(L, 3);
|
||||
|
||||
int w = 0;
|
||||
if(whence == 0) w = SEEK_CUR;
|
||||
else if(whence == 1) w = SEEK_SET;
|
||||
else if(whence == 2) w = SEEK_END;
|
||||
else return 0;
|
||||
int res = lseek(fd, w, offset);
|
||||
lua_pushnumber(L, res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_write (lua_State *L) {
|
||||
int fd = lua_tonumber(L, 1);
|
||||
size_t len = 0;
|
||||
const char* data = lua_tolstring(L, 2, &len);
|
||||
|
||||
//TODO: May not all data be written?
|
||||
if(write(fd, data, len) == -1) {
|
||||
lua_pushboolean(L, 0);
|
||||
} else {
|
||||
lua_pushboolean(L, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_spaceTotal (lua_State *L) {
|
||||
const char* fname = lua_tostring(L, 1);
|
||||
struct statvfs s;
|
||||
if( statvfs(fname, &s) != -1 ) {
|
||||
lua_pushnumber(L, s.f_frsize * s.f_blocks);
|
||||
} else {
|
||||
lua_pushnumber(L, -1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_rename (lua_State *L) {
|
||||
const char* from = lua_tostring(L, 1);
|
||||
const char* to = lua_tostring(L, 1);
|
||||
if( rename( from, to ) != -1 ) {
|
||||
lua_pushboolean(L, 1);
|
||||
} else {
|
||||
lua_pushboolean(L, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_list (lua_State *L) {
|
||||
const char* path = lua_tostring(L, 1);
|
||||
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
if ((dir = opendir(path)) != NULL) {
|
||||
lua_newtable(L);
|
||||
int n = 1;
|
||||
while ((ent = readdir(dir)) != NULL) { //TODO: Check if it should be freed
|
||||
lua_pushstring(L, ent->d_name);
|
||||
lua_rawseti(L, -2, n++);
|
||||
}
|
||||
closedir(dir);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_lastModified (lua_State *L) {
|
||||
const char* path = lua_tostring(L, 1);
|
||||
struct stat s;
|
||||
if( stat(path, &s) != -1 ) {
|
||||
lua_pushnumber(L, s.st_mtime);
|
||||
} else {
|
||||
return 0; //TODO: No error?
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rm(const char *path, const struct stat *s, int flag, struct FTW *f) {
|
||||
int status;
|
||||
int (*rm_func)(const char *);
|
||||
|
||||
switch(flag) {
|
||||
default: rm_func = unlink; break;
|
||||
case FTW_DP: rm_func = rmdir;
|
||||
}
|
||||
if(status = rm_func(path), status != 0)
|
||||
perror(path);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int l_fs_remove (lua_State *L) {
|
||||
const char* path = lua_tostring(L, 1);
|
||||
|
||||
if( nftw( path, rm, FOPEN_MAX, FTW_DEPTH )) {
|
||||
lua_pushboolean(L, 0);
|
||||
} else {
|
||||
lua_pushboolean(L, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_close (lua_State *L) {
|
||||
int fd = lua_tonumber(L, 1);
|
||||
|
||||
if(close(fd) == -1) {
|
||||
lua_pushboolean(L, 0);
|
||||
} else {
|
||||
lua_pushboolean(L, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_size (lua_State *L) {
|
||||
const char* path = lua_tostring(L, 1);
|
||||
struct stat s;
|
||||
if( stat(path, &s) != -1 ) {
|
||||
lua_pushnumber(L, s.st_size);
|
||||
} else {
|
||||
return 0; //TODO: No error?
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_fs_read (lua_State *L) {
|
||||
int fd = lua_tonumber(L, 1);
|
||||
int count = lua_tonumber(L, 2);
|
||||
void* buf = malloc(count);
|
||||
size_t res = read(fd, buf, count);
|
||||
if(res != -1) {
|
||||
lua_pushlstring(L, buf, res);
|
||||
free(buf);
|
||||
return 1;
|
||||
}
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CLOCK_TICK_RATE
|
||||
#define CLOCK_TICK_RATE 1193180
|
||||
#endif
|
||||
|
||||
//Filesystem end
|
||||
static int l_beep (lua_State *L) {
|
||||
int freq = lua_tonumber(L, 1);
|
||||
int btime = lua_tonumber(L, 2);
|
||||
int console_fd = -1;
|
||||
|
||||
if((console_fd = open("/dev/console", O_WRONLY)) == -1) {
|
||||
//fprintf(stderr, "Could not open /dev/console for writing.\n");
|
||||
printf("\a");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(ioctl(console_fd, KIOCSOUND, (int)(CLOCK_TICK_RATE/freq)) < 0) {
|
||||
printf("\a");
|
||||
return 0;
|
||||
}
|
||||
|
||||
usleep(1000 * btime);
|
||||
ioctl(console_fd, KIOCSOUND, 0);
|
||||
close(console_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void luanative_start(lua_State *L) {
|
||||
lua_createtable (L, 0, 1);
|
||||
pushctuple(L, "sleep", l_sleep);
|
||||
|
||||
pushctuple(L, "sleep", l_sleep);
|
||||
|
||||
pushctuple(L, "fs_exists", l_fs_exists);
|
||||
pushctuple(L, "fs_mkdir", l_fs_mkdir);
|
||||
pushctuple(L, "fs_isdir", l_fs_isdir);
|
||||
pushctuple(L, "fs_spaceUsed", l_fs_spaceUsed);
|
||||
pushctuple(L, "fs_open", l_fs_open);
|
||||
pushctuple(L, "fs_seek", l_fs_seek);
|
||||
pushctuple(L, "fs_write", l_fs_write);
|
||||
pushctuple(L, "fs_spaceTotal", l_fs_spaceTotal);
|
||||
pushctuple(L, "fs_rename", l_fs_rename);
|
||||
pushctuple(L, "fs_lastModified", l_fs_lastModified);
|
||||
pushctuple(L, "fs_remove", l_fs_remove);
|
||||
pushctuple(L, "fs_close", l_fs_close);
|
||||
pushctuple(L, "fs_size", l_fs_size);
|
||||
pushctuple(L, "fs_read", l_fs_read);
|
||||
|
||||
pushctuple(L, "beep", l_beep);
|
||||
|
||||
lua_setglobal(L, "native");
|
||||
}
|
@ -13,6 +13,7 @@ void setup_modules(lua_State *L) {
|
||||
pushstuple(L, "computer", lua_computer);
|
||||
pushstuple(L, "eeprom", lua_eeprom);
|
||||
pushstuple(L, "eepromDefault", lua_eepromDefault);
|
||||
pushstuple(L, "filesystem", lua_filesystem);
|
||||
pushstuple(L, "sandbox", lua_sandbox);
|
||||
pushstuple(L, "textgpu", lua_textgpu);
|
||||
pushstuple(L, "color", lua_util_color);
|
||||
|
12
src/c/run.c
12
src/c/run.c
@ -5,6 +5,15 @@
|
||||
#include <lauxlib.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void run_init() {
|
||||
lua_State *L;
|
||||
L = luaL_newstate();
|
||||
@ -14,7 +23,8 @@ void run_init() {
|
||||
luanative_start (L);
|
||||
termutils_start (L);
|
||||
|
||||
int status = luaL_loadstring(L, lua_init);
|
||||
//int status = luaL_loadstring(L, lua_init);
|
||||
int status = luaL_loadbuffer(L, lua_init, strlen(lua_init), "=INIT");
|
||||
if (status) {
|
||||
fprintf(stderr, "Couldn't load init: %s\n", lua_tostring(L, -1));
|
||||
exit(1);
|
||||
|
@ -4,39 +4,41 @@ function boot.boot()
|
||||
local gpu = modules.component.api.proxy(modules.component.api.list("gpu", true)())
|
||||
local w, h = gpu.getResolution()
|
||||
|
||||
local function bsod(err)
|
||||
local function bsod(...)
|
||||
gpu.setBackground(0x0000FF)
|
||||
gpu.setForeground(0xFFFFFF)
|
||||
gpu.fill(0, 0, w, h, " ")
|
||||
gpu.fill(1, 1, w, h, " ")
|
||||
gpu.set(2, 2, "CRITICAL ERROR OCCURED")
|
||||
gpu.set(2, 3, "Lua BIOS Has failed:")
|
||||
gpu.set(2, 5, tostring(err))
|
||||
io.flush()
|
||||
native.sleep(2000000)
|
||||
gpu.set(2, 3, "Lua BIOS has failed:")
|
||||
for n, v in pairs({...}) do
|
||||
gpu.set(2, 4 + n, tostring(v))
|
||||
end
|
||||
gpu.set(2, h-1, "SYSTEM WILL STOP")
|
||||
gpu.setForeground(0xFFFFFF)
|
||||
gpu.setBackground(0x000000)
|
||||
|
||||
native.sleep(4000000)
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
print("r= " .. tostring(w) .. " " .. tostring(h))
|
||||
gpu.fill(0, 0, w, h, " ")
|
||||
gpu.set(10, 5, "HHHHHHHHHHHHH")
|
||||
gpu.set(11, 11, "VVVVVVVVVVVVVVVVV", true)
|
||||
print("LuPI L2 INIT")
|
||||
|
||||
gpu.fill(1, 1, w, h, " ")
|
||||
gpu.set(1, h - 2, "LuPI L2 INIT")
|
||||
local code = modules.component.api.invoke(modules.component.api.list("eeprom", true)(), "get")
|
||||
if not code then
|
||||
print("No bootcode")
|
||||
error("No bootcode")
|
||||
bsod("No bootcode")
|
||||
end
|
||||
local f, reason = load(code, "=BIOS", nil, modules.sandbox)
|
||||
local f, reason = load(code, "=USERBIOS", nil, modules.sandbox)
|
||||
if not f then
|
||||
print(reason)
|
||||
bsod(reason)
|
||||
else
|
||||
local e, reason = pcall(f)
|
||||
if not e then
|
||||
bsod(reason)
|
||||
end
|
||||
print("System quit, Panic")
|
||||
xpcall(f, function(e)
|
||||
local trace = {}
|
||||
for s in string.gmatch(debug.traceback(e, 2), "[^\r\n]+") do
|
||||
trace[#trace + 1] = s
|
||||
end
|
||||
bsod("System crashed", "Stack traceback:", table.unpack(trace))
|
||||
end)
|
||||
bsod("System quit")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -35,7 +35,7 @@ function api.register(address, ctype, proxy, doc)
|
||||
end
|
||||
end
|
||||
modules.computer.api.pushSignal("component_added", address, ctype)
|
||||
return true
|
||||
return address
|
||||
end
|
||||
|
||||
function api.unregister(address)
|
||||
@ -65,7 +65,7 @@ function api.invoke(address, method, ...)
|
||||
error("No such component")
|
||||
end
|
||||
if not components[address].rawproxy[method] then
|
||||
error("No such method")
|
||||
error("No such method: " .. tostring(components[address].type) .. "." .. tostring(method))
|
||||
end
|
||||
return components[address].rawproxy[method](...)
|
||||
end
|
||||
|
@ -10,4 +10,10 @@ function api.pushSignal(...)
|
||||
--FIXME: ASAP: Implement
|
||||
end
|
||||
|
||||
function api.beep(freq, time)
|
||||
if not freq then freq = 1000 end
|
||||
if not time then time = 0.2 end
|
||||
native.beep(freq, time * 1000)
|
||||
end
|
||||
|
||||
return computer
|
158
src/lua/core/filesystem.lua
Normal file
158
src/lua/core/filesystem.lua
Normal file
@ -0,0 +1,158 @@
|
||||
--Native side at lnative.c
|
||||
|
||||
local filesystem = {}
|
||||
|
||||
local function segments(path)
|
||||
path = path:gsub("\\", "/")
|
||||
repeat local n; path, n = path:gsub("//", "/") until n == 0
|
||||
local parts = {}
|
||||
for part in path:gmatch("[^/]+") do
|
||||
table.insert(parts, part)
|
||||
end
|
||||
local i = 1
|
||||
while i <= #parts do
|
||||
if parts[i] == "." then
|
||||
table.remove(parts, i)
|
||||
elseif parts[i] == ".." then
|
||||
table.remove(parts, i)
|
||||
i = i - 1
|
||||
if i > 0 then
|
||||
table.remove(parts, i)
|
||||
else
|
||||
i = 1
|
||||
end
|
||||
else
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return parts
|
||||
end
|
||||
|
||||
local function canonical(path)
|
||||
local result = table.concat(segments(path), "/")
|
||||
if string.sub(path, 1, 1) == "/" then
|
||||
return "/" .. result
|
||||
else
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
local function concat(pathA, pathB, ...)
|
||||
checkArg(1, pathA, "string")
|
||||
checkArg(2, pathB, "string", "nil")
|
||||
local function _concat(n, a, b, ...)
|
||||
if not b then
|
||||
return a
|
||||
end
|
||||
checkArg(n, b, "string")
|
||||
return _concat(n + 1, a .. "/" .. b, ...)
|
||||
end
|
||||
return canonical(_concat(2, pathA, pathB, ...))
|
||||
end
|
||||
|
||||
function filesystem.register(basePath)
|
||||
checkArg(1, basePath, "string")
|
||||
|
||||
if not native.fs_exists(basePath) then
|
||||
native.fs_mkdir(basePath)
|
||||
end
|
||||
if not native.fs_isdir(basePath) then
|
||||
error("Filesystem root is not a directory!")
|
||||
end
|
||||
local function realpath(path)
|
||||
checkArg(1, path, "string")
|
||||
return concat(basePath, path)
|
||||
end
|
||||
|
||||
--TODO: checkArg all
|
||||
local fs = {}
|
||||
function fs.spaceUsed()
|
||||
return native.fs_spaceUsed(basePath)
|
||||
end
|
||||
function fs.open(path, mode)
|
||||
checkArg(1, path, "string")
|
||||
checkArg(2, path, "string", "nil")
|
||||
local m = "r"
|
||||
if mode == "a" then m = "a"
|
||||
elseif mode == "w" then m = "w" end
|
||||
local fd = native.fs_open(realpath(path), m)
|
||||
if not fd then
|
||||
return nil, path
|
||||
end
|
||||
return fd
|
||||
end
|
||||
function fs.seek(handle, whence, offset) --TODO: Test
|
||||
checkArg(1, handle, "number")
|
||||
checkArg(2, whence, "string")
|
||||
checkArg(3, offset, "number")
|
||||
local w = 0
|
||||
if whence == "cur" then w = 0
|
||||
elseif whence == "set" then w = 1
|
||||
elseif whence == "end" then w = 2
|
||||
else error("Invalid whence") end
|
||||
return native.fs_seek(handle, w, offset or 0)
|
||||
end
|
||||
function fs.makeDirectory(path) --TODO: check if creates parrent dirs
|
||||
checkArg(1, path, "string")
|
||||
return native.fs_mkdir(realpath(path))
|
||||
end
|
||||
function fs.exists(path)
|
||||
checkArg(1, path, "string")
|
||||
return native.fs_exists(realpath(path))
|
||||
end
|
||||
function fs.isReadOnly()
|
||||
return false --TODO: Implement
|
||||
end
|
||||
function fs.write(handle, value) --TODO: check behaviour on invalid FDs
|
||||
checkArg(1, handle, "number")
|
||||
checkArg(2, value, "string")
|
||||
return native.fs_write(handle, value)
|
||||
end
|
||||
function fs.spaceTotal()
|
||||
return native.fs_spaceTotal(basePath)
|
||||
end
|
||||
function fs.isDirectory(path)
|
||||
checkArg(1, path, "string")
|
||||
return native.fs_isdir(realpath(path))
|
||||
end
|
||||
function fs.rename(from, to)
|
||||
checkArg(1, from, "string")
|
||||
checkArg(2, to, "string")
|
||||
return native.fs_rename(realpath(from), realpath(to))
|
||||
end
|
||||
function fs.list(path)
|
||||
checkArg(1, path, "string")
|
||||
return native.fs_list(realpath(path)) --TODO: Test, check if dirs get / at end
|
||||
end
|
||||
function fs.lastModified(path)
|
||||
checkArg(1, path, "string")
|
||||
return native.fs_lastModified(realpath(path))
|
||||
end
|
||||
function fs.getLabel()
|
||||
return --TODO: Implement, use real labels
|
||||
end
|
||||
function fs.remove(path) --TODO: TEST!!
|
||||
checkArg(1, path, "string")
|
||||
return native.fs_remove(realpath(path))
|
||||
end
|
||||
function fs.close(handle)
|
||||
checkArg(1, handle, "number")
|
||||
return native.fs_close()
|
||||
end
|
||||
function fs.size(path)
|
||||
checkArg(1, path, "string")
|
||||
return native.fs_size(realpath(path))
|
||||
end
|
||||
function fs.read(handle, count) --FIXME: Hudgeread, fix in general
|
||||
checkArg(1, handle, "number")
|
||||
checkArg(2, count, "number")
|
||||
return native.fs_read(handle, count)
|
||||
end
|
||||
function fs.setLabel(value)
|
||||
checkArg(1, value, "number")
|
||||
return value --TODO: Implement, use real labels
|
||||
end
|
||||
return modules.component.api.register(nil, "filesystem", fs)
|
||||
end
|
||||
|
||||
return filesystem
|
@ -18,6 +18,7 @@ end
|
||||
|
||||
print("LuPI L1 INIT")
|
||||
modules = {}
|
||||
deadhooks = {}
|
||||
|
||||
local function loadModule(name)
|
||||
print("LuPI L1 INIT > Load module > " .. name)
|
||||
@ -26,7 +27,7 @@ local function loadModule(name)
|
||||
if not moduleCode[name] then
|
||||
error("No code for module " .. tostring(name))
|
||||
end
|
||||
local code, reason = load(moduleCode[name])
|
||||
local code, reason = load(moduleCode[name], "=Module "..name)
|
||||
if not code then
|
||||
print("Failed loading module " .. name .. ": " .. reason)
|
||||
else
|
||||
@ -34,28 +35,47 @@ local function loadModule(name)
|
||||
end
|
||||
end
|
||||
|
||||
--Load modules
|
||||
--Utils
|
||||
loadModule("random")
|
||||
loadModule("color")
|
||||
function main()
|
||||
--Load modules
|
||||
--Utils
|
||||
loadModule("random")
|
||||
loadModule("color")
|
||||
|
||||
--Core
|
||||
loadModule("component")
|
||||
loadModule("computer")
|
||||
--Core
|
||||
loadModule("component")
|
||||
loadModule("computer")
|
||||
|
||||
--Components
|
||||
loadModule("eeprom")
|
||||
loadModule("textgpu")
|
||||
--Components
|
||||
loadModule("eeprom")
|
||||
loadModule("textgpu")
|
||||
loadModule("filesystem")
|
||||
|
||||
--Userspace
|
||||
loadModule("sandbox")
|
||||
loadModule("boot")
|
||||
--Userspace
|
||||
loadModule("sandbox")
|
||||
loadModule("boot")
|
||||
|
||||
--Setup core modules
|
||||
modules.component.prepare()
|
||||
modules.computer.prepare()
|
||||
--Setup core modules
|
||||
modules.component.prepare()
|
||||
modules.computer.prepare()
|
||||
|
||||
modules.eeprom.register()
|
||||
modules.textgpu.start()
|
||||
modules.eeprom.register()
|
||||
modules.filesystem.register("root")
|
||||
modules.textgpu.start()
|
||||
|
||||
modules.boot.boot()
|
||||
modules.boot.boot()
|
||||
end
|
||||
|
||||
local state, cause = pcall(main)
|
||||
if not state then
|
||||
print("LuPI finished with following error:")
|
||||
print(cause)
|
||||
end
|
||||
|
||||
print("Running shutdown hooks")
|
||||
for k, hook in ipairs(deadhooks) do
|
||||
local state, cause = pcall(hook)
|
||||
if not state then
|
||||
print("Shutdown hook with following error:")
|
||||
print(cause)
|
||||
end
|
||||
end
|
@ -160,7 +160,8 @@ sandbox = {
|
||||
len = utf8.len,
|
||||
offset = utf8.offset
|
||||
},
|
||||
checkArg = checkArg
|
||||
checkArg = checkArg,
|
||||
og = _G
|
||||
}
|
||||
|
||||
sandbox._G = sandbox
|
||||
|
@ -25,7 +25,8 @@ function textgpu.start()
|
||||
return --TODO: Maybe?
|
||||
end
|
||||
background = modules.color.nearest(color, mapping)
|
||||
io.write("\x1b[4" .. background .. "m")
|
||||
io.write("\x1b[4" .. math.floor(background) .. "m")
|
||||
io.flush()
|
||||
end
|
||||
function gpu.setForeground(color, isPaletteIndex)
|
||||
checkArg(1, color, "number")
|
||||
@ -33,8 +34,9 @@ function textgpu.start()
|
||||
if isPaletteIndex then
|
||||
return --TODO: Maybe?
|
||||
end
|
||||
background = modules.color.nearest(color, mapping)
|
||||
io.write("\x1b[3" .. background .. "m")
|
||||
foreground = modules.color.nearest(color, mapping)
|
||||
io.write("\x1b[3" .. math.floor(foreground) .. "m")
|
||||
io.flush()
|
||||
end
|
||||
function gpu.getBackground()
|
||||
return mapping[background], false
|
||||
@ -79,6 +81,8 @@ function textgpu.start()
|
||||
checkArg(2, y, "number")
|
||||
checkArg(3, value, "string")
|
||||
checkArg(4, vertical, "boolean", "nil")
|
||||
x = math.floor(x)
|
||||
y = math.floor(y)
|
||||
if not vertical then
|
||||
io.write("\x1b[" .. y .. ";" .. x .. "H" .. value)
|
||||
else
|
||||
@ -87,6 +91,7 @@ function textgpu.start()
|
||||
io.write(c .. "\x1b[D\x1b[B")
|
||||
end)
|
||||
end
|
||||
io.flush()
|
||||
return true
|
||||
end
|
||||
function gpu.copy(x, y, w, h, tx, ty)
|
||||
@ -112,10 +117,15 @@ function textgpu.start()
|
||||
return true
|
||||
end
|
||||
|
||||
io.write("\x1b[?25l") --Disable cursor
|
||||
gpu.setForeground(0xFFFFFF)
|
||||
gpu.setBackground(0x000000)
|
||||
|
||||
modules.component.api.register(nil, "gpu", gpu)
|
||||
|
||||
deadhooks[#deadhooks + 1] = function()
|
||||
io.write("\x1b[?25h") --Enable cursor on quit
|
||||
end
|
||||
end
|
||||
|
||||
return textgpu
|
Loading…
Reference in New Issue
Block a user