Add an un-ordered chunk for extra company settings: PLYX.

This is similar to the PATX chunk.
Minor refactoring to enable some code sharing between two chunks.
Fix MakeSettingsPatxList always regenerating cache.
Update documentation of PATX chunk structure.
pull/155/head
Jonathan G Rennison 9 years ago
parent d6395b97a7
commit e606a847c6

@ -16,6 +16,7 @@
#include "../tunnelbridge_map.h"
#include "../tunnelbridge.h"
#include "../station_base.h"
#include "../settings_func.h"
#include "saveload.h"
@ -486,6 +487,7 @@ static void Load_PLYR()
int index;
while ((index = SlIterateArray()) != -1) {
Company *c = new (index) Company();
SetDefaultCompanySettings(c->index);
SaveLoad_PLYR(c);
_company_colours[index] = (Colours)c->colour;
}
@ -529,7 +531,25 @@ static void Ptrs_PLYR()
}
}
extern void LoadSettingsPlyx(bool skip);
extern void SaveSettingsPlyx();
static void Load_PLYX()
{
LoadSettingsPlyx(false);
}
static void Check_PLYX()
{
LoadSettingsPlyx(true);
}
static void Save_PLYX()
{
SaveSettingsPlyx();
}
extern const ChunkHandler _company_chunk_handlers[] = {
{ 'PLYR', Save_PLYR, Load_PLYR, Ptrs_PLYR, Check_PLYR, CH_ARRAY | CH_LAST},
{ 'PLYR', Save_PLYR, Load_PLYR, Ptrs_PLYR, Check_PLYR, CH_ARRAY },
{ 'PLYX', Save_PLYX, Load_PLYX, NULL, Check_PLYX, CH_RIFF | CH_LAST},
};

