diff --git a/athenasub/athenasub_2008.vcproj b/athenasub/athenasub_2008.vcproj
index add3e3045ffdbe581e121ea638f6e8a7220da0d4..c714e22c8859689acd2d06fb2742461b4724ba54 100644
--- a/athenasub/athenasub_2008.vcproj
+++ b/athenasub/athenasub_2008.vcproj
@@ -254,10 +254,6 @@
 				RelativePath=".\src\exception.cpp"
 				>
 			</File>
-			<File
-				RelativePath=".\include\aegilib\exception.h"
-				>
-			</File>
 			<File
 				RelativePath=".\include\aegilib\fastbuffer.h"
 				>
diff --git a/athenasub/include/athenasub/exception.h b/athenasub/include/athenasub/exception.h
index cdddec7d515c58c6a495a9335abd56b3942ca319..bf265f2830b2029f8807b6d5026469493aacba37 100644
--- a/athenasub/include/athenasub/exception.h
+++ b/athenasub/include/athenasub/exception.h
@@ -35,8 +35,7 @@
 
 #pragma once
 
-//#include "athenastring.h"
-#include <string>
+#include "athenastring.h"
 #include <exception>
 
 namespace Athenasub {
@@ -59,15 +58,13 @@ namespace Athenasub {
 			TODO
 		};
 
-		Exception(ExceptionList _code);
-		Exception(ExceptionList _code,const char* file,const long line);
+		Exception(ExceptionList code,String message="",const char* file=NULL,const long line=0);
 
-		//String GetMessageString() const { return String(what(),wxConvLocal); }
 		int GetCode() { return code; }
 
 	private:
 		static std::string GetMessageChar(int code);
-		static std::string GetMessageFile(int code,const char *file,long line);
+		static std::string GetExceptionMessage(int code,String message,const char *file,long line);
 
 		ExceptionList code;
 	};
