diff --git a/src/fios.h b/src/fios.h index e22e14c0b5..b17ab8e4ce 100644 --- a/src/fios.h +++ b/src/fios.h @@ -48,6 +48,9 @@ struct LoadCheckData { struct LoggedAction *gamelog_action; ///< Gamelog actions uint gamelog_actions; ///< Number of gamelog actions + bool want_debug_log_data = false; + std::string debug_log_data; + LoadCheckData() : error_data(nullptr), grfconfig(nullptr), grf_compatibility(GLC_NOT_FOUND), gamelog_action(nullptr), gamelog_actions(0) { diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index fe4fa469fd..8d1da7aa75 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -67,6 +67,8 @@ void LoadCheckData::Clear() this->gamelog_actions = 0; ClearGRFConfigList(&this->grfconfig); + + this->debug_log_data.clear(); } /** Load game/scenario with optional content download */ diff --git a/src/openttd.cpp b/src/openttd.cpp index e312934d60..012c1376e9 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -322,6 +322,40 @@ static void WriteSavegameInfo(const char *name) #endif } +static void WriteSavegameDebugData(const char *name) +{ + char *buf = MallocT(4096); + char *buflast = buf + 4095; + char *p = buf; + auto bump_size = [&]() { + size_t offset = p - buf; + size_t new_size = buflast - buf + 1 + 4096; + buf = ReallocT(buf, new_size); + buflast = buf + new_size - 1; + p = buf + offset; + }; + p += seprintf(p, buflast, "Name: %s\n", name); + if (_load_check_data.debug_log_data.size()) { + p += seprintf(p, buflast, "%u bytes of debug data in savegame\n", (uint) _load_check_data.debug_log_data.size()); + std::string buffer = _load_check_data.debug_log_data; + ProcessLineByLine(const_cast(buffer.data()), [&](const char *line) { + if (buflast - p <= 1024) bump_size(); + p += seprintf(p, buflast, "> %s\n", line); + }); + } else { + p += seprintf(p, buflast, "No debug data in savegame\n"); + } + + /* ShowInfo put output to stderr, but version information should go + * to stdout; this is the only exception */ +#if !defined(_WIN32) + printf("%s\n", buf); +#else + ShowInfo(buf); +#endif + free(buf); +} + /** * Extract the resolution from the given string and store @@ -611,6 +645,7 @@ static const OptionData _options[] = { GETOPT_SHORT_VALUE('c'), GETOPT_SHORT_NOVAL('x'), GETOPT_SHORT_VALUE('q'), + GETOPT_SHORT_VALUE('K'), GETOPT_SHORT_NOVAL('h'), GETOPT_SHORT_VALUE('J'), GETOPT_END() @@ -729,7 +764,8 @@ int openttd_main(int argc, char *argv[]) scanner->generation_seed = InteractiveRandom(); } break; - case 'q': { + case 'q': + case 'K': { DeterminePaths(argv[0]); if (StrEmpty(mgo.opt)) { ret = 1; @@ -741,6 +777,7 @@ int openttd_main(int argc, char *argv[]) FiosGetSavegameListCallback(SLO_LOAD, mgo.opt, strrchr(mgo.opt, '.'), title, lastof(title)); _load_check_data.Clear(); + if (i == 'K') _load_check_data.want_debug_log_data = true; SaveOrLoadResult res = SaveOrLoad(mgo.opt, SLO_CHECK, DFT_GAME_FILE, SAVE_DIR, false); if (res != SL_OK || _load_check_data.HasErrors()) { fprintf(stderr, "Failed to open savegame\n"); @@ -754,7 +791,11 @@ int openttd_main(int argc, char *argv[]) goto exit_noshutdown; } - WriteSavegameInfo(title); + if (i == 'q') { + WriteSavegameInfo(title); + } else { + WriteSavegameDebugData(title); + } goto exit_noshutdown; } diff --git a/src/saveload/debug_sl.cpp b/src/saveload/debug_sl.cpp index e4c163495d..5a41516066 100644 --- a/src/saveload/debug_sl.cpp +++ b/src/saveload/debug_sl.cpp @@ -14,6 +14,7 @@ #include "../debug.h" #include "saveload.h" #include "saveload_buffer.h" +#include "../fios.h" #include "../safeguards.h" @@ -37,6 +38,19 @@ static void Load_DBGL() } } +static void Check_DBGL() +{ + if (!_load_check_data.want_debug_log_data) { + SlSkipBytes(SlGetFieldLength()); + return; + } + size_t length = SlGetFieldLength(); + if (length) { + _load_check_data.debug_log_data.resize(length); + ReadBuffer::GetCurrent()->CopyBytes(reinterpret_cast(const_cast(_load_check_data.debug_log_data.data())), length); + } +} + extern const ChunkHandler _debug_chunk_handlers[] = { - { 'DBGL', Save_DBGL, Load_DBGL, nullptr, nullptr, CH_RIFF | CH_LAST}, + { 'DBGL', Save_DBGL, Load_DBGL, nullptr, Check_DBGL, CH_RIFF | CH_LAST}, };