#include "lua.h" #include "lua/lua.hpp" #include "lua.debug.h" #include "mini.h" #include "jfile.h" #include "log.h" #include #include #include #include #include #include #include #include #include #include #include #include #include //extern "C" { namespace mini { namespace lua { lua_State *L; bool is_playing = false; bool init_exists = false; bool update_exists = false; namespace wrappers { namespace surf { static int create(lua_State *L) { int w = luaL_checknumber(L, 1); int h = luaL_checknumber(L, 2); uint8_t s = mini::surf::create(w, h); if (s==255) { luaL_error(L, "Error while creating new surface: Max surfaces reached"); return 0; } lua_pushinteger(L, s); return 1; } static int load(lua_State *L) { const char* str = luaL_checkstring(L, 1); uint8_t s = mini::surf::load(str); if (s==255) { luaL_error(L, "Error while loading surface: Max surfaces reached"); return 0; } lua_pushinteger(L, s); return 1; } static int loadex(lua_State *L) { const char* str = luaL_checkstring(L, 1); uint8_t s = mini::surf::load(str, true); if (s==255) { luaL_error(L, "Error while loading surface: Max surfaces reached"); return 0; } lua_pushinteger(L, s); return 1; } static int save(lua_State *L) { uint8_t surface = luaL_checkinteger(L, 1); const char* str = luaL_checkstring(L, 2); if (lua_istable(L, -1)) { const int len = SDL_min(256, lua_rawlen(L, -1)); uint8_t *pal = (uint8_t*)malloc(len*3); uint8_t *p=pal; for (int i=1;i<=len;++i) { lua_rawgeti(L, -1, i); lua_getfield(L, -1, "r"); *(p++) = luaL_checknumber(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "g"); *(p++) = luaL_checknumber(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "b"); *(p++) = luaL_checknumber(L, -1); lua_pop(L, 1); lua_pop(L, 1); //pal[i-1] = (r<<16)+(g<<8)+b; } mini::surf::save(surface, str, pal, len); } else { mini::surf::save(surface, str, nullptr); } return 0; } static int free(lua_State *L) { uint8_t surface = luaL_checkinteger(L, 1); mini::surf::destroy(surface); return 0; } static int size(lua_State *L) { uint8_t surface = luaL_checkinteger(L, 1); lua_pushinteger(L, mini::surf::width(surface)); lua_pushinteger(L, mini::surf::height(surface)); return 2; } static int target(lua_State *L) { const int numargs = lua_gettop(L); switch (numargs) { case 0: { lua_pushinteger(L, mini::surf::target::get()); return 1; } case 1: { uint8_t surface = luaL_checkinteger(L, 1); mini::surf::target::set(surface); return 0; } default: return luaL_error(L, "Function 'surface.target' Unexpected number of parameters."); }; } static int source(lua_State *L) { const int numargs = lua_gettop(L); switch (numargs) { case 0: { lua_pushinteger(L, mini::surf::source::get()); return 1; } case 1: { uint8_t surface = luaL_checkinteger(L, 1); mini::surf::source::set(surface); return 0; } default: return luaL_error(L, "Function 'surface.source' Unexpected number of parameters."); }; } static int cls(lua_State *L) { uint8_t color = luaL_optinteger(L, 1, 0); mini::surf::cls(color); return 0; } static int pixel(lua_State *L) { if (lua_gettop(L)==2) { int x = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); lua_pushinteger(L, mini::surf::pixel::get(x, y)); return 1; } else { int x = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); uint8_t color = luaL_checkinteger(L, 3); mini::surf::pixel::set(x, y, color); return 0; } } } namespace map { static int surf(lua_State *L) { if (lua_gettop(L)==1) { uint8_t surface = luaL_checkinteger(L, 1); mini::map::surf::set(surface); } else { lua_pushinteger(L, mini::map::surf::get()); return 1; } return 0; } static int draw(lua_State *L) { mini::map::draw(); return 0; } static int tile(lua_State *L) { if (lua_gettop(L)==2) { int celx = luaL_checknumber(L, 1); int cely = luaL_checknumber(L, 2); lua_pushinteger(L, mini::map::tile::get(celx, cely)); return 1; } else { int celx = luaL_checknumber(L, 1); int cely = luaL_checknumber(L, 2); uint8_t snum = luaL_checkinteger(L, 3); mini::map::tile::set(celx, cely, snum); return 0; } } static int cell(lua_State *L) { if (lua_gettop(L)==2) { int celx = luaL_checknumber(L, 1); int cely = luaL_checknumber(L, 2); mini::map::cell::set(celx, cely); return 0; } else { lua_pushinteger(L, mini::map::cell::getw()); lua_pushinteger(L, mini::map::cell::geth()); return 2; } } } namespace pal { static int load(lua_State *L) { const char* str = luaL_checkstring(L, 1); uint16_t size; uint32_t *pal = mini::pal::load(str, &size); lua_createtable(L, 2, 0); for (int i=0;i>16)&0xff); lua_setfield(L, -2, "r"); lua_pushinteger(L, (color>>8)&0xff); lua_setfield(L, -2, "g"); lua_pushinteger(L, color&0xff); lua_setfield(L, -2, "b"); lua_rawseti(L, -2, i+1); } free(pal); return 1; } static int set(lua_State *L) { int r,g,b; if (lua_istable(L, -1)) { uint32_t pal[256]; const int len = SDL_min(256, lua_rawlen(L, -1)); for (int i=0;i>16)&0xff); lua_pushinteger(L, (color>>8)&0xff); lua_pushinteger(L, color&0xff); return 3; } else { uint8_t index = luaL_checkinteger(L, 1); uint8_t r = luaL_checkinteger(L, 2); uint8_t g = luaL_optinteger(L, 3, 0); uint8_t b = luaL_optinteger(L, 4, 0); uint32_t color = (r<<16) + (g<<8) + b; mini::pal::color::set(index, color); return 0; } } static int trans(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushinteger(L, mini::pal::trans::get()); return 1; } else { uint8_t index = luaL_checkinteger(L, 1); mini::pal::trans::set(index); return 0; } } static int subpal(lua_State *L) { const int num_params = lua_gettop(L); uint8_t index, index2, color; switch (num_params) { case 0: mini::pal::subpal::reset(); break; case 1: index = luaL_checkinteger(L, 1); lua_pushinteger(L, mini::pal::subpal::set(index,index)); return 1; break; case 2: index = luaL_checkinteger(L, 1); color = luaL_checkinteger(L, 2); lua_pushinteger(L, mini::pal::subpal::set(index, color)); return 1; break; case 3: index = luaL_checkinteger(L, 1); index2 = luaL_checkinteger(L, 2); color = luaL_checkinteger(L, 3); for (int i=index;i<=index2;++i) mini::pal::subpal::set(i, color); break; } return 0; } } namespace view { static int clip(lua_State *L) { if (lua_gettop(L)==0) { mini::view::clip::reset(); return 0; } else { int x = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); int w = luaL_checknumber(L, 3); int h = luaL_checknumber(L, 4); mini::view::clip::set(x, y, w, h); return 0; } } static int origin(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushinteger(L, mini::view::origin::getx()); lua_pushinteger(L, mini::view::origin::gety()); return 2; } else { int x = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); mini::view::origin::set(x, y); return 0; } } static int tolocal(lua_State *L) { int x = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); lua_pushinteger(L, x+mini::view::origin::getx()); lua_pushinteger(L, y+mini::view::origin::gety()); return 2; } } namespace draw { static int line(lua_State *L) { int x0 = luaL_checknumber(L, 1); int y0 = luaL_checknumber(L, 2); int x1 = luaL_checknumber(L, 3); int y1 = luaL_checknumber(L, 4); uint8_t color = luaL_checkinteger(L, 5); mini::draw::line(x0, y0, x1, y1, color); return 0; } static int hline(lua_State *L) { int x0 = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); int x1 = luaL_checknumber(L, 3); uint8_t color = luaL_checkinteger(L, 4); mini::draw::hline(x0, y, x1, color); return 0; } static int vline(lua_State *L) { int x = luaL_checknumber(L, 1); int y0 = luaL_checknumber(L, 2); int y1 = luaL_checknumber(L, 3); uint8_t color = luaL_checkinteger(L, 4); mini::draw::vline(x, y0, y1, color); return 0; } static int rect(lua_State *L) { int x = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); int w = luaL_checknumber(L, 3); int h = luaL_checknumber(L, 4); uint8_t color = luaL_checkinteger(L, 5); mini::draw::rect(x, y, w, h, color); return 0; } static int rectf(lua_State *L) { int x = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); int w = luaL_checknumber(L, 3); int h = luaL_checknumber(L, 4); uint8_t color = luaL_checkinteger(L, 5); mini::draw::rectf(x, y, w, h, color); return 0; } static int circ(lua_State *L) { int x = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); int r = luaL_optnumber(L, 3, 4); uint8_t color = luaL_checkinteger(L, 4); mini::draw::circ(x, y, r, color); return 0; } static int circf(lua_State *L) { int x = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); int r = luaL_optnumber(L, 3, 4); uint8_t color = luaL_checkinteger(L, 4); mini::draw::circf(x, y, r, color); return 0; } static int roundrect(lua_State *L) { int x = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); int w = luaL_checknumber(L, 3); int h = luaL_checknumber(L, 4); int r = luaL_optnumber(L, 5, 4); uint8_t color = luaL_checkinteger(L, 6); mini::draw::roundrect(x, y, w, h, r, color); return 0; } static int roundrectf(lua_State *L) { int x = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); int w = luaL_checknumber(L, 3); int h = luaL_checknumber(L, 4); int r = luaL_optnumber(L, 5, 4); uint8_t color = luaL_checkinteger(L, 6); mini::draw::roundrectf(x, y, w, h, r, color); return 0; } static int oval(lua_State *L) { int x0 = luaL_checknumber(L, 1); int y0 = luaL_checknumber(L, 2); int x1 = luaL_checknumber(L, 3); int y1 = luaL_checknumber(L, 4); uint8_t color = luaL_checkinteger(L, 5); mini::draw::oval(x0, y0, x1, y1, color); return 0; } static int ovalf(lua_State *L) { int x0 = luaL_checknumber(L, 1); int y0 = luaL_checknumber(L, 2); int x1 = luaL_checknumber(L, 3); int y1 = luaL_checknumber(L, 4); uint8_t color = luaL_checkinteger(L, 5); mini::draw::ovalf(x0, y0, x1, y1, color); return 0; } static int pattern(lua_State *L) { if (lua_gettop(L) == 0) { mini::draw::pattern::set(0xffff); } else { uint16_t pat = luaL_checkinteger(L, 1); bool transparent = lua_toboolean(L, 2); mini::draw::pattern::set(pat, transparent); } return 0; } static int surf(lua_State *L) { int sx = luaL_checknumber(L, 1); int sy = luaL_checknumber(L, 2); int sw = luaL_checknumber(L, 3); int sh = luaL_checknumber(L, 4); int dx = luaL_checknumber(L, 5); int dy = luaL_checknumber(L, 6); int dw = luaL_optnumber(L, 7, 0); int dh = luaL_optnumber(L, 8, 0); bool flip_x = lua_toboolean(L, 9); bool flip_y = lua_toboolean(L, 10); bool invert = lua_toboolean(L, 11); mini::draw::surf(sx, sy, sw, sh, dx, dy, dw, dh, flip_x, flip_y, invert); return 0; } static int surfrot(lua_State *L) { int sx = luaL_checknumber(L, 1); int sy = luaL_checknumber(L, 2); int sw = luaL_checknumber(L, 3); int sh = luaL_checknumber(L, 4); int dx = luaL_checknumber(L, 5); int dy = luaL_checknumber(L, 6); float a = luaL_checknumber(L, 7); int dw = luaL_optnumber(L, 8, 0); int dh = luaL_optnumber(L, 9, 0); bool flip_x = lua_toboolean(L, 10); bool flip_y = lua_toboolean(L, 11); mini::draw::surfrot(sx, sy, sw, sh, dx, dy, dw, dh, flip_x, flip_y, a); return 0; } static int text(lua_State *L) { const char* str = luaL_checkstring(L, 1); int x = luaL_checknumber(L, 2); int y = luaL_checknumber(L, 3); uint8_t color = luaL_checkinteger(L, 4); mini::draw::text(str, x, y, color); return 0; } static int mode(lua_State *L) { int mode = luaL_checknumber(L, 1); mini::draw::mode::set(mode); return 0; } } namespace shader { static int init(lua_State *L) { const char* vstr = luaL_optstring(L, 1, NULL); const char* fstr = luaL_optstring(L, 2, NULL); mini::shader::init(vstr, fstr); return 0; } static int enable(lua_State *L) { mini::shader::enable(); return 0; } static int disable(lua_State *L) { mini::shader::disable(); return 0; } } namespace music { static int play(lua_State *L) { const char* str = luaL_checkstring(L, 1); const int loop = luaL_optinteger(L, 2, -1); mini::audio::music::play(str, loop); return 0; } static int pause(lua_State *L) { mini::audio::music::pause(); return 0; } static int resume(lua_State *L) { mini::audio::music::resume(); return 0; } static int stop(lua_State *L) { const int time = luaL_optinteger(L, 1, 1000); mini::audio::music::stop(time); return 0; } static int pos(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushnumber(L, mini::audio::music::pos::get()); return 1; } else { mini::audio::music::pos::set(luaL_checknumber(L, 1)); return 0; } } static int enable(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushboolean(L, mini::audio::music::enable::get()); return 1; } else { mini::audio::music::enable::set(lua_toboolean(L, 1)); return 0; } } } namespace sound { static int load(lua_State *L) { const char* str = luaL_checkstring(L, 1); lua_pushinteger(L, mini::audio::sound::load(str)); return 1; } static int free(lua_State *L) { const int sound = luaL_checknumber(L, 1); mini::audio::sound::free(sound); return 0; } static int play(lua_State *L) { const int sound = luaL_checknumber(L, 1); const int volume = luaL_optinteger(L, 2, -1); lua_pushinteger(L, mini::audio::sound::play(sound, volume)); return 1; } static int stop(lua_State *L) { const int sound = luaL_checknumber(L, 1); mini::audio::sound::stop(sound); return 0; } static int enable(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushboolean(L, mini::audio::sound::enable::get()); return 1; } else { mini::audio::sound::enable::set(lua_toboolean(L, 1)); return 0; } } } namespace sys { static int delta(lua_State *L) { lua_pushnumber(L, mini::sys::delta()); return 1; } static int time(lua_State *L) { lua_pushnumber(L, mini::sys::time()); return 1; } static uint32_t chrono_time = 0; static int chrono(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushnumber(L, float(SDL_GetTicks()-chrono_time)/1000.0f); return 1; } else { chrono_time = SDL_GetTicks(); return 0; } } static int beat(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushboolean(L, mini::sys::beat(-1)); return 1; } else { int16_t beats = luaL_optnumber(L, 1, -1); mini::sys::beat(beats); return 0; } } static int update(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushinteger(L, mini::sys::update::get()); return 1; } else { int mode = luaL_checknumber(L, 1); int interval = luaL_optinteger(L, 2, 0); mini::sys::update::set(mode, interval); return 0; } } namespace fs = std::filesystem; static int dir(lua_State *L) { std::string path = "./data"; if (lua_gettop(L) > 0) path = luaL_checkstring(L, 1); // Collect entries std::vector entries; for (const auto& entry : fs::directory_iterator(path)) { entries.push_back(entry); } // Sort: directories first, then files; both alphabetically std::sort(entries.begin(), entries.end(), [](const fs::directory_entry& a, const fs::directory_entry& b) { bool adir = a.is_directory(); bool bdir = b.is_directory(); if (adir != bdir) return adir > bdir; // directories before files return a.path().filename().string() < b.path().filename().string(); }); // Build Lua table lua_newtable(L); int i = 1; for (const auto& entry : entries) { lua_newtable(L); // name field (canonical absolute path) lua_pushstring(L, (const char*)fs::canonical(entry.path()).u8string().c_str()); lua_setfield(L, -2, "name"); // dir field lua_pushboolean(L, entry.is_directory()); lua_setfield(L, -2, "dir"); lua_rawseti(L, -2, i++); } return 1; } static int exit(lua_State *L) { mini::sys::exit(); return 0; } static int fps(lua_State *L) { lua_pushnumber(L, mini::sys::getfps()); return 1; } static int debug(lua_State *L) { #ifdef DEBUG lua_pushboolean(L, true); #else lua_pushboolean(L, false); #endif return 1; } static int clipboard(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushstring(L, SDL_GetClipboardText()); return 1; } else { const char* value = luaL_checkstring(L, 1); SDL_SetClipboardText(value); return 0; } } static int version(lua_State *L) { lua_pushstring(L, MINI_VERSION); return 1; } } namespace win { static int zoom(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushinteger(L, mini::win::zoom::get()); return 1; } else { const int value = luaL_optinteger(L, 1, 0); mini::win::zoom::set(value); return 0; } } static int fullscreen(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushboolean(L, mini::win::fullscreen::get()); return 1; } else { mini::win::fullscreen::set(lua_toboolean(L, 1)); return 0; } } static int cursor(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushboolean(L, mini::win::cursor::get()); return 1; } else { mini::win::cursor::set(lua_toboolean(L, 1)); return 0; } } static int res(lua_State *L) { if (lua_gettop(L) == 0) { lua_pushinteger(L, mini::win::res::getw()); lua_pushinteger(L, mini::win::res::geth()); return 2; } else { const int w = luaL_optinteger(L, 1, 160); const int h = luaL_optinteger(L, 2, 120); mini::win::res::set(w, h); return 0; } } } namespace conf { static int key(lua_State *L) { const char* key = luaL_checkstring(L, 1); if (lua_gettop(L) > 1) { const char* value = luaL_checkstring(L, 2); mini::config::key::set(key, value); return 0; } else { const char* value = mini::config::key::get(key); if (value==NULL) { lua_pushnil(L); } else { lua_pushstring(L, value); } return 1; } } static int folder(lua_State *L) { lua_pushstring(L, mini::config::folder()); return 1; } } namespace font { static int load(lua_State *L) { const char* str = luaL_checkstring(L, 1); uint8_t s = mini::font::load(str); if (s==255) { luaL_error(L, "Error while loading font: Max fonts reached"); return 0; } lua_pushinteger(L, s); return 1; } static int current(lua_State *L) { const int numargs = lua_gettop(L); switch (numargs) { case 0: { lua_pushinteger(L, mini::font::current::get()); return 1; } case 1: { uint8_t font = luaL_checkinteger(L, 1); mini::font::current::set(font); return 0; } default: return luaL_error(L, "Function 'font.current' Unexpected number of parameters."); }; } static int spacing(lua_State *L) { const int numargs = lua_gettop(L); switch (numargs) { case 0: { lua_pushinteger(L, mini::font::spacing::get()); return 1; } case 1: { uint8_t spacing = luaL_checkinteger(L, 1); mini::font::spacing::set(spacing); return 0; } default: return luaL_error(L, "Function 'font.spacing' Unexpected number of parameters."); }; } } namespace mouse { static int pos(lua_State *L) { lua_pushinteger(L, mini::mouse::posx()); lua_pushinteger(L, mini::mouse::posy()); return 2; } static int wheel(lua_State *L) { lua_pushinteger(L, mini::mouse::wheel()); return 1; } static int down(lua_State *L) { uint8_t i = luaL_checkinteger(L, 1); lua_pushboolean(L, mini::mouse::down(i)); return 1; } static int press(lua_State *L) { uint8_t i = luaL_checkinteger(L, 1); lua_pushboolean(L, mini::mouse::press(i)); return 1; } static int dblclick(lua_State *L) { lua_pushboolean(L, mini::mouse::dblclick()); return 1; } static int discard(lua_State *L) { mini::mouse::discard(); return 0; } static int inside(lua_State *L) { int x = luaL_checkinteger(L, 1); int y = luaL_checkinteger(L, 2); int w = luaL_checkinteger(L, 3); int h = luaL_checkinteger(L, 4); lua_pushboolean(L, mini::mouse::inside(x,y,w,h)); return 1; } } namespace key { static int down(lua_State *L) { uint8_t i = luaL_checkinteger(L, 1); lua_pushboolean(L, mini::key::down(i)); return 1; } static int press(lua_State *L) { if (lua_gettop(L) >=1 ) { uint8_t i = luaL_checkinteger(L, 1); lua_pushboolean(L, mini::key::press(i)); } else { lua_pushinteger(L, mini::key::press()); } return 1; } static int any(lua_State *L) { lua_pushboolean(L, mini::key::any()); return 1; } static int text(lua_State *L) { mini::key::text(lua_toboolean(L, 1)); return 0; } static int utf8char(lua_State *L) { lua_pushstring(L, mini::key::utf8char()); return 1; } } namespace pad { static int down(lua_State *L) { int8_t i = luaL_checkinteger(L, 1); lua_pushboolean(L, mini::pad::down(i)); return 1; } static int press(lua_State *L) { if (lua_gettop(L) >=1 ) { int8_t i = luaL_checkinteger(L, 1); lua_pushboolean(L, mini::pad::press(i)); } else { lua_pushinteger(L, mini::pad::press()); } return 1; } static int any(lua_State *L) { lua_pushinteger(L, mini::pad::press()); return 1; } } } } } static int cpp_utf8_sub(lua_State *L) { size_t slen; const char *s = luaL_checklstring(L, 1, &slen); int i = luaL_checkinteger(L, 2); int j = luaL_optinteger(L, 3, -1); // Get utf8.offset lua_getglobal(L, "utf8"); lua_getfield(L, -1, "offset"); // Compute start byte index lua_pushvalue(L, 1); // string lua_pushinteger(L, i); // start index lua_call(L, 2, 1); // utf8.offset(s, i) lua_Integer start = lua_tointeger(L, -1); lua_pop(L, 1); if (start == 0) { lua_pushliteral(L, ""); lua_pop(L, 1); // pop utf8 table return 1; } // Compute end byte index (j+1) lua_getfield(L, -1, "offset"); lua_pushvalue(L, 1); lua_pushinteger(L, j + 1); lua_call(L, 2, 1); lua_Integer end = lua_tointeger(L, -1); lua_pop(L, 2); // pop result + utf8 table if (end == 0) { // until end of string lua_pushlstring(L, s + start - 1, slen - (start - 1)); return 1; } lua_pushlstring(L, s + start - 1, (end - 1) - (start - 1)); return 1; } namespace mini { namespace lua { bool running() { debug::process_commands(L); return is_playing; } void push_functions() { lua_newtable(L); lua_setglobal(L, "mini"); lua_newtable(L); lua_pushcfunction(L,wrappers::surf::create); lua_setfield(L, -2, "new"); lua_pushcfunction(L,wrappers::surf::load); lua_setfield(L, -2, "load"); lua_pushcfunction(L,wrappers::surf::loadex); lua_setfield(L, -2, "loadex"); lua_pushcfunction(L,wrappers::surf::save); lua_setfield(L, -2, "save"); lua_pushcfunction(L,wrappers::surf::free); lua_setfield(L, -2, "free"); lua_pushcfunction(L,wrappers::surf::size); lua_setfield(L, -2, "size"); lua_pushcfunction(L,wrappers::surf::target); lua_setfield(L, -2, "target"); lua_pushcfunction(L,wrappers::surf::source); lua_setfield(L, -2, "source"); lua_pushcfunction(L,wrappers::surf::cls); lua_setfield(L, -2, "cls"); lua_pushcfunction(L,wrappers::surf::pixel); lua_setfield(L, -2, "pixel"); lua_pushinteger(L, 0); lua_setfield(L, -2, "SCREEN"); lua_setglobal(L, "surf"); lua_newtable(L); lua_pushcfunction(L,wrappers::map::surf); lua_setfield(L, -2, "surf"); lua_pushcfunction(L,wrappers::map::draw); lua_setfield(L, -2, "draw"); lua_pushcfunction(L,wrappers::map::tile); lua_setfield(L, -2, "tile"); lua_pushcfunction(L,wrappers::map::cell); lua_setfield(L, -2, "cell"); lua_setglobal(L, "map"); lua_newtable(L); lua_pushcfunction(L,wrappers::pal::load); lua_setfield(L, -2, "load"); lua_pushcfunction(L,wrappers::pal::set); lua_setfield(L, -2, "set"); lua_pushcfunction(L,wrappers::pal::color); lua_setfield(L, -2, "color"); lua_pushcfunction(L,wrappers::pal::trans); lua_setfield(L, -2, "trans"); lua_pushcfunction(L,wrappers::pal::subpal); lua_setfield(L, -2, "subpal"); lua_setglobal(L, "pal"); lua_newtable(L); lua_pushcfunction(L,wrappers::view::clip); lua_setfield(L, -2, "clip"); lua_pushcfunction(L,wrappers::view::origin); lua_setfield(L, -2, "origin"); lua_pushcfunction(L,wrappers::view::tolocal); lua_setfield(L, -2, "tolocal"); lua_setglobal(L, "view"); lua_newtable(L); lua_pushcfunction(L,wrappers::draw::line); lua_setfield(L, -2, "line"); lua_pushcfunction(L,wrappers::draw::hline); lua_setfield(L, -2, "hline"); lua_pushcfunction(L,wrappers::draw::vline); lua_setfield(L, -2, "vline"); lua_pushcfunction(L,wrappers::draw::rect); lua_setfield(L, -2, "rect"); lua_pushcfunction(L,wrappers::draw::rectf); lua_setfield(L, -2, "rectf"); lua_pushcfunction(L,wrappers::draw::circ); lua_setfield(L, -2, "circ"); lua_pushcfunction(L,wrappers::draw::circf); lua_setfield(L, -2, "circf"); lua_pushcfunction(L,wrappers::draw::roundrect); lua_setfield(L, -2, "rrect"); lua_pushcfunction(L,wrappers::draw::roundrectf); lua_setfield(L, -2, "rrectf"); lua_pushcfunction(L,wrappers::draw::oval); lua_setfield(L, -2, "oval"); lua_pushcfunction(L,wrappers::draw::ovalf); lua_setfield(L, -2, "ovalf"); lua_pushcfunction(L,wrappers::draw::pattern); lua_setfield(L, -2, "pattern"); lua_pushcfunction(L,wrappers::draw::surf); lua_setfield(L, -2, "surf"); lua_pushcfunction(L,wrappers::draw::surfrot); lua_setfield(L, -2, "surfrot"); lua_pushcfunction(L,wrappers::draw::text); lua_setfield(L, -2, "text"); lua_pushcfunction(L,wrappers::draw::mode); lua_setfield(L, -2, "mode"); lua_pushinteger(L, 0); lua_setfield(L, -2, "NORMAL"); lua_pushinteger(L, 1); lua_setfield(L, -2, "PATTERN"); lua_pushinteger(L, 2); lua_setfield(L, -2, "AND"); lua_pushinteger(L, 3); lua_setfield(L, -2, "OR"); lua_pushinteger(L, 4); lua_setfield(L, -2, "XOR"); lua_pushinteger(L, 5); lua_setfield(L, -2, "NOT"); lua_setglobal(L, "draw"); lua_newtable(L); lua_pushcfunction(L,wrappers::shader::init); lua_setfield(L, -2, "init"); lua_pushcfunction(L,wrappers::shader::enable); lua_setfield(L, -2, "enable"); lua_pushcfunction(L,wrappers::shader::disable); lua_setfield(L, -2, "disable"); lua_setglobal(L, "shader"); lua_newtable(L); lua_pushcfunction(L,wrappers::music::play); lua_setfield(L, -2, "play"); lua_pushcfunction(L,wrappers::music::pause); lua_setfield(L, -2, "pause"); lua_pushcfunction(L,wrappers::music::resume); lua_setfield(L, -2, "resume"); lua_pushcfunction(L,wrappers::music::stop); lua_setfield(L, -2, "stop"); lua_pushcfunction(L,wrappers::music::pos); lua_setfield(L, -2, "pos"); lua_pushcfunction(L,wrappers::music::enable); lua_setfield(L, -2, "enabled"); lua_setglobal(L, "music"); lua_newtable(L); lua_pushcfunction(L,wrappers::sound::load); lua_setfield(L, -2, "load"); lua_pushcfunction(L,wrappers::sound::free); lua_setfield(L, -2, "free"); lua_pushcfunction(L,wrappers::sound::play); lua_setfield(L, -2, "play"); lua_pushcfunction(L,wrappers::sound::stop); lua_setfield(L, -2, "stop"); lua_pushcfunction(L,wrappers::sound::enable); lua_setfield(L, -2, "enabled"); lua_setglobal(L, "sound"); lua_newtable(L); lua_pushcfunction(L,wrappers::sys::delta); lua_setfield(L, -2, "delta"); lua_pushcfunction(L,wrappers::sys::time); lua_setfield(L, -2, "time"); lua_pushcfunction(L,wrappers::sys::chrono); lua_setfield(L, -2, "chrono"); lua_pushcfunction(L,wrappers::sys::beat); lua_setfield(L, -2, "beat"); lua_pushcfunction(L,wrappers::sys::update); lua_setfield(L, -2, "update"); lua_pushcfunction(L,wrappers::sys::dir); lua_setfield(L, -2, "dir"); lua_pushcfunction(L,wrappers::sys::exit); lua_setfield(L, -2, "quit"); lua_pushcfunction(L,wrappers::sys::fps); lua_setfield(L, -2, "fps"); lua_pushcfunction(L,wrappers::sys::debug); lua_setfield(L, -2, "debug"); lua_pushcfunction(L,wrappers::sys::clipboard); lua_setfield(L, -2, "clipboard"); lua_pushcfunction(L,wrappers::sys::version); lua_setfield(L, -2, "version"); lua_pushinteger(L, 0); lua_setfield(L, -2, "UPDATE_ALWAYS"); lua_pushinteger(L, 1); lua_setfield(L, -2, "UPDATE_WAIT"); lua_pushinteger(L, 2); lua_setfield(L, -2, "UPDATE_TIMEOUT"); lua_setglobal(L, "sys"); lua_newtable(L); lua_pushcfunction(L,wrappers::win::zoom); lua_setfield(L, -2, "zoom"); lua_pushcfunction(L,wrappers::win::fullscreen); lua_setfield(L, -2, "fullscreen"); lua_pushcfunction(L,wrappers::win::cursor); lua_setfield(L, -2, "cursor"); lua_pushcfunction(L,wrappers::win::res); lua_setfield(L, -2, "res"); lua_setglobal(L, "win"); lua_newtable(L); lua_pushcfunction(L,wrappers::conf::key); lua_setfield(L, -2, "key"); lua_pushcfunction(L,wrappers::conf::folder); lua_setfield(L, -2, "folder"); lua_setglobal(L, "config"); lua_newtable(L); lua_pushcfunction(L,wrappers::font::load); lua_setfield(L, -2, "load"); lua_pushcfunction(L,wrappers::font::current); lua_setfield(L, -2, "current"); lua_pushcfunction(L,wrappers::font::spacing); lua_setfield(L, -2, "spacing"); lua_pushinteger(L, 0); lua_setfield(L, -2, "DEFAULT"); lua_setglobal(L, "font"); lua_newtable(L); lua_pushcfunction(L,wrappers::mouse::pos); lua_setfield(L, -2, "pos"); lua_pushcfunction(L,wrappers::mouse::wheel); lua_setfield(L, -2, "wheel"); lua_pushcfunction(L,wrappers::mouse::down); lua_setfield(L, -2, "down"); lua_pushcfunction(L,wrappers::mouse::press); lua_setfield(L, -2, "press"); lua_pushcfunction(L,wrappers::mouse::dblclick); lua_setfield(L, -2, "dblclick"); lua_pushcfunction(L,wrappers::mouse::discard); lua_setfield(L, -2, "discard"); lua_pushcfunction(L,wrappers::mouse::inside); lua_setfield(L, -2, "inside"); lua_pushinteger(L, 1); lua_setfield(L, -2, "LEFT"); lua_pushinteger(L, 2); lua_setfield(L, -2, "MIDDLE"); lua_pushinteger(L, 3); lua_setfield(L, -2, "RIGHT"); lua_setglobal(L, "mouse"); lua_newtable(L); lua_pushcfunction(L,wrappers::key::down); lua_setfield(L, -2, "down"); lua_pushcfunction(L,wrappers::key::press); lua_setfield(L, -2, "press"); lua_pushcfunction(L,wrappers::key::any); lua_setfield(L, -2, "any"); lua_pushcfunction(L,wrappers::key::text); lua_setfield(L, -2, "text"); lua_pushcfunction(L,wrappers::key::utf8char); lua_setfield(L, -2, "utf8char"); //lua_setglobal(L, "key"); //lua_newtable(L); lua_pushinteger(L, 0); lua_setfield(L, -2, "UNKNOWN"); lua_pushinteger(L, 4); lua_setfield(L, -2, "A"); lua_pushinteger(L, 5); lua_setfield(L, -2, "B"); lua_pushinteger(L, 6); lua_setfield(L, -2, "C"); lua_pushinteger(L, 7); lua_setfield(L, -2, "D"); lua_pushinteger(L, 8); lua_setfield(L, -2, "E"); lua_pushinteger(L, 9); lua_setfield(L, -2, "F"); lua_pushinteger(L, 10); lua_setfield(L, -2, "G"); lua_pushinteger(L, 11); lua_setfield(L, -2, "H"); lua_pushinteger(L, 12); lua_setfield(L, -2, "I"); lua_pushinteger(L, 13); lua_setfield(L, -2, "J"); lua_pushinteger(L, 14); lua_setfield(L, -2, "K"); lua_pushinteger(L, 15); lua_setfield(L, -2, "L"); lua_pushinteger(L, 16); lua_setfield(L, -2, "M"); lua_pushinteger(L, 17); lua_setfield(L, -2, "N"); lua_pushinteger(L, 18); lua_setfield(L, -2, "O"); lua_pushinteger(L, 19); lua_setfield(L, -2, "P"); lua_pushinteger(L, 20); lua_setfield(L, -2, "Q"); lua_pushinteger(L, 21); lua_setfield(L, -2, "R"); lua_pushinteger(L, 22); lua_setfield(L, -2, "S"); lua_pushinteger(L, 23); lua_setfield(L, -2, "T"); lua_pushinteger(L, 24); lua_setfield(L, -2, "U"); lua_pushinteger(L, 25); lua_setfield(L, -2, "V"); lua_pushinteger(L, 26); lua_setfield(L, -2, "W"); lua_pushinteger(L, 27); lua_setfield(L, -2, "X"); lua_pushinteger(L, 28); lua_setfield(L, -2, "Y"); lua_pushinteger(L, 29); lua_setfield(L, -2, "Z"); lua_pushinteger(L, 30); lua_setfield(L, -2, "N1"); lua_pushinteger(L, 31); lua_setfield(L, -2, "N2"); lua_pushinteger(L, 32); lua_setfield(L, -2, "N3"); lua_pushinteger(L, 33); lua_setfield(L, -2, "N4"); lua_pushinteger(L, 34); lua_setfield(L, -2, "N5"); lua_pushinteger(L, 35); lua_setfield(L, -2, "N6"); lua_pushinteger(L, 36); lua_setfield(L, -2, "N7"); lua_pushinteger(L, 37); lua_setfield(L, -2, "N8"); lua_pushinteger(L, 38); lua_setfield(L, -2, "N9"); lua_pushinteger(L, 39); lua_setfield(L, -2, "N0"); lua_pushinteger(L, 40); lua_setfield(L, -2, "RETURN"); lua_pushinteger(L, 41); lua_setfield(L, -2, "ESCAPE"); lua_pushinteger(L, 42); lua_setfield(L, -2, "BACKSPACE"); lua_pushinteger(L, 43); lua_setfield(L, -2, "TAB"); lua_pushinteger(L, 44); lua_setfield(L, -2, "SPACE"); lua_pushinteger(L, 45); lua_setfield(L, -2, "MINUS"); lua_pushinteger(L, 46); lua_setfield(L, -2, "EQUALS"); lua_pushinteger(L, 47); lua_setfield(L, -2, "LEFTBRACKET"); lua_pushinteger(L, 48); lua_setfield(L, -2, "RIGHTBRACKET"); lua_pushinteger(L, 49); lua_setfield(L, -2, "BACKSLASH"); lua_pushinteger(L, 50); lua_setfield(L, -2, "NONUSHASH"); lua_pushinteger(L, 51); lua_setfield(L, -2, "SEMICOLON"); lua_pushinteger(L, 52); lua_setfield(L, -2, "APOSTROPHE"); lua_pushinteger(L, 53); lua_setfield(L, -2, "GRAVE"); lua_pushinteger(L, 54); lua_setfield(L, -2, "COMMA"); lua_pushinteger(L, 55); lua_setfield(L, -2, "PERIOD"); lua_pushinteger(L, 56); lua_setfield(L, -2, "SLASH"); lua_pushinteger(L, 57); lua_setfield(L, -2, "CAPSLOCK"); lua_pushinteger(L, 58); lua_setfield(L, -2, "F1"); lua_pushinteger(L, 59); lua_setfield(L, -2, "F2"); lua_pushinteger(L, 60); lua_setfield(L, -2, "F3"); lua_pushinteger(L, 61); lua_setfield(L, -2, "F4"); lua_pushinteger(L, 62); lua_setfield(L, -2, "F5"); lua_pushinteger(L, 63); lua_setfield(L, -2, "F6"); lua_pushinteger(L, 64); lua_setfield(L, -2, "F7"); lua_pushinteger(L, 65); lua_setfield(L, -2, "F8"); lua_pushinteger(L, 66); lua_setfield(L, -2, "F9"); lua_pushinteger(L, 67); lua_setfield(L, -2, "F10"); lua_pushinteger(L, 68); lua_setfield(L, -2, "F11"); lua_pushinteger(L, 69); lua_setfield(L, -2, "F12"); lua_pushinteger(L, 70); lua_setfield(L, -2, "PRINTSCREEN"); lua_pushinteger(L, 71); lua_setfield(L, -2, "SCROLLLOCK"); lua_pushinteger(L, 72); lua_setfield(L, -2, "PAUSE"); lua_pushinteger(L, 73); lua_setfield(L, -2, "INSERT"); lua_pushinteger(L, 74); lua_setfield(L, -2, "HOME"); lua_pushinteger(L, 75); lua_setfield(L, -2, "PAGEUP"); lua_pushinteger(L, 76); lua_setfield(L, -2, "DELETE"); lua_pushinteger(L, 77); lua_setfield(L, -2, "END"); lua_pushinteger(L, 78); lua_setfield(L, -2, "PAGEDOWN"); lua_pushinteger(L, 79); lua_setfield(L, -2, "RIGHT"); lua_pushinteger(L, 80); lua_setfield(L, -2, "LEFT"); lua_pushinteger(L, 81); lua_setfield(L, -2, "DOWN"); lua_pushinteger(L, 82); lua_setfield(L, -2, "UP"); lua_pushinteger(L, 83); lua_setfield(L, -2, "NUMLOCKCLEAR"); lua_pushinteger(L, 84); lua_setfield(L, -2, "KP_DIVIDE"); lua_pushinteger(L, 85); lua_setfield(L, -2, "KP_MULTIPLY"); lua_pushinteger(L, 86); lua_setfield(L, -2, "KP_MINUS"); lua_pushinteger(L, 87); lua_setfield(L, -2, "KP_PLUS"); lua_pushinteger(L, 88); lua_setfield(L, -2, "KP_ENTER"); lua_pushinteger(L, 89); lua_setfield(L, -2, "KP_1"); lua_pushinteger(L, 90); lua_setfield(L, -2, "KP_2"); lua_pushinteger(L, 91); lua_setfield(L, -2, "KP_3"); lua_pushinteger(L, 92); lua_setfield(L, -2, "KP_4"); lua_pushinteger(L, 93); lua_setfield(L, -2, "KP_5"); lua_pushinteger(L, 94); lua_setfield(L, -2, "KP_6"); lua_pushinteger(L, 95); lua_setfield(L, -2, "KP_7"); lua_pushinteger(L, 96); lua_setfield(L, -2, "KP_8"); lua_pushinteger(L, 97); lua_setfield(L, -2, "KP_9"); lua_pushinteger(L, 98); lua_setfield(L, -2, "KP_0"); lua_pushinteger(L, 99); lua_setfield(L, -2, "KP_PERIOD"); lua_pushinteger(L, 100); lua_setfield(L, -2, "NONUSBACKSLASH"); lua_pushinteger(L, 101); lua_setfield(L, -2, "APPLICATION"); lua_pushinteger(L, 224); lua_setfield(L, -2, "LCTRL"); lua_pushinteger(L, 225); lua_setfield(L, -2, "LSHIFT"); lua_pushinteger(L, 226); lua_setfield(L, -2, "LALT"); lua_pushinteger(L, 227); lua_setfield(L, -2, "LGUI"); lua_pushinteger(L, 228); lua_setfield(L, -2, "RCTRL"); lua_pushinteger(L, 229); lua_setfield(L, -2, "RSHIFT"); lua_pushinteger(L, 230); lua_setfield(L, -2, "RALT"); lua_pushinteger(L, 231); lua_setfield(L, -2, "RGUI"); lua_setglobal(L, "key"); lua_newtable(L); lua_pushcfunction(L,wrappers::pad::down); lua_setfield(L, -2, "down"); lua_pushcfunction(L,wrappers::pad::press); lua_setfield(L, -2, "press"); lua_pushcfunction(L,wrappers::pad::any); lua_setfield(L, -2, "any"); //lua_setglobal(L, "gamepad"); //lua_newtable(L); lua_pushinteger(L, -1); lua_setfield(L, -2, "INVALID"); lua_pushinteger(L, 0); lua_setfield(L, -2, "A"); lua_pushinteger(L, 1); lua_setfield(L, -2, "B"); lua_pushinteger(L, 2); lua_setfield(L, -2, "X"); lua_pushinteger(L, 3); lua_setfield(L, -2, "Y"); lua_pushinteger(L, 4); lua_setfield(L, -2, "BACK"); lua_pushinteger(L, 5); lua_setfield(L, -2, "GUIDE"); lua_pushinteger(L, 6); lua_setfield(L, -2, "START"); lua_pushinteger(L, 7); lua_setfield(L, -2, "LEFTSTICK"); lua_pushinteger(L, 8); lua_setfield(L, -2, "RIGHTSTICK"); lua_pushinteger(L, 9); lua_setfield(L, -2, "LEFTSHOULDER"); lua_pushinteger(L, 10); lua_setfield(L, -2, "RIGHTSHOULDER"); lua_pushinteger(L, 11); lua_setfield(L, -2, "UP"); lua_pushinteger(L, 12); lua_setfield(L, -2, "DOWN"); lua_pushinteger(L, 13); lua_setfield(L, -2, "LEFT"); lua_pushinteger(L, 14); lua_setfield(L, -2, "RIGHT"); lua_pushinteger(L, 15); lua_setfield(L, -2, "MISC1"); lua_pushinteger(L, 16); lua_setfield(L, -2, "PADDLE1"); lua_pushinteger(L, 17); lua_setfield(L, -2, "PADDLE2"); lua_pushinteger(L, 18); lua_setfield(L, -2, "PADDLE3"); lua_pushinteger(L, 19); lua_setfield(L, -2, "PADDLE4"); lua_pushinteger(L, 20); lua_setfield(L, -2, "TOUCHPAD"); lua_setglobal(L, "pad"); lua_getglobal(L, "utf8"); // push utf8 table lua_pushcfunction(L, cpp_utf8_sub); // push C function lua_setfield(L, -2, "sub"); // utf8.sub = cpp_utf8_sub lua_pop(L, 1); // pop utf8 table } int MiniLoader(lua_State *L) { const char *name = luaL_checkstring(L, 1); // 1. Convertir puntos en barras std::string path(name); std::string regpath(name); std::replace(path.begin(), path.end(), '.', '/'); // 2. Detectar comodín "/*" bool load_all = false; if (path.size() >= 2 && path.substr(path.size()-2) == "/*") { load_all = true; path = path.substr(0, path.size()-2); // quitar "/*" regpath = regpath.substr(0, regpath.size()-2); // quitar "/*" } if (load_all) { std::vector files = file_listdir(path.c_str(), "lua"); // Ejecutar todos los módulos for (auto &f : files) { std::string fullpath = path + "/" + f; std::string registerpath = std::string(regpath + "." + f.substr(0,f.size()-4)); int size; char* buffer = file_getfilebuffer(fullpath.c_str(), size); if (!buffer) continue; if (luaL_loadbuffer(L, buffer, size, registerpath.c_str()) == LUA_OK) { lua_pcall(L, 0, 0, 0); // ejecutar módulo, sin devolver nada lua_getglobal(L, "package"); lua_getfield(L, -1, "loaded"); lua_pushboolean(L, 1); lua_setfield(L, -2, registerpath.c_str()); lua_pop(L, 2); } else { log_msg(LOG_LUALD, "Error cargando %s: %s\n", fullpath.c_str(), lua_tostring(L, -1)); lua_pop(L, 1); } free(buffer); } // Devolver un loader vacío lua_pushcfunction(L, [](lua_State* L) -> int { lua_pushboolean(L, 1); // require devuelve true return 1; }); return 1; } // 3. Cargar un único archivo std::string filename = path + ".lua"; int size; char* buffer = file_getfilebuffer(filename.c_str(), size); if (!buffer) { lua_pushnil(L); return 1; } if (luaL_loadbuffer(L, buffer, size, name)) { log_msg(LOG_LUALD, "%s\n", lua_tostring(L, -1)); lua_pop(L, 1); free(buffer); lua_pushnil(L); return 1; } free(buffer); return 1; } void init(const char *main_lua_file) { L = luaL_newstate(); luaL_openlibs(L); push_functions(); lua_register(L, "mini_loader", MiniLoader); luaL_dostring(L, "table.insert(package.searchers,2,mini_loader)\n"); int size; char* buffer = file_getfilebuffer(main_lua_file, size); if (luaL_loadbuffer(L, buffer, size, "main")) { log_msg(LOG_LUALD, "%s\n", lua_tostring(L, -1)); lua_pop(L,1); return; } free(buffer); if (lua_pcall(L,0, LUA_MULTRET, 0)) { //luaL_traceback(L, L, NULL, 1); log_msg(LOG_LUART, "%s\n", lua_tostring(L, -1)); lua_pop(L,1); return; } // Check if _init and _update exist lua_getglobal(L, "mini"); lua_getfield(L, -1, "init"); if (lua_isfunction(L,-1)) init_exists = true; lua_pop(L,1); lua_pop(L,1); lua_getglobal(L, "mini"); lua_getfield(L, -1, "update"); if (lua_isfunction(L,-1)) update_exists = true; lua_pop(L,1); lua_pop(L,1); //std::thread(debugCommandThread).detach(); printf("stdin isatty: %d\n", isatty(0)); is_playing = true; } void quit() { if (!is_playing) return; is_playing = false; lua_close(L); } void cleanup() { debug::kill_thread(); } namespace callbacks { void init() { if (!init_exists) return; debug::process_commands(L); lua_getglobal(L, "mini"); lua_getfield(L, -1, "init"); is_playing = debug::call_and_handle_exceptions(L); } void update() { if (!update_exists) return; lua_getglobal(L, "mini"); lua_getfield(L, -1, "update"); is_playing = debug::call_and_handle_exceptions(L); } } } }