No game screen;

This commit is contained in:
bjorn 2017-04-02 05:55:21 -07:00
parent 66bb9063f5
commit 7f687f9732
28 changed files with 3292 additions and 255 deletions

2
.gitignore vendored
View File

@ -2,7 +2,7 @@
build
/lovr
deps
data
/data
src/obj
src/Tupfile
/watch.sh

View File

@ -2,7 +2,6 @@
#include "audio/audio.h"
#include "audio/source.h"
#include "loaders/source.h"
#include "filesystem/filesystem.h"
map_int_t TimeUnits;
@ -71,21 +70,12 @@ int l_lovrAudioIsSpatialized(lua_State* L) {
}
int l_lovrAudioNewSource(lua_State* L) {
const char* filename = luaL_checkstring(L, 1);
if (!strstr(filename, ".ogg")) {
return luaL_error(L, "Only .ogg files are supported");
}
size_t size;
void* data = lovrFilesystemRead(filename, &size);
if (!data) {
return luaL_error(L, "Could not load source from file '%s'", filename);
}
SourceData* sourceData = lovrSourceDataFromFile(data, size);
Blob* blob = luax_readblob(L, 1, "Source");
SourceData* sourceData = lovrSourceDataCreate(blob);
Source* source = lovrSourceCreate(sourceData);
luax_pushtype(L, Source, source);
lovrRelease(&source->ref);
lovrRelease(&blob->ref);
return 1;
}

View File

