Move boot.lua to src/modules/love/ with raw string literal format.

Split it up into 3 files to keep under VS2013's raw string literal character limit.
Now boot.lua doesn't need a regeneration step when it's modified.
This commit is contained in:
Alex Szpakowski
2021-10-19 21:22:26 -03:00
parent 0f4adbab0d
commit e27a71f798
7 changed files with 919 additions and 2411 deletions
@@ -1267,7 +1267,6 @@
217DFBD41D9F6D490055D849 /* url.lua.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = url.lua.h; sourceTree = "<group>"; };
217DFBD51D9F6D490055D849 /* usocket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = usocket.c; sourceTree = "<group>"; };
217DFBD61D9F6D490055D849 /* usocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usocket.h; sourceTree = "<group>"; };
503971A86B7167A91B670FBA /* boot.lua.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = boot.lua.h; sourceTree = "<group>"; };
FA08F5AE16C7525600F007B5 /* liblove-macosx.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "liblove-macosx.plist"; path = "macosx/liblove-macosx.plist"; sourceTree = "<group>"; };
FA0A3A5D23366CE9001C269E /* floattypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = floattypes.h; sourceTree = "<group>"; };
FA0A3A5E23366CE9001C269E /* floattypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = floattypes.cpp; sourceTree = "<group>"; };
@@ -1777,6 +1776,8 @@
FA1E887D1DF363CD00E808AA /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
FA1E88811DF363DB00E808AA /* Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Filter.cpp; sourceTree = "<group>"; };
FA1E88821DF363DB00E808AA /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
FA1E95B4271F932B0044CF08 /* arg.lua */ = {isa = PBXFileReference; lastKnownFileType = text; path = arg.lua; sourceTree = "<group>"; };
FA1E95B5271F932B0044CF08 /* callbacks.lua */ = {isa = PBXFileReference; lastKnownFileType = text; path = callbacks.lua; sourceTree = "<group>"; };
FA24348021D401CB00B8918A /* pch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pch.cpp; sourceTree = "<group>"; };
FA24348121D401CB00B8918A /* attribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = attribute.h; sourceTree = "<group>"; };
FA24348221D401CB00B8918A /* attribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = attribute.cpp; sourceTree = "<group>"; };
@@ -2101,8 +2102,6 @@
isa = PBXGroup;
children = (
FA577A8C16C71D3600860150 /* auto.lua */,
FA577A8D16C71D3600860150 /* boot.lua */,
503971A86B7167A91B670FBA /* boot.lua.h */,
FA283EDC1B27CFAA00C70067 /* nogame.lua */,
FA283EDD1B27CFAA00C70067 /* nogame.lua.h */,
);
@@ -2964,6 +2963,9 @@
FA0B7BFD1A95902C000E1D17 /* love */ = {
isa = PBXGroup;
children = (
FA1E95B4271F932B0044CF08 /* arg.lua */,
FA577A8D16C71D3600860150 /* boot.lua */,
FA1E95B5271F932B0044CF08 /* callbacks.lua */,
FA0B7BFE1A95902C000E1D17 /* love.cpp */,
FA0B7BFF1A95902C000E1D17 /* love.h */,
);
+186
View File
@@ -0,0 +1,186 @@
R"luastring"--(
-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string.
-- There is a matching delimiter at the bottom of the file.
--[[
Copyright (c) 2006-2021 LOVE Development Team
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
--]]
local love = require("love")
-- Used for setup:
love.path = {}
love.arg = {}
-- Replace any \ with /.
function love.path.normalslashes(p)
return p:gsub("\\", "/")
end
-- Makes sure there is a slash at the end
-- of a path.
function love.path.endslash(p)
if p:sub(-1) ~= "/" then
return p .. "/"
else
return p
end
end
-- Checks whether a path is absolute or not.
function love.path.abs(p)
local tmp = love.path.normalslashes(p)
-- Path is absolute if it starts with a "/".
if tmp:find("/") == 1 then
return true
end
-- Path is absolute if it starts with a
-- letter followed by a colon.
if tmp:find("%a:") == 1 then
return true
end
-- Relative.
return false
end
-- Converts any path into a full path.
function love.path.getFull(p)
if love.path.abs(p) then
return love.path.normalslashes(p)
end
local cwd = love.filesystem.getWorkingDirectory()
cwd = love.path.normalslashes(cwd)
cwd = love.path.endslash(cwd)
-- Construct a full path.
local full = cwd .. love.path.normalslashes(p)
-- Remove trailing /., if applicable
return full:match("(.-)/%.$") or full
end
-- Returns the leaf of a full path.
function love.path.leaf(p)
p = love.path.normalslashes(p)
local a = 1
local last = p
while a do
a = p:find("/", a+1)
if a then
last = p:sub(a+1)
end
end
return last
end
-- Finds the key in the table with the lowest integral index. The lowest
-- will typically the executable, for instance "lua5.1.exe".
function love.arg.getLow(a)
local m = math.huge
for k,v in pairs(a) do
if k < m then
m = k
end
end
return a[m], m
end
love.arg.options = {
console = { a = 0 },
fused = {a = 0 },
game = { a = 1 }
}
love.arg.optionIndices = {}
function love.arg.parseOption(m, i)
m.set = true
if m.a > 0 then
m.arg = {}
for j=i,i+m.a-1 do
love.arg.optionIndices[j] = true
table.insert(m.arg, arg[j])
end
end
return m.a
end
function love.arg.parseOptions()
local game
local argc = #arg
local i = 1
while i <= argc do
-- Look for options.
local m = arg[i]:match("^%-%-(.*)")
if m and m ~= "" and love.arg.options[m] and not love.arg.options[m].set then
love.arg.optionIndices[i] = true
i = i + love.arg.parseOption(love.arg.options[m], i+1)
elseif m == "" then -- handle '--' as an option
love.arg.optionIndices[i] = true
if not game then -- handle '--' followed by game name
game = i + 1
end
break
elseif not game then
game = i
end
i = i + 1
end
if not love.arg.options.game.set then
love.arg.parseOption(love.arg.options.game, game or 0)
end
end
-- Returns the arguments that are passed to your game via love.load()
-- arguments that were parsed as options are skipped.
function love.arg.parseGameArguments(a)
local out = {}
local _, lowindex = love.arg.getLow(a)
local o = lowindex
for i=lowindex, #a do
if not love.arg.optionIndices[i] then
out[o] = a[i]
o = o + 1
end
end
return out
end
-- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
--)luastring"--"
+379
View File
@@ -0,0 +1,379 @@
R"luastring"--(
-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string.
-- There is a matching delimiter at the bottom of the file.
--[[
Copyright (c) 2006-2021 LOVE Development Team
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
--]]
-- Make sure love exists.
local love = require("love")
-- Essential code boot/init.
require("love.arg")
require("love.callbacks")
local function uridecode(s)
return s:gsub("%%%x%x", function(str)
return string.char(tonumber(str:sub(2), 16))
end)
end
local no_game_code = false
local invalid_game_path = nil
-- This can't be overridden.
function love.boot()
-- This is absolutely needed.
require("love.filesystem")
local arg0 = love.arg.getLow(arg)
love.filesystem.init(arg0)
local exepath = love.filesystem.getExecutablePath()
if #exepath == 0 then
-- This shouldn't happen, but just in case we'll fall back to arg0.
exepath = arg0
end
no_game_code = false
invalid_game_path = nil
-- Is this one of those fancy "fused" games?
local can_has_game = pcall(love.filesystem.setSource, exepath)
-- It's a fused game, don't parse --game argument
if can_has_game then
love.arg.options.game.set = true
end
-- Parse options now that we know which options we're looking for.
love.arg.parseOptions()
local o = love.arg.options
local is_fused_game = can_has_game or love.arg.options.fused.set
love.filesystem.setFused(is_fused_game)
love.setDeprecationOutput(not love.filesystem.isFused())
local identity = ""
if not can_has_game and o.game.set and o.game.arg[1] then
local nouri = o.game.arg[1]
if nouri:sub(1, 7) == "file://" then
nouri = uridecode(nouri:sub(8))
end
local full_source = love.path.getFull(nouri)
can_has_game = pcall(love.filesystem.setSource, full_source)
if not can_has_game then
invalid_game_path = full_source
end
-- Use the name of the source .love as the identity for now.
identity = love.path.leaf(full_source)
else
-- Use the name of the exe as the identity for now.
identity = love.path.leaf(exepath)
end
-- Try to use the archive containing main.lua as the identity name. It
-- might not be available, in which case the fallbacks above are used.
local realdir = love.filesystem.getRealDirectory("main.lua")
if realdir then
identity = love.path.leaf(realdir)
end
identity = identity:gsub("^([%.]+)", "") -- strip leading "."'s
identity = identity:gsub("%.([^%.]+)$", "") -- strip extension
identity = identity:gsub("%.", "_") -- replace remaining "."'s with "_"
identity = #identity > 0 and identity or "lovegame"
-- When conf.lua is initially loaded, the main source should be checked
-- before the save directory (the identity should be appended.)
pcall(love.filesystem.setIdentity, identity, true)
if can_has_game and not (love.filesystem.getInfo("main.lua") or love.filesystem.getInfo("conf.lua")) then
no_game_code = true
end
if not can_has_game then
local nogame = require("love.nogame")
nogame()
end
end
function love.init()
-- Create default configuration settings.
-- NOTE: Adding a new module to the modules list
-- will NOT make it load, see below.
local c = {
title = "Untitled",
version = love._version,
window = {
width = 800,
height = 600,
x = nil,
y = nil,
minwidth = 1,
minheight = 1,
fullscreen = false,
fullscreentype = "desktop",
display = 1,
vsync = 1,
msaa = 0,
borderless = false,
resizable = false,
centered = true,
highdpi = false,
usedpiscale = true,
},
modules = {
data = true,
event = true,
keyboard = true,
mouse = true,
timer = true,
joystick = true,
touch = true,
image = true,
graphics = true,
audio = true,
math = true,
physics = true,
sound = true,
system = true,
font = true,
thread = true,
window = true,
video = true,
},
audio = {
mixwithsystem = true, -- Only relevant for Android / iOS.
mic = false, -- Only relevant for Android.
},
console = false, -- Only relevant for windows.
identity = false,
appendidentity = false,
externalstorage = false, -- Only relevant for Android.
accelerometerjoystick = true, -- Only relevant for Android / iOS.
gammacorrect = false,
}
-- Console hack, part 1.
local openedconsole = false
if love.arg.options.console.set and love._openConsole then
love._openConsole()
openedconsole = true
end
-- If config file exists, load it and allow it to update config table.
local confok, conferr
if (not love.conf) and love.filesystem and love.filesystem.getInfo("conf.lua") then
confok, conferr = pcall(require, "conf")
end
-- Yes, conf.lua might not exist, but there are other ways of making
-- love.conf appear, so we should check for it anyway.
if love.conf then
confok, conferr = pcall(love.conf, c)
-- If love.conf errors, we'll trigger the error after loading modules so
-- the error message can be displayed in the window.
end
-- Console hack, part 2.
if c.console and love._openConsole and not openedconsole then
love._openConsole()
end
-- Hack for disabling accelerometer-as-joystick on Android / iOS.
if love._setAccelerometerAsJoystick then
love._setAccelerometerAsJoystick(c.accelerometerjoystick)
end
if love._setGammaCorrect then
love._setGammaCorrect(c.gammacorrect)
end
if love._setAudioMixWithSystem then
if c.audio and c.audio.mixwithsystem ~= nil then
love._setAudioMixWithSystem(c.audio.mixwithsystem)
end
end
if love._requestRecordingPermission then
love._requestRecordingPermission(c.audio and c.audio.mic)
end
-- Gets desired modules.
for k,v in ipairs{
"data",
"thread",
"timer",
"event",
"keyboard",
"joystick",
"mouse",
"touch",
"sound",
"system",
"audio",
"image",
"video",
"font",
"window",
"graphics",
"math",
"physics",
} do
if c.modules[v] then
require("love." .. v)
end
end
if love.event then
love.createhandlers()
end
-- Check the version
c.version = tostring(c.version)
if not love.isVersionCompatible(c.version) then
local major, minor, revision = c.version:match("^(%d+)%.(%d+)%.(%d+)$")
if (not major or not minor or not revision) or (major ~= love._version_major and minor ~= love._version_minor) then
local msg = ("This game indicates it was made for version '%s' of LOVE.\n"..
"It may not be compatible with the running version (%s)."):format(c.version, love._version)
print(msg)
if love.window then
love.window.showMessageBox("Compatibility Warning", msg, "warning")
end
end
end
if not confok and conferr then
error(conferr)
end
-- Setup window here.
if c.window and c.modules.window then
love.window.setTitle(c.window.title or c.title)
assert(love.window.setMode(c.window.width, c.window.height,
{
fullscreen = c.window.fullscreen,
fullscreentype = c.window.fullscreentype,
vsync = c.window.vsync,
msaa = c.window.msaa,
stencil = c.window.stencil,
depth = c.window.depth,
resizable = c.window.resizable,
minwidth = c.window.minwidth,
minheight = c.window.minheight,
borderless = c.window.borderless,
centered = c.window.centered,
display = c.window.display,
highdpi = c.window.highdpi,
usedpiscale = c.window.usedpiscale,
x = c.window.x,
y = c.window.y,
}), "Could not set window mode")
if c.window.icon then
assert(love.image, "If an icon is set in love.conf, love.image must be loaded!")
love.window.setIcon(love.image.newImageData(c.window.icon))
end
end
-- Our first timestep, because window creation can take some time
if love.timer then
love.timer.step()
end
if love.filesystem then
love.filesystem._setAndroidSaveExternal(c.externalstorage)
love.filesystem.setIdentity(c.identity or love.filesystem.getIdentity(), c.appendidentity)
if love.filesystem.getInfo("main.lua") then
require("main")
end
end
if no_game_code then
error("No code to run\nYour game might be packaged incorrectly.\nMake sure main.lua is at the top level of the zip.")
elseif invalid_game_path then
error("Cannot load game at path '" .. invalid_game_path .. "'.\nMake sure a folder exists at the specified path.")
end
end
local print, debug, tostring = print, debug, tostring
local function error_printer(msg, layer)
print((debug.traceback("Error: " .. tostring(msg), 1+(layer or 1)):gsub("\n[^\n]+$", "")))
end
-----------------------------------------------------------
-- The root of all calls.
-----------------------------------------------------------
return function()
local func
local inerror = false
local function deferErrhand(...)
local errhand = love.errorhandler or love.errhand
local handler = (not inerror and errhand) or error_printer
inerror = true
func = handler(...)
end
local function earlyinit()
-- If love.boot fails, return 1 and finish immediately
local result = xpcall(love.boot, error_printer)
if not result then return 1 end
-- If love.init or love.run fails, don't return a value,
-- as we want the error handler to take over
result = xpcall(love.init, deferErrhand)
if not result then return end
-- NOTE: We can't assign to func directly, as we'd
-- overwrite the result of deferErrhand with nil on error
local main
result, main = xpcall(love.run, deferErrhand)
if result then
func = main
end
end
func = earlyinit
while func do
local _, retval = xpcall(func, deferErrhand)
if retval then return retval end
coroutine.yield()
end
return 1
end
-- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
--)luastring"--"
+316
View File
@@ -0,0 +1,316 @@
R"luastring"--(
-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string.
-- There is a matching delimiter at the bottom of the file.
--[[
Copyright (c) 2006-2021 LOVE Development Team
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
--]]
local love = require("love")
function love.createhandlers()
-- Standard callback handlers.
love.handlers = setmetatable({
keypressed = function (b,s,r)
if love.keypressed then return love.keypressed(b,s,r) end
end,
keyreleased = function (b,s)
if love.keyreleased then return love.keyreleased(b,s) end
end,
textinput = function (t)
if love.textinput then return love.textinput(t) end
end,
textedited = function (t,s,l)
if love.textedited then return love.textedited(t,s,l) end
end,
mousemoved = function (x,y,dx,dy,t)
if love.mousemoved then return love.mousemoved(x,y,dx,dy,t) end
end,
mousepressed = function (x,y,b,t,c)
if love.mousepressed then return love.mousepressed(x,y,b,t,c) end
end,
mousereleased = function (x,y,b,t,c)
if love.mousereleased then return love.mousereleased(x,y,b,t,c) end
end,
wheelmoved = function (x,y)
if love.wheelmoved then return love.wheelmoved(x,y) end
end,
touchpressed = function (id,x,y,dx,dy,p)
if love.touchpressed then return love.touchpressed(id,x,y,dx,dy,p) end
end,
touchreleased = function (id,x,y,dx,dy,p)
if love.touchreleased then return love.touchreleased(id,x,y,dx,dy,p) end
end,
touchmoved = function (id,x,y,dx,dy,p)
if love.touchmoved then return love.touchmoved(id,x,y,dx,dy,p) end
end,
joystickpressed = function (j,b)
if love.joystickpressed then return love.joystickpressed(j,b) end
end,
joystickreleased = function (j,b)
if love.joystickreleased then return love.joystickreleased(j,b) end
end,
joystickaxis = function (j,a,v)
if love.joystickaxis then return love.joystickaxis(j,a,v) end
end,
joystickhat = function (j,h,v)
if love.joystickhat then return love.joystickhat(j,h,v) end
end,
gamepadpressed = function (j,b)
if love.gamepadpressed then return love.gamepadpressed(j,b) end
end,
gamepadreleased = function (j,b)
if love.gamepadreleased then return love.gamepadreleased(j,b) end
end,
gamepadaxis = function (j,a,v)
if love.gamepadaxis then return love.gamepadaxis(j,a,v) end
end,
joystickadded = function (j)
if love.joystickadded then return love.joystickadded(j) end
end,
joystickremoved = function (j)
if love.joystickremoved then return love.joystickremoved(j) end
end,
focus = function (f)
if love.focus then return love.focus(f) end
end,
mousefocus = function (f)
if love.mousefocus then return love.mousefocus(f) end
end,
visible = function (v)
if love.visible then return love.visible(v) end
end,
quit = function ()
return
end,
threaderror = function (t, err)
if love.threaderror then return love.threaderror(t, err) end
end,
resize = function (w, h)
if love.resize then return love.resize(w, h) end
end,
filedropped = function (f)
if love.filedropped then return love.filedropped(f) end
end,
directorydropped = function (dir)
if love.directorydropped then return love.directorydropped(dir) end
end,
lowmemory = function ()
if love.lowmemory then love.lowmemory() end
collectgarbage()
collectgarbage()
end,
displayrotated = function (display, orient)
if love.displayrotated then return love.displayrotated(display, orient) end
end,
}, {
__index = function(self, name)
error("Unknown event: " .. name)
end,
})
end
-----------------------------------------------------------
-- Default callbacks.
-----------------------------------------------------------
function love.run()
if love.load then love.load(love.arg.parseGameArguments(arg), arg) end
-- We don't want the first frame's dt to include time taken by love.load.
if love.timer then love.timer.step() end
local dt = 0
-- Main loop time.
return function()
-- Process events.
if love.event then
love.event.pump()
for name, a,b,c,d,e,f in love.event.poll() do
if name == "quit" then
if not love.quit or not love.quit() then
return a or 0
end
end
love.handlers[name](a,b,c,d,e,f)
end
end
-- Update dt, as we'll be passing it to update
if love.timer then dt = love.timer.step() end
-- Call update and draw
if love.update then love.update(dt) end -- will pass 0 if love.timer is disabled
if love.graphics and love.graphics.isActive() then
love.graphics.origin()
love.graphics.clear(love.graphics.getBackgroundColor())
if love.draw then love.draw() end
love.graphics.present()
end
if love.timer then love.timer.sleep(0.001) end
end
end
local debug, print, tostring, error = debug, print, tostring, error
function love.threaderror(t, err)
error("Thread error ("..tostring(t)..")\n\n"..err, 0)
end
local utf8 = require("utf8")
local function error_printer(msg, layer)
print((debug.traceback("Error: " .. tostring(msg), 1+(layer or 1)):gsub("\n[^\n]+$", "")))
end
function love.errhand(msg)
msg = tostring(msg)
error_printer(msg, 2)
if not love.window or not love.graphics or not love.event then
return
end
if not love.graphics.isCreated() or not love.window.isOpen() then
local success, status = pcall(love.window.setMode, 800, 600)
if not success or not status then
return
end
end
-- Reset state.
if love.mouse then
love.mouse.setVisible(true)
love.mouse.setGrabbed(false)
love.mouse.setRelativeMode(false)
if love.mouse.isCursorSupported() then
love.mouse.setCursor()
end
end
if love.joystick then
-- Stop all joystick vibrations.
for i,v in ipairs(love.joystick.getJoysticks()) do
v:setVibration()
end
end
if love.audio then love.audio.stop() end
love.graphics.reset()
local font = love.graphics.setNewFont(14)
love.graphics.setColor(1, 1, 1)
local trace = debug.traceback()
love.graphics.origin()
local sanitizedmsg = {}
for char in msg:gmatch(utf8.charpattern) do
table.insert(sanitizedmsg, char)
end
sanitizedmsg = table.concat(sanitizedmsg)
local err = {}
table.insert(err, "Error\n")
table.insert(err, sanitizedmsg)
if #sanitizedmsg ~= #msg then
table.insert(err, "Invalid UTF-8 string in error message.")
end
table.insert(err, "\n")
for l in trace:gmatch("(.-)\n") do
if not l:match("boot.lua") then
l = l:gsub("stack traceback:", "Traceback\n")
table.insert(err, l)
end
end
local p = table.concat(err, "\n")
p = p:gsub("\t", "")
p = p:gsub("%[string \"(.-)\"%]", "%1")
local function draw()
local pos = 70
love.graphics.clear(89/255, 157/255, 220/255)
love.graphics.printf(p, pos, pos, love.graphics.getWidth() - pos)
love.graphics.present()
end
local fullErrorText = p
local function copyToClipboard()
if not love.system then return end
love.system.setClipboardText(fullErrorText)
p = p .. "\nCopied to clipboard!"
draw()
end
if love.system then
p = p .. "\n\nPress Ctrl+C or tap to copy this error"
end
return function()
love.event.pump()
for e, a, b, c in love.event.poll() do
if e == "quit" then
return 1
elseif e == "keypressed" and a == "escape" then
return 1
elseif e == "keypressed" and a == "c" and love.keyboard.isDown("lctrl", "rctrl") then
copyToClipboard()
elseif e == "touchpressed" then
local name = love.window.getTitle()
if #name == 0 or name == "Untitled" then name = "Game" end
local buttons = {"OK", "Cancel"}
if love.system then
buttons[3] = "Copy to clipboard"
end
local pressed = love.window.showMessageBox("Quit "..name.."?", "", buttons)
if pressed == 1 then
return 1
elseif pressed == 3 then
copyToClipboard()
end
end
end
draw()
if love.timer then
love.timer.sleep(0.1)
end
end
end
-- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
--)luastring"--"
+33 -4
View File
@@ -81,9 +81,21 @@ extern "C"
# include "audio/Audio.h"
#endif
// Scripts
// Scripts.
#include "scripts/nogame.lua.h"
#include "scripts/boot.lua.h"
// Put the Lua code directly into a raw string literal.
static const char arg_lua[] =
#include "arg.lua"
;
static const char callbacks_lua[] =
#include "callbacks.lua"
;
static const char boot_lua[] =
#include "boot.lua"
;
// All modules define a c-accessible luaopen
// so let's make use of those, instead
@@ -148,6 +160,8 @@ extern "C"
extern int luaopen_love_window(lua_State*);
#endif
extern int luaopen_love_nogame(lua_State*);
extern int luaopen_love_arg(lua_State*);
extern int luaopen_love_callbacks(lua_State*);
extern int luaopen_love_boot(lua_State*);
}
@@ -210,6 +224,8 @@ static const luaL_Reg modules[] = {
{ "love.window", luaopen_love_window },
#endif
{ "love.nogame", luaopen_love_nogame },
{ "love.arg", luaopen_love_arg },
{ "love.callbacks", luaopen_love_callbacks },
{ "love.boot", luaopen_love_boot },
{ 0, 0 }
};
@@ -641,13 +657,26 @@ int luaopen_love_nogame(lua_State *L)
return 1;
}
int luaopen_love_boot(lua_State *L)
int luaopen_love_arg(lua_State *L)
{
if (luaL_loadbuffer(L, (const char *)love::boot_lua, sizeof(love::boot_lua), "boot.lua") == 0)
if (luaL_loadbuffer(L, arg_lua, sizeof(arg_lua), "arg.lua") == 0)
lua_call(L, 0, 1);
return 1;
}
int luaopen_love_callbacks(lua_State *L)
{
if (luaL_loadbuffer(L, callbacks_lua, sizeof(callbacks_lua), "callbacks.lua") == 0)
lua_call(L, 0, 1);
return 1;
}
int luaopen_love_boot(lua_State *L)
{
if (luaL_loadbuffer(L, boot_lua, sizeof(boot_lua), "boot.lua") == 0)
lua_call(L, 0, 1);
return 1;
}
-808
View File
@@ -1,808 +0,0 @@
--[[
Copyright (c) 2006-2021 LOVE Development Team
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
--]]
-- Make sure love exists.
local love = require("love")
-- Used for setup:
love.path = {}
love.arg = {}
-- Replace any \ with /.
function love.path.normalslashes(p)
return p:gsub("\\", "/")
end
-- Makes sure there is a slash at the end
-- of a path.
function love.path.endslash(p)
if p:sub(-1) ~= "/" then
return p .. "/"
else
return p
end
end
-- Checks whether a path is absolute or not.
function love.path.abs(p)
local tmp = love.path.normalslashes(p)
-- Path is absolute if it starts with a "/".
if tmp:find("/") == 1 then
return true
end
-- Path is absolute if it starts with a
-- letter followed by a colon.
if tmp:find("%a:") == 1 then
return true
end
-- Relative.
return false
end
-- Converts any path into a full path.
function love.path.getFull(p)
if love.path.abs(p) then
return love.path.normalslashes(p)
end
local cwd = love.filesystem.getWorkingDirectory()
cwd = love.path.normalslashes(cwd)
cwd = love.path.endslash(cwd)
-- Construct a full path.
local full = cwd .. love.path.normalslashes(p)
-- Remove trailing /., if applicable
return full:match("(.-)/%.$") or full
end
-- Returns the leaf of a full path.
function love.path.leaf(p)
p = love.path.normalslashes(p)
local a = 1
local last = p
while a do
a = p:find("/", a+1)
if a then
last = p:sub(a+1)
end
end
return last
end
-- Finds the key in the table with the lowest integral index. The lowest
-- will typically the executable, for instance "lua5.1.exe".
function love.arg.getLow(a)
local m = math.huge
for k,v in pairs(a) do
if k < m then
m = k
end
end
return a[m], m
end
love.arg.options = {
console = { a = 0 },
fused = {a = 0 },
game = { a = 1 }
}
love.arg.optionIndices = {}
function love.arg.parseOption(m, i)
m.set = true
if m.a > 0 then
m.arg = {}
for j=i,i+m.a-1 do
love.arg.optionIndices[j] = true
table.insert(m.arg, arg[j])
end
end
return m.a
end
function love.arg.parseOptions()
local game
local argc = #arg
local i = 1
while i <= argc do
-- Look for options.
local m = arg[i]:match("^%-%-(.*)")
if m and m ~= "" and love.arg.options[m] and not love.arg.options[m].set then
love.arg.optionIndices[i] = true
i = i + love.arg.parseOption(love.arg.options[m], i+1)
elseif m == "" then -- handle '--' as an option
love.arg.optionIndices[i] = true
if not game then -- handle '--' followed by game name
game = i + 1
end
break
elseif not game then
game = i
end
i = i + 1
end
if not love.arg.options.game.set then
love.arg.parseOption(love.arg.options.game, game or 0)
end
end
-- Returns the arguments that are passed to your game via love.load()
-- arguments that were parsed as options are skipped.
function love.arg.parseGameArguments(a)
local out = {}
local _, lowindex = love.arg.getLow(a)
local o = lowindex
for i=lowindex, #a do
if not love.arg.optionIndices[i] then
out[o] = a[i]
o = o + 1
end
end
return out
end
function love.createhandlers()
-- Standard callback handlers.
love.handlers = setmetatable({
keypressed = function (b,s,r)
if love.keypressed then return love.keypressed(b,s,r) end
end,
keyreleased = function (b,s)
if love.keyreleased then return love.keyreleased(b,s) end
end,
textinput = function (t)
if love.textinput then return love.textinput(t) end
end,
textedited = function (t,s,l)
if love.textedited then return love.textedited(t,s,l) end
end,
mousemoved = function (x,y,dx,dy,t)
if love.mousemoved then return love.mousemoved(x,y,dx,dy,t) end
end,
mousepressed = function (x,y,b,t,c)
if love.mousepressed then return love.mousepressed(x,y,b,t,c) end
end,
mousereleased = function (x,y,b,t,c)
if love.mousereleased then return love.mousereleased(x,y,b,t,c) end
end,
wheelmoved = function (x,y)
if love.wheelmoved then return love.wheelmoved(x,y) end
end,
touchpressed = function (id,x,y,dx,dy,p)
if love.touchpressed then return love.touchpressed(id,x,y,dx,dy,p) end
end,
touchreleased = function (id,x,y,dx,dy,p)
if love.touchreleased then return love.touchreleased(id,x,y,dx,dy,p) end
end,
touchmoved = function (id,x,y,dx,dy,p)
if love.touchmoved then return love.touchmoved(id,x,y,dx,dy,p) end
end,
joystickpressed = function (j,b)
if love.joystickpressed then return love.joystickpressed(j,b) end
end,
joystickreleased = function (j,b)
if love.joystickreleased then return love.joystickreleased(j,b) end
end,
joystickaxis = function (j,a,v)
if love.joystickaxis then return love.joystickaxis(j,a,v) end
end,
joystickhat = function (j,h,v)
if love.joystickhat then return love.joystickhat(j,h,v) end
end,
gamepadpressed = function (j,b)
if love.gamepadpressed then return love.gamepadpressed(j,b) end
end,
gamepadreleased = function (j,b)
if love.gamepadreleased then return love.gamepadreleased(j,b) end
end,
gamepadaxis = function (j,a,v)
if love.gamepadaxis then return love.gamepadaxis(j,a,v) end
end,
joystickadded = function (j)
if love.joystickadded then return love.joystickadded(j) end
end,
joystickremoved = function (j)
if love.joystickremoved then return love.joystickremoved(j) end
end,
focus = function (f)
if love.focus then return love.focus(f) end
end,
mousefocus = function (f)
if love.mousefocus then return love.mousefocus(f) end
end,
visible = function (v)
if love.visible then return love.visible(v) end
end,
quit = function ()
return
end,
threaderror = function (t, err)
if love.threaderror then return love.threaderror(t, err) end
end,
resize = function (w, h)
if love.resize then return love.resize(w, h) end
end,
filedropped = function (f)
if love.filedropped then return love.filedropped(f) end
end,
directorydropped = function (dir)
if love.directorydropped then return love.directorydropped(dir) end
end,
lowmemory = function ()
if love.lowmemory then love.lowmemory() end
collectgarbage()
collectgarbage()
end,
displayrotated = function (display, orient)
if love.displayrotated then return love.displayrotated(display, orient) end
end,
}, {
__index = function(self, name)
error("Unknown event: " .. name)
end,
})
end
local function uridecode(s)
return s:gsub("%%%x%x", function(str)
return string.char(tonumber(str:sub(2), 16))
end)
end
local no_game_code = false
local invalid_game_path = nil
-- This can't be overridden.
function love.boot()
-- This is absolutely needed.
require("love.filesystem")
local arg0 = love.arg.getLow(arg)
love.filesystem.init(arg0)
local exepath = love.filesystem.getExecutablePath()
if #exepath == 0 then
-- This shouldn't happen, but just in case we'll fall back to arg0.
exepath = arg0
end
no_game_code = false
invalid_game_path = nil
-- Is this one of those fancy "fused" games?
local can_has_game = pcall(love.filesystem.setSource, exepath)
-- It's a fused game, don't parse --game argument
if can_has_game then
love.arg.options.game.set = true
end
-- Parse options now that we know which options we're looking for.
love.arg.parseOptions()
local o = love.arg.options
local is_fused_game = can_has_game or love.arg.options.fused.set
love.filesystem.setFused(is_fused_game)
love.setDeprecationOutput(not love.filesystem.isFused())
local identity = ""
if not can_has_game and o.game.set and o.game.arg[1] then
local nouri = o.game.arg[1]
if nouri:sub(1, 7) == "file://" then
nouri = uridecode(nouri:sub(8))
end
local full_source = love.path.getFull(nouri)
can_has_game = pcall(love.filesystem.setSource, full_source)
if not can_has_game then
invalid_game_path = full_source
end
-- Use the name of the source .love as the identity for now.
identity = love.path.leaf(full_source)
else
-- Use the name of the exe as the identity for now.
identity = love.path.leaf(exepath)
end
-- Try to use the archive containing main.lua as the identity name. It
-- might not be available, in which case the fallbacks above are used.
local realdir = love.filesystem.getRealDirectory("main.lua")
if realdir then
identity = love.path.leaf(realdir)
end
identity = identity:gsub("^([%.]+)", "") -- strip leading "."'s
identity = identity:gsub("%.([^%.]+)$", "") -- strip extension
identity = identity:gsub("%.", "_") -- replace remaining "."'s with "_"
identity = #identity > 0 and identity or "lovegame"
-- When conf.lua is initially loaded, the main source should be checked
-- before the save directory (the identity should be appended.)
pcall(love.filesystem.setIdentity, identity, true)
if can_has_game and not (love.filesystem.getInfo("main.lua") or love.filesystem.getInfo("conf.lua")) then
no_game_code = true
end
if not can_has_game then
local nogame = require("love.nogame")
nogame()
end
end
function love.init()
-- Create default configuration settings.
-- NOTE: Adding a new module to the modules list
-- will NOT make it load, see below.
local c = {
title = "Untitled",
version = love._version,
window = {
width = 800,
height = 600,
x = nil,
y = nil,
minwidth = 1,
minheight = 1,
fullscreen = false,
fullscreentype = "desktop",
display = 1,
vsync = 1,
msaa = 0,
borderless = false,
resizable = false,
centered = true,
highdpi = false,
usedpiscale = true,
},
modules = {
data = true,
event = true,
keyboard = true,
mouse = true,
timer = true,
joystick = true,
touch = true,
image = true,
graphics = true,
audio = true,
math = true,
physics = true,
sound = true,
system = true,
font = true,
thread = true,
window = true,
video = true,
},
audio = {
mixwithsystem = true, -- Only relevant for Android / iOS.
mic = false, -- Only relevant for Android.
},
console = false, -- Only relevant for windows.
identity = false,
appendidentity = false,
externalstorage = false, -- Only relevant for Android.
accelerometerjoystick = true, -- Only relevant for Android / iOS.
gammacorrect = false,
}
-- Console hack, part 1.
local openedconsole = false
if love.arg.options.console.set and love._openConsole then
love._openConsole()
openedconsole = true
end
-- If config file exists, load it and allow it to update config table.
local confok, conferr
if (not love.conf) and love.filesystem and love.filesystem.getInfo("conf.lua") then
confok, conferr = pcall(require, "conf")
end
-- Yes, conf.lua might not exist, but there are other ways of making
-- love.conf appear, so we should check for it anyway.
if love.conf then
confok, conferr = pcall(love.conf, c)
-- If love.conf errors, we'll trigger the error after loading modules so
-- the error message can be displayed in the window.
end
-- Console hack, part 2.
if c.console and love._openConsole and not openedconsole then
love._openConsole()
end
-- Hack for disabling accelerometer-as-joystick on Android / iOS.
if love._setAccelerometerAsJoystick then
love._setAccelerometerAsJoystick(c.accelerometerjoystick)
end
if love._setGammaCorrect then
love._setGammaCorrect(c.gammacorrect)
end
if love._setAudioMixWithSystem then
if c.audio and c.audio.mixwithsystem ~= nil then
love._setAudioMixWithSystem(c.audio.mixwithsystem)
end
end
if love._requestRecordingPermission then
love._requestRecordingPermission(c.audio and c.audio.mic)
end
-- Gets desired modules.
for k,v in ipairs{
"data",
"thread",
"timer",
"event",
"keyboard",
"joystick",
"mouse",
"touch",
"sound",
"system",
"audio",
"image",
"video",
"font",
"window",
"graphics",
"math",
"physics",
} do
if c.modules[v] then
require("love." .. v)
end
end
if love.event then
love.createhandlers()
end
-- Check the version
c.version = tostring(c.version)
if not love.isVersionCompatible(c.version) then
local major, minor, revision = c.version:match("^(%d+)%.(%d+)%.(%d+)$")
if (not major or not minor or not revision) or (major ~= love._version_major and minor ~= love._version_minor) then
local msg = ("This game indicates it was made for version '%s' of LOVE.\n"..
"It may not be compatible with the running version (%s)."):format(c.version, love._version)
print(msg)
if love.window then
love.window.showMessageBox("Compatibility Warning", msg, "warning")
end
end
end
if not confok and conferr then
error(conferr)
end
-- Setup window here.
if c.window and c.modules.window then
love.window.setTitle(c.window.title or c.title)
assert(love.window.setMode(c.window.width, c.window.height,
{
fullscreen = c.window.fullscreen,
fullscreentype = c.window.fullscreentype,
vsync = c.window.vsync,
msaa = c.window.msaa,
stencil = c.window.stencil,
depth = c.window.depth,
resizable = c.window.resizable,
minwidth = c.window.minwidth,
minheight = c.window.minheight,
borderless = c.window.borderless,
centered = c.window.centered,
display = c.window.display,
highdpi = c.window.highdpi,
usedpiscale = c.window.usedpiscale,
x = c.window.x,
y = c.window.y,
}), "Could not set window mode")
if c.window.icon then
assert(love.image, "If an icon is set in love.conf, love.image must be loaded!")
love.window.setIcon(love.image.newImageData(c.window.icon))
end
end
-- Our first timestep, because window creation can take some time
if love.timer then
love.timer.step()
end
if love.filesystem then
love.filesystem._setAndroidSaveExternal(c.externalstorage)
love.filesystem.setIdentity(c.identity or love.filesystem.getIdentity(), c.appendidentity)
if love.filesystem.getInfo("main.lua") then
require("main")
end
end
if no_game_code then
error("No code to run\nYour game might be packaged incorrectly.\nMake sure main.lua is at the top level of the zip.")
elseif invalid_game_path then
error("Cannot load game at path '" .. invalid_game_path .. "'.\nMake sure a folder exists at the specified path.")
end
end
-----------------------------------------------------------
-- Default callbacks.
-----------------------------------------------------------
function love.run()
if love.load then love.load(love.arg.parseGameArguments(arg), arg) end
-- We don't want the first frame's dt to include time taken by love.load.
if love.timer then love.timer.step() end
local dt = 0
-- Main loop time.
return function()
-- Process events.
if love.event then
love.event.pump()
for name, a,b,c,d,e,f in love.event.poll() do
if name == "quit" then
if not love.quit or not love.quit() then
return a or 0
end
end
love.handlers[name](a,b,c,d,e,f)
end
end
-- Update dt, as we'll be passing it to update
if love.timer then dt = love.timer.step() end
-- Call update and draw
if love.update then love.update(dt) end -- will pass 0 if love.timer is disabled
if love.graphics and love.graphics.isActive() then
love.graphics.origin()
love.graphics.clear(love.graphics.getBackgroundColor())
if love.draw then love.draw() end
love.graphics.present()
end
if love.timer then love.timer.sleep(0.001) end
end
end
local debug, print, error = debug, print, error
function love.threaderror(t, err)
error("Thread error ("..tostring(t)..")\n\n"..err, 0)
end
local utf8 = require("utf8")
local function error_printer(msg, layer)
print((debug.traceback("Error: " .. tostring(msg), 1+(layer or 1)):gsub("\n[^\n]+$", "")))
end
function love.errhand(msg)
msg = tostring(msg)
error_printer(msg, 2)
if not love.window or not love.graphics or not love.event then
return
end
if not love.graphics.isCreated() or not love.window.isOpen() then
local success, status = pcall(love.window.setMode, 800, 600)
if not success or not status then
return
end
end
-- Reset state.
if love.mouse then
love.mouse.setVisible(true)
love.mouse.setGrabbed(false)
love.mouse.setRelativeMode(false)
if love.mouse.isCursorSupported() then
love.mouse.setCursor()
end
end
if love.joystick then
-- Stop all joystick vibrations.
for i,v in ipairs(love.joystick.getJoysticks()) do
v:setVibration()
end
end
if love.audio then love.audio.stop() end
love.graphics.reset()
local font = love.graphics.setNewFont(14)
love.graphics.setColor(1, 1, 1)
local trace = debug.traceback()
love.graphics.origin()
local sanitizedmsg = {}
for char in msg:gmatch(utf8.charpattern) do
table.insert(sanitizedmsg, char)
end
sanitizedmsg = table.concat(sanitizedmsg)
local err = {}
table.insert(err, "Error\n")
table.insert(err, sanitizedmsg)
if #sanitizedmsg ~= #msg then
table.insert(err, "Invalid UTF-8 string in error message.")
end
table.insert(err, "\n")
for l in trace:gmatch("(.-)\n") do
if not l:match("boot.lua") then
l = l:gsub("stack traceback:", "Traceback\n")
table.insert(err, l)
end
end
local p = table.concat(err, "\n")
p = p:gsub("\t", "")
p = p:gsub("%[string \"(.-)\"%]", "%1")
local function draw()
local pos = 70
love.graphics.clear(89/255, 157/255, 220/255)
love.graphics.printf(p, pos, pos, love.graphics.getWidth() - pos)
love.graphics.present()
end
local fullErrorText = p
local function copyToClipboard()
if not love.system then return end
love.system.setClipboardText(fullErrorText)
p = p .. "\nCopied to clipboard!"
draw()
end
if love.system then
p = p .. "\n\nPress Ctrl+C or tap to copy this error"
end
return function()
love.event.pump()
for e, a, b, c in love.event.poll() do
if e == "quit" then
return 1
elseif e == "keypressed" and a == "escape" then
return 1
elseif e == "keypressed" and a == "c" and love.keyboard.isDown("lctrl", "rctrl") then
copyToClipboard()
elseif e == "touchpressed" then
local name = love.window.getTitle()
if #name == 0 or name == "Untitled" then name = "Game" end
local buttons = {"OK", "Cancel"}
if love.system then
buttons[3] = "Copy to clipboard"
end
local pressed = love.window.showMessageBox("Quit "..name.."?", "", buttons)
if pressed == 1 then
return 1
elseif pressed == 3 then
copyToClipboard()
end
end
end
draw()
if love.timer then
love.timer.sleep(0.1)
end
end
end
-----------------------------------------------------------
-- The root of all calls.
-----------------------------------------------------------
return function()
local func
local inerror = false
local function deferErrhand(...)
local errhand = love.errorhandler or love.errhand
local handler = (not inerror and errhand) or error_printer
inerror = true
func = handler(...)
end
local function earlyinit()
-- If love.boot fails, return 1 and finish immediately
local result = xpcall(love.boot, error_printer)
if not result then return 1 end
-- If love.init or love.run fails, don't return a value,
-- as we want the error handler to take over
result = xpcall(love.init, deferErrhand)
if not result then return end
-- NOTE: We can't assign to func directly, as we'd
-- overwrite the result of deferErrhand with nil on error
local main
result, main = xpcall(love.run, deferErrhand)
if result then
func = main
end
end
func = earlyinit
while func do
local _, retval = xpcall(func, deferErrhand)
if retval then return retval end
coroutine.yield()
end
return 1
end
File diff suppressed because it is too large Load Diff