Skip to content

Commit

Permalink
Codechange: make [Save|Load]Settings() behave more like other Save/Lo…
Browse files Browse the repository at this point in the history
…ad code

Prepare the full description and send it to SlObject. This does
require some code to be able to read to a SLE_VAR_NULL, like strings
etc, as there is no way to know their length beforehand.
  • Loading branch information
TrueBrain committed Jun 3, 2021
1 parent b8607ad commit 4f4f79c
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 29 deletions.
13 changes: 11 additions & 2 deletions src/saveload/saveload.cpp
Expand Up @@ -578,7 +578,7 @@ static inline uint SlGetArrayLength(size_t length)
* @param conv VarType type of variable that is used for calculating the size
* @return Return the size of this type in bytes
*/
uint SlCalcConvMemLen(VarType conv)
static inline uint SlCalcConvMemLen(VarType conv)
{
static const byte conv_mem_size[] = {1, 1, 1, 2, 2, 4, 4, 8, 8, 0};
byte length = GB(conv, 4, 4);
Expand Down Expand Up @@ -937,6 +937,9 @@ static void SlString(void *ptr, size_t length, VarType conv)

switch (GetVarMemType(conv)) {
default: NOT_REACHED();
case SLE_VAR_NULL:
SlSkipBytes(len);
return;
case SLE_VAR_STRB:
if (len >= length) {
DEBUG(sl, 1, "String length in savegame is bigger than buffer, truncating");
Expand Down Expand Up @@ -1001,8 +1004,12 @@ static void SlStdString(void *ptr, VarType conv)
case SLA_LOAD_CHECK:
case SLA_LOAD: {
size_t len = SlReadArrayLength();
char *buf = AllocaM(char, len + 1);
if (GetVarMemType(conv) == SLE_VAR_NULL) {
SlSkipBytes(len);
return;
}

char *buf = AllocaM(char, len + 1);
SlCopyBytes(buf, len);
buf[len] = '\0'; // properly terminate the string

Expand Down Expand Up @@ -1463,6 +1470,8 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld)
*/
[[maybe_unused]] static bool IsVariableSizeRight(const SaveLoad &sld)
{
if (GetVarMemType(sld.conv) == SLE_VAR_NULL) return true;

switch (sld.cmd) {
case SL_VAR:
switch (GetVarMemType(sld.conv)) {
Expand Down
1 change: 0 additions & 1 deletion src/saveload/saveload.h
Expand Up @@ -891,7 +891,6 @@ void WriteValue(void *ptr, VarType conv, int64 val);
void SlSetArrayIndex(uint index);
int SlIterateArray();

uint SlCalcConvMemLen(VarType conv);
void SlAutolength(AutolengthProc *proc, void *arg);
size_t SlGetFieldLength();
void SlSetLength(size_t length);
Expand Down
62 changes: 36 additions & 26 deletions src/settings.cpp
Expand Up @@ -2014,6 +2014,31 @@ void IConsoleListSettings(const char *prefilter)
IConsolePrintF(CC_WARNING, "Use 'setting' command to change a value");
}

/**
* Get the SaveLoad description for the SettingTable.
* @param settings SettingDesc struct containing all information.
* @param is_loading True iff the SaveLoad table is for loading.
* @return Vector with SaveLoad entries for the SettingTable.
*/
static std::vector<SaveLoad> GetSettingsDesc(const SettingTable &settings, bool is_loading)
{
std::vector<SaveLoad> saveloads;
for (auto &sd : settings) {
if (sd->flags & SF_NOT_IN_SAVE) continue;

if (is_loading && (sd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) {
/* We don't want to read this setting, so we do need to skip over it. */
saveloads.push_back({sd->save.cmd, GetVarFileType(sd->save.conv) | SLE_VAR_NULL, sd->save.length, sd->save.version_from, sd->save.version_to, 0, nullptr, 0});
continue;
}

saveloads.push_back(sd->save);
}

return saveloads;
}


/**
* Save and load handler for settings
* @param settings SettingDesc struct containing all information
Expand All @@ -2022,20 +2047,18 @@ void IConsoleListSettings(const char *prefilter)
*/
static void LoadSettings(const SettingTable &settings, void *object)
{
for (auto &osd : settings) {
if (osd->flags & SF_NOT_IN_SAVE) continue;
const std::vector<SaveLoad> slt = GetSettingsDesc(settings, true);

SaveLoad sl = osd->save;
if ((osd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) {
/* We don't want to read this setting, so we do need to skip over it. */
sl = SLE_NULL(static_cast<uint16>(SlCalcConvMemLen(osd->save.conv) * osd->save.length));
}
SlObject(object, slt);

void *ptr = GetVariableAddress(object, sl);
if (!SlObjectMember(ptr, sl)) continue;
/* Ensure all IntSettings are valid (min/max could have changed between versions etc). */
for (auto &sd : settings) {
if (sd->flags & SF_NOT_IN_SAVE) continue;
if ((sd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) continue;
if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;

if (osd->IsIntSetting()) {
const IntSettingDesc *int_setting = osd->AsIntSetting();
if (sd->IsIntSetting()) {
const IntSettingDesc *int_setting = sd->AsIntSetting();
int_setting->MakeValueValidAndWrite(object, int_setting->Read(object));
}
}
Expand All @@ -2049,22 +2072,9 @@ static void LoadSettings(const SettingTable &settings, void *object)
*/
static void SaveSettings(const SettingTable &settings, void *object)
{
/* We need to write the CH_RIFF header, but unfortunately can't call
* SlCalcLength() because we have a different format. So do this manually */
size_t length = 0;
for (auto &sd : settings) {
if (sd->flags & SF_NOT_IN_SAVE) continue;

length += SlCalcObjMemberLength(object, sd->save);
}
SlSetLength(length);
const std::vector<SaveLoad> slt = GetSettingsDesc(settings, false);

for (auto &sd : settings) {
if (sd->flags & SF_NOT_IN_SAVE) continue;

void *ptr = GetVariableAddress(object, sd->save);
SlObjectMember(ptr, sd->save);
}
SlObject(object, slt);
}

static void Load_OPTS()
Expand Down

0 comments on commit 4f4f79c

Please sign in to comment.