This commit is contained in:
bjorn 2019-09-26 20:19:50 -07:00
parent 0129a80b27
commit 2e44926767
2 changed files with 40 additions and 26 deletions

View File

@ -81,6 +81,11 @@ LDFLAGS += @(ENET_LDFLAGS)
CFLAGS += @(CFLAGS)
LDFLAGS += @(LDFLAGS)
# Platforms
ifeq (@(TUP_PLATFORM),macosx)
LDFLAGS += -lobjc
endif
# Macros
!compile = |> ^ CC %f^ @(CC) $(CFLAGS) $(CFLAGS_y) -c %f -o %o |> $(ROOT)/.obj/%B.o $(ROOT)/<objects>
!link = |> ^ LD %o^ @(CC) $(LDFLAGS) -o %o |>

View File

@ -40,6 +40,35 @@ static struct {
char requirePath[2][1024];
} state;
// Return the path to a LÖVR archive bundled to the executable.
// On most platforms, the zip is appended to the executable file itself.
// On macOS, we have to use Objective C to find it inside the .app folder.
static bool getBundlePath(char* buffer, size_t size) {
#ifdef __APPLE__
id extension = objc_msgSend((id) objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "lovr");
id bundle = objc_msgSend((id) objc_getClass("NSBundle"), sel_registerName("mainBundle"));
id path = objc_msgSend(bundle, sel_registerName("pathForResource:ofType:"), nil, extension);
if (path == nil) {
return false;
}
char* cpath = NULL;
object_getInstanceVariable(path, "UTF8String", (void**) &cpath);
size_t length = strlen(cpath);
if (length >= size) {
return false;
}
memcpy(buffer, cpath, length);
buffer[length] = '\0';
return true;
#else
return lovrFilesystemGetExecutablePath(buffer, size) == 0;
#endif
}
bool lovrFilesystemInit(const char* argExe, const char* argGame, const char* argRoot) {
if (state.initialized) return false;
state.initialized = true;
@ -56,41 +85,21 @@ bool lovrFilesystemInit(const char* argExe, const char* argGame, const char* arg
lovrFilesystemSetRequirePath("?.lua;?/init.lua;lua_modules/?.lua;lua_modules/?/init.lua;deps/?.lua;deps/?/init.lua");
lovrFilesystemSetCRequirePath("??;lua_modules/??;deps/??");
// Try to mount either an archive fused to the executable or an archive from the command line
lovrFilesystemGetExecutablePath(state.source, LOVR_PATH_MAX);
if (!lovrFilesystemMount(state.source, NULL, 1, argRoot)) { // Attempt to load fused. If that fails...
#ifdef __APPLE__
// NSString* path = [[NSBundle mainBundle] pathForResource:nil ofType:@"lovr"]
// if (!path || !lovrFilesystemMount(path.UTF8string, NULL, 1, argRoot)) {
//
// }
id lovrNSString = objc_msgSend((id) objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "lovr");
id mainBundle = objc_msgSend((id) objc_getClass("NSBundle"), sel_registerName("mainBundle"));
id resource = objc_msgSend(mainBundle, sel_registerName("pathForResource:ofType:"), nil, lovrNSString);
const char* resourcePath = NULL;
if (resource != nil) {
object_getInstanceVariable(resource, "UTF8String", (void**) &resourcePath);
}
if (!resourcePath || !lovrFilesystemMount(resourcePath, NULL, 1, argRoot)) {
#endif
// Try to mount either an archive fused to the executable
if (!getBundlePath(state.source, LOVR_PATH_MAX) || !lovrFilesystemMount(state.source, NULL, 1, argRoot)) {
state.fused = false;
// If that didn't work, try loading an archive from the command line
if (argGame) {
strncpy(state.source, argGame, LOVR_PATH_MAX);
if (lovrFilesystemMount(state.source, NULL, 1, argRoot)) { // Attempt to load from arg. If success, init is done
if (lovrFilesystemMount(state.source, NULL, 1, argRoot)) {
return true;
}
}
free(state.source); // Couldn't load from argProject, so apparently it isn't the source
// Otherwise, give up
free(state.source);
state.source = NULL;
#ifdef __APPLE__
}
#endif
}
return true;