This commit is contained in:
bjorn 2019-08-21 16:30:20 -07:00
parent 8d4760167f
commit cd09e1e695
17 changed files with 50 additions and 1728 deletions

View File

@ -325,7 +325,6 @@ set(LOVR_SRC
src/api/api.c
src/api/l_lovr.c
src/lib/map/map.c
src/lib/sds/sds.c
)
if (LOVR_BUILD_SHARED)

View File

@ -2,7 +2,6 @@
#include "util.h"
#include "core/ref.h"
#include "core/platform.h"
#include "lib/sds/sds.h"
#include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
@ -197,27 +196,22 @@ int luax_getstack(lua_State *L) {
// A version of print that uses lovrLog, for platforms that need it (Android)
int luax_print(lua_State* L) {
sds str = sdsempty();
int n = lua_gettop(L); /* number of arguments */
int i;
luaL_Buffer buffer;
int n = lua_gettop(L);
lua_getglobal(L, "tostring");
for (i=1; i<=n; i++) {
const char *s;
lua_pushvalue(L, -1); /* function to be called */
lua_pushvalue(L, i); /* value to print */
luaL_buffinit(L, &buffer);
for (int i = 1; i <= n; i++) {
lua_pushvalue(L, -1);
lua_pushvalue(L, i);
lua_call(L, 1, 1);
s = lua_tostring(L, -1); /* get result */
if (s == NULL)
return luaL_error(L, LUA_QL("tostring") " must return a string to "
LUA_QL("print"));
if (i>1) str = sdscat(str, "\t");
str = sdscat(str, s);
lua_pop(L, 1); /* pop result */
lovrAssert(lua_type(L, -1) == LUA_TSTRING, LUA_QL("tostring") " must return a string to " LUA_QL("print"));
luaL_addvalue(&buffer);
if (i > 1) {
luaL_addchar(&buffer, '\t');
}
}
lovrLog("%s", str);
sdsfree(str);
luaL_pushresult(&buffer);
lovrLog("%s", lua_tostring(L, -1));
return 0;
}

View File

@ -85,6 +85,19 @@ static int l_lovrFilesystemGetAppdataDirectory(lua_State* L) {
return 1;
}
static int l_lovrFilesystemGetApplicationId(lua_State *L) {
char buffer[LOVR_PATH_MAX];
if (lovrFilesystemGetApplicationId(buffer, sizeof(buffer))) {
lua_pushstring(L, buffer);
} else {
lua_pushnil(L);
}
return 1;
}
static int l_lovrFilesystemGetDirectoryItems(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
lua_newtable(L);
@ -279,21 +292,11 @@ static int l_lovrFilesystemWrite(lua_State* L) {
return 1;
}
static int l_lovrFilesystemGetApplicationId(lua_State *L) {
sds applicationId = lovrPlatformGetApplicationId();
if (applicationId) {
lua_pushstring(L, applicationId);
sdsfree(applicationId);
} else {
lua_pushnil(L);
}
return 1;
}
static const luaL_Reg lovrFilesystem[] = {
{ "append", l_lovrFilesystemAppend },
{ "createDirectory", l_lovrFilesystemCreateDirectory },
{ "getAppdataDirectory", l_lovrFilesystemGetAppdataDirectory },
{ "getApplicationId", l_lovrFilesystemGetApplicationId },
{ "getDirectoryItems", l_lovrFilesystemGetDirectoryItems },
{ "getExecutablePath", l_lovrFilesystemGetExecutablePath },
{ "getIdentity", l_lovrFilesystemGetIdentity },
@ -317,7 +320,6 @@ static const luaL_Reg lovrFilesystem[] = {
{ "setIdentity", l_lovrFilesystemSetIdentity },
{ "unmount", l_lovrFilesystemUnmount },
{ "write", l_lovrFilesystemWrite },
{ "getApplicationId", l_lovrFilesystemGetApplicationId },
{ NULL, NULL }
};

View File

@ -1,6 +1,5 @@
#include <stdint.h>
#include <stdbool.h>
#include <lib/sds/sds.h>
#pragma once
@ -94,7 +93,6 @@ bool lovrPlatformIsMouseDown(MouseButton button);
bool lovrPlatformIsKeyDown(KeyCode key);
void lovrPlatformSleep(double seconds);
int lovrPlatformGetExecutablePath(char* dest, uint32_t size);
sds lovrPlatformGetApplicationId(void);
#ifdef _WIN32
#include <windows.h>
HANDLE lovrPlatformGetWindow(void);

View File

@ -91,25 +91,6 @@ int lovrPlatformGetExecutablePath(char* dest, uint32_t size) {
return 1;
}
sds lovrPlatformGetApplicationId() {
pid_t pid = getpid();
sds procPath = sdscatfmt(sdsempty(), "/proc/%i/cmdline", (int)pid);
FILE *procFile = fopen(procPath, "r");
sdsfree(procPath);
if (procFile) {
sds procData = sdsempty();
char data[64];
int read;
while ((read = fread(data, 1, sizeof(data), procFile))) {
procData = sdscatlen(procData, data, read);
}
return procData;
} else {
return NULL;
}
}
#include <EGL/egl.h>
#include <EGL/eglext.h>
getProcAddressProc lovrGetProcAddress = eglGetProcAddress;

View File

@ -23,7 +23,3 @@ int lovrPlatformGetExecutablePath(char* dest, uint32_t size) {
}
return 1;
}
sds lovrPlatformGetApplicationId() {
return NULL;
}

View File

@ -19,8 +19,3 @@ void lovrPlatformOpenConsole() {
int lovrPlatformGetExecutablePath(char* dest, uint32_t size) {
return _NSGetExecutablePath(dest, &size);
}
// TODO: Actually, this could perfectly well return the bundle ID, but who would need it?
sds lovrPlatformGetApplicationId() {
return NULL;
}

View File

@ -18,7 +18,3 @@ int lovrPlatformGetExecutablePath(char* dest, uint32_t size) {
void lovrPlatformOpenConsole() {
//
}
sds lovrPlatformGetApplicationId() {
return NULL;
}

View File

@ -22,7 +22,3 @@ void lovrPlatformOpenConsole() {
int lovrPlatformGetExecutablePath(char* dest, uint32_t size) {
return !GetModuleFileName(NULL, dest, size);
}
sds lovrPlatformGetApplicationId() {
return NULL;
}

View File

@ -1,24 +0,0 @@
Copyright (c) 2006-2014, Salvatore Sanfilippo <antirez at gmail dot com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because it is too large Load Diff

View File

@ -1,296 +0,0 @@
/* SDSLib 2.x -- A C dynamic strings library
*
* Copyright (c) 2018 Lynn Kirby <lynn@arrak.is>
* Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>
* Copyright (c) 2015, Oran Agra
* Copyright (c) 2015, Redis Labs, Inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __SDS_H
#define __SDS_H
#define SDS_MAX_PREALLOC (1024*1024)
extern const char *SDS_NOINIT;
#include <sys/types.h>
#include <stdarg.h>
#include <stdint.h>
typedef char *sds;
#ifdef __cplusplus
#define DUMMY_ELEMENT 1
#else
#define DUMMY_ELEMENT
#endif
#ifdef _MSC_VER
#define PACK(decl) __pragma(pack(push, 1)) decl __pragma(pack(pop))
#if defined(_WIN64)
typedef __int64 ssize_t;
#else
typedef long ssize_t;
#endif
#else
#define PACK(decl) decl __attribute__((__packed__))
#endif
/* Note: sdshdr5 is never used, we just access the flags byte directly.
* However is here to document the layout of type 5 SDS strings. */
PACK(struct sdshdr5 {
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
char buf[DUMMY_ELEMENT];
});
PACK(struct sdshdr8 {
uint8_t len; /* used */
uint8_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[DUMMY_ELEMENT];
});
PACK(struct sdshdr16 {
uint16_t len; /* used */
uint16_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[DUMMY_ELEMENT];
});
PACK(struct sdshdr32 {
uint32_t len; /* used */
uint32_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[DUMMY_ELEMENT];
});
PACK(struct sdshdr64 {
uint64_t len; /* used */
uint64_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[DUMMY_ELEMENT];
});
#undef PACK
#define SDS_TYPE_5 0
#define SDS_TYPE_8 1
#define SDS_TYPE_16 2
#define SDS_TYPE_32 3
#define SDS_TYPE_64 4
#define SDS_TYPE_MASK 7
#define SDS_TYPE_BITS 3
#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)));
#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))
#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)
static inline size_t sdslen(const sds s) {
unsigned char flags = s[-1];
switch(flags&SDS_TYPE_MASK) {
case SDS_TYPE_5:
return SDS_TYPE_5_LEN(flags);
case SDS_TYPE_8:
return SDS_HDR(8,s)->len;
case SDS_TYPE_16:
return SDS_HDR(16,s)->len;
case SDS_TYPE_32:
return SDS_HDR(32,s)->len;
case SDS_TYPE_64:
return SDS_HDR(64,s)->len;
}
return 0;
}
static inline size_t sdsavail(const sds s) {
unsigned char flags = s[-1];
switch(flags&SDS_TYPE_MASK) {
case SDS_TYPE_5: {
return 0;
}
case SDS_TYPE_8: {
SDS_HDR_VAR(8,s);
return sh->alloc - sh->len;
}
case SDS_TYPE_16: {
SDS_HDR_VAR(16,s);
return sh->alloc - sh->len;
}
case SDS_TYPE_32: {
SDS_HDR_VAR(32,s);
return sh->alloc - sh->len;
}
case SDS_TYPE_64: {
SDS_HDR_VAR(64,s);
return sh->alloc - sh->len;
}
}
return 0;
}
static inline void sdssetlen(sds s, size_t newlen) {
unsigned char flags = s[-1];
switch(flags&SDS_TYPE_MASK) {
case SDS_TYPE_5:
{
unsigned char *fp = ((unsigned char*)s)-1;
*fp = (unsigned char) (SDS_TYPE_5 | (newlen << SDS_TYPE_BITS));
}
break;
case SDS_TYPE_8:
SDS_HDR(8,s)->len = (uint8_t) newlen;
break;
case SDS_TYPE_16:
SDS_HDR(16,s)->len = (uint16_t) newlen;
break;
case SDS_TYPE_32:
SDS_HDR(32,s)->len = (uint32_t) newlen;
break;
case SDS_TYPE_64:
SDS_HDR(64,s)->len = (uint64_t) newlen;
break;
}
}
static inline void sdsinclen(sds s, size_t inc) {
unsigned char flags = s[-1];
switch(flags&SDS_TYPE_MASK) {
case SDS_TYPE_5:
{
unsigned char *fp = ((unsigned char*)s)-1;
unsigned char newlen = (unsigned char) (SDS_TYPE_5_LEN(flags)+inc);
*fp = (unsigned char) (SDS_TYPE_5 | (newlen << SDS_TYPE_BITS));
}
break;
case SDS_TYPE_8:
SDS_HDR(8,s)->len += (uint8_t) inc;
break;
case SDS_TYPE_16:
SDS_HDR(16,s)->len += (uint16_t) inc;
break;
case SDS_TYPE_32:
SDS_HDR(32,s)->len += (uint32_t) inc;
break;
case SDS_TYPE_64:
SDS_HDR(64,s)->len += (uint64_t) inc;
break;
}
}
/* sdsalloc() = sdsavail() + sdslen() */
static inline size_t sdsalloc(const sds s) {
unsigned char flags = s[-1];
switch(flags&SDS_TYPE_MASK) {
case SDS_TYPE_5:
return SDS_TYPE_5_LEN(flags);
case SDS_TYPE_8:
return SDS_HDR(8,s)->alloc;
case SDS_TYPE_16:
return SDS_HDR(16,s)->alloc;
case SDS_TYPE_32:
return SDS_HDR(32,s)->alloc;
case SDS_TYPE_64:
return SDS_HDR(64,s)->alloc;
}
return 0;
}
static inline void sdssetalloc(sds s, size_t newlen) {
unsigned char flags = s[-1];
switch(flags&SDS_TYPE_MASK) {
case SDS_TYPE_5:
/* Nothing to do, this type has no total allocation info. */
break;
case SDS_TYPE_8:
SDS_HDR(8,s)->alloc = (uint8_t) newlen;
break;
case SDS_TYPE_16:
SDS_HDR(16,s)->alloc = (uint16_t) newlen;
break;
case SDS_TYPE_32:
SDS_HDR(32,s)->alloc = (uint32_t) newlen;
break;
case SDS_TYPE_64:
SDS_HDR(64,s)->alloc = (uint64_t) newlen;
break;
}
}
sds sdsnewlen(const void *init, size_t initlen);
sds sdsnew(const char *init);
sds sdsempty(void);
sds sdsdup(const sds s);
void sdsfree(sds s);
sds sdsgrowzero(sds s, size_t len);
sds sdscatlen(sds s, const void *t, size_t len);
sds sdscat(sds s, const char *t);
sds sdscatsds(sds s, const sds t);
sds sdscpylen(sds s, const char *t, size_t len);
sds sdscpy(sds s, const char *t);
sds sdscatvprintf(sds s, const char *fmt, va_list ap);
#ifdef __GNUC__
sds sdscatprintf(sds s, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
#else
sds sdscatprintf(sds s, const char *fmt, ...);
#endif
sds sdscatfmt(sds s, char const *fmt, ...);
sds sdstrim(sds s, const char *cset);
void sdsrange(sds s, ssize_t start, ssize_t end);
void sdsupdatelen(sds s);
void sdsclear(sds s);
int sdscmp(const sds s1, const sds s2);
sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count);
void sdsfreesplitres(sds *tokens, int count);
void sdstolower(sds s);
void sdstoupper(sds s);
sds sdsfromlonglong(long long value);
sds sdscatrepr(sds s, const char *p, size_t len);
sds *sdssplitargs(const char *line, int *argc);
sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);
sds sdsjoin(char **argv, int argc, char *sep);
sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);
/* Low level functions exposed to the user API */
sds sdsMakeRoomFor(sds s, size_t addlen);
void sdsIncrLen(sds s, ssize_t incr);
sds sdsRemoveFreeSpace(sds s);
size_t sdsAllocSize(sds s);
void *sdsAllocPtr(sds s);
/* Export the allocator used by SDS to the program using SDS.
* Sometimes the program SDS is linked to, may use a different set of
* allocators, but may want to allocate or free things that SDS will
* respectively free or allocate. */
void *sds_malloc(size_t size);
void *sds_realloc(void *ptr, size_t size);
void sds_free(void *ptr);
#ifdef REDIS_TEST
int sdsTest(int argc, char *argv[]);
#endif
#endif

View File

@ -1,42 +0,0 @@
/* SDSLib 2.0 -- A C dynamic strings library
*
* Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>
* Copyright (c) 2015, Oran Agra
* Copyright (c) 2015, Redis Labs, Inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* SDS allocator selection.
*
* This file is used in order to change the SDS allocator at compile time.
* Just define the following defines to what you want to use. Also add
* the include of your alternate allocator if needed (not needed in order
* to use the default libc allocator). */
#define s_malloc malloc
#define s_realloc realloc
#define s_free free

View File

@ -123,6 +123,23 @@ bool lovrFilesystemGetAppdataDirectory(char* dest, unsigned int size) {
return false;
}
bool lovrFilesystemGetApplicationId(char* dest, size_t size) {
#ifdef __ANDROID__
pid_t pid = getpid();
char path[32];
snprintf(path, LOVR_PATH_MAX, "/proc/%i/cmdline", (int) pid);
FILE* file = fopen(path, "r");
if (file) {
size_t read = fread(dest, 1, size, file);
fclose(file);
return true;
}
return false;
#else
return false;
#endif
}
void lovrFilesystemGetDirectoryItems(const char* path, getDirectoryItemsCallback callback, void* userdata) {
PHYSFS_enumerate(path, (PHYSFS_EnumerateCallback) callback, userdata);
}

View File

@ -14,6 +14,7 @@ bool lovrFilesystemInit(const char* argExe, const char* argGame, const char* arg
void lovrFilesystemDestroy(void);
bool lovrFilesystemCreateDirectory(const char* path);
bool lovrFilesystemGetAppdataDirectory(char* dest, unsigned int size);
bool lovrFilesystemGetApplicationId(char* dest, size_t size);
void lovrFilesystemGetDirectoryItems(const char* path, getDirectoryItemsCallback callback, void* userdata);
int lovrFilesystemGetExecutablePath(char* path, uint32_t size);
const char* lovrFilesystemGetIdentity(void);

View File

@ -205,7 +205,6 @@ BlockType lovrShaderBlockGetType(ShaderBlock* block) {
return block->type;
}
// TODO use sds!
char* lovrShaderBlockGetShaderCode(ShaderBlock* block, const char* blockName, size_t* length) {
// Calculate

View File

@ -297,7 +297,6 @@ bool lovrPlatformHasWindow() {
#include <assert.h>
#include "oculus_mobile_bridge.h"
#include "lib/sds/sds.h"
#include "api/api.h"
#include "lib/lua-cjson/lua_cjson.h"
@ -331,8 +330,6 @@ enum {
int lovr_luaB_print_override (lua_State *L);
#define SDS(...) sdscatfmt(sdsempty(), __VA_ARGS__)
static void android_vthrow(lua_State* L, const char* format, va_list args) {
#define MAX_ERROR_LENGTH 1024
char lovrErrorMessage[MAX_ERROR_LENGTH];
@ -416,7 +413,10 @@ void bridgeLovrInit(BridgeLovrInitData *initData) {
// Save writable data directory for LovrFilesystemInit later
{
lovrOculusMobileWritablePath = sdsRemoveFreeSpace(SDS("%s/data", initData->writablePath));
size_t length = strlen(initData->writablePath);
lovrOculusMobileWritablePath = malloc(length + strlen("/data") + 1);
memcpy(lovrOculusMobileWritablePath, initData->writablePath, length);
memcpy(lovrOculusMobileWritablePath + length, "/data", strlen("/data") + 1);
mkdir(lovrOculusMobileWritablePath, 0777);
}
@ -519,4 +519,5 @@ void bridgeLovrPaused(bool paused) {
void bridgeLovrClose() {
pauseState = PAUSESTATE_NONE;
lua_close(L);
free(lovrOculusMobileWritablePath);
}