@ -2235,10 +2235,10 @@ static void SaveSettings(const SettingDesc *sd, void *object)
*
* The PATX chunk contents has the following format:
*
* uint32 chunk flags
* uint32 chunk flags (unused)
* uint32 number of settings
* For each of N settings:
* uint32 setting flags
* uint32 setting flags (unused)
* SLE_STR setting name
* uint32 length of setting field
* N bytes setting field
@ -2269,6 +2269,7 @@ static void MakeSettingsPatxList(const SettingDesc *sd)
static const SettingDesc *previous = NULL;
if (sd == previous) return;
previous = sd;
_sorted_patx_settings.clear();
for (const SettingDesc *desc = sd; desc->save.cmd != SL_END; desc++) {
@ -2279,16 +2280,6 @@ static void MakeSettingsPatxList(const SettingDesc *sd)
std::sort(_sorted_patx_settings.begin(), _sorted_patx_settings.end(), StringSorter());
}
/**
* Internal structure used in LoadSettingsPatx()
* placed outside for legacy compiler compatibility
*/
struct SettingsPatxLoad {
uint32 flags;
char name[256];
uint32 setting_length;
};
/**
* Internal structure used in LoadSettingsPatx()
* placed outside for legacy compiler compatibility
@ -2308,6 +2299,38 @@ struct StringSearcher {
}
};
/**
* Internal structure used in LoadSettingsPatx() and LoadSettingsPlyx()
*/
struct SettingsExtLoad {
uint32 flags;
char name[256];
uint32 setting_length;
};
static const SaveLoad _settings_ext_load_desc[] = {
SLE_VAR(SettingsExtLoad, flags, SLE_UINT32),
SLE_STR(SettingsExtLoad, name, SLE_STRB, 256),
SLE_VAR(SettingsExtLoad, setting_length, SLE_UINT32),
SLE_END()
};
/**
* 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()
};
/**
* Load handler for settings which go in the PATX chunk
* @param osd SettingDesc struct containing all information
@ -2318,14 +2341,7 @@ static void LoadSettingsPatx(const SettingDesc *sd, void *object)
{
MakeSettingsPatxList(sd);
SettingsPatxLoad current_setting;
static const SaveLoad _settings_patx_desc[] = {
SLE_VAR(SettingsPatxLoad, flags, SLE_UINT32),
SLE_STR(SettingsPatxLoad, name, SLE_STRB, 256),
SLE_VAR(SettingsPatxLoad, setting_length, SLE_UINT32),
SLE_END()
};
SettingsExtLoad current_setting;
uint32 flags = SlReadUint32();
// flags are not in use yet, reserve for future expansion
@ -2333,7 +2349,7 @@ static void LoadSettingsPatx(const SettingDesc *sd, void *object)
uint32 settings_count = SlReadUint32();
for (uint32 i = 0; i < settings_count; i++) {
SlObject(&current_setting, _settings_patx_desc);
SlObject(&current_setting, _settings_ext_load_desc);
// flags are not in use yet, reserve for future expansion
if (current_setting.flags != 0) SlErrorCorruptFmt("PATX chunk: unknown setting header flags: 0x%X", current_setting.flags);
@ -2377,19 +2393,7 @@ struct SettingToAdd {
*/
static void SaveSettingsPatx(const SettingDesc *sd, void *object)
{
struct SettingsPatxSave {
uint32 flags;
const char *name;
uint32 setting_length;
};
SettingsPatxSave current_setting;
static const SaveLoad _settings_patx_desc[] = {
SLE_VAR(SettingsPatxSave, flags, SLE_UINT32),
SLE_STR(SettingsPatxSave, name, SLE_STR, 0),
SLE_VAR(SettingsPatxSave, setting_length, SLE_UINT32),
SLE_END()
};
SettingsExtSave current_setting;
std::vector<SettingToAdd> settings_to_add;
@ -2402,7 +2406,7 @@ static void SaveSettingsPatx(const SettingDesc *sd, void *object)
current_setting.name = desc->patx_name;
// add length of setting header
length += SlCalcObjLength(&current_setting, _settings_patx_desc);
length += SlCalcObjLength(&current_setting, _settings_ext_save_desc);
// add length of actual setting
length += setting_length;
@ -2421,12 +2425,171 @@ static void SaveSettingsPatx(const SettingDesc *sd, void *object)
current_setting.flags = 0;
current_setting.name = desc->patx_name;
current_setting.setting_length = settings_to_add[i].setting_length;
SlObject(&current_setting, _settings_patx_desc);
SlObject(&current_setting, _settings_ext_save_desc);
void *ptr = GetVariableAddress(object, &desc->save);
SlObjectMember(ptr, &desc->save);
}
}
/** @file
*
* The PLYX chunk stores additional company settings in an unordered
* format which is tolerant of extra, missing or reordered settings.
* The format is similar to the PATX chunk.
* Additional settings generally means those that aren't in trunk.
*
* The PLYX chunk contents has the following format:
*
* uint32 chunk flags (unused)
* uint32 number of companies
* For each of N companies:
* uint32 company ID
* uint32 company flags (unused)
* uint32 number of settings
* For each of N settings:
* uint32 setting flags (unused)
* SLE_STR setting name
* uint32 length of setting field
* N bytes setting field
*/
/**
* Load handler for company settings which go in the PLYX chunk
* @param check_mode Whether to skip over settings without reading
*/
void LoadSettingsPlyx(bool skip)
{
SettingsExtLoad current_setting;
uint32 chunk_flags = SlReadUint32();
// flags are not in use yet, reserve for future expansion
if (chunk_flags != 0) SlErrorCorruptFmt("PLYX chunk: unknown chunk header flags: 0x%X", chunk_flags);
uint32 company_count = SlReadUint32();
for (uint32 i = 0; i < company_count; i++) {
uint32 company_id = SlReadUint32();
if (company_id >= MAX_COMPANIES) SlErrorCorruptFmt("PLYX chunk: invalid company ID: %u", company_id);
const Company *c = NULL;
if (!skip) {
c = Company::GetIfValid(company_id);
if (c == NULL) SlErrorCorruptFmt("PLYX chunk: non-existant company ID: %u", company_id);
}
uint32 company_flags = SlReadUint32();
// flags are not in use yet, reserve for future expansion
if (company_flags != 0) SlErrorCorruptFmt("PLYX chunk: unknown company flags: 0x%X", company_flags);
uint32 settings_count = SlReadUint32();
for (uint32 j = 0; j < settings_count; j++) {
SlObject(&current_setting, _settings_ext_load_desc);
// flags are not in use yet, reserve for future expansion
if (current_setting.flags != 0) SlErrorCorruptFmt("PLYX chunk: unknown setting header flags: 0x%X", current_setting.flags);
if (skip) {
SlSkipBytes(current_setting.setting_length);
continue;
}
const SettingDesc *setting = NULL;
// not many company settings, so perform a linear scan
for (const SettingDesc *desc = _company_settings; desc->save.cmd != SL_END; desc++) {
if (desc->patx_name != NULL && strcmp(desc->patx_name, current_setting.name) == 0) {
setting = desc;
break;
}
}
if (setting != NULL) {
// found setting
const SaveLoad *sld = &(setting->save);
size_t read = SlGetBytesRead();
void *ptr = GetVariableAddress(&(c->settings), sld);
SlObjectMember(ptr, sld);
if (SlGetBytesRead() != read + current_setting.setting_length) {
SlErrorCorruptFmt("PLYX chunk: setting read length mismatch for setting: '%s'", current_setting.name);
}
if (IsNumericType(sld->conv)) Write_ValidateSetting(ptr, setting, ReadValue(ptr, sld->conv));
} else {
DEBUG(sl, 1, "PLYX chunk: Could not find company setting: '%s', ignoring", current_setting.name);
SlSkipBytes(current_setting.setting_length);
}
}
}
}
/**
* Save handler for settings which go in the PLYX chunk
*/
void SaveSettingsPlyx()
{
SettingsExtSave current_setting;
static const SaveLoad _settings_plyx_desc[] = {
SLE_VAR(SettingsExtSave, flags, SLE_UINT32),
SLE_STR(SettingsExtSave, name, SLE_STR, 0),
SLE_VAR(SettingsExtSave, setting_length, SLE_UINT32),
SLE_END()
};
std::vector<uint32> company_setting_counts;
size_t length = 8;
uint32 companies_count = 0;
Company *c;
FOR_ALL_COMPANIES(c) {
length += 12;
companies_count++;
uint32 setting_count = 0;
for (const SettingDesc *desc = _company_settings; desc->save.cmd != SL_END; desc++) {
if (desc->patx_name == NULL) continue;
uint32 setting_length = SlCalcObjMemberLength(&(c->settings), &desc->save);
if (!setting_length) continue;
current_setting.name = desc->patx_name;
// add length of setting header
length += SlCalcObjLength(&current_setting, _settings_ext_save_desc);
// add length of actual setting
length += setting_length;
setting_count++;
}
company_setting_counts.push_back(setting_count);
}
SlSetLength(length);
SlWriteUint32(0); // flags
SlWriteUint32(companies_count); // companies count
size_t index = 0;
FOR_ALL_COMPANIES(c) {
length += 12;
companies_count++;
SlWriteUint32(c->index); // company ID
SlWriteUint32(0); // flags
SlWriteUint32(company_setting_counts[index]); // setting count
index++;
for (const SettingDesc *desc = _company_settings; desc->save.cmd != SL_END; desc++) {
if (desc->patx_name == NULL) continue;
uint32 setting_length = SlCalcObjMemberLength(&(c->settings), &desc->save);
if (!setting_length) continue;
current_setting.flags = 0;
current_setting.name = desc->patx_name;
current_setting.setting_length = setting_length;
SlObject(&current_setting, _settings_plyx_desc);
void *ptr = GetVariableAddress(&(c->settings), &desc->save);
SlObjectMember(ptr, &desc->save);
}
}
}
static void Load_OPTS()
{
/* Copy over default setting since some might not get loaded in

@ -18,8 +18,8 @@ static const SettingDesc _company_settings[] = {
[post-amble]
};
[templates]
SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, NULL),
SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, NULL),
SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, $patxname),
SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, $patxname),
SDT_END = SDT_END()
[defaults]
@ -35,6 +35,7 @@ from = 0
to = SL_MAX_VERSION
cat = SC_ADVANCED
extver = SlXvFeatureTest()
patxname = NULL

Loading…
Cancel
Save