From 5a9790a19656d278ae0e3f07dda829b6400f4d3e Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 21 May 2019 01:49:40 +0100 Subject: [PATCH] Store crash/desync logs in crash/desync savegame Add console command to dump loaded debug log --- projects/openttd_vs140.vcxproj | 1 + projects/openttd_vs140.vcxproj.filters | 3 ++ projects/openttd_vs141.vcxproj | 1 + projects/openttd_vs141.vcxproj.filters | 3 ++ projects/openttd_vs142.vcxproj | 1 + projects/openttd_vs142.vcxproj.filters | 3 ++ source.list | 1 + src/console_cmds.cpp | 13 ++++++++ src/crashlog.cpp | 3 ++ src/debug.cpp | 3 ++ src/debug.h | 4 +++ src/misc.cpp | 1 + src/openttd.cpp | 1 + src/os/macosx/crashlog_osx.cpp | 2 ++ src/os/windows/crashlog_win.cpp | 3 ++ src/saveload/debug_sl.cpp | 42 ++++++++++++++++++++++++++ src/saveload/extended_ver_sl.cpp | 1 + src/saveload/extended_ver_sl.h | 1 + src/saveload/saveload.cpp | 2 ++ src/saveload/saveload_buffer.h | 2 +- 20 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/saveload/debug_sl.cpp diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj index 7c0de35422..dbd1e67191 100644 --- a/projects/openttd_vs140.vcxproj +++ b/projects/openttd_vs140.vcxproj @@ -938,6 +938,7 @@ + diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters index ed2e78db64..187ef0e7c0 100644 --- a/projects/openttd_vs140.vcxproj.filters +++ b/projects/openttd_vs140.vcxproj.filters @@ -1908,6 +1908,9 @@ Save/Load handlers + + Save/Load handlers + Save/Load handlers diff --git a/projects/openttd_vs141.vcxproj b/projects/openttd_vs141.vcxproj index 8d74580569..2bd1670b37 100644 --- a/projects/openttd_vs141.vcxproj +++ b/projects/openttd_vs141.vcxproj @@ -938,6 +938,7 @@ + diff --git a/projects/openttd_vs141.vcxproj.filters b/projects/openttd_vs141.vcxproj.filters index ed2e78db64..187ef0e7c0 100644 --- a/projects/openttd_vs141.vcxproj.filters +++ b/projects/openttd_vs141.vcxproj.filters @@ -1908,6 +1908,9 @@ Save/Load handlers + + Save/Load handlers + Save/Load handlers diff --git a/projects/openttd_vs142.vcxproj b/projects/openttd_vs142.vcxproj index c786e641f1..cffc03b69d 100644 --- a/projects/openttd_vs142.vcxproj +++ b/projects/openttd_vs142.vcxproj @@ -938,6 +938,7 @@ + diff --git a/projects/openttd_vs142.vcxproj.filters b/projects/openttd_vs142.vcxproj.filters index ed2e78db64..187ef0e7c0 100644 --- a/projects/openttd_vs142.vcxproj.filters +++ b/projects/openttd_vs142.vcxproj.filters @@ -1908,6 +1908,9 @@ Save/Load handlers + + Save/Load handlers + Save/Load handlers diff --git a/source.list b/source.list index 0bd34c426c..2dc1659aec 100644 --- a/source.list +++ b/source.list @@ -652,6 +652,7 @@ saveload/cargomonitor_sl.cpp saveload/cargopacket_sl.cpp saveload/cheat_sl.cpp saveload/company_sl.cpp +saveload/debug_sl.cpp saveload/depot_sl.cpp saveload/economy_sl.cpp saveload/engine_sl.cpp diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 923cd19d49..84ada30d93 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -2054,6 +2054,18 @@ DEF_CONSOLE_CMD(ConDumpGameEvents) return true; } +DEF_CONSOLE_CMD(ConDumpLoadDebugLog) +{ + if (argc == 0) { + IConsoleHelp("Dump load debug log."); + return true; + } + + std::string dbgl = _loadgame_DBGL_data; + PrintLineByLine(const_cast(_loadgame_DBGL_data.c_str())); + return true; +} + DEF_CONSOLE_CMD(ConCheckCaches) { if (argc == 0) { @@ -2329,6 +2341,7 @@ void IConsoleStdLibRegister() IConsoleCmdRegister("dump_veh_stats", ConVehicleStats, nullptr, true); IConsoleCmdRegister("dump_map_stats", ConMapStats, nullptr, true); IConsoleCmdRegister("dump_game_events", ConDumpGameEvents, nullptr, true); + IConsoleCmdRegister("dump_load_debug_log", ConDumpLoadDebugLog, nullptr, true); IConsoleCmdRegister("check_caches", ConCheckCaches, nullptr, true); /* NewGRF development stuff */ diff --git a/src/crashlog.cpp b/src/crashlog.cpp index 1e5347dfd9..9582551884 100644 --- a/src/crashlog.cpp +++ b/src/crashlog.cpp @@ -587,6 +587,7 @@ bool CrashLog::MakeCrashLog() const } SetScreenshotAuxiliaryText("Crash Log", buffer); + _savegame_DBGL_data = buffer; if (IsNonMainThread()) { printf("Asking main thread to write crash savegame and screenshot...\n\n"); @@ -633,6 +634,7 @@ bool CrashLog::MakeDesyncCrashLog() const ret = false; } + _savegame_DBGL_data = buffer; bret = this->WriteSavegame(filename, lastof(filename), name_buffer); if (bret) { printf("Desync savegame written to %s. Please add this file and the last (auto)save to any bug reports.\n\n", filename); @@ -640,6 +642,7 @@ bool CrashLog::MakeDesyncCrashLog() const ret = false; printf("Writing desync savegame failed. Please attach the last (auto)save to any bug reports.\n\n"); } + _savegame_DBGL_data = nullptr; if (!(_screen.width < 1 || _screen.height < 1 || _screen.dst_ptr == nullptr)) { SetScreenshotAuxiliaryText("Desync Log", buffer); diff --git a/src/debug.cpp b/src/debug.cpp index 6ae3041876..210a150012 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -54,6 +54,9 @@ int _debug_sound_level; int _debug_random_level; #endif +const char *_savegame_DBGL_data = nullptr; +std::string _loadgame_DBGL_data; + uint32 _realtime_tick = 0; struct DebugLevel { diff --git a/src/debug.h b/src/debug.h index 3121a9bf9f..2f8ce7db2d 100644 --- a/src/debug.h +++ b/src/debug.h @@ -14,6 +14,7 @@ #include "cpu.h" #include +#include /* Debugging messages policy: * These should be the severities used for direct DEBUG() calls @@ -58,6 +59,9 @@ extern int _debug_sound_level; extern int _debug_random_level; #endif +extern const char *_savegame_DBGL_data; +extern std::string _loadgame_DBGL_data; + void CDECL debug(const char *dbg, const char *format, ...) WARN_FORMAT(2, 3); char *DumpDebugFacilityNames(char *buf, char *last); diff --git a/src/misc.cpp b/src/misc.cpp index 0768ddbbc0..d9a7534a8b 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -81,6 +81,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin _thd.redsq = INVALID_TILE; _game_events_since_load = (GameEventFlags) 0; _game_events_overall = (GameEventFlags) 0; + _loadgame_DBGL_data.clear(); if (reset_settings) MakeNewgameSettingsLive(); if (reset_date) { diff --git a/src/openttd.cpp b/src/openttd.cpp index 80e371fa3e..6dced32c05 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -384,6 +384,7 @@ static void ShutdownGame() _game_events_since_load = (GameEventFlags) 0; _game_events_overall = (GameEventFlags) 0; + _loadgame_DBGL_data.clear(); } /** diff --git a/src/os/macosx/crashlog_osx.cpp b/src/os/macosx/crashlog_osx.cpp index 7be858a424..a70d8acf5b 100644 --- a/src/os/macosx/crashlog_osx.cpp +++ b/src/os/macosx/crashlog_osx.cpp @@ -16,6 +16,7 @@ #include "../../saveload/saveload.h" #include "../../thread.h" #include "../../screenshot.h" +#include "../../debug.h" #include "macos.h" #include @@ -427,6 +428,7 @@ public: } printf("Writing crash savegame...\n"); + _savegame_DBGL_data = buffer; if (!this->WriteSavegame(filename_save, lastof(filename_save))) { filename_save[0] = '\0'; ret = false; diff --git a/src/os/windows/crashlog_win.cpp b/src/os/windows/crashlog_win.cpp index 988ea922a3..1b4db6d287 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -23,6 +23,7 @@ #include "../../video/video_driver.hpp" #include "../../openttd.h" #include "../../screenshot.h" +#include "../../debug.h" #if defined(WITH_DEMANGLE) #include #endif @@ -708,6 +709,7 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA CrashLog::AfterCrashLogCleanup(); ExitProcess(2); case 13: // Emergency save + _savegame_DBGL_data = CrashLogWindows::current->crashlog; char filename[MAX_PATH]; if (CrashLogWindows::current->WriteSavegame(filename, lastof(filename))) { size_t len = _tcslen(_save_succeeded) + _tcslen(OTTD2FS(filename)) + 1; @@ -717,6 +719,7 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA } else { MessageBox(wnd, _T("Save failed"), _T("Save failed"), MB_ICONINFORMATION); } + _savegame_DBGL_data = nullptr; break; case 15: // Expand window to show crash-message _expanded ^= 1; diff --git a/src/saveload/debug_sl.cpp b/src/saveload/debug_sl.cpp new file mode 100644 index 0000000000..e4c163495d --- /dev/null +++ b/src/saveload/debug_sl.cpp @@ -0,0 +1,42 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file debug_sl.cpp Code handling saving and loading of debugging information */ + +#include "../stdafx.h" + +#include "../debug.h" +#include "saveload.h" +#include "saveload_buffer.h" + +#include "../safeguards.h" + +static void Save_DBGL() +{ + if (_savegame_DBGL_data != nullptr) { + size_t length = strlen(_savegame_DBGL_data); + SlSetLength(length); + MemoryDumper::GetCurrent()->CopyBytes(reinterpret_cast(_savegame_DBGL_data), length); + } else { + SlSetLength(0); + } +} + +static void Load_DBGL() +{ + size_t length = SlGetFieldLength(); + if (length) { + _loadgame_DBGL_data.resize(length); + ReadBuffer::GetCurrent()->CopyBytes(reinterpret_cast(const_cast(_loadgame_DBGL_data.data())), length); + } +} + +extern const ChunkHandler _debug_chunk_handlers[] = { + { 'DBGL', Save_DBGL, Load_DBGL, nullptr, nullptr, CH_RIFF | CH_LAST}, +}; diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 3905aa59e2..8a9d8b5b76 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -106,6 +106,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_RV_OVERTAKING, XSCF_NULL, 1, 1, "roadveh_overtaking", nullptr, nullptr, nullptr }, { XSLFI_LINKGRAPH_MODES, XSCF_NULL, 1, 1, "linkgraph_modes", nullptr, nullptr, nullptr }, { XSLFI_GAME_EVENTS, XSCF_NULL, 1, 1, "game_events", nullptr, nullptr, nullptr }, + { XSLFI_DEBUG, XSCF_IGNORABLE_ALL, 1, 1, "debug", nullptr, nullptr, "DBGL" }, { XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker }; diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index f0bb6fe095..41fc298555 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -73,6 +73,7 @@ enum SlXvFeatureIndex { XSLFI_RV_OVERTAKING, ///< Roadvehicle overtaking XSLFI_LINKGRAPH_MODES, ///< Linkgraph additional distribution modes XSLFI_GAME_EVENTS, ///< Game event flags + XSLFI_DEBUG, ///< Debugging info XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index e8929fc4b4..370eb821b8 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -274,6 +274,7 @@ extern const ChunkHandler _template_replacement_chunk_handlers[]; extern const ChunkHandler _template_vehicle_chunk_handlers[]; extern const ChunkHandler _bridge_signal_chunk_handlers[]; extern const ChunkHandler _tunnel_chunk_handlers[]; +extern const ChunkHandler _debug_chunk_handlers[]; /** Array of all chunks in a savegame, \c nullptr terminated. */ static const ChunkHandler * const _chunk_handlers[] = { @@ -318,6 +319,7 @@ static const ChunkHandler * const _chunk_handlers[] = { _template_vehicle_chunk_handlers, _bridge_signal_chunk_handlers, _tunnel_chunk_handlers, + _debug_chunk_handlers, nullptr, }; diff --git a/src/saveload/saveload_buffer.h b/src/saveload/saveload_buffer.h index 3565be6dde..01d914b315 100644 --- a/src/saveload/saveload_buffer.h +++ b/src/saveload/saveload_buffer.h @@ -197,7 +197,7 @@ struct MemoryDumper { *this->buf++ = b; } - inline void CopyBytes(byte *ptr, size_t length) + inline void CopyBytes(const byte *ptr, size_t length) { while (length) { if (unlikely(this->buf == this->bufe)) {