diff --git a/src/cheat.cpp b/src/cheat.cpp index 9fba889da0..fc3f8b9904 100644 --- a/src/cheat.cpp +++ b/src/cheat.cpp @@ -10,15 +10,23 @@ #include "stdafx.h" #include "cheat_type.h" +#include +#include + #include "safeguards.h" /** All the cheats. */ Cheats _cheats; +ExtraCheats _extra_cheats; + +std::map _unknown_cheats; /** Reinitialise all the cheats. */ void InitializeCheats() { memset(&_cheats, 0, sizeof(Cheats)); + memset(&_extra_cheats, 0, sizeof(ExtraCheats)); + _unknown_cheats.clear(); } /** @@ -35,5 +43,12 @@ bool CheatHasBeenUsed() if (cht->been_used) return true; } + cht = (Cheat*)&_extra_cheats; + cht_last = &cht[sizeof(_extra_cheats) / sizeof(Cheat)]; + + for (; cht != cht_last; cht++) { + if (cht->been_used) return true; + } + return false; } diff --git a/src/cheat_func.h b/src/cheat_func.h index 6d26e71c4a..248601372d 100644 --- a/src/cheat_func.h +++ b/src/cheat_func.h @@ -13,6 +13,7 @@ #include "cheat_type.h" extern Cheats _cheats; +extern ExtraCheats _extra_cheats; void ShowCheatWindow(); diff --git a/src/cheat_type.h b/src/cheat_type.h index d8ebc1143e..429c19ac07 100644 --- a/src/cheat_type.h +++ b/src/cheat_type.h @@ -37,6 +37,9 @@ struct Cheats { Cheat edit_max_hl; ///< edit the maximum heightlevel; this is a cheat because of the fact that it needs to reset NewGRF game state and doing so as a simple configuration breaks the expectation of many }; +struct ExtraCheats { +}; + /** Available cheats. */ enum CheatNumbers { CHT_MONEY, ///< Change amount of money. @@ -52,5 +55,6 @@ enum CheatNumbers { }; extern Cheats _cheats; +extern ExtraCheats _extra_cheats; #endif /* CHEAT_TYPE_H */ diff --git a/src/saveload/cheat_sl.cpp b/src/saveload/cheat_sl.cpp index 9af1759221..bbc324c0ec 100644 --- a/src/saveload/cheat_sl.cpp +++ b/src/saveload/cheat_sl.cpp @@ -9,11 +9,25 @@ #include "../stdafx.h" #include "../cheat_type.h" +#include "../debug.h" #include "saveload.h" +#include +#include + #include "../safeguards.h" +extern std::map _unknown_cheats; + +struct ExtraCheatNameDesc { + const char *name; + Cheat *cht; +}; + +static ExtraCheatNameDesc _extra_cheat_descs[] = { +}; + /** * Save the cheat values. */ @@ -47,7 +61,100 @@ static void Load_CHTS() } } +/** + * Load the extra cheat values. + */ +static void Load_CHTX() +{ + struct CheatsExtLoad { + char name[256]; + Cheat cht; + }; + + static const SaveLoad _cheats_ext_load_desc[] = { + SLE_STR(CheatsExtLoad, name, SLE_STRB, 256), + SLE_VAR(CheatsExtLoad, cht.been_used, SLE_BOOL), + SLE_VAR(CheatsExtLoad, cht.value, SLE_BOOL), + SLE_END() + }; + + CheatsExtLoad current_cheat; + + uint32 chunk_flags = SlReadUint32(); + // flags are not in use yet, reserve for future expansion + if (chunk_flags != 0) SlErrorCorruptFmt("CHTX chunk: unknown chunk header flags: 0x%X", chunk_flags); + + uint32 cheat_count = SlReadUint32(); + for (uint32 i = 0; i < cheat_count; i++) { + SlObject(¤t_cheat, _cheats_ext_load_desc); + + bool found = false; + for (uint j = 0; j < lengthof(_extra_cheat_descs); j++) { + const ExtraCheatNameDesc &desc = _extra_cheat_descs[j]; + if (strcmp(desc.name, current_cheat.name) == 0) { + *(desc.cht) = current_cheat.cht; + found = true; + break; + } + } + if (!found) { + DEBUG(sl, 1, "CHTX chunk: Could not find cheat: '%s'", current_cheat.name); + _unknown_cheats[current_cheat.name] = current_cheat.cht; + } + } +} + +/** + * Save the extra cheat values. + */ +static void Save_CHTX() +{ + struct CheatsExtSave { + const char *name; + Cheat cht; + }; + + static const SaveLoad _cheats_ext_save_desc[] = { + SLE_STR(CheatsExtSave, name, SLE_STR, 0), + SLE_VAR(CheatsExtSave, cht.been_used, SLE_BOOL), + SLE_VAR(CheatsExtSave, cht.value, SLE_BOOL), + SLE_END() + }; + + SlAutolength([](void *) { + SlWriteUint32(0); // flags + SlWriteUint32(lengthof(_extra_cheat_descs) + _unknown_cheats.size()); // cheat count + + for (uint j = 0; j < lengthof(_extra_cheat_descs); j++) { + CheatsExtSave save = { _extra_cheat_descs[j].name, *(_extra_cheat_descs[j].cht) }; + SlObject(&save, _cheats_ext_save_desc); + } + for (const auto &iter : _unknown_cheats) { + CheatsExtSave save = { iter.first.c_str(), iter.second }; + SlObject(&save, _cheats_ext_save_desc); + } + }, nullptr); +} + +/** + * Internal structure used in SaveSettingsPatx() and SaveSettingsPlyx() + */ +struct SettingsExtSave { + uint32 flags; + const char *name; + uint32 setting_length; +}; + +static const SaveLoad _settings_ext_save_desc[] = { + SLE_VAR(SettingsExtSave, flags, SLE_UINT32), + SLE_STR(SettingsExtSave, name, SLE_STR, 0), + SLE_VAR(SettingsExtSave, setting_length, SLE_UINT32), + SLE_END() +}; + + /** Chunk handlers related to cheats. */ extern const ChunkHandler _cheat_chunk_handlers[] = { - { 'CHTS', Save_CHTS, Load_CHTS, nullptr, nullptr, CH_RIFF | CH_LAST}, + { 'CHTS', Save_CHTS, Load_CHTS, nullptr, nullptr, CH_RIFF}, + { 'CHTX', Save_CHTX, Load_CHTX, nullptr, nullptr, CH_RIFF | CH_LAST}, }; diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index dcb5275f3b..ab07ca7085 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -114,6 +114,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { 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 }, { XSLFI_DOCKING_CACHE_VER, XSCF_IGNORABLE_ALL, 1, 1, "docking_cache_ver", nullptr, nullptr, nullptr }, + { XSLFI_EXTRA_CHEATS, XSCF_NULL, 1, 1, "extra_cheats", nullptr, nullptr, "CHTX" }, { 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 6de2106937..27493fa8ed 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -79,6 +79,7 @@ enum SlXvFeatureIndex { XSLFI_SPEED_RESTRICTION, ///< Train speed restrictions XSLFI_STATION_GOODS_EXTRA, ///< Extra station goods entry statuses XSLFI_DOCKING_CACHE_VER, ///< Multiple docks - docking tile cache version + XSLFI_EXTRA_CHEATS, ///< Extra cheats 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