OpenTTD Source 20250328-master-gc3457cd4c0
newgrf_act7_9.cpp
Go to the documentation of this file.
1/*
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/>.
6 */
7
10#include "../stdafx.h"
11#include "../debug.h"
12#include "../genworld.h"
13#include "../network/network.h"
14#include "../newgrf_engine.h"
15#include "../newgrf_cargo.h"
16#include "../rail.h"
17#include "../road.h"
18#include "../settings_type.h"
19#include "newgrf_bytereader.h"
20#include "newgrf_internal.h"
21
22#include "../safeguards.h"
23
25static std::array<uint32_t, 8> _ttdpatch_flags;
26
29{
30 _ttdpatch_flags[0] = ((_settings_game.station.never_expire_airports ? 1U : 0U) << 0x0C) // keepsmallairport
31 | (1U << 0x0D) // newairports
32 | (1U << 0x0E) // largestations
33 | ((_settings_game.construction.max_bridge_length > 16 ? 1U : 0U) << 0x0F) // longbridges
34 | (0U << 0x10) // loadtime
35 | (1U << 0x12) // presignals
36 | (1U << 0x13) // extpresignals
37 | ((_settings_game.vehicle.never_expire_vehicles ? 1U : 0U) << 0x16) // enginespersist
38 | (1U << 0x1B) // multihead
39 | (1U << 0x1D) // lowmemory
40 | (1U << 0x1E); // generalfixes
41
42 _ttdpatch_flags[1] = ((_settings_game.economy.station_noise_level ? 1U : 0U) << 0x07) // moreairports - based on units of noise
43 | (1U << 0x08) // mammothtrains
44 | (1U << 0x09) // trainrefit
45 | (0U << 0x0B) // subsidiaries
46 | ((_settings_game.order.gradual_loading ? 1U : 0U) << 0x0C) // gradualloading
47 | (1U << 0x12) // unifiedmaglevmode - set bit 0 mode. Not revelant to OTTD
48 | (1U << 0x13) // unifiedmaglevmode - set bit 1 mode
49 | (1U << 0x14) // bridgespeedlimits
50 | (1U << 0x16) // eternalgame
51 | (1U << 0x17) // newtrains
52 | (1U << 0x18) // newrvs
53 | (1U << 0x19) // newships
54 | (1U << 0x1A) // newplanes
55 | ((_settings_game.construction.train_signal_side == 1 ? 1U : 0U) << 0x1B) // signalsontrafficside
56 | ((_settings_game.vehicle.disable_elrails ? 0U : 1U) << 0x1C); // electrifiedrailway
57
58 _ttdpatch_flags[2] = (1U << 0x01) // loadallgraphics - obsolote
59 | (1U << 0x03) // semaphores
60 | (1U << 0x0A) // newobjects
61 | (0U << 0x0B) // enhancedgui
62 | (0U << 0x0C) // newagerating
63 | ((_settings_game.construction.build_on_slopes ? 1U : 0U) << 0x0D) // buildonslopes
64 | (1U << 0x0E) // fullloadany
65 | (1U << 0x0F) // planespeed
66 | (0U << 0x10) // moreindustriesperclimate - obsolete
67 | (0U << 0x11) // moretoylandfeatures
68 | (1U << 0x12) // newstations
69 | (1U << 0x13) // tracktypecostdiff
70 | (1U << 0x14) // manualconvert
71 | ((_settings_game.construction.build_on_slopes ? 1U : 0U) << 0x15) // buildoncoasts
72 | (1U << 0x16) // canals
73 | (1U << 0x17) // newstartyear
74 | ((_settings_game.vehicle.freight_trains > 1 ? 1U : 0U) << 0x18) // freighttrains
75 | (1U << 0x19) // newhouses
76 | (1U << 0x1A) // newbridges
77 | (1U << 0x1B) // newtownnames
78 | (1U << 0x1C) // moreanimation
79 | ((_settings_game.vehicle.wagon_speed_limits ? 1U : 0U) << 0x1D) // wagonspeedlimits
80 | (1U << 0x1E) // newshistory
81 | (0U << 0x1F); // custombridgeheads
82
83 _ttdpatch_flags[3] = (0U << 0x00) // newcargodistribution
84 | (1U << 0x01) // windowsnap
85 | ((_settings_game.economy.allow_town_roads || _generating_world ? 0U : 1U) << 0x02) // townbuildnoroad
86 | (1U << 0x03) // pathbasedsignalling
87 | (0U << 0x04) // aichoosechance
88 | (1U << 0x05) // resolutionwidth
89 | (1U << 0x06) // resolutionheight
90 | (1U << 0x07) // newindustries
91 | ((_settings_game.order.improved_load ? 1U : 0U) << 0x08) // fifoloading
92 | (0U << 0x09) // townroadbranchprob
93 | (0U << 0x0A) // tempsnowline
94 | (1U << 0x0B) // newcargo
95 | (1U << 0x0C) // enhancemultiplayer
96 | (1U << 0x0D) // onewayroads
97 | (1U << 0x0E) // irregularstations
98 | (1U << 0x0F) // statistics
99 | (1U << 0x10) // newsounds
100 | (1U << 0x11) // autoreplace
101 | (1U << 0x12) // autoslope
102 | (0U << 0x13) // followvehicle
103 | (1U << 0x14) // trams
104 | (0U << 0x15) // enhancetunnels
105 | (1U << 0x16) // shortrvs
106 | (1U << 0x17) // articulatedrvs
107 | ((_settings_game.vehicle.dynamic_engines ? 1U : 0U) << 0x18) // dynamic engines
108 | (1U << 0x1E) // variablerunningcosts
109 | (1U << 0x1F); // any switch is on
110
111 _ttdpatch_flags[4] = (1U << 0x00) // larger persistent storage
112 | ((_settings_game.economy.inflation ? 1U : 0U) << 0x01) // inflation is on
113 | (1U << 0x02); // extended string range
114}
115
116uint32_t GetParamVal(uint8_t param, uint32_t *cond_val)
117{
118 /* First handle variable common with VarAction2 */
119 uint32_t value;
120 if (GetGlobalVariable(param - 0x80, &value, _cur.grffile)) return value;
121
122
123 /* Non-common variable */
124 switch (param) {
125 case 0x84: { // GRF loading stage
126 uint32_t res = 0;
127
128 if (_cur.stage > GLS_INIT) SetBit(res, 0);
129 if (_cur.stage == GLS_RESERVE) SetBit(res, 8);
130 if (_cur.stage == GLS_ACTIVATION) SetBit(res, 9);
131 return res;
132 }
133
134 case 0x85: // TTDPatch flags, only for bit tests
135 if (cond_val == nullptr) {
136 /* Supported in Action 0x07 and 0x09, not 0x0D */
137 return 0;
138 } else {
139 uint32_t index = *cond_val / 0x20;
140 uint32_t param_val = index < std::size(_ttdpatch_flags) ? _ttdpatch_flags[index] : 0;
141 *cond_val %= 0x20;
142 return param_val;
143 }
144
145 case 0x88: // GRF ID check
146 return 0;
147
148 /* case 0x99: Global ID offset not implemented */
149
150 default:
151 /* GRF Parameter */
152 if (param < 0x80) return _cur.grffile->GetParam(param);
153
154 /* In-game variable. */
155 GrfMsg(1, "Unsupported in-game variable 0x{:02X}", param);
156 return UINT_MAX;
157 }
158}
159
160/* Action 0x07
161 * Action 0x09 */
162static void SkipIf(ByteReader &buf)
163{
164 /* <07/09> <param-num> <param-size> <condition-type> <value> <num-sprites>
165 *
166 * B param-num
167 * B param-size
168 * B condition-type
169 * V value
170 * B num-sprites */
171 uint32_t cond_val = 0;
172 uint32_t mask = 0;
173 bool result;
174
175 uint8_t param = buf.ReadByte();
176 uint8_t paramsize = buf.ReadByte();
177 uint8_t condtype = buf.ReadByte();
178
179 if (condtype < 2) {
180 /* Always 1 for bit tests, the given value should be ignored. */
181 paramsize = 1;
182 }
183
184 switch (paramsize) {
185 case 8: cond_val = buf.ReadDWord(); mask = buf.ReadDWord(); break;
186 case 4: cond_val = buf.ReadDWord(); mask = 0xFFFFFFFF; break;
187 case 2: cond_val = buf.ReadWord(); mask = 0x0000FFFF; break;
188 case 1: cond_val = buf.ReadByte(); mask = 0x000000FF; break;
189 default: break;
190 }
191
192 if (param < 0x80 && std::size(_cur.grffile->param) <= param) {
193 GrfMsg(7, "SkipIf: Param {} undefined, skipping test", param);
194 return;
195 }
196
197 GrfMsg(7, "SkipIf: Test condtype {}, param 0x{:02X}, condval 0x{:08X}", condtype, param, cond_val);
198
199 /* condtypes that do not use 'param' are always valid.
200 * condtypes that use 'param' are either not valid for param 0x88, or they are only valid for param 0x88.
201 */
202 if (condtype >= 0x0B) {
203 /* Tests that ignore 'param' */
204 switch (condtype) {
205 case 0x0B: result = !IsValidCargoType(GetCargoTypeByLabel(CargoLabel(std::byteswap(cond_val))));
206 break;
207 case 0x0C: result = IsValidCargoType(GetCargoTypeByLabel(CargoLabel(std::byteswap(cond_val))));
208 break;
209 case 0x0D: result = GetRailTypeByLabel(std::byteswap(cond_val)) == INVALID_RAILTYPE;
210 break;
211 case 0x0E: result = GetRailTypeByLabel(std::byteswap(cond_val)) != INVALID_RAILTYPE;
212 break;
213 case 0x0F: {
214 RoadType rt = GetRoadTypeByLabel(std::byteswap(cond_val));
215 result = rt == INVALID_ROADTYPE || !RoadTypeIsRoad(rt);
216 break;
217 }
218 case 0x10: {
219 RoadType rt = GetRoadTypeByLabel(std::byteswap(cond_val));
220 result = rt != INVALID_ROADTYPE && RoadTypeIsRoad(rt);
221 break;
222 }
223 case 0x11: {
224 RoadType rt = GetRoadTypeByLabel(std::byteswap(cond_val));
225 result = rt == INVALID_ROADTYPE || !RoadTypeIsTram(rt);
226 break;
227 }
228 case 0x12: {
229 RoadType rt = GetRoadTypeByLabel(std::byteswap(cond_val));
230 result = rt != INVALID_ROADTYPE && RoadTypeIsTram(rt);
231 break;
232 }
233 default: GrfMsg(1, "SkipIf: Unsupported condition type {:02X}. Ignoring", condtype); return;
234 }
235 } else if (param == 0x88) {
236 /* GRF ID checks */
237
238 GRFConfig *c = GetGRFConfig(cond_val, mask);
239
242 c = nullptr;
243 }
244
245 if (condtype != 10 && c == nullptr) {
246 GrfMsg(7, "SkipIf: GRFID 0x{:08X} unknown, skipping test", std::byteswap(cond_val));
247 return;
248 }
249
250 switch (condtype) {
251 /* Tests 0x06 to 0x0A are only for param 0x88, GRFID checks */
252 case 0x06: // Is GRFID active?
253 result = c->status == GCS_ACTIVATED;
254 break;
255
256 case 0x07: // Is GRFID non-active?
257 result = c->status != GCS_ACTIVATED;
258 break;
259
260 case 0x08: // GRFID is not but will be active?
261 result = c->status == GCS_INITIALISED;
262 break;
263
264 case 0x09: // GRFID is or will be active?
265 result = c->status == GCS_ACTIVATED || c->status == GCS_INITIALISED;
266 break;
267
268 case 0x0A: // GRFID is not nor will be active
269 /* This is the only condtype that doesn't get ignored if the GRFID is not found */
270 result = c == nullptr || c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND;
271 break;
272
273 default: GrfMsg(1, "SkipIf: Unsupported GRF condition type {:02X}. Ignoring", condtype); return;
274 }
275 } else {
276 /* Tests that use 'param' and are not GRF ID checks. */
277 uint32_t param_val = GetParamVal(param, &cond_val); // cond_val is modified for param == 0x85
278 switch (condtype) {
279 case 0x00: result = !!(param_val & (1 << cond_val));
280 break;
281 case 0x01: result = !(param_val & (1 << cond_val));
282 break;
283 case 0x02: result = (param_val & mask) == cond_val;
284 break;
285 case 0x03: result = (param_val & mask) != cond_val;
286 break;
287 case 0x04: result = (param_val & mask) < cond_val;
288 break;
289 case 0x05: result = (param_val & mask) > cond_val;
290 break;
291 default: GrfMsg(1, "SkipIf: Unsupported condition type {:02X}. Ignoring", condtype); return;
292 }
293 }
294
295 if (!result) {
296 GrfMsg(2, "SkipIf: Not skipping sprites, test was false");
297 return;
298 }
299
300 uint8_t numsprites = buf.ReadByte();
301
302 /* numsprites can be a GOTO label if it has been defined in the GRF
303 * file. The jump will always be the first matching label that follows
304 * the current nfo_line. If no matching label is found, the first matching
305 * label in the file is used. */
306 const GRFLabel *choice = nullptr;
307 for (const auto &label : _cur.grffile->labels) {
308 if (label.label != numsprites) continue;
309
310 /* Remember a goto before the current line */
311 if (choice == nullptr) choice = &label;
312 /* If we find a label here, this is definitely good */
313 if (label.nfo_line > _cur.nfo_line) {
314 choice = &label;
315 break;
316 }
317 }
318
319 if (choice != nullptr) {
320 GrfMsg(2, "SkipIf: Jumping to label 0x{:X} at line {}, test was true", choice->label, choice->nfo_line);
321 _cur.file->SeekTo(choice->pos, SEEK_SET);
322 _cur.nfo_line = choice->nfo_line;
323 return;
324 }
325
326 GrfMsg(2, "SkipIf: Skipping {} sprites, test was true", numsprites);
327 _cur.skip_sprites = numsprites;
328 if (_cur.skip_sprites == 0) {
329 /* Zero means there are no sprites to skip, so
330 * we use -1 to indicate that all further
331 * sprites should be skipped. */
332 _cur.skip_sprites = -1;
333
334 /* If an action 8 hasn't been encountered yet, disable the grf. */
335 if (_cur.grfconfig->status != (_cur.stage < GLS_RESERVE ? GCS_INITIALISED : GCS_ACTIVATED)) {
336 DisableGrf();
337 }
338 }
339}
340
341template <> void GrfActionHandler<0x07>::FileScan(ByteReader &) { }
343template <> void GrfActionHandler<0x07>::LabelScan(ByteReader &) { }
344template <> void GrfActionHandler<0x07>::Init(ByteReader &) { }
345template <> void GrfActionHandler<0x07>::Reserve(ByteReader &buf) { SkipIf(buf); }
346template <> void GrfActionHandler<0x07>::Activation(ByteReader &buf) { SkipIf(buf); }
347
348template <> void GrfActionHandler<0x09>::FileScan(ByteReader &) { }
350template <> void GrfActionHandler<0x09>::LabelScan(ByteReader &) { }
351template <> void GrfActionHandler<0x09>::Init(ByteReader &buf) { SkipIf(buf); }
352template <> void GrfActionHandler<0x09>::Reserve(ByteReader &buf) { SkipIf(buf); }
353template <> void GrfActionHandler<0x09>::Activation(ByteReader &buf) { SkipIf(buf); }
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:106
StrongType::Typedef< uint32_t, struct CargoLabelTag, StrongType::Compare > CargoLabel
Globally unique label of a cargo type.
Definition cargo_type.h:18
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Class to read from a NewGRF file.
uint32_t ReadDWord()
Read a single DWord (32 bits).
uint16_t ReadWord()
Read a single Word (16 bits).
uint8_t ReadByte()
Read a single byte (8 bits).
void SeekTo(size_t pos, int mode)
Seek in the current file.
bool _generating_world
Whether we are generating the map or not.
Definition genworld.cpp:74
bool _networking
are we in networking mode?
Definition network.cpp:67
void DisableStaticNewGRFInfluencingNonStaticNewGRFs(GRFConfig &c)
Disable a static NewGRF when it is influencing another (non-static) NewGRF as this could cause desync...
Definition newgrf.cpp:161
GRFError * DisableGrf(StringID message, GRFConfig *config)
Disable a GRF.
Definition newgrf.cpp:131
bool GetGlobalVariable(uint8_t param, uint32_t *value, const GRFFile *grffile)
Reads a variable common to VarAction2 and Action7/9/D.
void InitializePatchFlags()
Initialize the TTDPatch flags.
static std::array< uint32_t, 8 > _ttdpatch_flags
32 * 8 = 256 flags.
NewGRF buffer reader definition.
GRFConfig * GetGRFConfig(uint32_t grfid, uint32_t mask)
Retrieve a NewGRF from the current config by its grfid.
@ GCS_INITIALISED
GRF file has been initialised.
@ GCS_DISABLED
GRF file is disabled.
@ GCS_NOT_FOUND
GRF file was not found in the local cache.
@ GCS_ACTIVATED
GRF file has been activated.
@ Static
GRF file is used statically (can be used in any MP game)
NewGRF internal processing state.
RailType GetRailTypeByLabel(RailTypeLabel label, bool allow_alternate_labels)
Get the rail type for a given label.
Definition rail.cpp:313
@ INVALID_RAILTYPE
Flag for invalid railtype.
Definition rail_type.h:32
RoadType GetRoadTypeByLabel(RoadTypeLabel label, bool allow_alternate_labels)
Get the road type for a given label.
Definition road.cpp:253
RoadType
The different roadtypes we support.
Definition road_type.h:23
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:28
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:59
bool build_on_slopes
allow building on slopes
uint16_t max_bridge_length
maximum length of bridges
uint8_t train_signal_side
show signals on left / driving / right side
bool inflation
disable inflation
bool allow_town_roads
towns are allowed to build roads (always allowed when generating world / in SE)
bool station_noise_level
build new airports when the town noise level is still within accepted limits
Information about GRF, used in the game and (part of it) in savegames.
GRFStatus status
NOSAVE: GRFStatus, enum.
GRFConfigFlags flags
NOSAVE: GCF_Flags, bitset.
uint32_t GetParam(uint number) const
Get GRF Parameter with range checking.
Definition newgrf.h:162
EconomySettings economy
settings to change the economy
ConstructionSettings construction
construction of things in-game
StationSettings station
settings related to station management
VehicleSettings vehicle
options for vehicles
OrderSettings order
settings related to orders
GRF action handler.
SpriteFile * file
File of currently processed GRF file.
GRFFile * grffile
Currently processed GRF file.
uint32_t nfo_line
Currently processed pseudo sprite number in the GRF.
GRFConfig * grfconfig
Config of the currently processed GRF file.
GrfLoadingStage stage
Current loading stage.
int skip_sprites
Number of pseudo sprites to skip before processing the next one. (-1 to skip to end of file)
bool improved_load
improved loading algorithm
bool gradual_loading
load vehicles gradually
bool never_expire_airports
never expire airports
bool wagon_speed_limits
enable wagon speed limits
bool dynamic_engines
enable dynamic allocation of engine data
uint8_t freight_trains
value to multiply the weight of cargo by
bool never_expire_vehicles
never expire vehicles
bool disable_elrails
when true, the elrails are disabled