Index: Consts.h
===================================================================
--- Consts.h	(revision 6abfd07ddaf9e27682c6ace96bbfc076078fa71a)
+++ Consts.h	(revision 6abfd07ddaf9e27682c6ace96bbfc076078fa71a)
@@ -0,0 +1,1 @@
+#define GAME_VERSION "0.01.000"
Index: CrashLogger.cpp
===================================================================
--- CrashLogger.cpp	(revision a23fc089e78744b5e954e76a7079245717fffdff)
+++ CrashLogger.cpp	(revision 6abfd07ddaf9e27682c6ace96bbfc076078fa71a)
@@ -4,17 +4,19 @@
 #include <cstdio>
 #include <csignal>
+#include <cstring>
 
 #include <fcntl.h>
 
 #include "Compiler.h"
+#include "Consts.h"
+
+// TODO: Double-check which includes are necessary
 
 #ifdef WINDOWS
-   // most of this can be removed since Windows uses __try __catch instead of signals
-
    #include <windows.h>
-   #include "StackWalker.h"
-
    #include <io.h>
    #include <sys/stat.h>
+
+   #include "FileStackWalker.h"
 
    // The windows analogues to the unix open, close, and write functions
@@ -25,4 +27,6 @@
 
    #define STDERR_FILENO 2
+
+   bool handleException(unsigned int expCode, EXCEPTION_POINTERS* pExp, HANDLE thread);
 #else
    #include <unistd.h>
@@ -31,16 +35,40 @@
    #include <cxxabi.h>
    #include <cstring>
+
+   void abortHandler(int signum);
+   static inline void printStackTrace(int fd_out = STDERR_FILENO);
 #endif
 
-CrashLogger::CrashLogger() {
-   // Apparently, sigaction should be used instead for Linux
-   // It gives more info. Check if I should bother switching
-
-   signal(SIGABRT, abortHandler);
-   signal(SIGSEGV, abortHandler);
-   signal(SIGILL, abortHandler);
-   signal(SIGFPE, abortHandler);
-
-   write(STDERR_FILENO, "Handlers attached\n", 18);
+void printInfo(int fd_out);
+
+CrashLogger::CrashLogger(int(*mainFunc)(int, char*[]), int argc, char* argv[]) {
+   write(STDERR_FILENO, "Calling main\n", 13);
+
+   #ifdef WINDOWS
+      __try {
+         mainFunc(argc, argv);
+         // maybe do this and call a function inside CrashLogger
+         // In that case, also pass GetCurrentThread() as a parameter to then pass to handleException
+         // I could also move almost all of this into CrashLogger by creating a function in CrashLogger that takes a reference
+         // to the effective main function and, for Windows, wraps it in all this error-handling stuff
+      } __except (handleException(
+            GetExceptionCode(),
+            GetExceptionInformation(),
+            GetCurrentThread())
+            ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_EXECUTE_HANDLER) {
+      }
+   #else
+      // Apparently, sigaction should be used instead for Linux
+      // It gives more info. Check if I should bother switching
+
+      signal(SIGABRT, abortHandler);
+      signal(SIGSEGV, abortHandler);
+      signal(SIGILL, abortHandler);
+      signal(SIGFPE, abortHandler);
+
+      write(STDERR_FILENO, "Handlers attached\n", 18);
+
+      mainFunc(argc, argv);
+   #endif
 }
 
@@ -48,5 +76,55 @@
 }
 
