diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index e4cdacad26..3dd21c2331 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -2133,6 +2133,18 @@ DEF_CONSOLE_CMD(ConDumpLoadDebugLog) return true; } +DEF_CONSOLE_CMD(ConDumpLoadDebugConfig) +{ + if (argc == 0) { + IConsoleHelp("Dump load debug config."); + return true; + } + + std::string dbgc = _loadgame_DBGC_data; + PrintLineByLine(const_cast(dbgc.c_str())); + return true; +} + DEF_CONSOLE_CMD(ConCheckCaches) { if (argc == 0) { @@ -2647,6 +2659,7 @@ void IConsoleStdLibRegister() IConsoleCmdRegister("dump_st_flow_stats", ConStFlowStats, nullptr, true); IConsoleCmdRegister("dump_game_events", ConDumpGameEvents, nullptr, true); IConsoleCmdRegister("dump_load_debug_log", ConDumpLoadDebugLog, nullptr, true); + IConsoleCmdRegister("dump_load_debug_config", ConDumpLoadDebugConfig, nullptr, true); IConsoleCmdRegister("check_caches", ConCheckCaches, nullptr, true); IConsoleCmdRegister("show_town_window", ConShowTownWindow, nullptr, true); IConsoleCmdRegister("show_station_window", ConShowStationWindow, nullptr, true); diff --git a/src/crashlog.cpp b/src/crashlog.cpp index 23e7d932ca..7122e0d3c6 100644 --- a/src/crashlog.cpp +++ b/src/crashlog.cpp @@ -662,6 +662,7 @@ bool CrashLog::MakeCrashLog() const SetScreenshotAuxiliaryText("Crash Log", buffer); _savegame_DBGL_data = buffer; + _save_DBGC_data = true; if (IsNonMainThread()) { printf("Asking main thread to write crash savegame and screenshot...\n\n"); @@ -716,6 +717,7 @@ bool CrashLog::MakeDesyncCrashLog(const std::string *log_in, std::string *log_ou } _savegame_DBGL_data = buffer; + _save_DBGC_data = true; 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); @@ -724,6 +726,7 @@ bool CrashLog::MakeDesyncCrashLog(const std::string *log_in, std::string *log_ou printf("Writing desync savegame failed. Please attach the last (auto)save to any bug reports.\n\n"); } _savegame_DBGL_data = nullptr; + _save_DBGC_data = false; 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 31951d03c8..271774a5e8 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -56,6 +56,8 @@ int _debug_random_level; const char *_savegame_DBGL_data = nullptr; std::string _loadgame_DBGL_data; +bool _save_DBGC_data = false; +std::string _loadgame_DBGC_data; uint32 _realtime_tick = 0; diff --git a/src/debug.h b/src/debug.h index 62e8ff8dbc..9a90e96762 100644 --- a/src/debug.h +++ b/src/debug.h @@ -59,6 +59,8 @@ extern int _debug_random_level; extern const char *_savegame_DBGL_data; extern std::string _loadgame_DBGL_data; +extern bool _save_DBGC_data; +extern std::string _loadgame_DBGC_data; void CDECL debug(const char *dbg, const char *format, ...) WARN_FORMAT(2, 3); diff --git a/src/fios.h b/src/fios.h index 363d3563d9..78e3c1a1ce 100644 --- a/src/fios.h +++ b/src/fios.h @@ -46,8 +46,9 @@ struct LoadCheckData { struct LoggedAction *gamelog_action; ///< Gamelog actions uint gamelog_actions; ///< Number of gamelog actions - bool want_debug_log_data = false; + bool want_debug_data = false; std::string debug_log_data; + std::string debug_config_data; LoadCheckData() : error_data(nullptr), grfconfig(nullptr), grf_compatibility(GLC_NOT_FOUND), gamelog_action(nullptr), gamelog_actions(0) diff --git a/src/ini_load.cpp b/src/ini_load.cpp index dd72831308..0ab4967736 100644 --- a/src/ini_load.cpp +++ b/src/ini_load.cpp @@ -207,7 +207,7 @@ void IniLoadFile::RemoveGroup(const char *name) * @param subdir the sub directory to load the file from. * @pre nothing has been loaded yet. */ -void IniLoadFile::LoadFromDisk(const char *filename, Subdirectory subdir) +void IniLoadFile::LoadFromDisk(const char *filename, Subdirectory subdir, std::string *save) { assert(this->last_group == &this->group); @@ -222,10 +222,16 @@ void IniLoadFile::LoadFromDisk(const char *filename, Subdirectory subdir) FILE *in = this->OpenFile(filename, subdir, &end); if (in == nullptr) return; + if (save != nullptr) { + save->clear(); + save->reserve(end); + } + end += ftell(in); /* for each line in the file */ while ((size_t)ftell(in) < end && fgets(buffer, sizeof(buffer), in)) { + if (save != nullptr) *save += buffer; char c, *s; /* trim whitespace from the left side */ for (s = buffer; *s == ' ' || *s == '\t'; s++) {} diff --git a/src/ini_type.h b/src/ini_type.h index 679969efda..aefa0a5e64 100644 --- a/src/ini_type.h +++ b/src/ini_type.h @@ -62,7 +62,7 @@ struct IniLoadFile { IniGroup *GetGroup(const char *name, size_t len = 0, bool create_new = true); void RemoveGroup(const char *name); - void LoadFromDisk(const char *filename, Subdirectory subdir); + void LoadFromDisk(const char *filename, Subdirectory subdir, std::string *save = nullptr); /** * Open the INI file. diff --git a/src/openttd.cpp b/src/openttd.cpp index e8f2f6baf5..fdcbb9d249 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -335,14 +335,24 @@ static void WriteSavegameDebugData(const char *name) }; 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()); + p += seprintf(p, buflast, "%u bytes of debug log 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"); + p += seprintf(p, buflast, "No debug log data in savegame\n"); + } + if (_load_check_data.debug_config_data.size()) { + p += seprintf(p, buflast, "%u bytes of debug config data in savegame\n", (uint) _load_check_data.debug_config_data.size()); + std::string buffer = _load_check_data.debug_config_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 config data in savegame\n"); } /* ShowInfo put output to stderr, but version information should go @@ -431,6 +441,7 @@ static void ShutdownGame() _game_load_tick_skip_counter = 0; _game_load_time = 0; _loadgame_DBGL_data.clear(); + _loadgame_DBGC_data.clear(); } /** @@ -777,7 +788,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; + if (i == 'K') _load_check_data.want_debug_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"); diff --git a/src/os/macosx/crashlog_osx.cpp b/src/os/macosx/crashlog_osx.cpp index b0b1df6cf2..9beb7597a7 100644 --- a/src/os/macosx/crashlog_osx.cpp +++ b/src/os/macosx/crashlog_osx.cpp @@ -401,6 +401,7 @@ public: printf("Writing crash savegame...\n"); _savegame_DBGL_data = buffer; + _save_DBGC_data = true; 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 a25c60a15b..3054ef8e32 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -829,6 +829,7 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA ExitProcess(2); case 13: // Emergency save _savegame_DBGL_data = CrashLogWindows::current->crashlog; + _save_DBGC_data = true; char filename[MAX_PATH]; if (CrashLogWindows::current->WriteSavegame(filename, lastof(filename))) { size_t len = _tcslen(_save_succeeded) + _tcslen(OTTD2FS(filename)) + 1; @@ -839,6 +840,7 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA MessageBox(wnd, _T("Save failed"), _T("Save failed"), MB_ICONINFORMATION); } _savegame_DBGL_data = nullptr; + _save_DBGC_data = false; 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 index ac964aa30c..fca47f5565 100644 --- a/src/saveload/debug_sl.cpp +++ b/src/saveload/debug_sl.cpp @@ -38,7 +38,7 @@ static void Load_DBGL() static void Check_DBGL() { - if (!_load_check_data.want_debug_log_data) { + if (!_load_check_data.want_debug_data) { SlSkipBytes(SlGetFieldLength()); return; } @@ -49,6 +49,44 @@ static void Check_DBGL() } } +static void Save_DBGC() +{ + extern std::string _config_file_text; + const char header[] = "*** openttd.cfg start ***\n"; + const char footer[] = "*** openttd.cfg end ***\n"; + if (_save_DBGC_data) { + SlSetLength(lengthof(header) + _config_file_text.size() + lengthof(footer) - 2); + MemoryDumper::GetCurrent()->CopyBytes(reinterpret_cast(header), lengthof(header) - 1); + MemoryDumper::GetCurrent()->CopyBytes(reinterpret_cast(_config_file_text.data()), _config_file_text.size()); + MemoryDumper::GetCurrent()->CopyBytes(reinterpret_cast(footer), lengthof(footer) - 1); + } else { + SlSetLength(0); + } +} + +static void Load_DBGC() +{ + size_t length = SlGetFieldLength(); + if (length) { + _loadgame_DBGC_data.resize(length); + ReadBuffer::GetCurrent()->CopyBytes(reinterpret_cast(const_cast(_loadgame_DBGC_data.data())), length); + } +} + +static void Check_DBGC() +{ + if (!_load_check_data.want_debug_data) { + SlSkipBytes(SlGetFieldLength()); + return; + } + size_t length = SlGetFieldLength(); + if (length) { + _load_check_data.debug_config_data.resize(length); + ReadBuffer::GetCurrent()->CopyBytes(reinterpret_cast(const_cast(_load_check_data.debug_config_data.data())), length); + } +} + extern const ChunkHandler _debug_chunk_handlers[] = { - { 'DBGL', Save_DBGL, Load_DBGL, nullptr, Check_DBGL, CH_RIFF | CH_LAST}, + { 'DBGL', Save_DBGL, Load_DBGL, nullptr, Check_DBGL, CH_RIFF}, + { 'DBGC', Save_DBGC, Load_DBGC, nullptr, Check_DBGC, CH_RIFF | CH_LAST}, }; diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index ab07ca7085..97491f9e18 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -109,7 +109,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_ROAD_LAYOUT_CHANGE_CTR, XSCF_NULL, 1, 1, "road_layout_change_ctr", nullptr, nullptr, nullptr }, { XSLFI_TOWN_CARGO_MATRIX, XSCF_NULL, 1, 1, "town_cargo_matrix", nullptr, nullptr, nullptr }, { XSLFI_STATE_CHECKSUM, XSCF_NULL, 1, 1, "state_checksum", nullptr, nullptr, nullptr }, - { XSLFI_DEBUG, XSCF_IGNORABLE_ALL, 1, 1, "debug", nullptr, nullptr, "DBGL" }, + { XSLFI_DEBUG, XSCF_IGNORABLE_ALL, 1, 1, "debug", nullptr, nullptr, "DBGL,DBGC" }, { XSLFI_FLOW_STAT_FLAGS, XSCF_NULL, 1, 1, "flow_stat_flags", nullptr, nullptr, nullptr }, { XSLFI_SPEED_RESTRICTION, XSCF_NULL, 1, 1, "speed_restriction", nullptr, nullptr, "VESR" }, { XSLFI_STATION_GOODS_EXTRA, XSCF_NULL, 1, 1, "station_goods_extra", nullptr, nullptr, nullptr }, diff --git a/src/settings.cpp b/src/settings.cpp index 7e6a9a78c3..a416d4626f 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -88,6 +88,7 @@ GameSettings _settings_game; ///< Game settings of a running game or the sce GameSettings _settings_newgame; ///< Game settings for new games (updated from the intro screen). VehicleDefaultSettings _old_vds; ///< Used for loading default vehicles settings from old savegames char *_config_file; ///< Configuration file of OpenTTD +std::string _config_file_text; typedef std::list ErrorList; static ErrorList _settings_error_list; ///< Errors while loading minimal settings. @@ -1891,7 +1892,7 @@ static void HandleSettingDescs(IniFile *ini, SettingDescProc *proc, SettingDescP static IniFile *IniLoadConfig() { IniFile *ini = new IniFile(_list_group_names); - ini->LoadFromDisk(_config_file, NO_DIRECTORY); + ini->LoadFromDisk(_config_file, NO_DIRECTORY, &_config_file_text); return ini; }