diff --git a/src/map.cpp b/src/map.cpp index 252f20b607..3bee6ab97e 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -387,3 +387,43 @@ uint GetClosestWaterDistance(TileIndex tile, bool water) return max_dist; } + +char *DumpTileInfo(char *b, const char *last, TileIndex tile) +{ + static const char *tile_type_names[16] = { + "MP_CLEAR", + "MP_RAILWAY", + "MP_ROAD", + "MP_HOUSE", + "MP_TREES", + "MP_STATION", + "MP_WATER", + "MP_VOID", + "MP_INDUSTRY", + "MP_TUNNELBRIDGE", + "MP_OBJECT", + "INVALID_B", + "INVALID_C", + "INVALID_D", + "INVALID_E", + "INVALID_F", + }; + + if (tile == INVALID_TILE) { + b += seprintf(b, last, "tile: %X (INVALID_TILE)", tile); + } else { + b += seprintf(b, last, "tile: %X (%u x %u)", tile, TileX(tile), TileY(tile)); + } + if (!_m || !_me) { + b += seprintf(b, last, ", NO MAP ALLOCATED"); + } else { + if (tile >= MapSize()) { + b += seprintf(b, last, ", TILE OUTSIDE MAP"); + } else { + b += seprintf(b, last, ", type: %02X (%s), height: %02X, data: %02X %04X %02X %02X %02X %02X %02X", + _m[tile].type, tile_type_names[GB(_m[tile].type, 4, 4)], _m[tile].height, + _m[tile].m1, _m[tile].m2, _m[tile].m3, _m[tile].m4, _m[tile].m5, _me[tile].m6, _me[tile].m7); + } + } + return b; +} diff --git a/src/map_func.h b/src/map_func.h index 9198c2cd1f..8c2752d95b 100644 --- a/src/map_func.h +++ b/src/map_func.h @@ -426,4 +426,6 @@ static inline TileIndex RandomTileSeed(uint32 r) uint GetClosestWaterDistance(TileIndex tile, bool water); +char *DumpTileInfo(char *b, const char *last, TileIndex tile); + #endif /* MAP_FUNC_H */ diff --git a/src/openttd.cpp b/src/openttd.cpp index 681d4f8b37..e9a52d0f81 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -124,7 +124,7 @@ void CDECL error(const char *s, ...) abort(); } -void CDECL assert_msg_error(int line, const char *file, const char *expr, const char *str, ...) +void CDECL assert_msg_error(int line, const char *file, const char *expr, const char *extra, const char *str, ...) { va_list va; char buf[2048]; @@ -132,6 +132,10 @@ void CDECL assert_msg_error(int line, const char *file, const char *expr, const char *b = buf; b += seprintf(b, lastof(buf), "Assertion failed at line %i of %s: %s\n\t", line, file, expr); + if (extra != nullptr) { + b += seprintf(b, lastof(buf), "%s\n\t", extra); + } + va_start(va, str); vseprintf(b, lastof(buf), str, va); va_end(va); @@ -143,6 +147,12 @@ void CDECL assert_msg_error(int line, const char *file, const char *expr, const abort(); } +const char *assert_tile_info(uint32 tile) { + static char buffer[128]; + DumpTileInfo(buffer, lastof(buffer), tile); + return buffer; +} + /** * Shows some information on the console/a popup box depending on the OS. * @param str the text to show. diff --git a/src/stdafx.h b/src/stdafx.h index 5d15ecf810..8c33b5e9cc 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -458,7 +458,8 @@ assert_compile(SIZE_MAX >= UINT32_MAX); void NORETURN CDECL usererror(const char *str, ...) WARN_FORMAT(1, 2); void NORETURN CDECL error(const char *str, ...) WARN_FORMAT(1, 2); -void NORETURN CDECL assert_msg_error(int line, const char *file, const char *expr, const char *str, ...) WARN_FORMAT(4, 5); +void NORETURN CDECL assert_msg_error(int line, const char *file, const char *expr, const char *extra, const char *str, ...) WARN_FORMAT(5, 6); +const char *assert_tile_info(uint32 tile); #define NOT_REACHED() error("NOT_REACHED triggered at line %i of %s", __LINE__, __FILE__) /* For non-debug builds with assertions enabled use the special assertion handler: @@ -473,9 +474,13 @@ void NORETURN CDECL assert_msg_error(int line, const char *file, const char *exp /* Asserts are enabled if NDEBUG isn't defined, or if we are using MSVC and WITH_ASSERT is defined. */ #if !defined(NDEBUG) || (defined(_MSC_VER) && defined(WITH_ASSERT)) #define OTTD_ASSERT - #define assert_msg(expression, ...) if (unlikely(!(expression))) assert_msg_error(__LINE__, __FILE__, #expression, __VA_ARGS__); + #define assert_msg(expression, ...) if (unlikely(!(expression))) assert_msg_error(__LINE__, __FILE__, #expression, nullptr, __VA_ARGS__); + #define assert_msg_tile(expression, tile, ...) if (unlikely(!(expression))) assert_msg_error(__LINE__, __FILE__, #expression, assert_tile_info(tile), __VA_ARGS__); + #define assert_tile(expression, tile) if (unlikely(!(expression))) error("Assertion failed at line %i of %s: %s\n\t%s", __LINE__, __FILE__, #expression, assert_tile_info(tile)); #else #define assert_msg(expression, ...) + #define assert_msg_tile(expression, tile, ...) + #define assert_tile(expression, tile) #endif #if defined(MORPHOS) || defined(__NDS__) || defined(__DJGPP__)