diff --git a/src/openrct2/core/Guard.cpp b/src/openrct2/core/Guard.cpp index 8419e782f0..94babbc74d 100644 --- a/src/openrct2/core/Guard.cpp +++ b/src/openrct2/core/Guard.cpp @@ -45,6 +45,8 @@ namespace Guard #endif ; + static std::optional _lastAssertMessage = std::nullopt; + #ifdef _WIN32 static void GetAssertMessage(char* buffer, size_t bufferSize, const char* formattedMessage); static void ForceCrash(); @@ -84,6 +86,11 @@ namespace Guard Console::Error::WriteLine(formattedMessage); } + if (formattedMessage != nullptr) + { + _lastAssertMessage = std::make_optional(formattedMessage); + } + #ifdef DEBUG Debug::Break(); #endif @@ -126,6 +133,11 @@ namespace Guard Assert_VA(false, message, args); } + std::optional GetLastAssertMessage() + { + return _lastAssertMessage; + } + #ifdef _WIN32 static void GetAssertMessage(char* buffer, size_t bufferSize, const char* formattedMessage) { diff --git a/src/openrct2/core/Guard.hpp b/src/openrct2/core/Guard.hpp index 5556232fd5..f8b696f30e 100644 --- a/src/openrct2/core/Guard.hpp +++ b/src/openrct2/core/Guard.hpp @@ -10,8 +10,10 @@ #pragma once #include +#include #include #include +#include void openrct2_assert_fwd(bool expression, const char* message, ...); @@ -41,6 +43,8 @@ namespace Guard void Fail(const char* message = nullptr, ...); void Fail_VA(const char* message, va_list args); + std::optional GetLastAssertMessage(); + template static void ArgumentNotNull(T* argument, const char* message = nullptr, ...) { va_list args; diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index e1367cc327..2e4f9ef343 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -1596,6 +1596,15 @@ static int32_t cc_terminate([[maybe_unused]] InteractiveConsole& console, [[mayb } #pragma warning(pop) +static int32_t cc_assert([[maybe_unused]] InteractiveConsole& console, [[maybe_unused]] const arguments_t& argv) +{ + if (!argv.empty()) + Guard::Assert(false, "%s", argv[0].c_str()); + else + Guard::Assert(false); + return 0; +} + using console_command_func = int32_t (*)(InteractiveConsole& console, const arguments_t& argv); struct console_command { @@ -1655,6 +1664,7 @@ static constexpr const utf8* console_window_table[] = { static constexpr const console_command console_command_table[] = { { "abort", cc_abort, "Calls std::abort(), for testing purposes only.", "abort" }, + { "assert", cc_assert, "Triggers assertion failure, for testing purposes only", "assert" }, { "clear", cc_clear, "Clears the console.", "clear" }, { "close", cc_close, "Closes the console.", "close" }, { "date", cc_for_date, "Sets the date to a given date.", "Format [ [ ]]." }, diff --git a/src/openrct2/platform/Crash.cpp b/src/openrct2/platform/Crash.cpp index b6a5db9fac..40d11e9ebe 100644 --- a/src/openrct2/platform/Crash.cpp +++ b/src/openrct2/platform/Crash.cpp @@ -27,6 +27,7 @@ # include "../Version.h" # include "../config/Config.h" # include "../core/Console.hpp" +# include "../core/Guard.hpp" # include "../core/String.hpp" # include "../interface/Screenshot.h" # include "../localisation/Language.h" @@ -70,6 +71,13 @@ static bool UploadMinidump(const std::map& files, in { parameters[L"commit"] = String::ToWideChar(gVersionInfoFull); } + + auto assertMsg = Guard::GetLastAssertMessage(); + if (assertMsg) + { + parameters[L"assert_failure"] = String::ToWideChar(*assertMsg); + } + int timeout = 10000; bool success = google_breakpad::HTTPUpload::SendRequest(url, parameters, files, &timeout, &response, &error); wprintf(L"Success = %d, error = %d, response = %s\n", success, error, response.c_str());