Merge branch 'save_ext' into signal_tunnels_bridges
This commit is contained in:
@@ -887,6 +887,8 @@
|
|||||||
<ClCompile Include="..\src\saveload\town_sl.cpp" />
|
<ClCompile Include="..\src\saveload\town_sl.cpp" />
|
||||||
<ClCompile Include="..\src\saveload\vehicle_sl.cpp" />
|
<ClCompile Include="..\src\saveload\vehicle_sl.cpp" />
|
||||||
<ClCompile Include="..\src\saveload\waypoint_sl.cpp" />
|
<ClCompile Include="..\src\saveload\waypoint_sl.cpp" />
|
||||||
|
<ClInclude Include="..\src\saveload\extended_ver_sl.h" />
|
||||||
|
<ClCompile Include="..\src\saveload\extended_ver_sl.cpp" />
|
||||||
<ClInclude Include="..\src\table\airport_defaults.h" />
|
<ClInclude Include="..\src\table\airport_defaults.h" />
|
||||||
<ClInclude Include="..\src\table\airport_movement.h" />
|
<ClInclude Include="..\src\table\airport_movement.h" />
|
||||||
<ClInclude Include="..\src\table\airporttile_ids.h" />
|
<ClInclude Include="..\src\table\airporttile_ids.h" />
|
||||||
|
@@ -1839,6 +1839,12 @@
|
|||||||
<ClCompile Include="..\src\saveload\waypoint_sl.cpp">
|
<ClCompile Include="..\src\saveload\waypoint_sl.cpp">
|
||||||
<Filter>Save/Load handlers</Filter>
|
<Filter>Save/Load handlers</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\src\saveload\extended_ver_sl.h">
|
||||||
|
<Filter>Save/Load handlers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\src\saveload\extended_ver_sl.cpp">
|
||||||
|
<Filter>Save/Load handlers</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClInclude Include="..\src\table\airport_defaults.h">
|
<ClInclude Include="..\src\table\airport_defaults.h">
|
||||||
<Filter>Tables</Filter>
|
<Filter>Tables</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
template<typename Tkey, typename Tvalue, typename Tcompare>
|
template<typename Tkey, typename Tvalue, typename Tcontainer, typename Tcompare>
|
||||||
class MultiMap;
|
class MultiMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,14 +23,15 @@ class MultiMap;
|
|||||||
* @tparam Tmap_iter Iterator type for the map in the MultiMap.
|
* @tparam Tmap_iter Iterator type for the map in the MultiMap.
|
||||||
* @tparam Tlist_iter Iterator type for the lists in the MultiMap.
|
* @tparam Tlist_iter Iterator type for the lists in the MultiMap.
|
||||||
* @tparam Tkey Key type of the MultiMap.
|
* @tparam Tkey Key type of the MultiMap.
|
||||||
* @tparam Tvalue Value type of the MultMap.
|
* @tparam Tvalue Value type of the MultiMap.
|
||||||
|
* @tparam Tcontainer Container type for the values of the MultiMap.
|
||||||
* @tparam Tcompare Comparator type for keys of the MultiMap.
|
* @tparam Tcompare Comparator type for keys of the MultiMap.
|
||||||
*/
|
*/
|
||||||
template<class Tmap_iter, class Tlist_iter, class Tkey, class Tvalue, class Tcompare>
|
template<class Tmap_iter, class Tlist_iter, class Tkey, class Tvalue, class Tcontainer, class Tcompare>
|
||||||
class MultiMapIterator {
|
class MultiMapIterator {
|
||||||
protected:
|
protected:
|
||||||
friend class MultiMap<Tkey, Tvalue, Tcompare>;
|
friend class MultiMap<Tkey, Tvalue, Tcontainer, Tcompare>;
|
||||||
typedef MultiMapIterator<Tmap_iter, Tlist_iter, Tkey, Tvalue, Tcompare> Self;
|
typedef MultiMapIterator<Tmap_iter, Tlist_iter, Tkey, Tvalue, Tcontainer, Tcompare> Self;
|
||||||
|
|
||||||
Tlist_iter list_iter; ///< Iterator pointing to current position in the current list of items with equal keys.
|
Tlist_iter list_iter; ///< Iterator pointing to current position in the current list of items with equal keys.
|
||||||
Tmap_iter map_iter; ///< Iterator pointing to the position of the current list of items with equal keys in the map.
|
Tmap_iter map_iter; ///< Iterator pointing to the position of the current list of items with equal keys in the map.
|
||||||
@@ -201,8 +202,8 @@ public:
|
|||||||
* @param iter2 Second iterator to compare.
|
* @param iter2 Second iterator to compare.
|
||||||
* @return If iter1 and iter2 are equal.
|
* @return If iter1 and iter2 are equal.
|
||||||
*/
|
*/
|
||||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcompare>
|
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcontainer1, class Tcontainer2, class Tcompare>
|
||||||
bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare> &iter2)
|
bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcontainer1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcontainer2, Tcompare> &iter2)
|
||||||
{
|
{
|
||||||
if (iter1.GetMapIter() != iter2.GetMapIter()) return false;
|
if (iter1.GetMapIter() != iter2.GetMapIter()) return false;
|
||||||
if (!iter1.ListValid()) return !iter2.ListValid();
|
if (!iter1.ListValid()) return !iter2.ListValid();
|
||||||
@@ -218,8 +219,8 @@ bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, T
|
|||||||
* @param iter2 Second iterator to compare.
|
* @param iter2 Second iterator to compare.
|
||||||
* @return If iter1 and iter2 are not equal.
|
* @return If iter1 and iter2 are not equal.
|
||||||
*/
|
*/
|
||||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcompare>
|
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcontainer1, class Tcontainer2, class Tcompare>
|
||||||
bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare> &iter2)
|
bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcontainer1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcontainer2, Tcompare> &iter2)
|
||||||
{
|
{
|
||||||
return !(iter1 == iter2);
|
return !(iter1 == iter2);
|
||||||
}
|
}
|
||||||
@@ -232,8 +233,8 @@ bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, T
|
|||||||
* @param iter2 Map iterator.
|
* @param iter2 Map iterator.
|
||||||
* @return If iter1 points to the begin of the list pointed to by iter2.
|
* @return If iter1 points to the begin of the list pointed to by iter2.
|
||||||
*/
|
*/
|
||||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
|
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcontainer, class Tcompare >
|
||||||
bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1, const Tmap_iter2 &iter2)
|
bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcontainer, Tcompare> &iter1, const Tmap_iter2 &iter2)
|
||||||
{
|
{
|
||||||
return !iter1.ListValid() && iter1.GetMapIter() == iter2;
|
return !iter1.ListValid() && iter1.GetMapIter() == iter2;
|
||||||
}
|
}
|
||||||
@@ -244,8 +245,8 @@ bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tc
|
|||||||
* @param iter2 Map iterator.
|
* @param iter2 Map iterator.
|
||||||
* @return If iter1 doesn't point to the begin of the list pointed to by iter2.
|
* @return If iter1 doesn't point to the begin of the list pointed to by iter2.
|
||||||
*/
|
*/
|
||||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
|
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcontainer, class Tcompare >
|
||||||
bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1, const Tmap_iter2 &iter2)
|
bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcontainer, Tcompare> &iter1, const Tmap_iter2 &iter2)
|
||||||
{
|
{
|
||||||
return iter1.ListValid() || iter1.GetMapIter() != iter2;
|
return iter1.ListValid() || iter1.GetMapIter() != iter2;
|
||||||
}
|
}
|
||||||
@@ -256,8 +257,8 @@ bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tc
|
|||||||
* @param iter1 MultiMap iterator.
|
* @param iter1 MultiMap iterator.
|
||||||
* @return If iter1 points to the begin of the list pointed to by iter2.
|
* @return If iter1 points to the begin of the list pointed to by iter2.
|
||||||
*/
|
*/
|
||||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
|
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcontainer, class Tcompare >
|
||||||
bool operator==(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1)
|
bool operator==(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcontainer, Tcompare> &iter1)
|
||||||
{
|
{
|
||||||
return !iter1.ListValid() && iter1.GetMapIter() == iter2;
|
return !iter1.ListValid() && iter1.GetMapIter() == iter2;
|
||||||
}
|
}
|
||||||
@@ -268,8 +269,8 @@ bool operator==(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlis
|
|||||||
* @param iter1 MultiMap iterator.
|
* @param iter1 MultiMap iterator.
|
||||||
* @return If iter1 doesn't point to the begin of the list pointed to by iter2.
|
* @return If iter1 doesn't point to the begin of the list pointed to by iter2.
|
||||||
*/
|
*/
|
||||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
|
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcontainer, class Tcompare >
|
||||||
bool operator!=(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1)
|
bool operator!=(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcontainer, Tcompare> &iter1)
|
||||||
{
|
{
|
||||||
return iter1.ListValid() || iter1.GetMapIter() != iter2;
|
return iter1.ListValid() || iter1.GetMapIter() != iter2;
|
||||||
}
|
}
|
||||||
@@ -282,10 +283,10 @@ bool operator!=(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlis
|
|||||||
* STL-compatible members are named in STL style, all others are named in OpenTTD
|
* STL-compatible members are named in STL style, all others are named in OpenTTD
|
||||||
* style.
|
* style.
|
||||||
*/
|
*/
|
||||||
template<typename Tkey, typename Tvalue, typename Tcompare = std::less<Tkey> >
|
template<typename Tkey, typename Tvalue, typename Tcontainer = std::list<Tvalue>, typename Tcompare = std::less<Tkey> >
|
||||||
class MultiMap : public std::map<Tkey, std::list<Tvalue>, Tcompare > {
|
class MultiMap : public std::map<Tkey, Tcontainer, Tcompare > {
|
||||||
public:
|
public:
|
||||||
typedef typename std::list<Tvalue> List;
|
typedef Tcontainer List;
|
||||||
typedef typename List::iterator ListIterator;
|
typedef typename List::iterator ListIterator;
|
||||||
typedef typename List::const_iterator ConstListIterator;
|
typedef typename List::const_iterator ConstListIterator;
|
||||||
|
|
||||||
@@ -293,8 +294,8 @@ public:
|
|||||||
typedef typename Map::iterator MapIterator;
|
typedef typename Map::iterator MapIterator;
|
||||||
typedef typename Map::const_iterator ConstMapIterator;
|
typedef typename Map::const_iterator ConstMapIterator;
|
||||||
|
|
||||||
typedef MultiMapIterator<MapIterator, ListIterator, Tkey, Tvalue, Tcompare> iterator;
|
typedef MultiMapIterator<MapIterator, ListIterator, Tkey, Tvalue, Tcontainer, Tcompare> iterator;
|
||||||
typedef MultiMapIterator<ConstMapIterator, ConstListIterator, Tkey, const Tvalue, Tcompare> const_iterator;
|
typedef MultiMapIterator<ConstMapIterator, ConstListIterator, Tkey, const Tvalue, Tcontainer, Tcompare> const_iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Erase the value pointed to by an iterator. The iterator may be invalid afterwards.
|
* Erase the value pointed to by an iterator. The iterator may be invalid afterwards.
|
||||||
|
@@ -249,7 +249,20 @@ static void WriteSavegameInfo(const char *name)
|
|||||||
char buf[8192];
|
char buf[8192];
|
||||||
char *p = buf;
|
char *p = buf;
|
||||||
p += seprintf(p, lastof(buf), "Name: %s\n", name);
|
p += seprintf(p, lastof(buf), "Name: %s\n", name);
|
||||||
p += seprintf(p, lastof(buf), "Savegame ver: %d\n", _sl_version);
|
const char *type = "";
|
||||||
|
extern bool _sl_is_faked_ext;
|
||||||
|
extern bool _sl_is_ext_version;
|
||||||
|
if (_sl_is_faked_ext) {
|
||||||
|
type = " (fake extended)";
|
||||||
|
} else if (_sl_is_ext_version) {
|
||||||
|
type = " (extended)";
|
||||||
|
}
|
||||||
|
p += seprintf(p, lastof(buf), "Savegame ver: %d%s\n", _sl_version, type);
|
||||||
|
for (size_t i = 0; i < XSLFI_SIZE; i++) {
|
||||||
|
if (_sl_xv_feature_versions[i] > 0) {
|
||||||
|
p += seprintf(p, lastof(buf), " Feature: %s = %d\n", SlXvGetFeatureName((SlXvFeatureIndex) i), _sl_xv_feature_versions[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
p += seprintf(p, lastof(buf), "NewGRF ver: 0x%08X\n", last_ottd_rev);
|
p += seprintf(p, lastof(buf), "NewGRF ver: 0x%08X\n", last_ottd_rev);
|
||||||
p += seprintf(p, lastof(buf), "Modified: %d\n", ever_modified);
|
p += seprintf(p, lastof(buf), "Modified: %d\n", ever_modified);
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include "../tunnelbridge_map.h"
|
#include "../tunnelbridge_map.h"
|
||||||
#include "../tunnelbridge.h"
|
#include "../tunnelbridge.h"
|
||||||
#include "../station_base.h"
|
#include "../station_base.h"
|
||||||
|
#include "../settings_func.h"
|
||||||
|
|
||||||
#include "saveload.h"
|
#include "saveload.h"
|
||||||
|
|
||||||
@@ -486,6 +487,7 @@ static void Load_PLYR()
|
|||||||
int index;
|
int index;
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
Company *c = new (index) Company();
|
Company *c = new (index) Company();
|
||||||
|
SetDefaultCompanySettings(c->index);
|
||||||
SaveLoad_PLYR(c);
|
SaveLoad_PLYR(c);
|
||||||
_company_colours[index] = (Colours)c->colour;
|
_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[] = {
|
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},
|
||||||
};
|
};
|
||||||
|
@@ -87,6 +87,20 @@ bool SlXvIsFeaturePresent(SlXvFeatureIndex feature, uint16 min_version, uint16 m
|
|||||||
return _sl_xv_feature_versions[feature] >= min_version && _sl_xv_feature_versions[feature] <= max_version;
|
return _sl_xv_feature_versions[feature] >= min_version && _sl_xv_feature_versions[feature] <= max_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if @p feature is present and has a version inclusively bounded by @p min_version and @p max_version
|
||||||
|
*/
|
||||||
|
const char *SlXvGetFeatureName(SlXvFeatureIndex feature)
|
||||||
|
{
|
||||||
|
const SlxiSubChunkInfo *info = _sl_xv_sub_chunk_infos;
|
||||||
|
for (; info->index != XSLFI_NULL; ++info) {
|
||||||
|
if (info->index == feature) {
|
||||||
|
return info->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "(unknown feature)";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets all extended feature versions to 0
|
* Resets all extended feature versions to 0
|
||||||
*/
|
*/
|
||||||
@@ -116,9 +130,7 @@ void SlXvSetCurrentState()
|
|||||||
*/
|
*/
|
||||||
void SlXvCheckSpecialSavegameVersions()
|
void SlXvCheckSpecialSavegameVersions()
|
||||||
{
|
{
|
||||||
extern uint16 _sl_version;
|
// Checks for special savegame versions go here
|
||||||
|
|
||||||
// TODO: check for savegame versions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,7 +177,6 @@ static void Save_SLXI()
|
|||||||
SlXvSetCurrentState();
|
SlXvSetCurrentState();
|
||||||
|
|
||||||
static const SaveLoad _xlsi_sub_chunk_desc[] = {
|
static const SaveLoad _xlsi_sub_chunk_desc[] = {
|
||||||
SLE_VAR(SlxiSubChunkInfo, save_version, SLE_UINT16),
|
|
||||||
SLE_STR(SlxiSubChunkInfo, name, SLE_STR, 0),
|
SLE_STR(SlxiSubChunkInfo, name, SLE_STR, 0),
|
||||||
SLE_END()
|
SLE_END()
|
||||||
};
|
};
|
||||||
@@ -179,9 +190,9 @@ static void Save_SLXI()
|
|||||||
chunk_counts.resize(XSLFI_SIZE);
|
chunk_counts.resize(XSLFI_SIZE);
|
||||||
const SlxiSubChunkInfo *info = _sl_xv_sub_chunk_infos;
|
const SlxiSubChunkInfo *info = _sl_xv_sub_chunk_infos;
|
||||||
for (; info->index != XSLFI_NULL; ++info) {
|
for (; info->index != XSLFI_NULL; ++info) {
|
||||||
if (info->save_version > 0) {
|
if (_sl_xv_feature_versions[info->index] > 0) {
|
||||||
item_count++;
|
item_count++;
|
||||||
length += 4;
|
length += 6;
|
||||||
length += SlCalcObjLength(info, _xlsi_sub_chunk_desc);
|
length += SlCalcObjLength(info, _xlsi_sub_chunk_desc);
|
||||||
if (info->save_proc) {
|
if (info->save_proc) {
|
||||||
uint32 extra_data_length = info->save_proc(info, true);
|
uint32 extra_data_length = info->save_proc(info, true);
|
||||||
@@ -209,7 +220,8 @@ static void Save_SLXI()
|
|||||||
// write data
|
// write data
|
||||||
info = _sl_xv_sub_chunk_infos;
|
info = _sl_xv_sub_chunk_infos;
|
||||||
for (; info->index != XSLFI_NULL; ++info) {
|
for (; info->index != XSLFI_NULL; ++info) {
|
||||||
if (info->save_version > 0) {
|
uint16 save_version = _sl_xv_feature_versions[info->index];
|
||||||
|
if (save_version > 0) {
|
||||||
SlxiSubChunkFlags flags = info->flags;
|
SlxiSubChunkFlags flags = info->flags;
|
||||||
assert(!(flags & (XSCF_EXTRA_DATA_PRESENT | XSCF_CHUNK_ID_LIST_PRESENT)));
|
assert(!(flags & (XSCF_EXTRA_DATA_PRESENT | XSCF_CHUNK_ID_LIST_PRESENT)));
|
||||||
uint32 extra_data_length = extra_data_lengths[info->index];
|
uint32 extra_data_length = extra_data_lengths[info->index];
|
||||||
@@ -217,6 +229,7 @@ static void Save_SLXI()
|
|||||||
if (extra_data_length > 0) flags |= XSCF_EXTRA_DATA_PRESENT;
|
if (extra_data_length > 0) flags |= XSCF_EXTRA_DATA_PRESENT;
|
||||||
if (chunk_count > 0) flags |= XSCF_CHUNK_ID_LIST_PRESENT;
|
if (chunk_count > 0) flags |= XSCF_CHUNK_ID_LIST_PRESENT;
|
||||||
SlWriteUint32(flags);
|
SlWriteUint32(flags);
|
||||||
|
SlWriteUint16(save_version);
|
||||||
SlObject(const_cast<SlxiSubChunkInfo *>(info), _xlsi_sub_chunk_desc);
|
SlObject(const_cast<SlxiSubChunkInfo *>(info), _xlsi_sub_chunk_desc);
|
||||||
|
|
||||||
if (extra_data_length > 0) {
|
if (extra_data_length > 0) {
|
||||||
|
@@ -66,6 +66,8 @@ inline bool SlXvIsFeatureMissing(SlXvFeatureIndex feature)
|
|||||||
return !SlXvIsFeaturePresent(feature);
|
return !SlXvIsFeaturePresent(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *SlXvGetFeatureName(SlXvFeatureIndex feature);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sub chunk flags, this is saved as-is
|
* sub chunk flags, this is saved as-is
|
||||||
* (XSCF_EXTRA_DATA_PRESENT and XSCF_CHUNK_ID_LIST_PRESENT must only be set by the save code, and read by the load code)
|
* (XSCF_EXTRA_DATA_PRESENT and XSCF_CHUNK_ID_LIST_PRESENT must only be set by the save code, and read by the load code)
|
||||||
|
@@ -52,6 +52,7 @@
|
|||||||
|
|
||||||
#include "../safeguards.h"
|
#include "../safeguards.h"
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -566,7 +567,7 @@ void NORETURN SlError(StringID string, const char *extra_msg, bool already_mallo
|
|||||||
/**
|
/**
|
||||||
* As SlError, except that it takes a format string and additional parameters
|
* As SlError, except that it takes a format string and additional parameters
|
||||||
*/
|
*/
|
||||||
void CDECL NORETURN SlErrorFmt(StringID string, const char *msg, ...)
|
void NORETURN CDECL SlErrorFmt(StringID string, const char *msg, ...)
|
||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, msg);
|
va_start(va, msg);
|
||||||
@@ -590,7 +591,7 @@ void NORETURN SlErrorCorrupt(const char *msg, bool already_malloced)
|
|||||||
/**
|
/**
|
||||||
* As SlErrorCorruptFmt, except that it takes a format string and additional parameters
|
* As SlErrorCorruptFmt, except that it takes a format string and additional parameters
|
||||||
*/
|
*/
|
||||||
void CDECL NORETURN SlErrorCorruptFmt(const char *msg, ...)
|
void NORETURN CDECL SlErrorCorruptFmt(const char *msg, ...)
|
||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, msg);
|
va_start(va, msg);
|
||||||
@@ -890,9 +891,20 @@ void SlSetLength(size_t length)
|
|||||||
case CH_RIFF:
|
case CH_RIFF:
|
||||||
/* Ugly encoding of >16M RIFF chunks
|
/* Ugly encoding of >16M RIFF chunks
|
||||||
* The lower 24 bits are normal
|
* The lower 24 bits are normal
|
||||||
* The uppermost 4 bits are bits 24:27 */
|
* The uppermost 4 bits are bits 24:27
|
||||||
assert(length < (1 << 28));
|
*
|
||||||
|
* If we have more than 28 bits, use an extra uint32 and
|
||||||
|
* signal this using the extended chunk header */
|
||||||
|
assert(length < (1LL << 32));
|
||||||
|
if (length >= (1 << 28)) {
|
||||||
|
/* write out extended chunk header */
|
||||||
|
SlWriteByte(CH_EXT_HDR);
|
||||||
|
SlWriteUint32(static_cast<uint32>(SLCEHF_BIG_RIFF));
|
||||||
|
}
|
||||||
SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
|
SlWriteUint32((uint32)((length & 0xFFFFFF) | ((length >> 24) << 28)));
|
||||||
|
if (length >= (1 << 28)) {
|
||||||
|
SlWriteUint32(length >> 28);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CH_ARRAY:
|
case CH_ARRAY:
|
||||||
assert(_sl.last_array_index <= _sl.array_index);
|
assert(_sl.last_array_index <= _sl.array_index);
|
||||||
@@ -1355,9 +1367,10 @@ static void *IntToReference(size_t index, SLRefType rt)
|
|||||||
* Return the size in bytes of a list
|
* Return the size in bytes of a list
|
||||||
* @param list The std::list to find the size of
|
* @param list The std::list to find the size of
|
||||||
*/
|
*/
|
||||||
|
template<typename PtrList>
|
||||||
static inline size_t SlCalcListLen(const void *list)
|
static inline size_t SlCalcListLen(const void *list)
|
||||||
{
|
{
|
||||||
const std::list<void *> *l = (const std::list<void *> *) list;
|
const PtrList *l = (const PtrList *) list;
|
||||||
|
|
||||||
int type_size = IsSavegameVersionBefore(69) ? 2 : 4;
|
int type_size = IsSavegameVersionBefore(69) ? 2 : 4;
|
||||||
/* Each entry is saved as type_size bytes, plus type_size bytes are used for the length
|
/* Each entry is saved as type_size bytes, plus type_size bytes are used for the length
|
||||||
@@ -1371,23 +1384,23 @@ static inline size_t SlCalcListLen(const void *list)
|
|||||||
* @param list The list being manipulated
|
* @param list The list being manipulated
|
||||||
* @param conv SLRefType type of the list (Vehicle *, Station *, etc)
|
* @param conv SLRefType type of the list (Vehicle *, Station *, etc)
|
||||||
*/
|
*/
|
||||||
|
template<typename PtrList>
|
||||||
static void SlList(void *list, SLRefType conv)
|
static void SlList(void *list, SLRefType conv)
|
||||||
{
|
{
|
||||||
/* Automatically calculate the length? */
|
/* Automatically calculate the length? */
|
||||||
if (_sl.need_length != NL_NONE) {
|
if (_sl.need_length != NL_NONE) {
|
||||||
SlSetLength(SlCalcListLen(list));
|
SlSetLength(SlCalcListLen<PtrList>(list));
|
||||||
/* Determine length only? */
|
/* Determine length only? */
|
||||||
if (_sl.need_length == NL_CALCLENGTH) return;
|
if (_sl.need_length == NL_CALCLENGTH) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::list<void *> PtrList;
|
|
||||||
PtrList *l = (PtrList *)list;
|
PtrList *l = (PtrList *)list;
|
||||||
|
|
||||||
switch (_sl.action) {
|
switch (_sl.action) {
|
||||||
case SLA_SAVE: {
|
case SLA_SAVE: {
|
||||||
SlWriteUint32((uint32)l->size());
|
SlWriteUint32((uint32)l->size());
|
||||||
|
|
||||||
PtrList::iterator iter;
|
typename PtrList::iterator iter;
|
||||||
for (iter = l->begin(); iter != l->end(); ++iter) {
|
for (iter = l->begin(); iter != l->end(); ++iter) {
|
||||||
void *ptr = *iter;
|
void *ptr = *iter;
|
||||||
SlWriteUint32((uint32)ReferenceToInt(ptr, conv));
|
SlWriteUint32((uint32)ReferenceToInt(ptr, conv));
|
||||||
@@ -1409,7 +1422,7 @@ static void SlList(void *list, SLRefType conv)
|
|||||||
PtrList temp = *l;
|
PtrList temp = *l;
|
||||||
|
|
||||||
l->clear();
|
l->clear();
|
||||||
PtrList::iterator iter;
|
typename PtrList::iterator iter;
|
||||||
for (iter = temp.begin(); iter != temp.end(); ++iter) {
|
for (iter = temp.begin(); iter != temp.end(); ++iter) {
|
||||||
void *ptr = IntToReference((size_t)*iter, conv);
|
void *ptr = IntToReference((size_t)*iter, conv);
|
||||||
l->push_back(ptr);
|
l->push_back(ptr);
|
||||||
@@ -1475,6 +1488,8 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
|
|||||||
case SL_ARR:
|
case SL_ARR:
|
||||||
case SL_STR:
|
case SL_STR:
|
||||||
case SL_LST:
|
case SL_LST:
|
||||||
|
case SL_DEQ:
|
||||||
|
case SL_VEC:
|
||||||
/* CONDITIONAL saveload types depend on the savegame version */
|
/* CONDITIONAL saveload types depend on the savegame version */
|
||||||
if (!SlIsObjectValidInSavegame(sld)) break;
|
if (!SlIsObjectValidInSavegame(sld)) break;
|
||||||
|
|
||||||
@@ -1483,7 +1498,9 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
|
|||||||
case SL_REF: return SlCalcRefLen();
|
case SL_REF: return SlCalcRefLen();
|
||||||
case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
|
case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
|
||||||
case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
|
case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
|
||||||
case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld));
|
case SL_LST: return SlCalcListLen<std::list<void *>>(GetVariableAddress(object, sld));
|
||||||
|
case SL_DEQ: return SlCalcListLen<std::deque<void *>>(GetVariableAddress(object, sld));
|
||||||
|
case SL_VEC: return SlCalcListLen<std::vector<void *>>(GetVariableAddress(object, sld));
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1546,6 +1563,8 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld)
|
|||||||
case SL_ARR:
|
case SL_ARR:
|
||||||
case SL_STR:
|
case SL_STR:
|
||||||
case SL_LST:
|
case SL_LST:
|
||||||
|
case SL_DEQ:
|
||||||
|
case SL_VEC:
|
||||||
/* CONDITIONAL saveload types depend on the savegame version */
|
/* CONDITIONAL saveload types depend on the savegame version */
|
||||||
if (!SlIsObjectValidInSavegame(sld)) return false;
|
if (!SlIsObjectValidInSavegame(sld)) return false;
|
||||||
if (SlSkipVariableOnLoad(sld)) return false;
|
if (SlSkipVariableOnLoad(sld)) return false;
|
||||||
@@ -1572,7 +1591,9 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld)
|
|||||||
break;
|
break;
|
||||||
case SL_ARR: SlArray(ptr, sld->length, conv); break;
|
case SL_ARR: SlArray(ptr, sld->length, conv); break;
|
||||||
case SL_STR: SlString(ptr, sld->length, sld->conv); break;
|
case SL_STR: SlString(ptr, sld->length, sld->conv); break;
|
||||||
case SL_LST: SlList(ptr, (SLRefType)conv); break;
|
case SL_LST: SlList<std::list<void *>>(ptr, (SLRefType)conv); break;
|
||||||
|
case SL_DEQ: SlList<std::deque<void *>>(ptr, (SLRefType)conv); break;
|
||||||
|
case SL_VEC: SlList<std::vector<void *>>(ptr, (SLRefType)conv); break;
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1663,6 +1684,16 @@ void SlAutolength(AutolengthProc *proc, void *arg)
|
|||||||
if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
|
if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notes on extended chunk header:
|
||||||
|
*
|
||||||
|
* If the chunk type is CH_EXT_HDR (15), then a u32 flags field follows.
|
||||||
|
* This flag field may define additional fields which follow the flags field in future.
|
||||||
|
* The standard chunk header follows, though it my be modified by the flags field.
|
||||||
|
* At present SLCEHF_BIG_RIFF increases the RIFF size limit to a theoretical 60 bits,
|
||||||
|
* by adding a further u32 field for the high bits after the existing RIFF size field.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a chunk of data (eg vehicles, stations, etc.)
|
* Load a chunk of data (eg vehicles, stations, etc.)
|
||||||
* @param ch The chunkhandler that will be used for the operation
|
* @param ch The chunkhandler that will be used for the operation
|
||||||
@@ -1676,6 +1707,15 @@ static void SlLoadChunk(const ChunkHandler *ch)
|
|||||||
_sl.block_mode = m;
|
_sl.block_mode = m;
|
||||||
_sl.obj_len = 0;
|
_sl.obj_len = 0;
|
||||||
|
|
||||||
|
SaveLoadChunkExtHeaderFlags ext_flags = static_cast<SaveLoadChunkExtHeaderFlags>(0);
|
||||||
|
if ((m & 0xF) == CH_EXT_HDR) {
|
||||||
|
ext_flags = static_cast<SaveLoadChunkExtHeaderFlags>(SlReadUint32());
|
||||||
|
|
||||||
|
/* read in real header */
|
||||||
|
m = SlReadByte();
|
||||||
|
_sl.block_mode = m;
|
||||||
|
}
|
||||||
|
|
||||||
switch (m) {
|
switch (m) {
|
||||||
case CH_ARRAY:
|
case CH_ARRAY:
|
||||||
_sl.array_index = 0;
|
_sl.array_index = 0;
|
||||||
@@ -1691,6 +1731,10 @@ static void SlLoadChunk(const ChunkHandler *ch)
|
|||||||
/* Read length */
|
/* Read length */
|
||||||
len = (SlReadByte() << 16) | ((m >> 4) << 24);
|
len = (SlReadByte() << 16) | ((m >> 4) << 24);
|
||||||
len += SlReadUint16();
|
len += SlReadUint16();
|
||||||
|
if (ext_flags & SLCEHF_BIG_RIFF) {
|
||||||
|
len |= SlReadUint32() << 28;
|
||||||
|
}
|
||||||
|
|
||||||
_sl.obj_len = len;
|
_sl.obj_len = len;
|
||||||
endoffs = _sl.reader->GetSize() + len;
|
endoffs = _sl.reader->GetSize() + len;
|
||||||
ch->load_proc();
|
ch->load_proc();
|
||||||
@@ -1716,9 +1760,21 @@ static void SlLoadCheckChunk(const ChunkHandler *ch)
|
|||||||
_sl.block_mode = m;
|
_sl.block_mode = m;
|
||||||
_sl.obj_len = 0;
|
_sl.obj_len = 0;
|
||||||
|
|
||||||
|
SaveLoadChunkExtHeaderFlags ext_flags = static_cast<SaveLoadChunkExtHeaderFlags>(0);
|
||||||
|
if ((m & 0xF) == CH_EXT_HDR) {
|
||||||
|
ext_flags = static_cast<SaveLoadChunkExtHeaderFlags>(SlReadUint32());
|
||||||
|
|
||||||
|
/* read in real header */
|
||||||
|
m = SlReadByte();
|
||||||
|
_sl.block_mode = m;
|
||||||
|
}
|
||||||
|
|
||||||
switch (m) {
|
switch (m) {
|
||||||
case CH_ARRAY:
|
case CH_ARRAY:
|
||||||
_sl.array_index = 0;
|
_sl.array_index = 0;
|
||||||
|
if (ext_flags) {
|
||||||
|
SlErrorCorruptFmt("CH_ARRAY does not take chunk header extension flags: 0x%X", ext_flags);
|
||||||
|
}
|
||||||
if (ch && ch->load_check_proc) {
|
if (ch && ch->load_check_proc) {
|
||||||
ch->load_check_proc();
|
ch->load_check_proc();
|
||||||
} else {
|
} else {
|
||||||
@@ -1726,6 +1782,9 @@ static void SlLoadCheckChunk(const ChunkHandler *ch)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CH_SPARSE_ARRAY:
|
case CH_SPARSE_ARRAY:
|
||||||
|
if (ext_flags) {
|
||||||
|
SlErrorCorruptFmt("CH_SPARSE_ARRAY does not take chunk header extension flags: 0x%X", ext_flags);
|
||||||
|
}
|
||||||
if (ch && ch->load_check_proc) {
|
if (ch && ch->load_check_proc) {
|
||||||
ch->load_check_proc();
|
ch->load_check_proc();
|
||||||
} else {
|
} else {
|
||||||
@@ -1734,9 +1793,19 @@ static void SlLoadCheckChunk(const ChunkHandler *ch)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if ((m & 0xF) == CH_RIFF) {
|
if ((m & 0xF) == CH_RIFF) {
|
||||||
|
if (ext_flags != (ext_flags & SLCEHF_BIG_RIFF)) {
|
||||||
|
SlErrorCorruptFmt("Unknown chunk header extension flags for CH_RIFF: 0x%X", ext_flags);
|
||||||
|
}
|
||||||
/* Read length */
|
/* Read length */
|
||||||
len = (SlReadByte() << 16) | ((m >> 4) << 24);
|
len = (SlReadByte() << 16) | ((m >> 4) << 24);
|
||||||
len += SlReadUint16();
|
len += SlReadUint16();
|
||||||
|
if (ext_flags & SLCEHF_BIG_RIFF) {
|
||||||
|
uint64 full_len = len | (static_cast<uint64>(SlReadUint32()) << 28);
|
||||||
|
if (full_len >= (1LL << 32)) {
|
||||||
|
SlErrorCorrupt("Chunk size too large: " OTTD_PRINTFHEX64, full_len);
|
||||||
|
}
|
||||||
|
len = static_cast<size_t>(full_len);
|
||||||
|
}
|
||||||
_sl.obj_len = len;
|
_sl.obj_len = len;
|
||||||
endoffs = _sl.reader->GetSize() + len;
|
endoffs = _sl.reader->GetSize() + len;
|
||||||
if (ch && ch->load_check_proc) {
|
if (ch && ch->load_check_proc) {
|
||||||
|
@@ -104,10 +104,17 @@ enum ChunkType {
|
|||||||
CH_ARRAY = 1,
|
CH_ARRAY = 1,
|
||||||
CH_SPARSE_ARRAY = 2,
|
CH_SPARSE_ARRAY = 2,
|
||||||
CH_TYPE_MASK = 3,
|
CH_TYPE_MASK = 3,
|
||||||
|
CH_EXT_HDR = 15, ///< Extended chunk header
|
||||||
CH_LAST = 8, ///< Last chunk in this array.
|
CH_LAST = 8, ///< Last chunk in this array.
|
||||||
CH_AUTO_LENGTH = 16,
|
CH_AUTO_LENGTH = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Flags for chunk extended headers */
|
||||||
|
enum SaveLoadChunkExtHeaderFlags {
|
||||||
|
SLCEHF_BIG_RIFF = 1 << 0, ///< This block uses a 60-bit RIFF chunk size
|
||||||
|
};
|
||||||
|
DECLARE_ENUM_AS_BIT_SET(SaveLoadChunkExtHeaderFlags)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VarTypes is the general bitmasked magic type that tells us
|
* VarTypes is the general bitmasked magic type that tells us
|
||||||
* certain characteristics about the variable it refers to. For example
|
* certain characteristics about the variable it refers to. For example
|
||||||
@@ -198,6 +205,8 @@ enum SaveLoadTypes {
|
|||||||
SL_ARR = 2, ///< Save/load an array.
|
SL_ARR = 2, ///< Save/load an array.
|
||||||
SL_STR = 3, ///< Save/load a string.
|
SL_STR = 3, ///< Save/load a string.
|
||||||
SL_LST = 4, ///< Save/load a list.
|
SL_LST = 4, ///< Save/load a list.
|
||||||
|
SL_DEQ = 5, ///< Save/load a deque.
|
||||||
|
SL_VEC = 6, ///< Save/load a vector.
|
||||||
/* non-normal save-load types */
|
/* non-normal save-load types */
|
||||||
SL_WRITEBYTE = 8,
|
SL_WRITEBYTE = 8,
|
||||||
SL_VEH_INCLUDE = 9,
|
SL_VEH_INCLUDE = 9,
|
||||||
@@ -303,6 +312,30 @@ typedef SaveLoad SaveLoadGlobVarList;
|
|||||||
#define SLE_CONDLST_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_LST, base, variable, type, 0, from, to, extver)
|
#define SLE_CONDLST_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_LST, base, variable, type, 0, from, to, extver)
|
||||||
#define SLE_CONDLST(base, variable, type, from, to) SLE_CONDLST_X(base, variable, type, from, to, SlXvFeatureTest())
|
#define SLE_CONDLST(base, variable, type, from, to) SLE_CONDLST_X(base, variable, type, from, to, SlXvFeatureTest())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storage of a deque in some savegame versions.
|
||||||
|
* @param base Name of the class or struct containing the list.
|
||||||
|
* @param variable Name of the variable in the class or struct referenced by \a base.
|
||||||
|
* @param type Storage of the data in memory and in the savegame.
|
||||||
|
* @param from First savegame version that has the list.
|
||||||
|
* @param to Last savegame version that has the list.
|
||||||
|
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||||
|
*/
|
||||||
|
#define SLE_CONDDEQ_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_DEQ, base, variable, type, 0, from, to, extver)
|
||||||
|
#define SLE_CONDDEQ(base, variable, type, from, to) SLE_CONDDEQ_X(base, variable, type, from, to, SlXvFeatureTest())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storage of a vector in some savegame versions.
|
||||||
|
* @param base Name of the class or struct containing the list.
|
||||||
|
* @param variable Name of the variable in the class or struct referenced by \a base.
|
||||||
|
* @param type Storage of the data in memory and in the savegame.
|
||||||
|
* @param from First savegame version that has the list.
|
||||||
|
* @param to Last savegame version that has the list.
|
||||||
|
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||||
|
*/
|
||||||
|
#define SLE_CONDVEC_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_VEC, base, variable, type, 0, from, to, extver)
|
||||||
|
#define SLE_CONDVEC(base, variable, type, from, to) SLE_CONDVEC_X(base, variable, type, from, to, SlXvFeatureTest())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage of a variable in every version of a savegame.
|
* Storage of a variable in every version of a savegame.
|
||||||
* @param base Name of the class or struct containing the variable.
|
* @param base Name of the class or struct containing the variable.
|
||||||
@@ -345,6 +378,22 @@ typedef SaveLoad SaveLoadGlobVarList;
|
|||||||
*/
|
*/
|
||||||
#define SLE_LST(base, variable, type) SLE_CONDLST(base, variable, type, 0, SL_MAX_VERSION)
|
#define SLE_LST(base, variable, type) SLE_CONDLST(base, variable, type, 0, SL_MAX_VERSION)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storage of a deque in every savegame version.
|
||||||
|
* @param base Name of the class or struct containing the list.
|
||||||
|
* @param variable Name of the variable in the class or struct referenced by \a base.
|
||||||
|
* @param type Storage of the data in memory and in the savegame.
|
||||||
|
*/
|
||||||
|
#define SLE_DEQ(base, variable, type) SLE_CONDDEQ(base, variable, type, 0, SL_MAX_VERSION)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storage of a vector in every savegame version.
|
||||||
|
* @param base Name of the class or struct containing the list.
|
||||||
|
* @param variable Name of the variable in the class or struct referenced by \a base.
|
||||||
|
* @param type Storage of the data in memory and in the savegame.
|
||||||
|
*/
|
||||||
|
#define SLE_VEC(base, variable, type) SLE_CONDVEC(base, variable, type, 0, SL_MAX_VERSION)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty space in every savegame version.
|
* Empty space in every savegame version.
|
||||||
* @param length Length of the empty space.
|
* @param length Length of the empty space.
|
||||||
@@ -440,6 +489,28 @@ typedef SaveLoad SaveLoadGlobVarList;
|
|||||||
#define SLEG_CONDLST_X(variable, type, from, to, extver) SLEG_GENERAL_X(SL_LST, variable, type, 0, from, to, extver)
|
#define SLEG_CONDLST_X(variable, type, from, to, extver) SLEG_GENERAL_X(SL_LST, variable, type, 0, from, to, extver)
|
||||||
#define SLEG_CONDLST(variable, type, from, to) SLEG_CONDLST_X(variable, type, from, to, SlXvFeatureTest())
|
#define SLEG_CONDLST(variable, type, from, to) SLEG_CONDLST_X(variable, type, from, to, SlXvFeatureTest())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storage of a global deque in some savegame versions.
|
||||||
|
* @param variable Name of the global variable.
|
||||||
|
* @param type Storage of the data in memory and in the savegame.
|
||||||
|
* @param from First savegame version that has the list.
|
||||||
|
* @param to Last savegame version that has the list.
|
||||||
|
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||||
|
*/
|
||||||
|
#define SLEG_CONDDEQ_X(variable, type, from, to, extver) SLEG_GENERAL_X(SL_DEQ, variable, type, 0, from, to, extver)
|
||||||
|
#define SLEG_CONDDEQ(variable, type, from, to) SLEG_CONDDEQ_X(variable, type, from, to, SlXvFeatureTest())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storage of a global vector in some savegame versions.
|
||||||
|
* @param variable Name of the global variable.
|
||||||
|
* @param type Storage of the data in memory and in the savegame.
|
||||||
|
* @param from First savegame version that has the list.
|
||||||
|
* @param to Last savegame version that has the list.
|
||||||
|
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
|
||||||
|
*/
|
||||||
|
#define SLEG_CONDVEC_X(variable, type, from, to, extver) SLEG_GENERAL_X(SL_VEC, variable, type, 0, from, to, extver)
|
||||||
|
#define SLEG_CONDVEC(variable, type, from, to) SLEG_CONDVEC_X(variable, type, from, to, SlXvFeatureTest())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage of a global variable in every savegame version.
|
* Storage of a global variable in every savegame version.
|
||||||
* @param variable Name of the global variable.
|
* @param variable Name of the global variable.
|
||||||
@@ -475,6 +546,20 @@ typedef SaveLoad SaveLoadGlobVarList;
|
|||||||
*/
|
*/
|
||||||
#define SLEG_LST(variable, type) SLEG_CONDLST(variable, type, 0, SL_MAX_VERSION)
|
#define SLEG_LST(variable, type) SLEG_CONDLST(variable, type, 0, SL_MAX_VERSION)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storage of a global deque in every savegame version.
|
||||||
|
* @param variable Name of the global variable.
|
||||||
|
* @param type Storage of the data in memory and in the savegame.
|
||||||
|
*/
|
||||||
|
#define SLEG_DEQ(variable, type) SLEG_CONDDEQ(variable, type, 0, SL_MAX_VERSION)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storage of a global vector in every savegame version.
|
||||||
|
* @param variable Name of the global variable.
|
||||||
|
* @param type Storage of the data in memory and in the savegame.
|
||||||
|
*/
|
||||||
|
#define SLEG_VEC(variable, type) SLEG_CONDVEC(variable, type, 0, SL_MAX_VERSION)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty global space in some savegame versions.
|
* Empty global space in some savegame versions.
|
||||||
* @param length Length of the empty space.
|
* @param length Length of the empty space.
|
||||||
@@ -629,8 +714,8 @@ void SlObject(void *object, const SaveLoad *sld);
|
|||||||
bool SlObjectMember(void *object, const SaveLoad *sld);
|
bool SlObjectMember(void *object, const SaveLoad *sld);
|
||||||
void NORETURN SlError(StringID string, const char *extra_msg = NULL, bool already_malloced = false);
|
void NORETURN SlError(StringID string, const char *extra_msg = NULL, bool already_malloced = false);
|
||||||
void NORETURN SlErrorCorrupt(const char *msg, bool already_malloced = false);
|
void NORETURN SlErrorCorrupt(const char *msg, bool already_malloced = false);
|
||||||
void CDECL NORETURN SlErrorFmt(StringID string, const char *msg, ...) WARN_FORMAT(2, 3);
|
void NORETURN CDECL SlErrorFmt(StringID string, const char *msg, ...) WARN_FORMAT(2, 3);
|
||||||
void CDECL NORETURN SlErrorCorruptFmt(const char *msg, ...) WARN_FORMAT(1, 2);
|
void NORETURN CDECL SlErrorCorruptFmt(const char *msg, ...) WARN_FORMAT(1, 2);
|
||||||
|
|
||||||
bool SaveloadCrashWithMissingNewGRFs();
|
bool SaveloadCrashWithMissingNewGRFs();
|
||||||
|
|
||||||
|
258
src/settings.cpp
258
src/settings.cpp
@@ -2235,10 +2235,10 @@ static void SaveSettings(const SettingDesc *sd, void *object)
|
|||||||
*
|
*
|
||||||
* The PATX chunk contents has the following format:
|
* The PATX chunk contents has the following format:
|
||||||
*
|
*
|
||||||
* uint32 chunk flags
|
* uint32 chunk flags (unused)
|
||||||
* uint32 number of settings
|
* uint32 number of settings
|
||||||
* For each of N settings:
|
* For each of N settings:
|
||||||
* uint32 setting flags
|
* uint32 setting flags (unused)
|
||||||
* SLE_STR setting name
|
* SLE_STR setting name
|
||||||
* uint32 length of setting field
|
* uint32 length of setting field
|
||||||
* N bytes setting field
|
* N bytes setting field
|
||||||
@@ -2257,6 +2257,7 @@ static void MakeSettingsPatxList(const SettingDesc *sd)
|
|||||||
static const SettingDesc *previous = NULL;
|
static const SettingDesc *previous = NULL;
|
||||||
|
|
||||||
if (sd == previous) return;
|
if (sd == previous) return;
|
||||||
|
previous = sd;
|
||||||
|
|
||||||
_sorted_patx_settings.clear();
|
_sorted_patx_settings.clear();
|
||||||
for (const SettingDesc *desc = sd; desc->save.cmd != SL_END; desc++) {
|
for (const SettingDesc *desc = sd; desc->save.cmd != SL_END; desc++) {
|
||||||
@@ -2264,15 +2265,42 @@ static void MakeSettingsPatxList(const SettingDesc *sd)
|
|||||||
_sorted_patx_settings.push_back(desc);
|
_sorted_patx_settings.push_back(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this makes me miss lambdas :/
|
std::sort(_sorted_patx_settings.begin(), _sorted_patx_settings.end(), [](const SettingDesc *a, const SettingDesc *b) {
|
||||||
struct StringSorter {
|
|
||||||
bool operator()(const SettingDesc *a, const SettingDesc *b)
|
|
||||||
{
|
|
||||||
return strcmp(a->patx_name, b->patx_name) < 0;
|
return strcmp(a->patx_name, b->patx_name) < 0;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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()
|
||||||
};
|
};
|
||||||
std::sort(_sorted_patx_settings.begin(), _sorted_patx_settings.end(), StringSorter());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load handler for settings which go in the PATX chunk
|
* Load handler for settings which go in the PATX chunk
|
||||||
@@ -2284,19 +2312,7 @@ static void LoadSettingsPatx(const SettingDesc *sd, void *object)
|
|||||||
{
|
{
|
||||||
MakeSettingsPatxList(sd);
|
MakeSettingsPatxList(sd);
|
||||||
|
|
||||||
struct SettingsPatxLoad {
|
SettingsExtLoad current_setting;
|
||||||
uint32 flags;
|
|
||||||
char name[256];
|
|
||||||
uint32 setting_length;
|
|
||||||
};
|
|
||||||
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()
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32 flags = SlReadUint32();
|
uint32 flags = SlReadUint32();
|
||||||
// flags are not in use yet, reserve for future expansion
|
// flags are not in use yet, reserve for future expansion
|
||||||
@@ -2304,27 +2320,18 @@ static void LoadSettingsPatx(const SettingDesc *sd, void *object)
|
|||||||
|
|
||||||
uint32 settings_count = SlReadUint32();
|
uint32 settings_count = SlReadUint32();
|
||||||
for (uint32 i = 0; i < settings_count; i++) {
|
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
|
// 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);
|
if (current_setting.flags != 0) SlErrorCorruptFmt("PATX chunk: unknown setting header flags: 0x%X", current_setting.flags);
|
||||||
|
|
||||||
// now try to find corresponding setting, this would be much easier with C++11 support...
|
// now try to find corresponding setting
|
||||||
bool exact_match = false;
|
bool exact_match = false;
|
||||||
struct StringSearcher {
|
auto iter = std::lower_bound(_sorted_patx_settings.begin(), _sorted_patx_settings.end(), current_setting.name, [&](const SettingDesc *a, const char *b) {
|
||||||
bool &m_exact_match;
|
|
||||||
|
|
||||||
StringSearcher(bool &exact_match)
|
|
||||||
: m_exact_match(exact_match) { }
|
|
||||||
|
|
||||||
bool operator()(const SettingDesc *a, const char *b)
|
|
||||||
{
|
|
||||||
int result = strcmp(a->patx_name, b);
|
int result = strcmp(a->patx_name, b);
|
||||||
if (result == 0) m_exact_match = true;
|
if (result == 0) exact_match = true;
|
||||||
return result < 0;
|
return result < 0;
|
||||||
}
|
});
|
||||||
};
|
|
||||||
std::vector<const SettingDesc *>::iterator iter = std::lower_bound(_sorted_patx_settings.begin(), _sorted_patx_settings.end(), current_setting.name, StringSearcher(exact_match));
|
|
||||||
|
|
||||||
if (exact_match) {
|
if (exact_match) {
|
||||||
assert(iter != _sorted_patx_settings.end());
|
assert(iter != _sorted_patx_settings.end());
|
||||||
@@ -2352,19 +2359,7 @@ static void LoadSettingsPatx(const SettingDesc *sd, void *object)
|
|||||||
*/
|
*/
|
||||||
static void SaveSettingsPatx(const SettingDesc *sd, void *object)
|
static void SaveSettingsPatx(const SettingDesc *sd, void *object)
|
||||||
{
|
{
|
||||||
struct SettingsPatxSave {
|
SettingsExtSave current_setting;
|
||||||
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()
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SettingToAdd {
|
struct SettingToAdd {
|
||||||
const SettingDesc *setting;
|
const SettingDesc *setting;
|
||||||
@@ -2381,12 +2376,14 @@ static void SaveSettingsPatx(const SettingDesc *sd, void *object)
|
|||||||
current_setting.name = desc->patx_name;
|
current_setting.name = desc->patx_name;
|
||||||
|
|
||||||
// add length of setting header
|
// 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
|
// add length of actual setting
|
||||||
length += setting_length;
|
length += setting_length;
|
||||||
|
|
||||||
settings_to_add.push_back({ desc, setting_length });
|
// duplicate copy made for compiler backwards compatibility
|
||||||
|
SettingToAdd new_setting = { desc, setting_length };
|
||||||
|
settings_to_add.push_back(new_setting);
|
||||||
}
|
}
|
||||||
SlSetLength(length);
|
SlSetLength(length);
|
||||||
|
|
||||||
@@ -2398,12 +2395,171 @@ static void SaveSettingsPatx(const SettingDesc *sd, void *object)
|
|||||||
current_setting.flags = 0;
|
current_setting.flags = 0;
|
||||||
current_setting.name = desc->patx_name;
|
current_setting.name = desc->patx_name;
|
||||||
current_setting.setting_length = settings_to_add[i].setting_length;
|
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);
|
void *ptr = GetVariableAddress(object, &desc->save);
|
||||||
SlObjectMember(ptr, &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()
|
static void Load_OPTS()
|
||||||
{
|
{
|
||||||
/* Copy over default setting since some might not get loaded in
|
/* Copy over default setting since some might not get loaded in
|
||||||
|
@@ -18,8 +18,8 @@ static const SettingDesc _company_settings[] = {
|
|||||||
[post-amble]
|
[post-amble]
|
||||||
};
|
};
|
||||||
[templates]
|
[templates]
|
||||||
SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $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, NULL),
|
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()
|
SDT_END = SDT_END()
|
||||||
|
|
||||||
[defaults]
|
[defaults]
|
||||||
@@ -35,6 +35,7 @@ from = 0
|
|||||||
to = SL_MAX_VERSION
|
to = SL_MAX_VERSION
|
||||||
cat = SC_ADVANCED
|
cat = SC_ADVANCED
|
||||||
extver = SlXvFeatureTest()
|
extver = SlXvFeatureTest()
|
||||||
|
patxname = NULL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user