int CorsixTH_lua_main_no_eval(lua_State *L) { // assert(_VERSION == LUA_VERSION) size_t iLength; lua_getglobal(L, "_VERSION"); const char* sVersion = lua_tolstring(L, -1, &iLength); if(iLength != strlen(LUA_VERSION) || strcmp(sVersion, LUA_VERSION) != 0) { lua_pushliteral(L, "Linked against a version of Lua different to the " "one used when compiling.\nPlease recompile CorsixTH against the " "same Lua version it is linked against."); return lua_error(L); } lua_pop(L, 1); // registry._CLEANUP = {} lua_newtable(L); lua_setfield(L, LUA_REGISTRYINDEX, "_CLEANUP"); // math.random* = Mersenne twister variant luaT_cpcall(L, luaopen_random, NULL); // package.preload["jit.opt"] = load(jit_opt_lua) // package.preload["jit.opt_inline"] = load(jit_opt_inline_lua) lua_getglobal(L, "package"); lua_getfield(L, -1, "preload"); luaL_loadbuffer(L, (const char*)jit_opt_lua, sizeof(jit_opt_lua), "jit/opt.luac"); lua_setfield(L, -2, "jit.opt"); luaL_loadbuffer(L, (const char*)jit_opt_inline_lua, sizeof(jit_opt_inline_lua), "jit/opt_inline.luac"); lua_setfield(L, -2, "jit.opt_inline"); lua_pop(L, 2); // if registry._LOADED.jit then // require"jit.opt".start() // else // print "Notice: ..." // end // (this could be done in Lua rather than here, but ideally the optimiser // should be turned on before any Lua code is loaded) lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, -1, "jit"); if(lua_type(L, -1) == LUA_TNIL) { lua_pop(L, 2); lua_getglobal(L, "print"); lua_pushliteral(L, "Notice: LuaJIT not being used.\nConsider replacing" " Lua with LuaJIT to improve performance."); #ifdef CORSIX_TH_64BIT lua_pushliteral(L, " Note that there is not currently a 64 bit version" " of LuaJIT."); lua_concat(L, 2); #endif lua_call(L, 1, 0); } else { lua_pop(L, 2); lua_getglobal(L, "require"); lua_pushliteral(L, "jit.opt"); lua_call(L, 1, 1); lua_getfield(L, -1, "start"); lua_call(L, 0, 0); lua_pop(L, 1); } // Fill in package.preload table so that calls to require("X") from Lua // will call the appropriate luaopen_X function in C. #define PRELOAD(name, fn) \ luaT_execute(L, "package.preload." name " = ...", fn) PRELOAD("lfs", luaopen_lfs_ext); PRELOAD("lpeg", luaopen_lpeg); PRELOAD("rnc", luaopen_rnc); PRELOAD("TH", luaopen_th); PRELOAD("ISO_FS", luaopen_iso_fs); PRELOAD("persist", luaopen_persist); PRELOAD("sdl", luaopen_sdl); #undef PRELOAD // require "debug" (Harmless in Lua 5.1, useful in 5.2 for compatbility) luaT_execute(L, "require \"debug\""); // Check for --interpreter and run that instead of CorsixTH.lua bool bGotScriptFile = false; int iNArgs = lua_gettop(L); for(int i = 1; i <= iNArgs; ++i) { if(lua_type(L, i) == LUA_TSTRING) { size_t iLen; const char* sCmd = lua_tolstring(L, i, &iLen); if(iLen > 14 && memcmp(sCmd, "--interpreter=", 14) == 0) { lua_getglobal(L, "assert"); lua_getglobal(L, "loadfile"); lua_pushlstring(L, sCmd + 14, iLen - 14); bGotScriptFile = true; break; } } } // Code to try several variations on finding CorsixTH.lua: // CorsixTH.lua // CorsixTH/CorsixTH.lua // ../CorsixTH.lua // ../CorsixTH/CorsixTH.lua // ../../CorsixTH.lua // ../../CorsixTH/CorsixTH.lua // ../../../CorsixTH.lua // ../../../CorsixTH/CorsixTH.lua // It is simpler to write this in Lua than in C. const char sLuaCorsixTHLuaOld[] = "local name, sep, code = \"CorsixTH.lua\", package.config:sub(1, 1)\n" "local root = (... or \"\"):match(\"^(.*[\"..sep..\"])\") or \"\"\n" "code = loadfile(\"%s\"..name)\n" "if code then return code end\n" #ifdef __APPLE__ // Darrell: Search inside the bundle first. // There's probably a better way of doing this. #if defined(IS_CORSIXTH_APP) "code = loadfile(\"CorsixTH.app/Contents/Resources/\"..name)\n" "if code then return code end\n" #elif defined(IS_MAPEDIT_APP) "code = loadfile(\"MapEdit.app/Contents/Resources/\"..name)\n" "if code then return code end\n" #endif #endif "for num_dotdot = 0, 3 do\n" " for num_dir = 0, 1 do\n" " code = loadfile(root..(\"..\"..sep):rep(num_dotdot)..\n" " (\"CorsixTH\"..sep):rep(num_dir)..name)\n" " if code then return code end \n" " end \n" "end \n" "return loadfile(name)"; char sLuaCorsixTHLua[sizeof(sLuaCorsixTHLuaOld) + sizeof(path)]; sprintf(sLuaCorsixTHLua, sLuaCorsixTHLuaOld, path); //LOGI(sLuaCorsixTHLua); // return assert(loadfile"CorsixTH.lua")(...) if(!bGotScriptFile) { lua_getglobal(L, "assert"); luaL_loadbuffer(L, sLuaCorsixTHLua, strlen(sLuaCorsixTHLua), "@main.cpp (l_main bootstrap)"); if(lua_gettop(L) == 2) lua_pushnil(L); else lua_pushvalue(L, 1); } lua_call(L, 1, 2); lua_call(L, 2, 1); lua_insert(L, 1); return lua_gettop(L); }
static int l_mainloop(lua_State *L) { luaL_checktype(L, 1, LUA_TTHREAD); lua_State *dispatcher = lua_tothread(L, 1); fps_ctrl *fps_control = (fps_ctrl*)lua_touserdata(L, luaT_upvalueindex(1)); SDL_TimerID timer = SDL_AddTimer(30, timer_frame_callback, nullptr); SDL_Event e; while(SDL_WaitEvent(&e) != 0) { bool do_frame = false; bool do_timer = false; do { int nargs; switch(e.type) { case SDL_QUIT: goto leave_loop; case SDL_KEYDOWN: lua_pushliteral(dispatcher, "keydown"); lua_pushstring(dispatcher, SDL_GetKeyName(e.key.keysym.sym)); l_push_modifiers_table(dispatcher, e.key.keysym.mod); lua_pushboolean(dispatcher, e.key.repeat != 0); nargs = 4; break; case SDL_KEYUP: lua_pushliteral(dispatcher, "keyup"); lua_pushstring(dispatcher, SDL_GetKeyName(e.key.keysym.sym)); nargs = 2; break; case SDL_TEXTINPUT: lua_pushliteral(dispatcher, "textinput"); lua_pushstring(dispatcher, e.text.text); nargs = 2; break; case SDL_TEXTEDITING: lua_pushliteral(dispatcher, "textediting"); lua_pushstring(dispatcher, e.edit.text); lua_pushinteger(dispatcher, e.edit.start); lua_pushinteger(dispatcher, e.edit.length); nargs = 4; break; case SDL_MOUSEBUTTONDOWN: lua_pushliteral(dispatcher, "buttondown"); lua_pushinteger(dispatcher, e.button.button); lua_pushinteger(dispatcher, e.button.x); lua_pushinteger(dispatcher, e.button.y); nargs = 4; break; case SDL_MOUSEBUTTONUP: lua_pushliteral(dispatcher, "buttonup"); lua_pushinteger(dispatcher, e.button.button); lua_pushinteger(dispatcher, e.button.x); lua_pushinteger(dispatcher, e.button.y); nargs = 4; break; case SDL_MOUSEWHEEL: lua_pushliteral(dispatcher, "mousewheel"); lua_pushinteger(dispatcher, e.wheel.x); lua_pushinteger(dispatcher, e.wheel.y); nargs = 3; break; case SDL_MOUSEMOTION: lua_pushliteral(dispatcher, "motion"); lua_pushinteger(dispatcher, e.motion.x); lua_pushinteger(dispatcher, e.motion.y); lua_pushinteger(dispatcher, e.motion.xrel); lua_pushinteger(dispatcher, e.motion.yrel); nargs = 5; break; case SDL_WINDOWEVENT: switch (e.window.event) { case SDL_WINDOWEVENT_FOCUS_GAINED: lua_pushliteral(dispatcher, "active"); lua_pushinteger(dispatcher, 1); nargs = 2; break; case SDL_WINDOWEVENT_FOCUS_LOST: lua_pushliteral(dispatcher, "active"); lua_pushinteger(dispatcher, 0); nargs = 2; break; default: nargs = 0; break; } break; case SDL_USEREVENT_MUSIC_OVER: lua_pushliteral(dispatcher, "music_over"); nargs = 1; break; case SDL_USEREVENT_CPCALL: if(luaT_cpcall(L, (lua_CFunction)e.user.data1, e.user.data2)) { SDL_RemoveTimer(timer); lua_pushliteral(L, "callback"); return 2; } nargs = 0; break; case SDL_USEREVENT_TICK: do_timer = true; nargs = 0; break; case SDL_USEREVENT_MOVIE_OVER: lua_pushliteral(dispatcher, "movie_over"); nargs = 1; break; case SDL_USEREVENT_SOUND_OVER: lua_pushliteral(dispatcher, "sound_over"); lua_pushinteger(dispatcher, *(static_cast<int*>(e.user.data1))); nargs = 2; break; default: nargs = 0; break; } if(nargs != 0) { if(luaT_resume(dispatcher, dispatcher, nargs) != LUA_YIELD) { goto leave_loop; } do_frame = do_frame || (lua_toboolean(dispatcher, 1) != 0); lua_settop(dispatcher, 0); } } while(SDL_PollEvent(&e) != 0); if(do_timer) { lua_pushliteral(dispatcher, "timer"); if(luaT_resume(dispatcher, dispatcher, 1) != LUA_YIELD) { break; } do_frame = do_frame || (lua_toboolean(dispatcher, 1) != 0); lua_settop(dispatcher, 0); } if(do_frame || !fps_control->limit_fps) { do { if(fps_control->track_fps) { fps_control->count_frame(); } lua_pushliteral(dispatcher, "frame"); if(luaT_resume(dispatcher, dispatcher, 1) != LUA_YIELD) { goto leave_loop; } lua_settop(dispatcher, 0); } while(fps_control->limit_fps == false && SDL_PollEvent(nullptr) == 0); } // No events pending - a good time to do a bit of garbage collection lua_gc(L, LUA_GCSTEP, 2); } leave_loop: SDL_RemoveTimer(timer); int n = lua_gettop(dispatcher); if(lua_status(dispatcher) >= LUA_ERRRUN) { n = 1; } lua_checkstack(L, n); lua_xmove(dispatcher, L, n); return n; }