diff --git a/Avara.msvc/AvaraCore.vcxproj b/Avara.msvc/AvaraCore.vcxproj
index 41b1a85a9..9117ed44b 100644
--- a/Avara.msvc/AvaraCore.vcxproj
+++ b/Avara.msvc/AvaraCore.vcxproj
@@ -319,11 +319,13 @@
+
+
@@ -368,6 +370,7 @@
+
@@ -507,6 +510,7 @@
+
diff --git a/Avara.msvc/AvaraCore.vcxproj.filters b/Avara.msvc/AvaraCore.vcxproj.filters
index a89427146..e12ef1b14 100644
--- a/Avara.msvc/AvaraCore.vcxproj.filters
+++ b/Avara.msvc/AvaraCore.vcxproj.filters
@@ -105,6 +105,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
Header Files
@@ -165,6 +171,9 @@
Header Files
+
+ Header Files
+
Header Files
@@ -662,6 +671,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/Avara.xcodeproj/project.pbxproj b/Avara.xcodeproj/project.pbxproj
index 7d746471a..091dc9b5f 100644
--- a/Avara.xcodeproj/project.pbxproj
+++ b/Avara.xcodeproj/project.pbxproj
@@ -7,6 +7,9 @@
objects = {
/* Begin PBXBuildFile section */
+ 601893AF2ECF106900AB3A6D /* Logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 601893AE2ECF106900AB3A6D /* Logging.cpp */; };
+ 601893B02ECF106900AB3A6D /* Logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 601893AE2ECF106900AB3A6D /* Logging.cpp */; };
+ 601893B12ECF106900AB3A6D /* Logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 601893AE2ECF106900AB3A6D /* Logging.cpp */; };
6025AE4E2C255E6A00A57EFB /* LegacyOpenGLRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 60C274E22C23EBE9005B67A9 /* LegacyOpenGLRenderer.cpp */; };
6055BF212DEA8A79005E3CFB /* BasePath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6055BF202DEA8A79005E3CFB /* BasePath.cpp */; };
6055BF222DEA8A79005E3CFB /* BasePath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6055BF202DEA8A79005E3CFB /* BasePath.cpp */; };
@@ -571,6 +574,10 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 601893AD2ECF0FB000AB3A6D /* Logging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Logging.h; sourceTree = ""; };
+ 601893AE2ECF106900AB3A6D /* Logging.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Logging.cpp; sourceTree = ""; };
+ 601893B22ED2CB6700AB3A6D /* backward.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = backward.hpp; sourceTree = ""; };
+ 601893B72ED5A1F500AB3A6D /* signalhandling.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = signalhandling.hpp; sourceTree = ""; };
6055BF1F2DEA8A79005E3CFB /* BasePath.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BasePath.h; sourceTree = ""; };
6055BF202DEA8A79005E3CFB /* BasePath.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BasePath.cpp; sourceTree = ""; };
60C274E22C23EBE9005B67A9 /* LegacyOpenGLRenderer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LegacyOpenGLRenderer.cpp; sourceTree = ""; };
@@ -1419,6 +1426,8 @@
E5890BB029895118007A875D /* RolloverCounter.h */,
E5890BB129895118007A875D /* SlidingHistogram.h */,
E2D76F732A1680FD000D24B3 /* JSONify.h */,
+ 601893AD2ECF0FB000AB3A6D /* Logging.h */,
+ 601893AE2ECF106900AB3A6D /* Logging.cpp */,
);
path = util;
sourceTree = "";
@@ -1709,6 +1718,8 @@
isa = PBXGroup;
children = (
E5890ED829895124007A875D /* AudioFile.h */,
+ 601893B22ED2CB6700AB3A6D /* backward.hpp */,
+ 601893B72ED5A1F500AB3A6D /* signalhandling.hpp */,
E5890D3F29895123007A875D /* csscolorparser.cpp */,
E5890EDB29895124007A875D /* csscolorparser.hpp */,
E5890D1829895123007A875D /* cute_files.h */,
@@ -2531,6 +2542,7 @@
E517F0E4299713DB0036B206 /* vscrollpanel.cpp in Sources */,
E517F0E5299713DB0036B206 /* widget.cpp in Sources */,
E517F0E6299713DB0036B206 /* window.cpp in Sources */,
+ 601893B12ECF106900AB3A6D /* Logging.cpp in Sources */,
E517F0E7299713DB0036B206 /* pugixml.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -2702,6 +2714,7 @@
E5890CFD29895118007A875D /* CBSPPart.cpp in Sources */,
E5890CEF29895118007A875D /* CWallSolid.cpp in Sources */,
E5890CB529895118007A875D /* CFreeSolid.cpp in Sources */,
+ 601893AF2ECF106900AB3A6D /* Logging.cpp in Sources */,
E5890CC529895118007A875D /* CGuardActor.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -2777,6 +2790,7 @@
E5A219F82DC59135007D54FF /* CParasite.cpp in Sources */,
E5A219F92DC59135007D54FF /* CPill.cpp in Sources */,
E5A219FA2DC59135007D54FF /* CPlacedActors.cpp in Sources */,
+ 601893B02ECF106900AB3A6D /* Logging.cpp in Sources */,
E5A219FB2DC59135007D54FF /* CPlayerActor.cpp in Sources */,
E5A219FC2DC59135007D54FF /* CPlayerManager.cpp in Sources */,
E5A219FD2DC59135007D54FF /* CPlayerMissile.cpp in Sources */,
@@ -3059,6 +3073,7 @@
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=macosx*]" = "";
ENABLE_HARDENED_RUNTIME = YES;
@@ -3077,6 +3092,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
+ LIBRARY_SEARCH_PATHS = "$(inherited)";
MARKETING_VERSION = 1.0;
OTHER_CFLAGS = (
"$(inherited)",
@@ -3118,6 +3134,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
+ LIBRARY_SEARCH_PATHS = "$(inherited)";
MARKETING_VERSION = 1.0;
OTHER_CFLAGS = (
"$(inherited)",
diff --git a/LICENSE.txt b/LICENSE.txt
index 4404312f0..c99c43f32 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -8,6 +8,12 @@ https://github.com/adamstark/AudioFile/
MIT License
Copyright (c) 2017 Adam Stark.
+backward-cpp
+https://github.com/bombela/backward-cpp
+François-Xavier Bourlet bombela@gmail.com
+MIT License
+Copyright 2013-2017 Google Inc. All Rights Reserved.
+
css-color-parser-cpp
https://github.com/mapbox/css-color-parser-cpp
MIT License
diff --git a/Makefile b/Makefile
index 4b1a5d0c7..834c07471 100644
--- a/Makefile
+++ b/Makefile
@@ -85,7 +85,7 @@ else
LDFLAGS += $(shell ${PKG_CONFIG} --libs-only-l sdl2)
CPPFLAGS += $(shell ${PKG_CONFIG} --cflags-only-I directfb)
CPPFLAGS += $(shell ${PKG_CONFIG} --cflags-only-I sdl2)
- CPPFLAGS += -fPIC
+ CPPFLAGS += -fPIC
POST_PROCESS ?= ls -lh
endif
diff --git a/src/Avara.cpp b/src/Avara.cpp
index 2be32fbce..a7c3a36ce 100644
--- a/src/Avara.cpp
+++ b/src/Avara.cpp
@@ -15,7 +15,9 @@
#include "FastMat.h"
#include "Preferences.h"
#include "BasePath.h"
-
+#include "Logging.h"
+#include "signal.h"
+#include "signalhandling.hpp"
#ifdef _WIN32
#include
#include
@@ -42,6 +44,8 @@ void SetHiDPI() {
#include
#include
+SignalHandling sh;
+
using namespace nanogui;
void NullLogger(void *userdata, int category, SDL_LogPriority priority, const char *message) {}
@@ -83,6 +87,8 @@ std::vector combinedArgs(std::string defaultArgs, int argc, char* a
}
int main(int argc, char *argv[]) {
+ // Open log file.
+ Logging::OpenLog();
// Check basepath override.
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--basepath") == 0) {
@@ -162,7 +168,6 @@ int main(int argc, char *argv[]) {
} else if(connectAddress.size() > 0) {
app->GetNet()->ChangeNet(kClientNet, connectAddress);
}
-
// outside of the game, use INACTIVE_LOOP_REFRESH (no need to poll when not playing)
mainloop(INACTIVE_LOOP_REFRESH);
@@ -170,7 +175,7 @@ int main(int argc, char *argv[]) {
// Shut it down!!
shutdown();
-
+ Logging::CloseLog();
return 0;
}
diff --git a/src/gui/Preferences.h b/src/gui/Preferences.h
index 964b3a515..b493ff703 100755
--- a/src/gui/Preferences.h
+++ b/src/gui/Preferences.h
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
using json = nlohmann::json;
@@ -220,13 +221,16 @@ static json defaultPrefs = {
{kControllerDamperMillis, 500.0}
};
-
-
-static std::string PrefPath() {
+static std::string PrefPath(const char* fn) {
char *prefPath = SDL_GetPrefPath("Avaraline", "Avara");
- std::string jsonPath = std::string(prefPath) + "prefs.json";
+ std::string filePath = std::string(prefPath);
+ filePath.append(fn);
SDL_free(prefPath);
- return jsonPath;
+ return filePath;
+}
+
+static std::string PrefPath() {
+ return PrefPath("prefs.json");
}
static inline json ReadDefaultPrefs() {
diff --git a/src/util/Logging.cpp b/src/util/Logging.cpp
new file mode 100644
index 000000000..46ae0809f
--- /dev/null
+++ b/src/util/Logging.cpp
@@ -0,0 +1,48 @@
+#include "Logging.h"
+#include "Preferences.h"
+
+std::ofstream Logging::logFile;
+
+
+static const char * const _priority_names[] = {
+ NULL,
+ "TRACE",
+ "VERBOSE",
+ "DEBUG",
+ "INFO",
+ "WARN",
+ "ERROR",
+ "CRITICAL"
+};
+
+void Logging::OpenLog() {
+ try {
+ std::string logPath = PrefPath("avara.log");
+ logFile.open(logPath, std::ios::out | std::ios::trunc);
+ if (logFile.fail()) {
+ SDL_Log("Failed to open log file at %s.", logPath.c_str());
+ }
+ else {
+ SDL_LogSetOutputFunction(Logging::Log, nullptr);
+ }
+ }
+ catch (std::exception e) {
+ SDL_Log("Error opening log file.");
+ }
+}
+
+void Logging::Log(void *userdata, int category, SDL_LogPriority priority, const char *message) {
+ if (logFile.is_open()) {
+ std::time_t t = std::time(nullptr);
+ std::tm tm = *std::localtime(&t);
+ logFile << std::put_time(&tm, "%Y%m%d %H%M%S ");
+ logFile << SDL_GetTicks64() << " " << _priority_names[priority] << ": " << message << "\n";
+ logFile.flush();
+ }
+ printf("%s: %s\n", _priority_names[priority], message);
+}
+
+void Logging::CloseLog() {
+ logFile.flush();
+ logFile.close();
+}
diff --git a/src/util/Logging.h b/src/util/Logging.h
new file mode 100644
index 000000000..320b966b7
--- /dev/null
+++ b/src/util/Logging.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include
+#include
+
+class Logging {
+private:
+ static std::ofstream logFile;
+public:
+ static void OpenLog();
+ static void Log(void *userdata, int category, SDL_LogPriority priority, const char *message);
+ static void CloseLog();
+ static std::ofstream& LogFile() { return logFile; }
+};
diff --git a/vendor/backward.hpp b/vendor/backward.hpp
new file mode 100644
index 000000000..263cd1b4c
--- /dev/null
+++ b/vendor/backward.hpp
@@ -0,0 +1,4530 @@
+/*
+ * backward.hpp
+ * Copyright 2013 Google Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef H_6B9572DA_A64B_49E6_B234_051480991C89
+#define H_6B9572DA_A64B_49E6_B234_051480991C89
+
+#ifndef __cplusplus
+#error "It's not going to compile without a C++ compiler..."
+#endif
+
+#if defined(BACKWARD_CXX11)
+#elif defined(BACKWARD_CXX98)
+#else
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+#define BACKWARD_CXX11
+#define BACKWARD_ATLEAST_CXX11
+#define BACKWARD_ATLEAST_CXX98
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+#define BACKWARD_ATLEAST_CXX17
+#endif
+#else
+#define BACKWARD_CXX98
+#define BACKWARD_ATLEAST_CXX98
+#endif
+#endif
+
+// You can define one of the following (or leave it to the auto-detection):
+//
+// #define BACKWARD_SYSTEM_LINUX
+// - specialization for linux
+//
+// #define BACKWARD_SYSTEM_DARWIN
+// - specialization for Mac OS X 10.5 and later.
+//
+// #define BACKWARD_SYSTEM_WINDOWS
+// - specialization for Windows (Clang 9 and MSVC2017)
+//
+// #define BACKWARD_SYSTEM_UNKNOWN
+// - placebo implementation, does nothing.
+//
+#if defined(BACKWARD_SYSTEM_LINUX)
+#elif defined(BACKWARD_SYSTEM_DARWIN)
+#elif defined(BACKWARD_SYSTEM_UNKNOWN)
+#elif defined(BACKWARD_SYSTEM_WINDOWS)
+#else
+#if defined(__linux) || defined(__linux__)
+#define BACKWARD_SYSTEM_LINUX
+#elif defined(__APPLE__)
+#define BACKWARD_SYSTEM_DARWIN
+#elif defined(_WIN32)
+#define BACKWARD_SYSTEM_WINDOWS
+#else
+#define BACKWARD_SYSTEM_UNKNOWN
+#endif
+#endif
+
+#define NOINLINE __attribute__((noinline))
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if defined(BACKWARD_SYSTEM_LINUX)
+
+// On linux, backtrace can back-trace or "walk" the stack using the following
+// libraries:
+//
+// #define BACKWARD_HAS_UNWIND 1
+// - unwind comes from libgcc, but I saw an equivalent inside clang itself.
+// - with unwind, the stacktrace is as accurate as it can possibly be, since
+// this is used by the C++ runtime in gcc/clang for stack unwinding on
+// exception.
+// - normally libgcc is already linked to your program by default.
+//
+// #define BACKWARD_HAS_LIBUNWIND 1
+// - libunwind provides, in some cases, a more accurate stacktrace as it knows
+// to decode signal handler frames and lets us edit the context registers when
+// unwinding, allowing stack traces over bad function references.
+//
+// #define BACKWARD_HAS_BACKTRACE == 1
+// - backtrace seems to be a little bit more portable than libunwind, but on
+// linux, it uses unwind anyway, but abstract away a tiny information that is
+// sadly really important in order to get perfectly accurate stack traces.
+// - backtrace is part of the (e)glib library.
+//
+// The default is:
+// #define BACKWARD_HAS_UNWIND == 1
+//
+// Note that only one of the define should be set to 1 at a time.
+//
+#if BACKWARD_HAS_UNWIND == 1
+#elif BACKWARD_HAS_LIBUNWIND == 1
+#elif BACKWARD_HAS_BACKTRACE == 1
+#else
+#undef BACKWARD_HAS_UNWIND
+#define BACKWARD_HAS_UNWIND 1
+#undef BACKWARD_HAS_LIBUNWIND
+#define BACKWARD_HAS_LIBUNWIND 0
+#undef BACKWARD_HAS_BACKTRACE
+#define BACKWARD_HAS_BACKTRACE 0
+#endif
+
+// On linux, backward can extract detailed information about a stack trace
+// using one of the following libraries:
+//
+// #define BACKWARD_HAS_DW 1
+// - libdw gives you the most juicy details out of your stack traces:
+// - object filename
+// - function name
+// - source filename
+// - line and column numbers
+// - source code snippet (assuming the file is accessible)
+// - variable names (if not optimized out)
+// - variable values (not supported by backward-cpp)
+// - You need to link with the lib "dw":
+// - apt-get install libdw-dev
+// - g++/clang++ -ldw ...
+//
+// #define BACKWARD_HAS_BFD 1
+// - With libbfd, you get a fair amount of details:
+// - object filename
+// - function name
+// - source filename
+// - line numbers
+// - source code snippet (assuming the file is accessible)
+// - You need to link with the lib "bfd":
+// - apt-get install binutils-dev
+// - g++/clang++ -lbfd ...
+//
+// #define BACKWARD_HAS_DWARF 1
+// - libdwarf gives you the most juicy details out of your stack traces:
+// - object filename
+// - function name
+// - source filename
+// - line and column numbers
+// - source code snippet (assuming the file is accessible)
+// - variable names (if not optimized out)
+// - variable values (not supported by backward-cpp)
+// - You need to link with the lib "dwarf":
+// - apt-get install libdwarf-dev
+// - g++/clang++ -ldwarf ...
+//
+// #define BACKWARD_HAS_BACKTRACE_SYMBOL 1
+// - backtrace provides minimal details for a stack trace:
+// - object filename
+// - function name
+// - backtrace is part of the (e)glib library.
+//
+// The default is:
+// #define BACKWARD_HAS_BACKTRACE_SYMBOL == 1
+//
+// Note that only one of the define should be set to 1 at a time.
+//
+#if BACKWARD_HAS_DW == 1
+#elif BACKWARD_HAS_BFD == 1
+#elif BACKWARD_HAS_DWARF == 1
+#elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1
+#else
+#undef BACKWARD_HAS_DW
+#define BACKWARD_HAS_DW 0
+#undef BACKWARD_HAS_BFD
+#define BACKWARD_HAS_BFD 0
+#undef BACKWARD_HAS_DWARF
+#define BACKWARD_HAS_DWARF 0
+#undef BACKWARD_HAS_BACKTRACE_SYMBOL
+#define BACKWARD_HAS_BACKTRACE_SYMBOL 1
+#endif
+
+#include
+#include
+#ifdef __ANDROID__
+// Old Android API levels define _Unwind_Ptr in both link.h and
+// unwind.h Rename the one in link.h as we are not going to be using
+// it
+#define _Unwind_Ptr _Unwind_Ptr_Custom
+#include
+#undef _Unwind_Ptr
+#else
+#include
+#endif
+#if defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || \
+ defined(__POWERPC__)
+// Linux kernel header required for the struct pt_regs definition
+// to access the NIP (Next Instruction Pointer) register value
+#include
+#endif
+#include
+#include
+#include
+#include
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#include
+#undef _GNU_SOURCE
+#else
+#include
+#endif
+
+#if BACKWARD_HAS_BFD == 1
+// NOTE: defining PACKAGE{,_VERSION} is required before including
+// bfd.h on some platforms, see also:
+// https://sourceware.org/bugzilla/show_bug.cgi?id=14243
+#ifndef PACKAGE
+#define PACKAGE
+#endif
+#ifndef PACKAGE_VERSION
+#define PACKAGE_VERSION
+#endif
+#include
+#endif
+
+#if BACKWARD_HAS_DW == 1
+#include
+#include
+#include
+#endif
+
+#if BACKWARD_HAS_DWARF == 1
+#include
+#include
+#include
+#include
+#include