-static inline void printStackTrace(int fd_out = STDERR_FILENO) {
+#ifdef WINDOWS
+
+bool handleException(unsigned int expCode, EXCEPTION_POINTERS* pExp, HANDLE thread) {
+   int crash_log = open(CRASH_LOG_FILE, O_RDWR | O_CREAT | O_APPEND, _S_IREAD | _S_IWRITE);
+
+   if (crash_log == -1) {
+      // TODO: Figure out exactly what perror does and if I should use it
+      perror("opening crash.log");  // TODO: Figure out exactly what perror does and if I should use it
+   }
+
+   printInfo(crash_log);
+
+   FileStackWalker sw(crash_log == -1 ? STDERR_FILENO  : crash_log);
+
+   if (pExp != NULL) {
+      sw.ShowCallstack(thread, pExp->ContextRecord);
+   } else {
+      write(crash_log, "Could not get the stack trace\n", 30);
+   }
+
+   close(crash_log);
+
+   if (expCode == EXCEPTION_ACCESS_VIOLATION) {
+      write(STDERR_FILENO, "ACCESS VIOLATION\n", 17);
+   }
+
+   return true;
+}
+
+#else
+
+void abortHandler(int signum) {
+   int crash_log = open(CRASH_LOG_FILE, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
+
+   if (crash_log == -1) {
+      // TODO: Figure out exactly what perror does and if I should use it
+      perror("opening crash.log"); 
+   }
+
+   printInfo(crash_log);
+
+   printStackTrace(crash_log);
+
+   close(crash_log);
+
+   write(STDERR_FILENO, "The game has crashed. Check crash.log for more info\n", 52);
+
+   exit(signum);
+}
+
+static inline void printStackTrace(int fd_out) {
    write(fd_out, "stack trace:\n", 13);
 
@@ -74,51 +152,51 @@
       char* begin_name = NULL;
       char* begin_offset = NULL;
-      char* end_offset = NULL; // Iirc, this is used in the Linux code
-
-      #ifdef MAC
-         for (char *p = symbollist[i]; *p; p++) {
-            if ((*p == '_') && (*(p-1) == ' ')) {
-               begin_name = p-1;
-            } else if(*p == '+') {
-               begin_offset = p-1;
-            }
+      char* end_offset = NULL; // Iirc, this is used in the Linux code (Check what it's used for)
+
+#ifdef MAC
+      for (char *p = symbollist[i]; *p; p++) {
+         if ((*p == '_') && (*(p-1) == ' ')) {
+            begin_name = p-1;
+         } else if(*p == '+') {
+            begin_offset = p-1;
          }
-
-         if (begin_name && begin_offset && (begin_name < begin_offset )) {
-            *begin_name++ = '\0';
-            *begin_offset++ = '\0';
-
-            // mangled name is now in [begin_name, begin_offset) and caller
-            // offset in [begin_offset, end_offset). now apply
-            // __cxa_demangle():
-            int status;
-            char* ret = abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status);
-
-            if (status == 0)  {
-               funcname = ret; // use possibly realloc()-ed string
-               write(fd_out, symbollist[i], strlen(symbollist[i]));
-               write(fd_out, " ", 1);
-               write(fd_out, funcname, strlen(funcname));
-               write(fd_out, " ", 1);
-               write(fd_out, begin_offset, strlen(begin_offset));
-            } else {
-               // demangling failed. Output function name as a C function with no arguments.
-               write(fd_out, "Error\n", 6);
-               write(fd_out, symbollist[i], strlen(symbollist[i]));
-               write(fd_out, " ", 1);
-               write(fd_out, begin_name, strlen(begin_name));
-               write(fd_out, "() ", 3);
-               write(fd_out, begin_offset, strlen(begin_offset));
-            }
+      }
+
+      if (begin_name && begin_offset && (begin_name < begin_offset )) {
+         *begin_name++ = '\0';
+         *begin_offset++ = '\0';
+
+         // mangled name is now in [begin_name, begin_offset) and caller
+         // offset in [begin_offset, end_offset). now apply
+         // __cxa_demangle():
+         int status;
+         char* ret = abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status);
+
+         if (status == 0)  {
+            funcname = ret; // use possibly realloc()-ed string
+            write(fd_out, symbollist[i], strlen(symbollist[i]));
+            write(fd_out, " ", 1);
+            write(fd_out, funcname, strlen(funcname));
+            write(fd_out, " ", 1);
+            write(fd_out, begin_offset, strlen(begin_offset));
          } else {
-            // couldn't parse the line? print the whole line.
+            // demangling failed. Output function name as a C function with no arguments.
+            write(fd_out, "Error\n", 6);
             write(fd_out, symbollist[i], strlen(symbollist[i]));
+            write(fd_out, " ", 1);
+            write(fd_out, begin_name, strlen(begin_name));
+            write(fd_out, "() ", 3);
+            write(fd_out, begin_offset, strlen(begin_offset));
          }
-         write(fd_out, "\n", 1);
-      #else
-         // Check that this works on Linux Mint
+      } else {
+         // couldn't parse the line? print the whole line.
          write(fd_out, symbollist[i], strlen(symbollist[i]));
-         write(fd_out, "\n", 1);
-      #endif
+      }
+      write(fd_out, "\n", 1);
+#else
+      // Check that this works on Linux Mint
+      write(fd_out, symbollist[i], strlen(symbollist[i]));
+      write(fd_out, "\n", 1);
+#endif
    }
 
@@ -129,20 +207,23 @@
 }
 
-// Most of this function could probably be shared between Windows and Linux/Mac
-void abortHandler(int signum) {
-   #ifdef WINDOWS
-      int crash_log = open("crash.log", O_RDWR | O_CREAT | O_APPEND, _S_IREAD | _S_IWRITE);
+#endif
+
+void printInfo(int fd_out) {
+   write(fd_out, "Game Version: ", 14);
+   write(fd_out, GAME_VERSION, strlen(GAME_VERSION));
+   write(fd_out, "\n", 1);
+
+   write(fd_out, "OS: ", 4);
+   #if defined WINDOWS
+      write(fd_out, "Windows", 7);
+   #elif defined LINUX
+      write(fd_out, "Linux", 5);
+   #elif defined MAC
+      write(fd_out, "Mac", 3);
    #else
-      int crash_log = open("crash.log", O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
+      write(fd_out, "Unknown", 7);
    #endif
-
-   if (crash_log == -1) {
-      perror("opening crash.log");  // TODO: Figure out exactly what perror does and if I should use it
-   }
-
-   printStackTrace(crash_log);
-
-   close(crash_log);
-
-   exit(signum);
-}
+   write(fd_out, "\n", 1);
+
+   write(fd_out, "\n", 1);
+}
Index: CrashLogger.h
===================================================================
--- CrashLogger.h	(revision a23fc089e78744b5e954e76a7079245717fffdff)
+++ CrashLogger.h	(revision 6abfd07ddaf9e27682c6ace96bbfc076078fa71a)
@@ -2,11 +2,11 @@
 #define CRASH_LOGGER_H
 
+#define CRASH_LOG_FILE "crash.log"
+
 class CrashLogger {
 public:
-   CrashLogger();
+   CrashLogger(int(*mainFunc)(int, char*[]), int argc, char* argv[]);
    ~CrashLogger();
 };
 
-void abortHandler(int signum);
-
 #endif
Index: FileStackWalker.cpp
===================================================================
--- FileStackWalker.cpp	(revision a23fc089e78744b5e954e76a7079245717fffdff)
+++ FileStackWalker.cpp	(revision 6abfd07ddaf9e27682c6ace96bbfc076078fa71a)
@@ -1,3 +1,10 @@
 #include "FileStackWalker.h"
+
+// Put this stuff in some common header shared by this and CrashLogger
+// Put this stuff in some common header shared by this and CrashLogger
+
+#include <io.h>
+
+#define write _write
 
 FileStackWalker::FileStackWalker(int fd_out) : StackWalker() {
Index: NewOpenGLGame.vcxproj
===================================================================
--- NewOpenGLGame.vcxproj	(revision a23fc089e78744b5e954e76a7079245717fffdff)
+++ NewOpenGLGame.vcxproj	(revision 6abfd07ddaf9e27682c6ace96bbfc076078fa71a)
@@ -136,4 +136,5 @@
   <ItemGroup>
     <ClCompile Include="CrashLogger.cpp" />
+    <ClCompile Include="FileStackWalker.cpp" />
     <ClCompile Include="IMGUI\imgui.cpp" />
     <ClCompile Include="IMGUI\imgui_demo.cpp" />
@@ -145,7 +146,9 @@
     <ClCompile Include="stb_image_write.h" />
     <ClCompile Include="stb_image.cpp" />
+    <ClCompile Include="utils.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="CrashLogger.h" />
+    <ClInclude Include="FileStackWalker.h" />
     <ClInclude Include="IMGUI\imgui.h" />
     <ClInclude Include="IMGUI\imgui_internal.h" />
Index: new-game.cpp
===================================================================
--- new-game.cpp	(revision a23fc089e78744b5e954e76a7079245717fffdff)
+++ new-game.cpp	(revision 6abfd07ddaf9e27682c6ace96bbfc076078fa71a)
@@ -35,14 +35,5 @@
 #include "Compiler.h"
 
-#ifdef WINDOWS
-   #include <windows.h>
-   #include <excpt.h>
-   #include <io.h>
-
-   #include "FileStackWalker.h"
-#else
-   // TODO: Move as much Windows crash-logging stuff into CrashLogger as well
-   #include "CrashLogger.h"
-#endif
+#include "CrashLogger.h"
 
 using namespace std;
@@ -300,33 +291,19 @@
 */
 
-CrashLogger logger;
-
 // Helps to test logging during crashes
-/*
-void badFunc() {
+int badFunc() {
    int* test = NULL;
+
+   string test2 = "lol";
+   cout << test2 << endl;
+
    *test = 1;
-}
-*/
-
-#ifdef WINDOWS
-
-// Give it a file handle to crash.log instead (using the code in CrashLogger.cpp)
-FileStackWalker sw(2);
-
-bool handleException(unsigned int expCode, EXCEPTION_POINTERS* pExp, HANDLE thread);
-#endif
+   return *test;
+}
+
+int __main(int argc, char* argv[]);
 
 int main(int argc, char* argv[]) {
-#ifdef WINDOWS
-   __try {
-      __main(argc, argv);
-      // maybe do this and call a function inside CrashLogger
-      // In that case, also pass GetCurrentThread() as a parameter to then pass to handleException
-      // I could also move almost all of this into CrashLogger by creating a function in CrashLogger that takes a reference
-      // to the effective main function and, for Windows, wraps it in all this error-handling stuff
-   } __except( handleException(GetExceptionCode(), GetExceptionInformation(), GetCurrentThread()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_EXECUTE_HANDLER) {
-      _write(2, "CAUGHT\n", 7);
-   }
+   CrashLogger logger(__main, argc, argv);
 
    exit(0);
@@ -334,5 +311,4 @@
 
 int __main(int argc, char* argv[]) {
-#endif
    cout << "New OpenGL Game" << endl;
 
@@ -1023,19 +999,7 @@
       delete *it;
    }
-}
-
-#ifdef WINDOWS
-bool handleException(unsigned int expCode, EXCEPTION_POINTERS* pExp, HANDLE thread) {
-   if (pExp != NULL) {
-      sw.ShowCallstack(thread, pExp->ContextRecord);
-   }
-
-   if (expCode == EXCEPTION_ACCESS_VIOLATION) {
-      _write(2, "ACCESS VIOLATION\n", 17);
-   }
-
-   return true;
-}
-#endif
+
+   return 0;
+}
 
 void glfw_error_callback(int error, const char* description) {
