mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-02 09:40:35 +00:00
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.
This commit is contained in:
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},
|
||||
};
|
||||
|
235
src/settings.cpp
235
src/settings.cpp
@ -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(¤t_setting, _settings_patx_desc);
|
||||
SlObject(¤t_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(¤t_setting, _settings_patx_desc);
|
||||
length += SlCalcObjLength(¤t_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(¤t_setting, _settings_patx_desc);
|
||||
SlObject(¤t_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(¤t_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(¤t_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(¤t_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…
Reference in New Issue
Block a user