diff --git a/include/Athena/Exception.hpp b/include/Athena/Exception.hpp index f3e82d8..f3f719e 100644 --- a/include/Athena/Exception.hpp +++ b/include/Athena/Exception.hpp @@ -45,7 +45,8 @@ public: m_message(message), m_file(file), m_function(function), - m_line(line) + m_line(line), + m_exceptionName("Exception") { } @@ -54,7 +55,7 @@ public: */ inline std::string message() const { - return m_message; + return m_exceptionName + (m_message.empty() ? "" : ": " + m_message); } inline std::string file() const @@ -74,28 +75,57 @@ public: inline std::string formattedMessage() const { - return Athena::utility::sprintf("%s : %s (%i) %s", m_file.c_str(), m_function.c_str(), m_line, m_message.c_str()); + return Athena::utility::sprintf("%s : %s (%i) %s", m_file.c_str(), m_function.c_str(), m_line, message().c_str()); } protected: std::string m_message; //!< The error message string std::string m_file; std::string m_function; int m_line; + std::string m_exceptionName; }; } // error } // Athena #ifdef _MSC_VER #define THROW_EXCEPTION(args,...) \ - do { \ - std::string msg = Athena::utility::sprintf(args, __VA_ARGS__); \ +do { \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, __VA_ARGS__); return; \ + } else { std::string msg = Athena::utility::sprintf(__VA_ARGS__); \ throw Athena::error::Exception(std::string("Exception: ")+msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ - } while(0) + } \ +} while(0) #elif defined(__GNUC__) #define THROW_EXCEPTION(args...) \ - do { \ +do { \ + if (atGetExceptionHandler()) { atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, args); return; \ + } else { \ std::string msg = Athena::utility::sprintf(args); \ + throw Athena::error::Exception(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ +} while(0) +#endif + +#ifdef _MSC_VER +#define THROW_EXCEPTION_RETURN(ret, args,...) \ +do { \ + if (atGetExceptionHandler()) \ + { \ + atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, __VA_ARGS__); \ + return ret; \ + } else { \ + std::string msg = Athena::utility::sprintf(__VA_ARGS__); \ throw Athena::error::Exception(std::string("Exception: ")+msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ - } while(0) + } \ +} while(0) +#elif defined(__GNUC__) +#define THROW_EXCEPTION_RETURN(ret, args...) \ +do { \ + if (atGetExceptionHandler()) { atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, args); return ret; \ + } else { \ + std::string msg = Athena::utility::sprintf(args); \ + throw Athena::error::Exception(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ +} while(0) #endif #endif // EXCEPTION_HPP diff --git a/include/Athena/FileNotFoundException.hpp b/include/Athena/FileNotFoundException.hpp index 6345415..9f52936 100644 --- a/include/Athena/FileNotFoundException.hpp +++ b/include/Athena/FileNotFoundException.hpp @@ -39,7 +39,9 @@ public: inline FileNotFoundException(const std::string& filename, const std::string& file, const std::string& function, const int line) : Exception(std::string("FileNotFoundException: Could not find file \"") + filename + std::string("\", please check that it exists."), file, function, line), m_filename(filename) - {} + { + m_exceptionName = "FileNotFoundException"; + } /*! \brief Returns the path of the offending file. * \return std::string The filename of the file including the path. @@ -51,7 +53,31 @@ private: } // error } // Athena +#ifndef THROW_FILE_NOT_FOUND_EXCEPTION #define THROW_FILE_NOT_FOUND_EXCEPTION(msg) \ - do { throw Athena::error::FileNotFoundException(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); } while(0) + do { \ + if (atGetExceptionHandler()) \ + { \ + atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, msg); \ + return; \ + } \ + else \ + throw Athena::error::FileNotFoundException(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ +} while(0) +#endif + +#ifndef THROW_FILE_NOT_FOUND_EXCEPTION_RETURN +#define THROW_FILE_NOT_FOUND_EXCEPTION_RETURN(ret, msg) \ + do { \ + if (atGetExceptionHandler()) \ + { \ + atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, msg); \ + return ret; \ + } \ + else \ + throw Athena::error::FileNotFoundException(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ +} while(0) +#endif + #endif // FILENOTFOUNDEXCEPTION_HPP diff --git a/include/Athena/Global.hpp b/include/Athena/Global.hpp index 0311a33..a9a65d5 100644 --- a/include/Athena/Global.hpp +++ b/include/Athena/Global.hpp @@ -107,6 +107,11 @@ typedef Vector2D Vector2Df; #endif // ATHENA_NO_SAKURA } // Athena +typedef void (*atEXCEPTION_HANDLER)(const std::string& file, const std::string& function, int line, const std::string&, ...); + +atEXCEPTION_HANDLER atGetExceptionHandler(); +void atSetExceptionHandler(atEXCEPTION_HANDLER func); + std::ostream& operator<<(std::ostream& os, const Athena::SeekOrigin& origin); std::ostream& operator<<(std::ostream& os, const Athena::Endian& endian); #endif // GLOBAL_HPP diff --git a/include/Athena/IOException.hpp b/include/Athena/IOException.hpp index db7f656..d498262 100644 --- a/include/Athena/IOException.hpp +++ b/include/Athena/IOException.hpp @@ -41,7 +41,9 @@ public: */ inline IOException(const std::string& message, const std::string& file, const std::string& function, const int line) : Exception(message, file, function, line) - {} + { + m_exceptionName = "IOException"; + } }; } // error @@ -50,14 +52,38 @@ public: #ifdef _MSC_VER #define THROW_IO_EXCEPTION(args, ...) \ do { \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, __VA_ARGS__); return; \ + } else { std::string msg = Athena::utility::sprintf(args, __VA_ARGS__); \ throw Athena::error::IOException(std::string("IOException: ")+msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ } while(0) #elif defined(__GNUC__) #define THROW_IO_EXCEPTION(args...) \ do { \ - std::string msg = Athena::utility::sprintf(args); \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, args); return; \ + } else { std::string msg = Athena::utility::sprintf(args); \ + throw Athena::error::IOException(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ + } while(0) +#endif + +#ifdef _MSC_VER +#define THROW_IO_EXCEPTION_RETURN(ret, args, ...) \ + do { \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, __VA_ARGS__); return ret; \ + } else { + std::string msg = Athena::utility::sprintf(args, __VA_ARGS__); \ throw Athena::error::IOException(std::string("IOException: ")+msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ + } while(0) +#elif defined(__GNUC__) +#define THROW_IO_EXCEPTION_RETURN(ret, args...) \ + do { \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, args); return ret; \ + } else { std::string msg = Athena::utility::sprintf(args); \ + throw Athena::error::IOException(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ } while(0) #endif diff --git a/include/Athena/InvalidDataException.hpp b/include/Athena/InvalidDataException.hpp index 73d3cd2..e781cfb 100644 --- a/include/Athena/InvalidDataException.hpp +++ b/include/Athena/InvalidDataException.hpp @@ -36,8 +36,9 @@ class InvalidDataException : public Exception { public: inline InvalidDataException(const std::string& error, const std::string& file, const std::string& function, const int line) - : Exception(error, file, function, line) + : Exception(("InvalidDataException") + error, file, function, line) { + m_exceptionName = "InvalidDataException"; } }; } // error @@ -46,14 +47,34 @@ public: #ifdef _MSC_VER #define THROW_INVALID_DATA_EXCEPTION(args, ...) \ do { \ - std::string msg = Athena::utility::sprintf(args, __VA_ARGS__); \ - throw Athena::error::InvalidDataException(std::string("InvalidDataException: ")+msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, __VA_ARGS__); return; } \ + else { std::string msg = Athena::utility::sprintf(args, __VA_ARGS__); \ + throw Athena::error::InvalidDataException(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ } while(0) #elif defined(__GNUC__) #define THROW_INVALID_DATA_EXCEPTION(args...) \ + do { if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, args); return; } \ + else { std::string msg = Athena::utility::sprintf(args); \ + throw Athena::error::InvalidDataException(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ + } while(0) +#endif + +#ifdef _MSC_VER +#define THROW_INVALID_DATA_EXCEPTION(args, ...) \ do { \ - std::string msg = Athena::utility::sprintf(args); \ - throw Athena::error::InvalidDataException(std::string("InvalidDataException: ")+msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, __VA_ARGS__); return; } \ + else { std::string msg = Athena::utility::sprintf(args, __VA_ARGS__); \ + throw Athena::error::InvalidDataException(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ + } while(0) +#elif defined(__GNUC__) +#define THROW_INVALID_DATA_EXCEPTION_RETURN(ret, args...) \ + do { if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, args); return ret; } \ + else { std::string msg = Athena::utility::sprintf(args); \ + throw Athena::error::InvalidDataException(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ } while(0) #endif #endif // INVALIDDATAEXCEPTION_HPP diff --git a/include/Athena/InvalidOperationException.hpp b/include/Athena/InvalidOperationException.hpp index 67c5643..c58f6b9 100644 --- a/include/Athena/InvalidOperationException.hpp +++ b/include/Athena/InvalidOperationException.hpp @@ -42,6 +42,7 @@ public: inline InvalidOperationException(const std::string& message, const std::string& file, const std::string& function, const int line) : Exception(message, file, function, line) { + m_exceptionName = "InvalidOperationException"; } }; } // error @@ -50,14 +51,38 @@ public: #ifdef _MSC_VER #define THROW_INVALID_OPERATION_EXCEPTION(args, ...) \ do { \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, __VA_ARGS__); return; \ + } else { std::string msg = Athena::utility::sprintf(args, __VA_ARGS__); \ throw Athena::error::InvalidOperationException(std::string("InvalidOperationException: ")+msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ } while(0) #elif defined (__GNUC__) #define THROW_INVALID_OPERATION_EXCEPTION(args...) \ do { \ - std::string msg = Athena::utility::sprintf(args); \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, args); return; \ + } else { std::string msg = Athena::utility::sprintf(args); \ + throw Athena::error::InvalidOperationException(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ + } while(0) +#endif + +#ifdef _MSC_VER +#define THROW_INVALID_OPERATION_EXCEPTIONRETURN(ret, args, ...) \ + do { \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, __VA_ARGS__); return ret; \ + } else { + std::string msg = Athena::utility::sprintf(args, __VA_ARGS__); \ throw Athena::error::InvalidOperationException(std::string("InvalidOperationException: ")+msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ + } while(0) +#elif defined(__GNUC__) +#define THROW_INVALID_OPERATION_EXCEPTION_RETURN(ret, args...) \ + do { \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, args); return ret; \ + } else { std::string msg = Athena::utility::sprintf(args); \ + throw Athena::error::InvalidOperationException(msg, __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ } while(0) #endif #endif // INVALID_OPERATION_EXCEPTION_HPP diff --git a/include/Athena/NotImplementedException.hpp b/include/Athena/NotImplementedException.hpp index cb49c21..4419724 100644 --- a/include/Athena/NotImplementedException.hpp +++ b/include/Athena/NotImplementedException.hpp @@ -27,12 +27,26 @@ class NotImplementedException : public Exception public: NotImplementedException(const std::string& message, const std::string& file, const std::string& function, const int line) : Exception(message, file, function, line) - {} + { + m_exceptionName = "NotImplementedException"; + } }; } // error } // Athena #define THROW_NOT_IMPLEMENTED_EXCEPTION() \ - do { throw Athena::error::NotImplementedException("NotImplementedException", __FILE__, AT_PRETTY_FUNCTION, __LINE__); } while(0) + do { \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, "NotImplementedException"); return; \ + } else { \ + throw Athena::error::NotImplementedException(std::string(), __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ + } while(0) +#define THROW_NOT_IMPLEMENTED_EXCEPTION_RETURN(ret) \ + do { \ + if (atGetExceptionHandler()) {atGetExceptionHandler()(__FILE__, AT_PRETTY_FUNCTION, __LINE__, "NotImplementedException"); return ret; \ + } else { \ + throw Athena::error::NotImplementedException(std::string(), __FILE__, AT_PRETTY_FUNCTION, __LINE__); \ + } \ + } while(0) #endif // NOTIMPLEMENTEDEXCEPTION_HPP diff --git a/src/Athena/ALTTPFile.cpp b/src/Athena/ALTTPFile.cpp index ae2a2d6..4301d2c 100644 --- a/src/Athena/ALTTPFile.cpp +++ b/src/Athena/ALTTPFile.cpp @@ -45,7 +45,7 @@ std::vector ALTTPFile::questList() const ALTTPQuest* ALTTPFile::quest(atUint32 id) const { if (id > m_quests.size()) - THROW_INVALID_OPERATION_EXCEPTION("index out of range"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(nullptr, "index out of range"); return m_quests[id]; } diff --git a/src/Athena/ALTTPQuest.cpp b/src/Athena/ALTTPQuest.cpp index 1273abb..082d9de 100644 --- a/src/Athena/ALTTPQuest.cpp +++ b/src/Athena/ALTTPQuest.cpp @@ -72,7 +72,7 @@ std::vector ALTTPQuest::overworldEvents() const ALTTPOverworldEvent* ALTTPQuest::overworldEvent(atUint32 id) const { if (id > m_overworldEvents.size() - 1) - THROW_INVALID_OPERATION_EXCEPTION("index out of range"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(nullptr, "index out of range"); return m_overworldEvents[id]; } @@ -310,7 +310,7 @@ void ALTTPQuest::setDungeonKeys(atUint32 id, atUint8 val) atUint8 ALTTPQuest::dungeonKeys(atUint32 id) const { if (id > m_dungeonKeys.size() - 1) - THROW_INVALID_OPERATION_EXCEPTION("index out of range"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "index out of range"); return m_dungeonKeys[id]; } @@ -407,7 +407,7 @@ void ALTTPQuest::setOldManFlag(atUint32 id, atUint8 val) atUint8 ALTTPQuest::oldManFlag(atUint32 id) { if (id > m_oldManFlags.size() - 1) - THROW_INVALID_OPERATION_EXCEPTION("index out of range"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "index out of range"); return m_oldManFlags[id]; } @@ -443,7 +443,7 @@ void ALTTPQuest::setUnknown1(atUint32 id, atUint8 val) atUint8 ALTTPQuest::unknown1(atUint32 id) { if (id > m_unknown1.size()) - THROW_INVALID_OPERATION_EXCEPTION("index out of range"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0,"index out of range"); return m_unknown1[id]; } @@ -629,7 +629,7 @@ void ALTTPQuest::setDungeonDeathTotal(atUint32 id, atUint16 val) atUint16 ALTTPQuest::dungeonDeathTotal(atUint32 id) const { if (id > m_dungeonDeathTotals.size()) - THROW_INVALID_OPERATION_EXCEPTION("index out of range"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "index out of range"); return m_dungeonDeathTotals[id]; } diff --git a/src/Athena/FileReader.cpp b/src/Athena/FileReader.cpp index 593b175..86a90fb 100644 --- a/src/Athena/FileReader.cpp +++ b/src/Athena/FileReader.cpp @@ -103,7 +103,7 @@ void FileReader::seek(atInt64 pos, SeekOrigin origin) bool FileReader::atEnd() const { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(true, "File not open"); return feof(m_fileHandle) != 0; } @@ -111,7 +111,7 @@ bool FileReader::atEnd() const atUint64 FileReader::position() const { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open"); return ftello64(m_fileHandle); } @@ -119,7 +119,7 @@ atUint64 FileReader::position() const atUint64 FileReader::length() const { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open"); return utility::fileSize(m_filename); } @@ -138,13 +138,13 @@ void FileReader::seekBit(int bit) bool FileReader::readBit() { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File is not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(false, "File is not open for reading"); if (!m_bitValid) { size_t size = fread(&m_currentByte, 1, 1, m_fileHandle); if (size != sizeof(atUint8)) - THROW_IO_EXCEPTION("Error reading from file."); + THROW_IO_EXCEPTION_RETURN(false, "Error reading from file."); m_bitShift = 0; m_bitValid = true; @@ -161,7 +161,7 @@ bool FileReader::readBit() atUint8 FileReader::readUByte() { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading"); m_bitValid = false; atUint8 val = 0; @@ -172,14 +172,14 @@ atUint8 FileReader::readUByte() atInt8 FileReader::readByte() { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading"); return (atInt8)readUByte(); } atUint8* FileReader::readUBytes(atUint64 len) { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(nullptr, "File not open for reading"); m_bitValid = false; atUint8* val = new atUint8[len]; fread(val, 1, len, m_fileHandle); @@ -189,7 +189,7 @@ atUint8* FileReader::readUBytes(atUint64 len) atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading"); m_bitValid = false; return fread(buf, 1, len, m_fileHandle); } @@ -197,14 +197,14 @@ atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len) atInt8* FileReader::readBytes(atUint64 len) { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(nullptr, "File not open for reading"); return (atInt8*)readUBytes(len); } atUint16 FileReader::readUint16() { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading"); m_bitValid = false; atUint16 val; @@ -219,7 +219,7 @@ atUint16 FileReader::readUint16() atInt16 FileReader::readInt16() { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading"); return (atInt16)readUint16(); } @@ -227,7 +227,7 @@ atInt16 FileReader::readInt16() atUint32 FileReader::readUint32() { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading"); m_bitValid = false; atUint32 val; @@ -242,7 +242,7 @@ atUint32 FileReader::readUint32() atInt32 FileReader::readInt32() { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading"); return (atInt32)readUint32(); } @@ -250,7 +250,7 @@ atInt32 FileReader::readInt32() atUint64 FileReader::readUint64() { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading"); m_bitValid = false; atUint64 val; @@ -265,7 +265,7 @@ atUint64 FileReader::readUint64() atInt64 FileReader::readInt64() { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading"); return (atInt64)readUint64(); } @@ -273,7 +273,7 @@ atInt64 FileReader::readInt64() double FileReader::readDouble() { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading"); m_bitValid = false; double val; @@ -288,7 +288,7 @@ double FileReader::readDouble() float FileReader::readFloat() { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading"); m_bitValid = false; float val; @@ -303,7 +303,7 @@ float FileReader::readFloat() bool FileReader::readBool() { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(false, "File not open for reading"); return (readByte() != 0); } @@ -330,7 +330,7 @@ std::string FileReader::readString(atInt32 maxlen) std::string FileReader::readUnicode(atInt32 maxlen) { if (!isOpen()) - THROW_INVALID_OPERATION_EXCEPTION("File not open for reading"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(std::string(), "File not open for reading"); std::string ret; std::vector tmp; diff --git a/src/Athena/Global.cpp b/src/Athena/Global.cpp index 570ec48..80ab8b5 100644 --- a/src/Athena/Global.cpp +++ b/src/Athena/Global.cpp @@ -46,3 +46,17 @@ std::ostream& operator<<(std::ostream& os, const Athena::Endian& endian) } return os; } + + +static atEXCEPTION_HANDLER g_atExceptionHandler = nullptr; + +atEXCEPTION_HANDLER atGetExceptionHandler() +{ + return g_atExceptionHandler; +} + + +void atSetExceptionHandler(atEXCEPTION_HANDLER func) +{ + g_atExceptionHandler = func; +} diff --git a/src/Athena/MemoryReader.cpp b/src/Athena/MemoryReader.cpp index 7c49464..9e1e936 100644 --- a/src/Athena/MemoryReader.cpp +++ b/src/Athena/MemoryReader.cpp @@ -99,17 +99,17 @@ void MemoryReader::seek(atInt64 position, SeekOrigin origin) { case SeekOrigin::Begin: if ((position < 0 || (atInt64)position > (atInt64)m_length)) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position); + THROW_IO_EXCEPTION("Position %0.8X outside stream bounds ", position); m_position = position; break; case SeekOrigin::Current: if ((((atInt64)m_position + position) < 0 || (m_position + position) > m_length)) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position); + THROW_IO_EXCEPTION("Position %0.8X outside stream bounds ", position); m_position += position; break; case SeekOrigin::End: if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length)) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position); + THROW_IO_EXCEPTION("Position %0.8X outside stream bounds ", position); m_position = m_length - position; break; } @@ -175,7 +175,7 @@ bool MemoryReader::readBit() if (!m_data) loadData(); if (m_position > m_length) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", m_position); + THROW_IO_EXCEPTION_RETURN(false, "Position %0.8X outside stream bounds ", m_position); bool ret = (*(atUint8*)(m_data + m_position) & (1 << m_bitPosition)) != 0; @@ -200,7 +200,7 @@ atInt8 MemoryReader::readByte() m_position += sizeof(atUint8); } if (m_position + 1 > m_length) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", m_position); + THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position); return *(atInt8*)(m_data + m_position++); } @@ -219,7 +219,7 @@ atUint8 MemoryReader::readUByte() m_position += sizeof(atUint8); } if (m_position + 1 > m_length) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", m_position); + THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position); return *(atUint8*)(m_data + m_position++); } @@ -236,7 +236,7 @@ atUint8* MemoryReader::readUBytes(atUint64 length) } if (m_position + length > m_length) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", m_position); + THROW_IO_EXCEPTION_RETURN(nullptr, "Position %0.8X outside stream bounds ", m_position); atUint8* ret; ret = new atUint8[length]; @@ -258,7 +258,7 @@ atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length) } if (m_position + length > m_length) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", m_position); + THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position); memcpy(buf, (const atUint8*)(m_data + m_position), length); m_position += length; @@ -277,7 +277,7 @@ atInt16 MemoryReader::readInt16() } if (m_position + sizeof(atInt16) > m_length) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", m_position); + THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position); atInt16 ret = *(atInt16*)(m_data + m_position); m_position += sizeof(atInt16); @@ -306,7 +306,7 @@ atInt32 MemoryReader::readInt32() } if (m_position + sizeof(atInt32) > m_length) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", m_position); + THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position); atInt32 ret = *(atInt32*)(m_data + m_position); m_position += 4; @@ -334,7 +334,7 @@ atInt64 MemoryReader::readInt64() m_position += sizeof(atUint8); } if (m_position + sizeof(atInt64) > m_length) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", m_position); + THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position); atInt64 ret = *(atInt64*)(m_data + m_position); m_position += 8; @@ -363,7 +363,7 @@ float MemoryReader::readFloat() m_position += sizeof(atUint8); } if (m_position + sizeof(float) > m_length) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", m_position); + THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position); float ret = *(float*)(m_data + m_position); m_position += 4; @@ -387,7 +387,7 @@ double MemoryReader::readDouble() m_position += sizeof(atUint8); } if (m_position + sizeof(double) > m_length) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", m_position); + THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position); double ret = *(double*)(m_data + m_position); m_position += 8; @@ -410,7 +410,7 @@ bool MemoryReader::readBool() m_position += sizeof(atUint8); } if (m_position + sizeof(bool) > m_length) - THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", m_position); + THROW_IO_EXCEPTION_RETURN(false, "Position %0.8X outside stream bounds ", m_position); bool ret = *(bool*)(m_data + m_position); m_position += 1; diff --git a/src/Athena/SkywardSwordFile.cpp b/src/Athena/SkywardSwordFile.cpp index cbb0367..5659e91 100644 --- a/src/Athena/SkywardSwordFile.cpp +++ b/src/Athena/SkywardSwordFile.cpp @@ -48,7 +48,7 @@ void SkywardSwordFile::addQuest(Athena::SkywardSwordQuest *q) SkywardSwordQuest *SkywardSwordFile::quest(atUint32 id) { if (id > m_quests.size() - 1) - THROW_INVALID_OPERATION_EXCEPTION("index out of range"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(nullptr, "index out of range"); return m_quests[id]; } diff --git a/src/Athena/SkywardSwordFileReader.cpp b/src/Athena/SkywardSwordFileReader.cpp index 68b91f4..b9cc215 100644 --- a/src/Athena/SkywardSwordFileReader.cpp +++ b/src/Athena/SkywardSwordFileReader.cpp @@ -44,18 +44,18 @@ SkywardSwordFile* SkywardSwordFileReader::read() try { if (base::length() != 0xFBE0) - THROW_INVALID_DATA_EXCEPTION("File not the expected size of 0xFBE0"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr, "File not the expected size of 0xFBE0"); atUint32 magic = base::readUint32(); if (magic != SkywardSwordFile::USMagic && magic != SkywardSwordFile::JAMagic && magic != SkywardSwordFile::EUMagic) - THROW_INVALID_DATA_EXCEPTION("Not a valid Skyward Sword save file"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Not a valid Skyward Sword save file"); base::seek(0x01C, SeekOrigin::Begin); atUint32 headerSize = base::readUint32(); // Seems to be (headerSize - 1) if (headerSize != 0x1D) - THROW_INVALID_DATA_EXCEPTION("Invalid header size, Corrupted data?"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Invalid header size, Corrupted data?"); // Time to read in each slot file = new SkywardSwordFile; diff --git a/src/Athena/SpriteFileReader.cpp b/src/Athena/SpriteFileReader.cpp index 680a864..3ffb079 100644 --- a/src/Athena/SpriteFileReader.cpp +++ b/src/Athena/SpriteFileReader.cpp @@ -47,13 +47,13 @@ Sakura::SpriteFile* SpriteFileReader::readFile() atUint32 magic = base::readUint32(); if (magic != Sakura::SpriteFile::Magic) - THROW_INVALID_DATA_EXCEPTION("Not a valid Sakura Sprite container"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Not a valid Sakura Sprite container"); atUint32 version = base::readUint32(); // TODO: Make this more verbose if (version != Sakura::SpriteFile::Version) - THROW_INVALID_DATA_EXCEPTION("Unsupported version"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Unsupported version"); // After reading in the magic and version we need to load some // metadata about the file. @@ -201,7 +201,7 @@ Sakura::SpriteFile* SpriteFileReader::readFile() sprites[sprite->name().toLower()] = sprite; #endif else - THROW_IO_EXCEPTION("Sprite names cannot be empty"); + THROW_IO_EXCEPTION_RETURN(nullptr,"Sprite names cannot be empty"); } ret->setSprites(sprites); diff --git a/src/Athena/WiiSaveReader.cpp b/src/Athena/WiiSaveReader.cpp index e78e873..f227ab6 100644 --- a/src/Athena/WiiSaveReader.cpp +++ b/src/Athena/WiiSaveReader.cpp @@ -55,21 +55,21 @@ WiiSave* WiiSaveReader::readSave() try { if (length() < 0xF0C0) - THROW_INVALID_DATA_EXCEPTION("Not a valid WiiSave"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Not a valid WiiSave"); WiiBanner* banner = this->readBanner(); if (!banner) - THROW_INVALID_DATA_EXCEPTION("Invalid banner"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Invalid banner"); ret->setBanner(banner); atUint32 bkVer = base::readUint32(); if (bkVer != 0x00000070) - THROW_INVALID_DATA_EXCEPTION("Invalid BacKup header size"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Invalid BacKup header size"); atUint32 bkMagic = base::readUint32(); if (bkMagic != 0x426B0001) - THROW_INVALID_DATA_EXCEPTION("Invalid BacKup header magic"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Invalid BacKup header magic"); atUint32 ngId = base::readUint32(); atUint32 numFiles = base::readUint32(); @@ -151,7 +151,7 @@ WiiBanner* WiiSaveReader::readBanner() std::cerr << std::endl; base::setData(oldData, oldLen); base::seek(oldPos, SeekOrigin::Begin); - THROW_INVALID_DATA_EXCEPTION("MD5 Mismatch"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"MD5 Mismatch"); } // Set the binary reader buffer; base::setData(dec, 0xF0C0); @@ -178,7 +178,7 @@ WiiBanner* WiiSaveReader::readBanner() // Make sure to reset m_reader values back to the old ones. base::setData(oldData, oldLen); base::seek(oldPos, SeekOrigin::Begin); - THROW_INVALID_DATA_EXCEPTION("Invalid Header Magic"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Invalid Header Magic"); } flags = base::readUint32(); diff --git a/src/Athena/WiiSaveWriter.cpp b/src/Athena/WiiSaveWriter.cpp index 72784c4..7e243d0 100644 --- a/src/Athena/WiiSaveWriter.cpp +++ b/src/Athena/WiiSaveWriter.cpp @@ -55,7 +55,7 @@ WiiSaveWriter::WiiSaveWriter(const std::string &filename) bool WiiSaveWriter::writeSave(WiiSave *save, atUint8 *macAddress, atUint32 ngId, atUint8 *ngPriv, atUint8 *ngSig, atUint32 ngKeyId,const std::string &filepath) { if (!save) - THROW_INVALID_OPERATION_EXCEPTION("save cannot be NULL"); + THROW_INVALID_OPERATION_EXCEPTION_RETURN(false, "save cannot be NULL"); if (filepath != "") m_filepath = filepath; diff --git a/src/Athena/ZQuestFileReader.cpp b/src/Athena/ZQuestFileReader.cpp index 683a144..a1752b0 100644 --- a/src/Athena/ZQuestFileReader.cpp +++ b/src/Athena/ZQuestFileReader.cpp @@ -52,12 +52,12 @@ ZQuestFile *ZQuestFileReader::read() magic = base::readUint32(); if ((magic & 0x00FFFFFF) != (ZQuestFile::Magic & 0x00FFFFFF)) - THROW_INVALID_DATA_EXCEPTION("Not a valid ZQuest file"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Not a valid ZQuest file"); version = base::readUint32(); if (version > ZQuestFile::Version) - THROW_INVALID_DATA_EXCEPTION("Unsupported ZQuest version"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Unsupported ZQuest version"); compressedLen = base::readUint32(); uncompressedLen = base::readUint32(); @@ -91,7 +91,7 @@ ZQuestFile *ZQuestFileReader::read() if (checksum != Athena::Checksums::crc32(data, compressedLen)) { delete[] data; - THROW_INVALID_DATA_EXCEPTION("Checksum mismatch, data corrupt"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Checksum mismatch, data corrupt"); } } else @@ -109,7 +109,7 @@ ZQuestFile *ZQuestFileReader::read() { delete[] dst; delete[] data; - THROW_INVALID_DATA_EXCEPTION("Error decompressing data"); + THROW_INVALID_DATA_EXCEPTION_RETURN(nullptr,"Error decompressing data"); } delete[] data;