@ -4,6 +4,27 @@
#include <stdlib.h>
#include <string.h>
// Returns a Blob, leaving stack unchanged. The Blob must be released when finished.
Blob* luax_readblob(lua_State* L, int index, const char* debug) {
Blob* blob;
if (lua_type(L, index) == LUA_TUSERDATA) {
blob = luax_checktype(L, index, Blob);
lovrRetain(&blob->ref);
return blob;
} else {
const char* path = luaL_checkstring(L, index);
size_t size;
void* data = lovrFilesystemRead(path, &size);
if (!data) {
luaL_error(L, "Could not read %s from '%s'", debug, path);
}
return lovrBlobCreate(data, size, path);
}
}
static void pushDirectoryItem(void* userdata, const char* path, const char* filename) {
lua_State* L = userdata;
int n = lua_objlen(L, -1);
@ -166,7 +187,14 @@ int l_lovrFilesystemGetSize(lua_State* L) {
}
int l_lovrFilesystemGetSource(lua_State* L) {
lua_pushstring(L, lovrFilesystemGetSource());
const char* source = lovrFilesystemGetSource();
if (source) {
lua_pushstring(L, source);
} else {
lua_pushnil(L);
}
return 1;
}
@ -215,19 +243,23 @@ int l_lovrFilesystemMount(lua_State* L) {
int l_lovrFilesystemNewBlob(lua_State* L) {
const char* path;
const char* data;
char* data;
size_t size;
if (lua_gettop(L) == 1) {
path = luaL_checkstring(L, 1);
data = lovrFilesystemRead(path, &size);
} else {
data = luaL_checklstring(L, 1, &size);
const char* str = luaL_checklstring(L, 1, &size);
data = malloc(size + 1); // Copy the Lua string so we can hold onto it
memcpy(data, str, size);
data[size] = '\0';
path = luaL_checkstring(L, 2);
}
Blob* blob = lovrBlobCreate((void*) data, size, path);
luax_pushtype(L, Blob, blob);
lovrRelease(&blob->ref);
return 1;
}

View File

@ -51,15 +51,10 @@ static void luax_readvertices(lua_State* L, int index, vec_float_t* points) {
}
static Texture* luax_readtexture(lua_State* L, int index) {
const char* path = luaL_checkstring(L, index);
size_t size;
void* data = lovrFilesystemRead(path, &size);
if (!data) {
luaL_error(L, "Could not load texture file '%s'", path);
}
TextureData* textureData = lovrTextureDataFromFile(data, size);
Blob* blob = luax_readblob(L, index, "Texture");
TextureData* textureData = lovrTextureDataFromBlob(blob);
Texture* texture = lovrTextureCreate(textureData);
free(data);
lovrRelease(&blob->ref);
return texture;
}
@ -559,28 +554,25 @@ int l_lovrGraphicsPrint(lua_State* L) {
// Types
int l_lovrGraphicsNewFont(lua_State* L) {
void* data = NULL;
size_t size = 0;
float fontSize;
Blob* blob = NULL;
float size;
if (lua_type(L, 1) == LUA_TNUMBER || lua_isnoneornil(L, 1)) {
data = NULL;
size = 0;
fontSize = luaL_optnumber(L, 1, 32);
size = luaL_optnumber(L, 1, 32);
} else {
const char* path = luaL_checkstring(L, 1);
fontSize = luaL_optnumber(L, 2, 32);
data = lovrFilesystemRead(path, &size);
if (!data) {
luaL_error(L, "Could not load font '%s'", path);
}
blob = luax_readblob(L, 1, "Font");
size = luaL_optnumber(L, 2, 32);
}
FontData* fontData = lovrFontDataCreate(data, size, fontSize);
FontData* fontData = lovrFontDataCreate(blob, size);
Font* font = lovrFontCreate(fontData);
luax_pushtype(L, Font, font);
lovrRelease(&font->ref);
if (blob) {
lovrRelease(&blob->ref);
}
return 1;
}
@ -654,14 +646,8 @@ int l_lovrGraphicsNewMesh(lua_State* L) {
}
int l_lovrGraphicsNewModel(lua_State* L) {
const char* path = lua_tostring(L, 1);
size_t size;
void* data = lovrFilesystemRead(path, &size);
if (!data) {
return luaL_error(L, "Could not load model file '%s'", path);
}
ModelData* modelData = lovrModelDataFromFile(data, size);
Blob* blob = luax_readblob(L, 1, "Model");
ModelData* modelData = lovrModelDataCreate(blob);
Model* model = lovrModelCreate(modelData);
if (lua_gettop(L) >= 2) {
@ -671,8 +657,8 @@ int l_lovrGraphicsNewModel(lua_State* L) {
}
luax_pushtype(L, Model, model);
free(data);
lovrRelease(&model->ref);
lovrRelease(&blob->ref);
return 1;
}
@ -700,14 +686,12 @@ int l_lovrGraphicsNewShader(lua_State* L) {
}
int l_lovrGraphicsNewSkybox(lua_State* L) {
void* data[6] = { NULL };
size_t size[6] = { 0 };
Blob* blobs[6];
SkyboxType type;
if (lua_gettop(L) == 1 && lua_type(L, 1) == LUA_TSTRING) {
const char* filename = lua_tostring(L, 1);
data[0] = lovrFilesystemRead(filename, size);
type = SKYBOX_PANORAMA;
blobs[0] = luax_readblob(L, 1, "Skybox");
} else if (lua_istable(L, 1)) {
if (lua_objlen(L, 1) != 6) {
return luaL_argerror(L, 1, "Expected 6 strings or a table containing 6 strings");
@ -720,27 +704,25 @@ int l_lovrGraphicsNewSkybox(lua_State* L) {
return luaL_argerror(L, 1, "Expected 6 strings or a table containing 6 strings");
}
const char* filename = lua_tostring(L, -1);
data[i] = lovrFilesystemRead(filename, size + i);
blobs[i] = luax_readblob(L, -1, "Skybox");
lua_pop(L, 1);
}
type = SKYBOX_CUBE;
} else {
for (int i = 0; i < 6; i++) {
const char* filename = luaL_checkstring(L, i + 1);
data[i] = lovrFilesystemRead(filename, size + i);
blobs[i] = luax_readblob(L, i + 1, "Skybox");
}
type = SKYBOX_CUBE;
}
Skybox* skybox = lovrSkyboxCreate(data, size, type);
Skybox* skybox = lovrSkyboxCreate(blobs, type);
luax_pushtype(L, Skybox, skybox);
lovrRelease(&skybox->ref);
for (int i = 0; i < 6; i++) {
free(data[i]);
lovrRelease(&blobs[i]->ref);
}
return 1;
@ -749,15 +731,15 @@ int l_lovrGraphicsNewSkybox(lua_State* L) {
int l_lovrGraphicsNewTexture(lua_State* L) {
Texture* texture;
if (lua_type(L, 1) == LUA_TSTRING) {
texture = luax_readtexture(L, 1);
} else {
if (lua_type(L, 1) == LUA_TNUMBER) {
int width = luaL_checknumber(L, 1);
int height = luaL_checknumber(L, 2);
TextureProjection* projection = luax_optenum(L, 3, "2d", &TextureProjections, "projection");
int msaa = luaL_optnumber(L, 4, 0);
TextureData* textureData = lovrTextureDataGetEmpty(width, height, FORMAT_RGBA);
texture = lovrTextureCreateWithFramebuffer(textureData, *projection, msaa);
} else {
texture = luax_readtexture(L, 1);
}
luax_pushtype(L, Texture, texture);

View File

@ -1,4 +1,5 @@
#include "luax.h"
#include "filesystem/blob.h"
#include "graphics/mesh.h"
#include "math/math.h"
#include "lib/map/map.h"
@ -49,4 +50,5 @@ extern map_int_t VerticalAligns;
extern map_int_t WrapModes;
void luax_checkmeshformat(lua_State* L, int index, MeshFormat* format);
int luax_readtransform(lua_State* L, int i, mat4 transform);
int luax_readtransform(lua_State* L, int index, mat4 transform);
Blob* luax_readblob(lua_State* L, int index, const char* debug);

View File

@ -3,25 +3,25 @@
int l_lovrBlobGetFilename(lua_State* L) {
Blob* blob = luax_checktype(L, 1, Blob);
lua_pushstring(L, lovrBlobGetName(blob));
lua_pushstring(L, blob->name);
return 1;
}
int l_lovrBlobGetPointer(lua_State* L) {
Blob* blob = luax_checktype(L, 1, Blob);
lua_pushlightuserdata(L, lovrBlobGetData(blob));
lua_pushlightuserdata(L, blob->data);
return 1;
}
int l_lovrBlobGetSize(lua_State* L) {
Blob* blob = luax_checktype(L, 1, Blob);
lua_pushinteger(L, lovrBlobGetSize(blob));
lua_pushinteger(L, blob->size);
return 1;
}
int l_lovrBlobGetString(lua_State* L) {
Blob* blob = luax_checktype(L, 1, Blob);
lua_pushlstring(L, lovrBlobGetData(blob), lovrBlobGetSize(blob));
lua_pushlstring(L, blob->data, blob->size);
return 1;
}

View File

@ -2,25 +2,25 @@
#include "math/mat4.h"
#include "math/transform.h"
int luax_readtransform(lua_State* L, int i, mat4 m) {
if (lua_isnumber(L, i)) {
float x = luaL_optnumber(L, i++, 0);
float y = luaL_optnumber(L, i++, 0);
float z = luaL_optnumber(L, i++, 0);
float s = luaL_optnumber(L, i++, 1);
float angle = luaL_optnumber(L, i++, 0);
float ax = luaL_optnumber(L, i++, 0);
float ay = luaL_optnumber(L, i++, 1);
float az = luaL_optnumber(L, i++, 0);
int luax_readtransform(lua_State* L, int index, mat4 m) {
if (lua_isnumber(L, index)) {
float x = luaL_optnumber(L, index++, 0);
float y = luaL_optnumber(L, index++, 0);
float z = luaL_optnumber(L, index++, 0);
float s = luaL_optnumber(L, index++, 1);
float angle = luaL_optnumber(L, index++, 0);
float ax = luaL_optnumber(L, index++, 0);
float ay = luaL_optnumber(L, index++, 1);
float az = luaL_optnumber(L, index++, 0);
mat4_setTransform(m, x, y, z, s, angle, ax, ay, az);
return i;
} else if (lua_isnoneornil(L, i)) {
return index;
} else if (lua_isnoneornil(L, index)) {
mat4_identity(m);
return i;
return index;
} else {
Transform* transform = luax_checktype(L, i, Transform);
Transform* transform = luax_checktype(L, index, Transform);
mat4_init(m, transform->matrix);
return ++i;
return ++index;
}
}

BIN
src/data/Cabin.ttf Normal file

Binary file not shown.

180
src/data/boot.lua Normal file
View File

@ -0,0 +1,180 @@
local conf = {
modules = {
audio = true,
event = true,
graphics = true,
headset = true,
math = true,
timer = true
},
headset = {
mirror = true
}
}
lovr.filesystem = require('lovr.filesystem')
local runnable = lovr.filesystem.isFile('conf.lua') or lovr.filesystem.isFile('main.lua')
if not lovr.filesystem.getSource() or not runnable then
function lovr.conf(t)
t.modules.audio = false
t.modules.math = false
end
function lovr.load()
lovr.filesystem.write('asdf.png', lovr._logo)
logo = lovr.graphics.newTexture(lovr.filesystem.newBlob(lovr._logo, 'logo.png'))
lovr.graphics.setBackgroundColor(245, 252, 255)
refreshControllers()
end
function lovr.draw()
if lovr.headset and lovr.headset.isPresent() then
ground = ground or lovr.graphics.newMesh(lovr.headset.getBoundsGeometry())
lovr.graphics.setColor(255, 255, 255)
ground:draw()
lovr.graphics.setColor(255, 255, 255)
for controller, model in pairs(controllers) do
local x, y, z = controller:getPosition()
model:draw(x, y, z, 1, controller:getOrientation())
end
lovr.graphics.translate(0, 2, 0)
else
lovr.graphics.translate(0, .2, 0)
end
local padding = .1
local font = lovr.graphics.getFont()
local fade = 80 + 150 * math.abs(math.sin(lovr.timer.getTime() * 2))
local titlePosition = -.5 - padding
local subtitlePosition = titlePosition - font:getHeight() * .25 - padding
lovr.graphics.setColor(255, 255, 255)
lovr.graphics.plane(logo, 0, 0, -3, 1, 0, 0, 1)
lovr.graphics.setColor(15, 15, 15)
lovr.graphics.print('LÖVR', -.01, titlePosition, -3, .25, 0, 0, 1, 0, nil, 'center', 'top')
lovr.graphics.setColor(15, 15, 15, fade)
lovr.graphics.print('No game :(', -.01, subtitlePosition, -3, .15, 0, 0, 1, 0, nil, 'center', 'top')
end
function refreshControllers()
if not lovr.headset then return end
controllers = {}
for _, controller in pairs(lovr.headset.getControllers()) do
controllers[controller] = controller:newModel()
end
end
lovr.controlleradded = refreshControllers
lovr.controllerremoved = refreshControllers
end
local success, err = pcall(require, 'conf')
if lovr.conf then
success, err = pcall(lovr.conf, conf)
end
local modules = { 'audio', 'event', 'graphics', 'headset', 'math', 'timer' }
for _, module in ipairs(modules) do
if conf.modules[module] then
lovr[module] = require('lovr.' .. module)
end
end
lovr.filesystem.setIdentity(conf.identity or 'default')
if lovr.headset then lovr.headset.setMirrored(conf.headset and conf.headset.mirror) end
lovr.handlers = setmetatable({
quit = function() end,
focus = function(f)
if lovr.focus then lovr.focus(f) end
end,
controlleradded = function(c)
if lovr.controlleradded then lovr.controlleradded(c) end
end,
controllerremoved = function(c)
if lovr.controllerremoved then lovr.controllerremoved(c) end
end,
controllerpressed = function(c, b)
if lovr.controllerpressed then lovr.controllerpressed(c, b) end
end,
controllerreleased = function(c, b)
if lovr.controllerreleased then lovr.controllerreleased(c, b) end
end
}, {
__index = function(self, event)
error('Unknown event: ' .. tostring(event))
end
})
function lovr.run()
if lovr.load then lovr.load() end
while true do
lovr.event.pump()
for name, a, b, c, d in lovr.event.poll() do
if name == 'quit' and (not lovr.quit or not lovr.quit()) then
return a
end
lovr.handlers[name](a, b, c, d)
end
local dt = lovr.timer.step()
if lovr.audio then
lovr.audio.update()
if lovr.headset and lovr.headset.isPresent() then
lovr.audio.setOrientation(lovr.headset.getOrientation())
lovr.audio.setPosition(lovr.headset.getPosition())
lovr.audio.setVelocity(lovr.headset.getVelocity())
end
end
if lovr.update then lovr.update(dt) end
lovr.graphics.clear()
lovr.graphics.origin()
if lovr.draw then
if lovr.headset and lovr.headset.isPresent() then
lovr.headset.renderTo(lovr.draw)
else
lovr.draw()
end
end
lovr.graphics.present()
lovr.timer.sleep(.001)
end
end
function lovr.errhand(message)
message = 'Error:\n' .. message:gsub('\n[^\n]+$', ''):gsub('\t', ''):gsub('stack traceback', '\nStack')
print(message)
lovr.graphics.reset()
lovr.graphics.setBackgroundColor(27, 25, 35)
lovr.graphics.setColor(220, 220, 220)
local font = lovr.graphics.getFont()
local pixelDensity = font:getPixelDensity()
local width = font:getWidth(message, .55 * pixelDensity)
local function render()
lovr.graphics.origin()
lovr.graphics.print(message, -width / 2, 0, -20, 1, 0, 0, 0, 0, .55 * pixelDensity, 'left')
end
while true do
lovr.event.pump()
for name in lovr.event.poll() do
if name == 'quit' then return end
end
lovr.graphics.clear()
if lovr.headset and lovr.headset.isPresent() then
lovr.headset.renderTo(render)
else
render()
end
lovr.graphics.present()
lovr.timer.sleep((lovr.headset and lovr.headset.isPresent()) and .001 or .1)
end
end
if lovr.filesystem.isFile('main.lua') then
require('main')
end

444
src/data/boot.lua.h Normal file
View File

@ -0,0 +1,444 @@
unsigned char boot_lua[] = {
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x20, 0x3d,
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73,
0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x75, 0x64,
0x69, 0x6f, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x74,
0x72, 0x75, 0x65, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x72, 0x61,
0x70, 0x68, 0x69, 0x63, 0x73, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65,
0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65,
0x74, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x6d, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75,
0x65, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x72,
0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x20, 0x20, 0x7d, 0x2c,
0x0a, 0x20, 0x20, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x3d,
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x69, 0x72, 0x72, 0x6f,
0x72, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x20, 0x20, 0x7d,
0x0a, 0x7d, 0x0a, 0x0a, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c,
0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x3d, 0x20, 0x72, 0x65,
0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x27, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x27, 0x29,
0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x75, 0x6e, 0x6e,
0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69,
0x73, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x27, 0x63, 0x6f, 0x6e, 0x66, 0x2e,
0x6c, 0x75, 0x61, 0x27, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x27, 0x6d, 0x61, 0x69,
0x6e, 0x2e, 0x6c, 0x75, 0x61, 0x27, 0x29, 0x0a, 0x69, 0x66, 0x20, 0x6e,
0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x67, 0x65, 0x74, 0x53, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x28, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x6f,
0x74, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66,
0x28, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x2e, 0x6d, 0x6f,
0x64, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x20,
0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x74, 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x6d, 0x61,
0x74, 0x68, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0a, 0x20,
0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x20, 0x20, 0x66, 0x75, 0x6e, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x6c, 0x6f,
0x61, 0x64, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
0x2e, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x27, 0x61, 0x73, 0x64, 0x66,
0x2e, 0x70, 0x6e, 0x67, 0x27, 0x2c, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x5f, 0x6c, 0x6f, 0x67, 0x6f, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c,
0x6f, 0x67, 0x6f, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67,
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x54,
0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x6e,
0x65, 0x77, 0x42, 0x6c, 0x6f, 0x62, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x5f, 0x6c, 0x6f, 0x67, 0x6f, 0x2c, 0x20, 0x27, 0x6c, 0x6f, 0x67, 0x6f,
0x2e, 0x70, 0x6e, 0x67, 0x27, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
0x73, 0x2e, 0x73, 0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x32, 0x34, 0x35,
0x2c, 0x20, 0x32, 0x35, 0x32, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x43,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x20, 0x20, 0x66, 0x75,
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x64, 0x72, 0x61, 0x77, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69,
0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x65, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x69, 0x73, 0x50, 0x72,
0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e,
0x64, 0x20, 0x3d, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x6f,
0x72, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68,
0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x4d, 0x65, 0x73, 0x68, 0x28,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74,
0x2e, 0x67, 0x65, 0x74, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x47, 0x65,
0x6f, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x28, 0x29, 0x29, 0x0a, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72,
0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x43, 0x6f,
0x6c, 0x6f, 0x72, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35,
0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x64, 0x72, 0x61, 0x77,
0x28, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e,
0x73, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x32, 0x35, 0x35,
0x2c, 0x20, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2c, 0x20, 0x6d, 0x6f,
0x64, 0x65, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73,
0x28, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x73,
0x29, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x78, 0x2c, 0x20, 0x79, 0x2c,
0x20, 0x7a, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x3a, 0x67, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x3a, 0x64, 0x72, 0x61, 0x77,
0x28, 0x78, 0x2c, 0x20, 0x79, 0x2c, 0x20, 0x7a, 0x2c, 0x20, 0x31, 0x2c,
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x3a,
0x67, 0x65, 0x74, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x30,
0x2c, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x30,
0x2c, 0x20, 0x2e, 0x32, 0x2c, 0x20, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f,
0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x20,
0x3d, 0x20, 0x2e, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63,
0x61, 0x6c, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e,
0x67, 0x65, 0x74, 0x46, 0x6f, 0x6e, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x61, 0x64, 0x65,
0x20, 0x3d, 0x20, 0x38, 0x30, 0x20, 0x2b, 0x20, 0x31, 0x35, 0x30, 0x20,
0x2a, 0x20, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x61, 0x62, 0x73, 0x28, 0x6d,
0x61, 0x74, 0x68, 0x2e, 0x73, 0x69, 0x6e, 0x28, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x74, 0x54, 0x69,
0x6d, 0x65, 0x28, 0x29, 0x20, 0x2a, 0x20, 0x32, 0x29, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x69, 0x74,
0x6c, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d,
0x20, 0x2d, 0x2e, 0x35, 0x20, 0x2d, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69,
0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x20, 0x73, 0x75, 0x62, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x50, 0x6f, 0x73,
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x74, 0x69, 0x74, 0x6c,
0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x2d, 0x20,
0x66, 0x6f, 0x6e, 0x74, 0x3a, 0x67, 0x65, 0x74, 0x48, 0x65, 0x69, 0x67,
0x68, 0x74, 0x28, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x32, 0x35, 0x20, 0x2d,
0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x0a, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68,
0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
0x28, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32,
0x35, 0x35, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x6c,
0x61, 0x6e, 0x65, 0x28, 0x6c, 0x6f, 0x67, 0x6f, 0x2c, 0x20, 0x30, 0x2c,
0x20, 0x30, 0x2c, 0x20, 0x2d, 0x33, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30,
0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
0x73, 0x2e, 0x73, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x31,
0x35, 0x2c, 0x20, 0x31, 0x35, 0x2c, 0x20, 0x31, 0x35, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70,
0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x27,
0x4c, 0xc3, 0x96, 0x56, 0x52, 0x27, 0x2c, 0x20, 0x2d, 0x2e, 0x30, 0x31,
0x2c, 0x20, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x2d, 0x33, 0x2c, 0x20, 0x2e, 0x32, 0x35,
0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30,
0x2c, 0x20, 0x6e, 0x69, 0x6c, 0x2c, 0x20, 0x27, 0x63, 0x65, 0x6e, 0x74,
0x65, 0x72, 0x27, 0x2c, 0x20, 0x27, 0x74, 0x6f, 0x70, 0x27, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61,
0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x43, 0x6f, 0x6c,
0x6f, 0x72, 0x28, 0x31, 0x35, 0x2c, 0x20, 0x31, 0x35, 0x2c, 0x20, 0x31,
0x35, 0x2c, 0x20, 0x66, 0x61, 0x64, 0x65, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69,
0x63, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x27, 0x4e, 0x6f,
0x20, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x3a, 0x28, 0x27, 0x2c, 0x20, 0x2d,
0x2e, 0x30, 0x31, 0x2c, 0x20, 0x73, 0x75, 0x62, 0x74, 0x69, 0x74, 0x6c,
0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x2d,
0x33, 0x2c, 0x20, 0x2e, 0x31, 0x35, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30,
0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x6e, 0x69, 0x6c, 0x2c,
0x20, 0x27, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x27, 0x2c, 0x20, 0x27,
0x74, 0x6f, 0x70, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x0a, 0x20, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x6e, 0x64,
0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x5f, 0x2c, 0x20, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x69, 0x6e,
0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x43,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x28, 0x29,
0x29, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x5b, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x5d, 0x20, 0x3d,
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x3a,
0x6e, 0x65, 0x77, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x28, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64,
0x0a, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x61, 0x64, 0x64, 0x65, 0x64,
0x20, 0x3d, 0x20, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x43, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x0a, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x3d,
0x20, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x0a, 0x65, 0x6e, 0x64, 0x0a,
0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65,
0x73, 0x73, 0x2c, 0x20, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x70, 0x63,
0x61, 0x6c, 0x6c, 0x28, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x2c,
0x20, 0x27, 0x63, 0x6f, 0x6e, 0x66, 0x27, 0x29, 0x0a, 0x69, 0x66, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x20, 0x74, 0x68,
0x65, 0x6e, 0x0a, 0x20, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73,
0x2c, 0x20, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x70, 0x63, 0x61, 0x6c,
0x6c, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2c,
0x20, 0x63, 0x6f, 0x6e, 0x66, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a,
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
0x73, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x27, 0x61, 0x75, 0x64, 0x69, 0x6f,
0x27, 0x2c, 0x20, 0x27, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x27, 0x2c, 0x20,
0x27, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x27, 0x2c, 0x20,
0x27, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x27, 0x2c, 0x20, 0x27,
0x6d, 0x61, 0x74, 0x68, 0x27, 0x2c, 0x20, 0x27, 0x74, 0x69, 0x6d, 0x65,
0x72, 0x27, 0x20, 0x7d, 0x0a, 0x66, 0x6f, 0x72, 0x20, 0x5f, 0x2c, 0x20,
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70,
0x61, 0x69, 0x72, 0x73, 0x28, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73,
0x29, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x63, 0x6f,
0x6e, 0x66, 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x5b, 0x6d,
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x5b, 0x6d, 0x6f, 0x64,
0x75, 0x6c, 0x65, 0x5d, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69,
0x72, 0x65, 0x28, 0x27, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x27, 0x20, 0x2e,
0x2e, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x29, 0x0a, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
0x2e, 0x73, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79,
0x28, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x74, 0x79, 0x20, 0x6f, 0x72, 0x20, 0x27, 0x64, 0x65, 0x66, 0x61, 0x75,
0x6c, 0x74, 0x27, 0x29, 0x0a, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x65, 0x74, 0x2e, 0x73, 0x65, 0x74, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72,
0x65, 0x64, 0x28, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x66,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x6d, 0x69, 0x72,
0x72, 0x6f, 0x72, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x20,
0x3d, 0x20, 0x73, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62,
0x6c, 0x65, 0x28, 0x7b, 0x0a, 0x20, 0x20, 0x71, 0x75, 0x69, 0x74, 0x20,
0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29,
0x20, 0x65, 0x6e, 0x64, 0x2c, 0x0a, 0x20, 0x20, 0x66, 0x6f, 0x63, 0x75,
0x73, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x28, 0x66, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x74, 0x68,
0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66, 0x6f, 0x63, 0x75,
0x73, 0x28, 0x66, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65,
0x6e, 0x64, 0x2c, 0x0a, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x3d, 0x20,
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x63, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x61, 0x64,
0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x61, 0x64, 0x64, 0x65, 0x64, 0x28, 0x63, 0x29, 0x20, 0x65, 0x6e, 0x64,
0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x2c, 0x0a, 0x20, 0x20, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x72, 0x65, 0x6d, 0x6f,
0x76, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x28, 0x63, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20,
0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x72, 0x65, 0x6d, 0x6f,
0x76, 0x65, 0x64, 0x28, 0x63, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20,
0x20, 0x65, 0x6e, 0x64, 0x2c, 0x0a, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65,
0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x28, 0x63, 0x2c, 0x20, 0x62, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69,
0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64,
0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x70, 0x72, 0x65,
0x73, 0x73, 0x65, 0x64, 0x28, 0x63, 0x2c, 0x20, 0x62, 0x29, 0x20, 0x65,
0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x2c, 0x0a, 0x20, 0x20,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x72, 0x65,
0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x63, 0x2c, 0x20, 0x62, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x72, 0x65,
0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x28,
0x63, 0x2c, 0x20, 0x62, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x7d, 0x2c, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x5f,
0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20,
0x65, 0x76, 0x65, 0x6e, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65,
0x72, 0x72, 0x6f, 0x72, 0x28, 0x27, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77,
0x6e, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x27, 0x20, 0x2e,
0x2e, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x65,
0x76, 0x65, 0x6e, 0x74, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64,
0x0a, 0x7d, 0x29, 0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x72, 0x75, 0x6e, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x6c,
0x6f, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x28, 0x29, 0x20, 0x65, 0x6e, 0x64,
0x0a, 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x75,
0x65, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 0x70,
0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e,
0x61, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x63,
0x2c, 0x20, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x6f, 0x6c, 0x6c, 0x28, 0x29,
0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66,
0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x71, 0x75,
0x69, 0x74, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x6e, 0x6f, 0x74,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x71, 0x75, 0x69, 0x74, 0x20, 0x6f,
0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x71,
0x75, 0x69, 0x74, 0x28, 0x29, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75,
0x72, 0x6e, 0x20, 0x61, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65,
0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x5b, 0x6e,
0x61, 0x6d, 0x65, 0x5d, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x63,
0x2c, 0x20, 0x64, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64,
0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x74, 0x69, 0x6d,
0x65, 0x72, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75,
0x64, 0x69, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69,
0x6f, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x64,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65,
0x74, 0x2e, 0x69, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28,
0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69,
0x6f, 0x2e, 0x73, 0x65, 0x74, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x4f, 0x72, 0x69,
0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74, 0x50, 0x6f,
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x50,
0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74, 0x56, 0x65, 0x6c,
0x6f, 0x63, 0x69, 0x74, 0x79, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x56, 0x65,
0x6c, 0x6f, 0x63, 0x69, 0x74, 0x79, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x75, 0x70, 0x64,
0x61, 0x74, 0x65, 0x28, 0x64, 0x74, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61,
0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x28,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67,
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6f, 0x72, 0x69, 0x67,
0x69, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x20, 0x74, 0x68,
0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74,
0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x69, 0x73, 0x50, 0x72, 0x65, 0x73,
0x65, 0x6e, 0x74, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x72, 0x65, 0x6e, 0x64,
0x65, 0x72, 0x54, 0x6f, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72,
0x61, 0x77, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c,
0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x28, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70,
0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e,
0x73, 0x6c, 0x65, 0x65, 0x70, 0x28, 0x2e, 0x30, 0x30, 0x31, 0x29, 0x0a,
0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x66,
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x65, 0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x28, 0x6d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x29, 0x0a, 0x20, 0x20, 0x6d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x20, 0x3d, 0x20, 0x27, 0x45, 0x72, 0x72, 0x6f, 0x72,
0x3a, 0x5c, 0x6e, 0x27, 0x20, 0x2e, 0x2e, 0x20, 0x6d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x27, 0x5c, 0x6e,
0x5b, 0x5e, 0x5c, 0x6e, 0x5d, 0x2b, 0x24, 0x27, 0x2c, 0x20, 0x27, 0x27,
0x29, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x27, 0x5c, 0x74, 0x27, 0x2c,
0x20, 0x27, 0x27, 0x29, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x27, 0x73,
0x74, 0x61, 0x63, 0x6b, 0x20, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61,
0x63, 0x6b, 0x27, 0x2c, 0x20, 0x27, 0x5c, 0x6e, 0x53, 0x74, 0x61, 0x63,
0x6b, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28,
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x29, 0x0a, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
0x2e, 0x72, 0x65, 0x73, 0x65, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
0x2e, 0x73, 0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
0x6e, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x32, 0x37, 0x2c, 0x20,
0x32, 0x35, 0x2c, 0x20, 0x33, 0x35, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e,
0x73, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x32, 0x32, 0x30,
0x2c, 0x20, 0x32, 0x32, 0x30, 0x2c, 0x20, 0x32, 0x32, 0x30, 0x29, 0x0a,
0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x6e, 0x74,
0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70,
0x68, 0x69, 0x63, 0x73, 0x2e, 0x67, 0x65, 0x74, 0x46, 0x6f, 0x6e, 0x74,
0x28, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70,
0x69, 0x78, 0x65, 0x6c, 0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x20,
0x3d, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x3a, 0x67, 0x65, 0x74, 0x50, 0x69,
0x78, 0x65, 0x6c, 0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x77, 0x69, 0x64,
0x74, 0x68, 0x20, 0x3d, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x3a, 0x67, 0x65,
0x74, 0x57, 0x69, 0x64, 0x74, 0x68, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x2c, 0x20, 0x2e, 0x35, 0x35, 0x20, 0x2a, 0x20, 0x70, 0x69,
0x78, 0x65, 0x6c, 0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x29, 0x0a,
0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x28,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67,
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6f, 0x72, 0x69, 0x67,
0x69, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70,
0x72, 0x69, 0x6e, 0x74, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x2c, 0x20, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x2f, 0x20, 0x32,
0x2c, 0x20, 0x30, 0x2c, 0x20, 0x2d, 0x32, 0x30, 0x2c, 0x20, 0x31, 0x2c,
0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c,
0x20, 0x2e, 0x35, 0x35, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c,
0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x27, 0x6c, 0x65,
0x66, 0x74, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20,
0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x75, 0x65, 0x20,
0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 0x70, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x61, 0x6d,
0x65, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x76,
0x65, 0x6e, 0x74, 0x2e, 0x70, 0x6f, 0x6c, 0x6c, 0x28, 0x29, 0x20, 0x64,
0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e,
0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x71, 0x75, 0x69, 0x74,
0x27, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
0x6e, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e,
0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67,
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x63, 0x6c, 0x65, 0x61,
0x72, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20,
0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x65, 0x74, 0x2e, 0x69, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65,
0x6e, 0x74, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x65, 0x74, 0x2e, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x54,
0x6f, 0x28, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e,
0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72,
0x2e, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x28, 0x28, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x64,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65,
0x74, 0x2e, 0x69, 0x73, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28,
0x29, 0x29, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x2e, 0x30, 0x30, 0x31, 0x20,
0x6f, 0x72, 0x20, 0x2e, 0x31, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64,
0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x27, 0x6d, 0x61, 0x69,
0x6e, 0x2e, 0x6c, 0x75, 0x61, 0x27, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x0a, 0x20, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x27,
0x6d, 0x61, 0x69, 0x6e, 0x27, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a
};
unsigned int boot_lua_len = 5291;

BIN
src/data/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

2529
src/data/logo.png.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -16,15 +16,3 @@ void lovrBlobDestroy(const Ref* ref) {
free(blob->data);
free(blob);
}
void* lovrBlobGetData(Blob* blob) {
return blob->data;
}
size_t lovrBlobGetSize(Blob* blob) {
return blob->size;
}
const char* lovrBlobGetName(Blob* blob) {
return blob->name;
}

View File

@ -11,6 +11,3 @@ typedef struct {
Blob* lovrBlobCreate(void* data, size_t size, const char* name);
void lovrBlobDestroy(const Ref* ref);
void* lovrBlobGetData(Blob* blob);
size_t lovrBlobGetSize(Blob* blob);
const char* lovrBlobGetName(Blob* blob);

View File

@ -30,15 +30,21 @@ void lovrFilesystemInit(const char* arg0, const char* arg1) {
// 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) && arg1) {
if (lovrFilesystemMount(state.source, NULL, 1)) {
state.isFused = 0;
strncpy(state.source, arg1, LOVR_PATH_MAX);
if (!state.source || lovrFilesystemMount(state.source, NULL, 1)) {
free(state.source);
state.source = NULL;
if (arg1) {
strncpy(state.source, arg1, LOVR_PATH_MAX);
if (!lovrFilesystemMount(state.source, NULL, 1)) {
goto mounted;
}
}
free(state.source);
state.source = NULL;
}
mounted:
atexit(lovrFilesystemDestroy);
}

View File

@ -261,7 +261,7 @@ void lovrGraphicsSetShader(Shader* shader) {
void lovrGraphicsEnsureFont() {
if (!state.activeFont && !state.defaultFont) {
FontData* fontData = lovrFontDataCreate(NULL, 0, 32);
FontData* fontData = lovrFontDataCreate(NULL, 32);
state.defaultFont = lovrFontCreate(fontData);
lovrGraphicsSetFont(state.defaultFont);
}

View File

@ -2,7 +2,7 @@
#include "lib/stb/stb_image.h"
#include <stdlib.h>
Skybox* lovrSkyboxCreate(void** data, size_t* size, SkyboxType type) {
Skybox* lovrSkyboxCreate(Blob** blobs, SkyboxType type) {
Skybox* skybox = lovrAlloc(sizeof(Skybox), lovrSkyboxDestroy);
if (!skybox) return NULL;
@ -25,7 +25,7 @@ Skybox* lovrSkyboxCreate(void** data, size_t* size, SkyboxType type) {
for (int i = 0; i < count; i++) {
int width, height, channels;
stbi_set_flip_vertically_on_load(0);
unsigned char* image = stbi_load_from_memory(data[i], size[i], &width, &height, &channels, 3);
unsigned char* image = stbi_load_from_memory(blobs[i]->data, blobs[i]->size, &width, &height, &channels, 3);
if (!image) {
error("Could not load skybox image %d", i);

View File

@ -1,3 +1,4 @@
#include "filesystem/blob.h"
#include "glfw.h"
#include "util.h"
@ -14,5 +15,5 @@ typedef struct {
GLuint texture;
} Skybox;
Skybox* lovrSkyboxCreate(void** data, size_t* size, SkyboxType type);
Skybox* lovrSkyboxCreate(Blob** blobs, SkyboxType type);
void lovrSkyboxDestroy(const Ref* ref);

View File

@ -1,5 +1,5 @@
#include "loaders/font.h"
#include "loaders/Cabin.ttf.h"
#include "data/Cabin.ttf.h"
#include "util.h"
#include <ft2build.h>
#include FT_FREETYPE_H
@ -7,20 +7,20 @@
static FT_Library ft = NULL;
FontData* lovrFontDataCreate(void* data, int size, int height) {
FontData* lovrFontDataCreate(Blob* blob, int size) {
if (!ft && FT_Init_FreeType(&ft)) {
error("Error initializing FreeType");
}
if (!data) {
data = Cabin_ttf;
size = Cabin_ttf_len;
}
FT_Face face = NULL;
FT_Error err = FT_Err_Ok;
err = err || FT_New_Memory_Face(ft, data, size, 0, &face);
err = err || FT_Set_Pixel_Sizes(face, 0, height);
if (blob) {
err = err || FT_New_Memory_Face(ft, blob->data, blob->size, 0, &face);
} else {
err = err || FT_New_Memory_Face(ft, Cabin_ttf, Cabin_ttf_len, 0, &face);
}
err = err || FT_Set_Pixel_Sizes(face, 0, size);
if (err) {
error("Problem loading font\n");
@ -28,7 +28,7 @@ FontData* lovrFontDataCreate(void* data, int size, int height) {
FontData* fontData = malloc(sizeof(FontData));
fontData->rasterizer = face;
fontData->size = height;
fontData->size = size;
FT_Size_Metrics metrics = face->size->metrics;
fontData->height = metrics.height >> 6;

View File

@ -1,3 +1,4 @@
#include "filesystem/blob.h"
#include "lib/map/map.h"
#include <stdint.h>
@ -24,7 +25,7 @@ typedef struct {
typedef map_t(Glyph) map_glyph_t;
FontData* lovrFontDataCreate(void* data, int size, int height);
FontData* lovrFontDataCreate(Blob* blob, int size);
void lovrFontDataDestroy(FontData* fontData);
void lovrFontDataLoadGlyph(FontData* fontData, uint32_t character, Glyph* glyph);
int lovrFontDataGetKerning(FontData* fontData, uint32_t left, uint32_t right);

View File

@ -25,7 +25,7 @@ static void assimpNodeTraversal(ModelNode* node, struct aiNode* assimpNode) {
}
}
ModelData* lovrModelDataFromFile(void* data, int size) {
ModelData* lovrModelDataCreate(Blob* blob) {
ModelData* modelData = malloc(sizeof(ModelData));
if (!modelData) return NULL;
@ -33,7 +33,7 @@ ModelData* lovrModelDataFromFile(void* data, int size) {
modelData->hasTexCoords = 0;
unsigned int flags = aiProcessPreset_TargetRealtime_MaxQuality | aiProcess_OptimizeGraph;
const struct aiScene* scene = aiImportFileFromMemory(data, size, flags, NULL);
const struct aiScene* scene = aiImportFileFromMemory(blob->data, blob->size, flags, NULL);
// Meshes
vec_init(&modelData->meshes);

View File

@ -1,3 +1,4 @@
#include "filesystem/blob.h"
#include "util.h"
#include "lib/vec/vec.h"
@ -39,5 +40,5 @@ typedef struct {
int hasTexCoords;
} ModelData;
ModelData* lovrModelDataFromFile(void* data, int size);
ModelData* lovrModelDataCreate(Blob* blob);
void lovrModelDataDestroy(ModelData* modelData);

View File

@ -1,12 +1,13 @@
#include "loaders/source.h"
#include "lib/stb/stb_vorbis.h"
#include "util.h"
#include <stdlib.h>
SourceData* lovrSourceDataFromFile(void* data, int size) {
SourceData* lovrSourceDataCreate(Blob* blob) {
SourceData* sourceData = malloc(sizeof(SourceData));
if (!sourceData) return NULL;
stb_vorbis* decoder = stb_vorbis_open_memory(data, size, NULL, NULL);
stb_vorbis* decoder = stb_vorbis_open_memory(blob->data, blob->size, NULL, NULL);
if (!decoder) {
free(sourceData);
@ -22,14 +23,15 @@ SourceData* lovrSourceDataFromFile(void* data, int size) {
sourceData->decoder = decoder;
sourceData->bufferSize = sourceData->channels * 4096 * sizeof(short);
sourceData->buffer = malloc(sourceData->bufferSize);
sourceData->data = data;
sourceData->blob = blob;
lovrRetain(&blob->ref);
return sourceData;
}
void lovrSourceDataDestroy(SourceData* sourceData) {
stb_vorbis_close(sourceData->decoder);
free(sourceData->data);
lovrRelease(&sourceData->blob->ref);
free(sourceData->buffer);
free(sourceData);
}

View File

@ -1,3 +1,5 @@
#include "filesystem/blob.h"
#pragma once
typedef struct {
@ -8,10 +10,10 @@ typedef struct {
int bufferSize;
void* buffer;
void* decoder;
void* data;
Blob* blob;
} SourceData;
SourceData* lovrSourceDataFromFile(void* data, int size);
SourceData* lovrSourceDataCreate(Blob* blob);
void lovrSourceDataDestroy(SourceData* sourceData);
int lovrSourceDataDecode(SourceData* sourceData);
void lovrSourceDataRewind(SourceData* sourceData);

View File

@ -49,7 +49,7 @@ TextureData* lovrTextureDataGetEmpty(int width, int height, TextureFormat format
return textureData;
}
TextureData* lovrTextureDataFromFile(void* data, int size) {
TextureData* lovrTextureDataFromBlob(Blob* blob) {
TextureData* textureData = malloc(sizeof(TextureData));
if (!textureData) return NULL;
@ -57,7 +57,7 @@ TextureData* lovrTextureDataFromFile(void* data, int size) {
int* h = &textureData->height;
int* c = &textureData->channels;
stbi_set_flip_vertically_on_load(0);
void* image = stbi_load_from_memory(data, size, w, h, c, 4);
void* image = stbi_load_from_memory(blob->data, blob->size, w, h, c, 4);
if (image) {
textureData->data = image;
@ -65,6 +65,7 @@ TextureData* lovrTextureDataFromFile(void* data, int size) {
return textureData;
}
error("Could not load texture data from %s", blob->name);
free(textureData);
return NULL;
}

View File

@ -1,3 +1,4 @@
#include "filesystem/blob.h"
#include <stdint.h>
#pragma once
@ -19,6 +20,6 @@ typedef struct {
TextureData* lovrTextureDataGetBlank(int width, int height, uint8_t value, TextureFormat format);
TextureData* lovrTextureDataGetEmpty(int width, int height, TextureFormat format);
TextureData* lovrTextureDataFromFile(void* data, int size);
TextureData* lovrTextureDataFromBlob(Blob* blob);
void lovrTextureDataResize(TextureData* textureData, int width, int height, uint8_t value);
void lovrTextureDataDestroy(TextureData* textureData);

View File

@ -1,5 +1,7 @@
#include "lovr.h"
#include "api/lovr.h"
#include "data/boot.lua.h"
#include "data/logo.png.h"
#include "glfw.h"
#include "util.h"
#include <stdlib.h>
@ -63,6 +65,8 @@ void lovrInit(lua_State* L, int argc, char** argv) {
lua_setfield(L, -2, "getOS");
lua_pushcfunction(L, lovrGetVersion);
lua_setfield(L, -2, "getVersion");
lua_pushlstring(L, (const char*) logo_png, logo_png_len);
lua_setfield(L, -2, "_logo");
lua_setglobal(L, "lovr");
// Preload modules
@ -74,133 +78,7 @@ void lovrInit(lua_State* L, int argc, char** argv) {
luax_preloadmodule(L, "lovr.math", l_lovrMathInit);
luax_preloadmodule(L, "lovr.timer", l_lovrTimerInit);
// Bootstrap
char buffer[8192];
snprintf(buffer, sizeof(buffer), "%s",
"-- boot.lua\n"
"local conf = { "
" modules = { "
" audio = true, "
" event = true, "
" graphics = true, "
" headset = true, "
" math = true, "
" timer = true "
" }, "
" headset = { "
" mirror = true "
" } "
"} "
"lovr.filesystem = require('lovr.filesystem') "
"local success, err = pcall(require, 'conf') "
"if lovr.conf then "
" success, err = pcall(lovr.conf, conf) "
"end "
"local modules = { 'audio', 'event', 'graphics', 'headset', 'math', 'timer' } "
"for _, module in ipairs(modules) do "
" if conf.modules[module] then "
" lovr[module] = require('lovr.' .. module) "
" end "
"end "
"lovr.filesystem.setIdentity(conf.identity or 'default') "
"if lovr.headset then lovr.headset.setMirrored(conf.headset and conf.headset.mirror) end "
"lovr.handlers = setmetatable({ "
" quit = function() end, "
" focus = function(f) "
" if lovr.focus then lovr.focus(f) end "
" end, "
" controlleradded = function(c) "
" if lovr.controlleradded then lovr.controlleradded(c) end "
" end, "
" controllerremoved = function(c) "
" if lovr.controllerremoved then lovr.controllerremoved(c) end "
" end, "
" controllerpressed = function(c, b) "
" if lovr.controllerpressed then lovr.controllerpressed(c, b) end "
" end, "
" controllerreleased = function(c, b) "
" if lovr.controllerreleased then lovr.controllerreleased(c, b) end "
" end "
"}, { "
" __index = function(self, event) "
" error('Unknown event: ' .. tostring(event)) "
" end "
"}) "
"function lovr.run() "
" if lovr.load then lovr.load() end "
" while true do "
" lovr.event.pump() "
" for name, a, b, c, d in lovr.event.poll() do "
" if name == 'quit' and (not lovr.quit or not lovr.quit()) then "
" return a "
" end "
" lovr.handlers[name](a, b, c, d) "
" end "
" local dt = lovr.timer.step() "
" if lovr.audio then "
" lovr.audio.update() "
" if lovr.headset and lovr.headset.isPresent() then "
" lovr.audio.setOrientation(lovr.headset.getOrientation()) "
" lovr.audio.setPosition(lovr.headset.getPosition()) "
" lovr.audio.setVelocity(lovr.headset.getVelocity()) "
" end "
" end "
" if lovr.update then lovr.update(dt) end "
" lovr.graphics.clear() "
" lovr.graphics.origin() "
" if lovr.draw then "
" if lovr.headset and lovr.headset.isPresent() then "
" lovr.headset.renderTo(lovr.draw) "
" else "
" lovr.draw() "
" end "
" end "
" lovr.graphics.present() "
" lovr.timer.sleep(.001) "
" end "
"end "
"function lovr.errhand(message) "
" message = 'Error:\\n' .. message:gsub('\\n[^\\n]+$', ''):gsub('\\t', ''):gsub('stack traceback', '\\nStack') "
" print(message) "
" lovr.graphics.reset() "
" lovr.graphics.setBackgroundColor(27, 25, 35) "
" lovr.graphics.setColor(220, 220, 220) "
" local font = lovr.graphics.getFont() "
" local pixelDensity = font:getPixelDensity() "
" local width = font:getWidth(message, .55 * pixelDensity) "
" local function render() "
" lovr.graphics.origin() "
" lovr.graphics.print(message, -width / 2, 0, -20, 1, 0, 0, 0, 0, .55 * pixelDensity, 'left') "
" end "
" while true do "
" lovr.event.pump() "
" for name in lovr.event.poll() do "
" if name == 'quit' then return end "
" end "
" lovr.graphics.clear() "
" if lovr.headset and lovr.headset.isPresent() then "
" lovr.headset.renderTo(render) "
" else "
" render() "
" end "
" lovr.graphics.present() "
" lovr.timer.sleep((lovr.headset and lovr.headset.isPresent()) and .001 or .1) "
" end "
"end "
"if lovr.filesystem.isFile('main.lua') then "
" require('main') "
"end"
);
if (luaL_dostring(L, buffer)) {
if (luaL_loadbuffer(L, (const char*) boot_lua, boot_lua_len, "boot.lua") || lua_pcall(L, 0, 0, 0)) {
const char* message = luaL_checkstring(L, 1);
error("Unable to bootstrap LOVR: %s", message);
}