/shell/main.c
#include <sysops.h>
#include <console.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
struct MemoryRange {
uint32_t start;
uint32_t length;
};
void svc64(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3);
__asm__(
".global svc64\n"
".type svc64,function\n"
"svc64:\n"
" svc #64\n"
" bx lr\n"
);
int peek(lua_State *L) {
int n_args = lua_gettop(L);
if (n_args != 1) {
puts("peek(addr)");
return 0;
}
uint32_t addr = lua_tointeger(L, 1);
uint32_t data = *(uint32_t *)addr;
lua_pushinteger(L, data);
return 1;
}
int poke(lua_State *L) {
int n_args = lua_gettop(L);
if (n_args != 2) {
puts("poke(addr, value)");
return 0;
}
uint32_t addr = lua_tointeger(L, 1);
uint32_t data = lua_tointeger(L, 2);
*(uint32_t *)addr = data;
return 0;
}
int keydebug() {
while (1) {
int k = sys_ops->console->readkey();
if (k == -1) continue;
if (is_command_key(k)) {
switch(k) {
case KEY_UP: puts("[up]"); break;
case KEY_DOWN: puts("[down]"); break;
case KEY_LEFT: puts("[left]"); break;
case KEY_RIGHT: puts("[right]"); break;
case KEY_ENTER: puts("[enter]"); break;
case KEY_BACKSPACE: puts("[backspace]"); break;
case KEY_TAB: puts("[tab]"); break;
case KEY_BREAK: puts("[break]"); break;
}
} else {
printf("%c (%02x)\n", (char)k, k);
}
}
}
void shell_main(struct MemoryRange *r) {
lua_State *L;
char buffer[128];
sys_ops->alloc->init(r->start, r->length);
L = luaL_newstate();
if (L == NULL) {
puts("Could not allocate lua state\r\n");
exit(EXIT_FAILURE);
}
luaL_openlibs(L);
lua_pushcfunction(L, peek);
lua_setglobal(L, "peek");
lua_pushcfunction(L, poke);
lua_setglobal(L, "poke");
puts(LUA_VERSION " Okay!\n");
while(1) {
fputs("> ", stdout);
fflush(stdout);
uint32_t n = sys_ops->console->readline((uint8_t *)buffer, 127);
buffer[n] = 0;
puts("");
if (strcmp(buffer, "clear") == 0) {
sys_ops->console->clear();
} else if (strcmp(buffer, "svcall") == 0) {
svc64(42, 69, 88, 64);
} else if (strcmp(buffer, "malloc") == 0) {
char *s = sys_ops->alloc->malloc(1024);
if (!s) {
puts("alloc failed");
continue;
}
const char hello[] = "Hello alloc!";
for (int i = 0; i < strlen(hello); i++) {
s[i] = hello[i];
}
} else if (strcmp(buffer, "dbz") == 0) {
// Enable DIV_0_TRP
*(uint32_t*)0xe000ed14 = 0x10;
__asm__(
"mov r0, #1\n"
"mov r1, #0\n"
"sdiv r0, r0, r1\n"
);
} else if (strcmp(buffer, "keydebug") == 0) {
keydebug();
} else {
luaL_loadstring(L, buffer);
int r = lua_pcall(L, 0, LUA_MULTRET, 0);
if (r != 0) {
fputs("error: ", stderr);
switch(r) {
case LUA_ERRRUN:
break;
case LUA_ERRMEM:
puts("memory allocation");
break;
case LUA_ERRERR:
puts("message handler");
break;
case LUA_ERRGCMM:
puts("__gc metamethod");
break;
default:
puts("unknown");
}
int top = lua_gettop(L);
puts(luaL_tolstring(L, top, NULL));
} else {
int top = lua_gettop(L);
if (top == 1) {
puts(luaL_tolstring(L, 1, NULL));
} else {
for (int i = 1; i <= top; i++) {
printf("%d: %s\n", i, luaL_tolstring(L, i, NULL));
}
}
}
lua_settop(L, 0);
}
}
}