@@ -76,8 +73,10 @@ namespace Athenasub {
 
 #ifndef THROW_ATHENA_EXCEPTION
 #ifdef _MSC_VER
-#define THROW_ATHENA_EXCEPTION(code) throw Athenasub::Exception(code,__FILE__,__LINE__)
+#define THROW_ATHENA_EXCEPTION(code) throw Athenasub::Exception(code,"",__FILE__,__LINE__)
+#define THROW_ATHENA_EXCEPTION_MSG(code,message) throw Athenasub::Exception(code,message,__FILE__,__LINE__)
 #else
 #define THROW_ATHENA_EXCEPTION(code) throw Athenasub::Exception(code)
+#define THROW_ATHENA_EXCEPTION_MSG(code,message) throw Athenasub::Exception(code,message)
 #endif
 #endif
diff --git a/athenasub/src/exception.cpp b/athenasub/src/exception.cpp
index f23c54c12cba22c44b31209e756db7a258a1f364..c8d81906ee4d25953657e79681d5d7e744bbb484 100644
--- a/athenasub/src/exception.cpp
+++ b/athenasub/src/exception.cpp
@@ -37,16 +37,32 @@
 using namespace Athenasub;
 
 
+///////////////////////
+// Stack walker helper
+#include <wx/stackwalk.h>
+#include <wx/filename.h>
+
+class Stack : public wxStackWalker {
+	std::string &str;
+public:
+	Stack(std::string &dest) : str(dest) {}
+
+	void OnStackFrame(const wxStackFrame& frame)
+	{
+		wxString line = wxString::Format(_T("\n\t%03i - "),frame.GetLevel()) + frame.GetName();
+		if (frame.HasSourceLocation()) {
+			wxFileName fn(frame.GetFileName());
+			line += _T(" (") + fn.GetFullName() + wxString::Format(_T(":%i)"),frame.GetLine());
+		}
+		str += line.mb_str(wxConvUTF8);
+	}
+};
+
+
 ////////////////
 // Constructors
-Exception::Exception(ExceptionList _code)
-: std::exception(GetMessageChar(_code).c_str())
-{
-	code = _code;
-}
-
-Exception::Exception(ExceptionList _code,const char* file,const long line)
-: std::exception(GetMessageFile(_code,file,line).c_str())
+Exception::Exception(ExceptionList _code,String message,const char* file,const long line)
+: std::exception(GetExceptionMessage(_code,message,file,line).c_str())
 {
 	code = _code;
 }
@@ -76,12 +92,21 @@ std::string Exception::GetMessageChar(int code)
 
 ///////////////////////////////////////////
 // Get the message string for the filename
-std::string Exception::GetMessageFile(int code,const char *file,long line)
+std::string Exception::GetExceptionMessage(int code,String message,const char *file,long line)
 {
 	std::string str = GetMessageChar(code);
-	str = str + " (" + file + ":";
-	char buffer[16];
-	_itoa_s(line,buffer,10);
-	str = str + buffer + ")";
+
+	// Append macro filename
+	if (file != NULL) {
+		str = str + " (" + file + ":";	// Yes, there's an actual reason why that's not += (operator overloading)
+		char buffer[16];
+		_itoa_s(line,buffer,10);
+		str = str + buffer + ")";
+	}
+
+	// Append stack trace
+	Stack stack(str);
+	stack.Walk(2);
+
 	return str;
 }
diff --git a/athenasub/src/section_entry_dialogue.h b/athenasub/src/section_entry_dialogue.h
index 2e8dfbedd720c87eb8d665d117a5e589e2be62d5..5f4eb8bd06db8c76dca5a594d78c12e3c92fd78d 100644
--- a/athenasub/src/section_entry_dialogue.h
+++ b/athenasub/src/section_entry_dialogue.h
@@ -66,17 +66,17 @@ namespace Athenasub {
 		virtual bool HasMargins() const { return false; }
 
 		// Read accessors
-		virtual const String& GetText() const { ThrowUnsupported(); return EmptyString(); }
-		//virtual Time& GetStartTime() const { ThrowUnsupported(); return Time(); }
-		//virtual Time& GetEndTime() const { ThrowUnsupported(); return Time(); }
-		virtual int GetStartFrame() const { ThrowUnsupported(); return 0; }
-		virtual int GetEndFrame() const { ThrowUnsupported(); return 0; }
-		virtual bool IsComment() const { ThrowUnsupported(); return false; }
-		virtual int GetLayer() const { ThrowUnsupported(); return 0; }
-		virtual int GetMargin(int n) const { ThrowUnsupported(); return n; }
-		virtual const String& GetStyle() const { ThrowUnsupported(); return EmptyString(); }
-		virtual const String& GetActor() const { ThrowUnsupported(); return EmptyString(); }
-		virtual const String& GetUserField() const { ThrowUnsupported(); return EmptyString(); }
+		virtual const String& GetText() const { ThrowUnsupported(); }
+		//virtual Time& GetStartTime() const { ThrowUnsupported(); }
+		//virtual Time& GetEndTime() const { ThrowUnsupported(); }
+		virtual int GetStartFrame() const { ThrowUnsupported(); }
+		virtual int GetEndFrame() const { ThrowUnsupported(); }
+		virtual bool IsComment() const { ThrowUnsupported(); }
+		virtual int GetLayer() const { ThrowUnsupported(); }
+		virtual int GetMargin(int n) const { (void) n; ThrowUnsupported(); }
+		virtual const String& GetStyle() const { ThrowUnsupported(); }
+		virtual const String& GetActor() const { ThrowUnsupported(); }
+		virtual const String& GetUserField() const { ThrowUnsupported(); }
 
 		// Write accessors
 		virtual void SetText(const String& text) { (void) text; ThrowUnsupported(); }
diff --git a/athenasub/src/section_entry_style.h b/athenasub/src/section_entry_style.h
index fce5fd4572d1a925174ca2376fb24c5facd9e217..77be9c8234c5cb6181e2f97e882b4ee59939d284 100644
--- a/athenasub/src/section_entry_style.h
+++ b/athenasub/src/section_entry_style.h
@@ -57,10 +57,10 @@ namespace Athenasub {
 
 		// Read accessors
 		virtual String GetName() const=0;
-		virtual String GetFontName() const { ThrowUnsupported(); return ""; }
-		virtual float GetFontSize() const { ThrowUnsupported(); return 0.0f; }
+		virtual String GetFontName() const { ThrowUnsupported(); }
+		virtual float GetFontSize() const { ThrowUnsupported(); }
 		//virtual IColour& GetColour(int n) const { (void) n; ThrowUnsupported(); return Colour(); }
-		virtual int GetMargin(int n) const { (void) n; ThrowUnsupported(); return 0; }
+		virtual int GetMargin(int n) const { (void) n; ThrowUnsupported(); }
 	};
 
 }