2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 /** @file engine_sl.cpp Code handling saving and loading of engines */
10 #include "../stdafx.h"
13 #include "compat/engine_sl_compat.h"
15 #include "saveload_internal.h"
16 #include "../engine_base.h"
17 #include "../string_func.h"
19 #include "../safeguards.h"
21 static const SaveLoad _engine_desc
[] = {
22 SLE_CONDVAR(Engine
, intro_date
, SLE_FILE_U16
| SLE_VAR_I32
, SL_MIN_VERSION
, SLV_31
),
23 SLE_CONDVAR(Engine
, intro_date
, SLE_INT32
, SLV_31
, SL_MAX_VERSION
),
24 SLE_CONDVAR(Engine
, age
, SLE_FILE_U16
| SLE_VAR_I32
, SL_MIN_VERSION
, SLV_31
),
25 SLE_CONDVAR(Engine
, age
, SLE_INT32
, SLV_31
, SL_MAX_VERSION
),
26 SLE_VAR(Engine
, reliability
, SLE_UINT16
),
27 SLE_VAR(Engine
, reliability_spd_dec
, SLE_UINT16
),
28 SLE_VAR(Engine
, reliability_start
, SLE_UINT16
),
29 SLE_VAR(Engine
, reliability_max
, SLE_UINT16
),
30 SLE_VAR(Engine
, reliability_final
, SLE_UINT16
),
31 SLE_VAR(Engine
, duration_phase_1
, SLE_UINT16
),
32 SLE_VAR(Engine
, duration_phase_2
, SLE_UINT16
),
33 SLE_VAR(Engine
, duration_phase_3
, SLE_UINT16
),
34 SLE_VAR(Engine
, flags
, SLE_UINT8
),
35 SLE_CONDVAR(Engine
, preview_asked
, SLE_UINT16
, SLV_179
, SL_MAX_VERSION
),
36 SLE_CONDVAR(Engine
, preview_company
, SLE_UINT8
, SLV_179
, SL_MAX_VERSION
),
37 SLE_VAR(Engine
, preview_wait
, SLE_UINT8
),
38 SLE_CONDVAR(Engine
, company_avail
, SLE_FILE_U8
| SLE_VAR_U16
, SL_MIN_VERSION
, SLV_104
),
39 SLE_CONDVAR(Engine
, company_avail
, SLE_UINT16
, SLV_104
, SL_MAX_VERSION
),
40 SLE_CONDVAR(Engine
, company_hidden
, SLE_UINT16
, SLV_193
, SL_MAX_VERSION
),
41 SLE_CONDSSTR(Engine
, name
, SLE_STR
, SLV_84
, SL_MAX_VERSION
),
44 static std::vector
<Engine
*> _temp_engine
;
47 * Allocate an Engine structure, but not using the pools.
48 * The allocated Engine must be freed using FreeEngine;
49 * @return Allocated engine.
51 static Engine
*CallocEngine()
53 uint8_t *zero
= CallocT
<uint8_t>(sizeof(Engine
));
54 Engine
*engine
= new (zero
) Engine();
59 * Deallocate an Engine constructed by CallocEngine.
60 * @param e Engine to free.
62 static void FreeEngine(Engine
*e
)
70 Engine
*GetTempDataEngine(EngineID index
)
72 if (index
< _temp_engine
.size()) {
73 return _temp_engine
[index
];
74 } else if (index
== _temp_engine
.size()) {
75 _temp_engine
.push_back(CallocEngine());
76 return _temp_engine
[index
];
82 struct ENGNChunkHandler
: ChunkHandler
{
83 ENGNChunkHandler() : ChunkHandler('ENGN', CH_TABLE
) {}
85 void Save() const override
87 SlTableHeader(_engine_desc
);
89 for (Engine
*e
: Engine::Iterate()) {
90 SlSetArrayIndex(e
->index
);
91 SlObject(e
, _engine_desc
);
95 void Load() const override
97 const std::vector
<SaveLoad
> slt
= SlCompatTableHeader(_engine_desc
, _engine_sl_compat
);
99 /* As engine data is loaded before engines are initialized we need to load
100 * this information into a temporary array. This is then copied into the
101 * engine pool after processing NewGRFs by CopyTempEngineData(). */
103 while ((index
= SlIterateArray()) != -1) {
104 Engine
*e
= GetTempDataEngine(index
);
107 if (IsSavegameVersionBefore(SLV_179
)) {
108 /* preview_company_rank was replaced with preview_company and preview_asked.
109 * Just cancel any previews. */
110 e
->flags
&= ~4; // ENGINE_OFFER_WINDOW_OPEN
111 e
->preview_company
= INVALID_COMPANY
;
112 e
->preview_asked
= MAX_UVALUE(CompanyMask
);
119 * Copy data from temporary engine array into the real engine pool.
121 void CopyTempEngineData()
123 for (Engine
*e
: Engine::Iterate()) {
124 if (e
->index
>= _temp_engine
.size()) break;
126 const Engine
*se
= GetTempDataEngine(e
->index
);
127 e
->intro_date
= se
->intro_date
;
129 e
->reliability
= se
->reliability
;
130 e
->reliability_spd_dec
= se
->reliability_spd_dec
;
131 e
->reliability_start
= se
->reliability_start
;
132 e
->reliability_max
= se
->reliability_max
;
133 e
->reliability_final
= se
->reliability_final
;
134 e
->duration_phase_1
= se
->duration_phase_1
;
135 e
->duration_phase_2
= se
->duration_phase_2
;
136 e
->duration_phase_3
= se
->duration_phase_3
;
137 e
->flags
= se
->flags
;
138 e
->preview_asked
= se
->preview_asked
;
139 e
->preview_company
= se
->preview_company
;
140 e
->preview_wait
= se
->preview_wait
;
141 e
->company_avail
= se
->company_avail
;
142 e
->company_hidden
= se
->company_hidden
;
146 ResetTempEngineData();
149 void ResetTempEngineData()
151 /* Get rid of temporary data */
152 for (std::vector
<Engine
*>::iterator it
= _temp_engine
.begin(); it
!= _temp_engine
.end(); ++it
) {
155 _temp_engine
.clear();
158 struct ENGSChunkHandler
: ChunkHandler
{
159 ENGSChunkHandler() : ChunkHandler('ENGS', CH_READONLY
) {}
161 void Load() const override
163 /* Load old separate String ID list into a temporary array. This
164 * was always 256 entries. */
167 SlCopy(names
, lengthof(names
), SLE_STRINGID
);
169 /* Copy each string into the temporary engine array. */
170 for (EngineID engine
= 0; engine
< lengthof(names
); engine
++) {
171 Engine
*e
= GetTempDataEngine(engine
);
172 e
->name
= CopyFromOldName(names
[engine
]);
177 /** Save and load the mapping between the engine id in the pool, and the grf file it came from. */
178 static const SaveLoad _engine_id_mapping_desc
[] = {
179 SLE_VAR(EngineIDMapping
, grfid
, SLE_UINT32
),
180 SLE_VAR(EngineIDMapping
, internal_id
, SLE_UINT16
),
181 SLE_VAR(EngineIDMapping
, type
, SLE_UINT8
),
182 SLE_VAR(EngineIDMapping
, substitute_id
, SLE_UINT8
),
185 struct EIDSChunkHandler
: ChunkHandler
{
186 EIDSChunkHandler() : ChunkHandler('EIDS', CH_TABLE
) {}
188 void Save() const override
190 SlTableHeader(_engine_id_mapping_desc
);
193 for (EngineIDMapping
&eid
: _engine_mngr
) {
194 SlSetArrayIndex(index
);
195 SlObject(&eid
, _engine_id_mapping_desc
);
200 void Load() const override
202 const std::vector
<SaveLoad
> slt
= SlCompatTableHeader(_engine_id_mapping_desc
, _engine_id_mapping_sl_compat
);
204 _engine_mngr
.clear();
206 while (SlIterateArray() != -1) {
207 EngineIDMapping
*eid
= &_engine_mngr
.emplace_back();
213 static const EIDSChunkHandler EIDS
;
214 static const ENGNChunkHandler ENGN
;
215 static const ENGSChunkHandler ENGS
;
216 static const ChunkHandlerRef engine_chunk_handlers
[] = {
222 extern const ChunkHandlerTable
_engine_chunk_handlers(engine_chunk_handlers
);