Refactor main; Add unused android entrypoint;

This commit is contained in:
bjorn 2020-01-28 21:38:44 -08:00
parent b19a391c32
commit c9a06a37cb
2 changed files with 105 additions and 109 deletions

View File

@ -4,6 +4,29 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
// Currently, the Android entrypoint is in lovr-oculus-mobile, so this one is not enabled.
#if 0
#include <android_native_app_glue.h>
#include <android/log.h>
static JavaVM* lovrJavaVM;
static JNIEnv* lovrJNIEnv;
int main(int argc, char** argv);
static void onAppCmd(struct android_app* app, int32_t cmd) {
// pause, resume, events, etc.
}
void android_main(struct android_app* app) {
lovrJavaVM = app->activity->vm;
lovrJavaVM->AttachCurrentThread(&lovrJNIEnv, NULL);
app->onAppCmd = onAppCmd;
main(0, NULL);
lovrJavaVM->DetachCurrentThread();
}
#endif
bool lovrPlatformInit() {
return true;
}
@ -17,21 +40,11 @@ const char* lovrPlatformGetName() {
}
void lovrPlatformPollEvents() {
//
// TODO
}
/* Temporarily implemented elsewhere
double lovrPlatformGetTime() {
}
void lovrPlatformSetTime(double t) {
}
*/
void lovrPlatformOpenConsole() {
//
// TODO
}
bool lovrPlatformCreateWindow(WindowFlags* flags) {
@ -43,12 +56,6 @@ void lovrPlatformGetWindowSize(int* width, int* height) {
if (height) *height = 0;
}
/* Temporarily implemented elsewhere
void lovrPlatformGetFramebufferSize(int* width, int* height) {
*width = *height = 0;
}
*/
void lovrPlatformSwapBuffers() {
//
}

View File

@ -6,14 +6,11 @@
#include <string.h>
#include <stdlib.h>
lua_State* lovrInit(lua_State* L, int argc, char** argv);
void lovrDestroy(void* arg);
int main(int argc, char** argv);
#ifndef LOVR_USE_OCULUS_MOBILE
#ifdef EMSCRIPTEN
#include <emscripten.h>
typedef struct {
lua_State* L;
lua_State* T;
@ -21,6 +18,7 @@ typedef struct {
char** argv;
} lovrEmscriptenContext;
// Called by JS
void lovrDestroy(void* arg) {
if (arg) {
lovrEmscriptenContext* context = arg;
@ -60,26 +58,101 @@ int main(int argc, char** argv) {
exit(0);
}
lovrAssert(lovrPlatformInit(), "Failed to initialize platform");
int status;
bool restart;
do {
lovrPlatformSetTime(0.);
lua_State* L = luaL_newstate();
luax_setmainthread(L);
luaL_openlibs(L);
lua_State* T = lovrInit(L, argc, argv);
if (!T) {
// arg table
// Args follow the lua standard https://en.wikibooks.org/wiki/Lua_Programming/command_line_parameter
// In this standard, the contents of argv are put in a global table named "arg", but with
// indices offset such that the "script" (in lovr, the game path) is at index 0. So all
// arguments (if any) intended for the script/game are at successive indices starting with 1,
// and the exe and its arguments are in normal order but stored in negative indices.
//
// LÖVR can be run in ways normal Lua can't. It can be run with an empty argv, or with no script
// (if fused). So in the case of LÖVR:
// * The script path will always be at index 0, but it can be nil.
// * For a fused executable, whatever is given in argv as script name is still at 0, but will be ignored.
// * The exe (argv[0]) will always be the lowest-integer index. If it's present, it will always be -1 or less.
// * Any named arguments parsed by Lovr will be stored in the arg table at their named keys.
// * An exe name will always be stored in the arg table at string key "exe", even if none was supplied in argv.
lua_newtable(L);
// push dummy "lovr" in case argv is empty
lua_pushliteral(L, "lovr");
lua_setfield(L, -2, "exe");
typedef enum { // What flag is being searched for?
ARGFLAG_NONE, // Not processing a flag
ARGFLAG_ROOT
} ArgFlag;
ArgFlag currentFlag = ARGFLAG_NONE;
int lovrArgs = 0; // Arg count up to but not including the game path
// One pass to parse flags
for (int i = 0; i < argc; i++) {
if (lovrArgs > 0) {
// This argument is an argument to a -- flag
if (currentFlag == ARGFLAG_ROOT) {
lua_pushstring(L, argv[i]);
lua_setfield(L, -2, "root");
currentFlag = ARGFLAG_NONE;
// This argument is a -- flag
} else if (!strcmp(argv[i], "--root") || !strcmp(argv[i], "-r")) {
currentFlag = ARGFLAG_ROOT;
} else if (!strcmp(argv[i], "--console")) {
lovrPlatformOpenConsole();
// This is the game path
} else {
break;
}
} else { // Found exe name
lua_pushstring(L, argv[i]);
lua_setfield(L, -2, "exe");
}
lovrArgs++;
}
// Now that we know the negative offset to start at, copy all args in the table
for (int i = 0; i < argc; i++) {
lua_pushstring(L, argv[i]);
lua_rawseti(L, -2, -lovrArgs + i);
}
lua_setglobal(L, "arg");
lua_getglobal(L, "package");
lua_getfield(L, -1, "preload");
luaL_register(L, NULL, lovrModules);
lua_pop(L, 2);
lua_pushcfunction(L, luax_getstack);
if (luaL_loadbuffer(L, (const char*) src_resources_boot_lua, src_resources_boot_lua_len, "@boot.lua") || lua_pcall(L, 0, 1, -2)) {
fprintf(stderr, "%s\n", lua_tostring(L, -1));
return 1;
}
lua_State* T = lua_newthread(L);
lua_pushvalue(L, -2);
lua_xmove(L, T, 1);
lovrSetErrorCallback(luax_vthrow, T);
#ifdef EMSCRIPTEN
lovrEmscriptenContext context = { L, T, argc, argv };
emscripten_set_main_loop_arg(emscriptenLoop, (void*) &context, 0, 1);
return 0;
#else
#endif
while (lua_resume(T, 0) == LUA_YIELD) {
lovrPlatformSleep(0.);
}
@ -87,93 +160,9 @@ int main(int argc, char** argv) {
restart = lua_type(T, -1) == LUA_TSTRING && !strcmp(lua_tostring(T, -1), "restart");
status = lua_tonumber(T, -1);
lua_close(L);
#endif
} while (restart);
lovrPlatformDestroy();
return status;
}
#endif
typedef enum { // What flag is being searched for?
ARGFLAG_NONE, // Not processing a flag
ARGFLAG_ROOT
} ArgFlag;
lua_State* lovrInit(lua_State* L, int argc, char** argv) {
lovrAssert(lovrPlatformInit(), "Failed to initialize platform");
// arg table
// Args follow the lua standard https://en.wikibooks.org/wiki/Lua_Programming/command_line_parameter
// In this standard, the contents of argv are put in a global table named "arg", but with indices offset
// such that the "script" (in lovr, the game path) is at index 0. So all arguments (if any) intended for
// the script/game are at successive indices starting with 1, and the exe and its arguments are in normal
// order but stored in negative indices.
//
// Lovr can be run in ways normal lua can't. It can be run with an empty argv, or with no script (if fused).
// So in the case of lovr:
// * The script path will always be at index 0, but it can be nil.
// * For a fused executable, whatever is given in argv as script name is still at 0, but will be ignored.
// * The exe (argv[0]) will always be the lowest-integer index. If it's present, it will always be -1 or less.
// * Any named arguments parsed by Lovr will be stored in the arg table at their named keys.
// * An exe name will always be stored in the arg table at string key "exe", even if none was supplied in argv.
lua_newtable(L);
// push dummy "lovr" in case argv is empty
lua_pushliteral(L, "lovr");
lua_setfield(L, -2, "exe");
ArgFlag currentFlag = ARGFLAG_NONE;
int lovrArgs = 0; // Arg count up to but not including the game path
// One pass to parse flags
for (int i = 0; i < argc; i++) {
if (lovrArgs > 0) {
// This argument is an argument to a -- flag
if (currentFlag == ARGFLAG_ROOT) {
lua_pushstring(L, argv[i]);
lua_setfield(L, -2, "root");
currentFlag = ARGFLAG_NONE;
// This argument is a -- flag
} else if (!strcmp(argv[i], "--root") || !strcmp(argv[i], "-r")) {
currentFlag = ARGFLAG_ROOT;
} else if (!strcmp(argv[i], "--console")) {
lovrPlatformOpenConsole();
// This is the game path
} else {
break;
}
} else { // Found exe name
lua_pushstring(L, argv[i]);
lua_setfield(L, -2, "exe");
}
lovrArgs++;
}
// Now that we know the negative offset to start at, copy all args in the table
for (int i = 0; i < argc; i++) {
lua_pushstring(L, argv[i]);
lua_rawseti(L, -2, -lovrArgs + i);
}
lua_setglobal(L, "arg");
lua_getglobal(L, "package");
lua_getfield(L, -1, "preload");
luaL_register(L, NULL, lovrModules);
lua_pop(L, 2);
lua_pushcfunction(L, luax_getstack);
if (luaL_loadbuffer(L, (const char*) src_resources_boot_lua, src_resources_boot_lua_len, "@boot.lua") || lua_pcall(L, 0, 1, -2)) {
fprintf(stderr, "%s\n", lua_tostring(L, -1));
return NULL;
}
lua_State* T = lua_newthread(L);
lua_pushvalue(L, -2);
lua_xmove(L, T, 1);
return T;
}