Example #1
0
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);
}
Example #2
0
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;
}