lovr/src/main.c

138 lines
3.2 KiB
C
Raw Normal View History

2018-09-27 04:55:54 +00:00
#ifdef LOVR_ENABLE_EVENT
#include "event/event.h"
#endif
#include "resources/boot.lua.h"
#include "lib/glfw.h"
2018-09-27 04:45:45 +00:00
#include "version.h"
2018-09-27 04:55:54 +00:00
#include "luax.h"
2018-10-29 19:01:20 +00:00
#include "platform.h"
2018-09-27 04:55:54 +00:00
#include "util.h"
#include <stdbool.h>
2018-05-15 04:38:50 +00:00
#include <string.h>
2018-02-17 17:18:08 +00:00
#include <stdlib.h>
2018-05-15 04:38:50 +00:00
#include <stdio.h>
2018-02-17 17:18:08 +00:00
2018-10-29 20:52:50 +00:00
lua_State* lovrInit(lua_State* L, int argc, char** argv);
2018-09-27 04:55:54 +00:00
void lovrQuit(int status);
#ifndef LOVR_USE_OCULUS_MOBILE
2016-08-08 20:51:22 +00:00
int main(int argc, char** argv) {
2018-09-27 04:45:45 +00:00
if (argc > 1 && (!strcmp(argv[1], "--version") || !strcmp(argv[1], "-v"))) {
2018-10-29 19:01:20 +00:00
lovrLog("LOVR %d.%d.%d (%s)\n", LOVR_VERSION_MAJOR, LOVR_VERSION_MINOR, LOVR_VERSION_PATCH, LOVR_VERSION_ALIAS);
2018-02-17 17:18:08 +00:00
exit(0);
}
2018-05-15 04:38:50 +00:00
int status;
2018-10-29 20:52:50 +00:00
bool restart;
do {
lua_State* L = luaL_newstate();
luaL_openlibs(L);
lovrSetErrorCallback((lovrErrorHandler) luax_vthrow, L);
lua_State* T = lovrInit(L, argc, argv);
if (!T) {
return 1;
}
2018-10-29 20:52:50 +00:00
#ifdef EMSCRIPTEN
lovrEmscriptenContext context = { L, T, argc, argv };
emscripten_set_main_loop_arg(emscriptenLoop, (void*) &context, 0, 1);
return 0;
#else
while (lua_resume(T, 0) == LUA_YIELD) {
lovrSleep(.001);
}
restart = lua_type(T, -1) == LUA_TSTRING && !strcmp(lua_tostring(T, -1), "restart");
status = lua_tonumber(T, -1);
lua_close(L);
#endif
} while (restart);
glfwTerminate();
return status;
2016-07-07 07:04:24 +00:00
}
2018-09-27 04:55:54 +00:00
#endif
2018-09-27 04:55:54 +00:00
#ifdef EMSCRIPTEN
#include <emscripten.h>
typedef struct {
lua_State* L;
2018-10-29 20:52:50 +00:00
lua_State* T;
2018-09-27 04:55:54 +00:00
int argc;
char** argv;
} lovrEmscriptenContext;
static void emscriptenLoop(void* arg) {
lovrEmscriptenContext* context = arg;
2018-10-29 20:52:50 +00:00
if (lua_resume(context->T, 0) != LUA_YIELD) {
bool restart = lua_type(context->T, -1) == LUA_TSTRING && !strcmp(lua_tostring(context->T, -1), "restart");
int status = lua_tonumber(context->T, -1);
2018-09-27 04:55:54 +00:00
2018-10-29 20:52:50 +00:00
lua_close(context->L);
2018-09-27 04:55:54 +00:00
emscripten_cancel_main_loop();
2018-10-29 20:52:50 +00:00
if (restart) {
main(context->argc, context->argv);
2018-09-27 04:55:54 +00:00
} else {
glfwTerminate();
exit(status);
}
}
}
#endif
static int loadSelf(lua_State* L) {
const char* moduleFunction = luaL_gsub(L, lua_tostring(L, -1), ".", "_");
char* hyphen = strchr(moduleFunction, '-');
moduleFunction = hyphen ? hyphen + 1 : moduleFunction;
char executablePath[1024] = { 0 };
lovrGetExecutablePath(executablePath, 1024);
luax_loadlib(L, executablePath, moduleFunction);
return 1;
}
static void onGlfwError(int code, const char* description) {
lovrThrow(description);
}
2018-10-29 20:52:50 +00:00
lua_State* lovrInit(lua_State* L, int argc, char** argv) {
2018-09-27 04:55:54 +00:00
glfwSetErrorCallback(onGlfwError);
lovrAssert(glfwInit(), "Error initializing GLFW");
glfwSetTime(0);
// arg
lua_newtable(L);
lua_pushstring(L, "lovr");
lua_rawseti(L, -2, -1);
for (int i = 0; i < argc; i++) {
lua_pushstring(L, argv[i]);
lua_rawseti(L, -2, i == 0 ? -2 : i);
}
lua_setglobal(L, "arg");
luax_registerloader(L, loadSelf, 1);
2018-09-27 04:55:54 +00:00
lua_pushcfunction(L, luax_getstack);
if (luaL_loadbuffer(L, (const char*) boot_lua, boot_lua_len, "boot.lua") || lua_pcall(L, 0, 1, -2)) {
2018-10-29 19:01:20 +00:00
lovrWarn("%s\n", lua_tostring(L, -1));
2018-10-29 20:52:50 +00:00
return NULL;
2018-09-27 04:55:54 +00:00
}
2018-10-29 20:52:50 +00:00
lua_State* T = lua_newthread(L);
2018-09-27 04:55:54 +00:00
lua_pushvalue(L, -2);
2018-10-29 20:52:50 +00:00
lua_xmove(L, T, 1);
return T;
2018-09-27 04:55:54 +00:00
}
void lovrQuit(int status) {
#ifdef LOVR_ENABLE_EVENT
lovrEventPush((Event) { .type = EVENT_QUIT, .data.quit = { false, status } });
#endif
}