21 AddGRFTextToList(_cur_gps.grfconfig->name, langid, _cur_gps.grfconfig->ident.grfid,
false, str);
28 AddGRFTextToList(_cur_gps.grfconfig->info, langid, _cur_gps.grfconfig->ident.grfid,
true, str);
35 AddGRFTextToList(_cur_gps.grfconfig->url, langid, _cur_gps.grfconfig->ident.grfid,
false, str);
43 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'NPAR' but got {}, ignoring this field", len);
46 _cur_gps.grfconfig->num_valid_params = std::min(buf.
ReadByte(), GRFConfig::MAX_NUM_PARAMS);
55 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'PALS' but got {}, ignoring this field", len);
66 GrfMsg(2,
"StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'PALS', ignoring this field", data);
71 _cur_gps.grfconfig->palette |= pal;
81 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'BLTR' but got {}, ignoring this field", len);
90 GrfMsg(2,
"StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'BLTR', ignoring this field", data);
94 _cur_gps.grfconfig->palette |= pal;
103 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'VRSN' but got {}, ignoring this field", len);
107 _cur_gps.grfconfig->version = _cur_gps.grfconfig->min_loadable_version = buf.
ReadDWord();
116 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'MINV' but got {}, ignoring this field", len);
119 _cur_gps.grfconfig->min_loadable_version = buf.
ReadDWord();
120 if (_cur_gps.grfconfig->version == 0) {
121 GrfMsg(2,
"StaticGRFInfo: 'MINV' defined before 'VRSN' or 'VRSN' set to 0, ignoring this field");
122 _cur_gps.grfconfig->min_loadable_version = 0;
124 if (_cur_gps.grfconfig->version < _cur_gps.grfconfig->min_loadable_version) {
125 GrfMsg(2,
"StaticGRFInfo: 'MINV' defined as {}, limiting it to 'VRSN'", _cur_gps.grfconfig->min_loadable_version);
126 _cur_gps.grfconfig->min_loadable_version = _cur_gps.grfconfig->version;
152 GrfMsg(2,
"StaticGRFInfo: expected 1 byte for 'INFO'->'PARA'->'TYPE' but got {}, ignoring this field", len);
159 GrfMsg(3,
"StaticGRFInfo: unknown parameter type {}, ignoring this field", type);
169 GrfMsg(2,
"StaticGRFInfo: 'INFO'->'PARA'->'LIMI' is only valid for parameters with type uint/enum, ignoring this field");
171 }
else if (len != 8) {
172 GrfMsg(2,
"StaticGRFInfo: expected 8 bytes for 'INFO'->'PARA'->'LIMI' but got {}, ignoring this field", len);
177 if (min_value <= max_value) {
181 GrfMsg(2,
"StaticGRFInfo: 'INFO'->'PARA'->'LIMI' values are incoherent, ignoring this field");
190 if (len < 1 || len > 3) {
191 GrfMsg(2,
"StaticGRFInfo: expected 1 to 3 bytes for 'INFO'->'PARA'->'MASK' but got {}, ignoring this field", len);
195 if (param_nr >= GRFConfig::MAX_NUM_PARAMS) {
196 GrfMsg(2,
"StaticGRFInfo: invalid parameter number in 'INFO'->'PARA'->'MASK', param {}, ignoring this field", param_nr);
212 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'PARA'->'DEFA' but got {}, ignoring this field", len);
217 _cur_gps.grfconfig->has_param_defaults =
true;
234 using Span = std::pair<const AllowedSubtags *, const AllowedSubtags *>;
237 std::variant<DataHandler, TextHandler, BranchHandler, Span>
handler;
255 GrfMsg(2,
"StaticGRFInfo: all child nodes of 'INFO'->'PARA'->param_num->'VALU' should have type 't' and the value/bit number as id");
262 std::string_view name_string = buf.
ReadString();
264 auto it = std::ranges::lower_bound(
_cur_parameter->value_names,
id, std::less{}, &GRFParameterInfo::ValueName::first);
265 if (it == std::end(
_cur_parameter->value_names) || it->first !=
id) {
268 AddGRFTextToList(it->second, langid, _cur_gps.grfconfig->ident.grfid,
false, name_string);
297 if (type !=
'C' ||
id >= _cur_gps.grfconfig->num_valid_params) {
298 GrfMsg(2,
"StaticGRFInfo: all child nodes of 'INFO'->'PARA' should have type 'C' and their parameter number as id");
304 if (
id >= _cur_gps.grfconfig->param_info.size()) {
305 _cur_gps.grfconfig->param_info.resize(
id + 1);
307 if (!_cur_gps.grfconfig->param_info[
id].has_value()) {
349 while (new_type != 0) {
386 struct type_visitor {
387 char operator()(
const DataHandler &) {
return 'B'; }
388 char operator()(
const TextHandler &) {
return 'T'; }
394 struct evaluate_visitor {
400 if (buf.Remaining() < len)
return false;
401 return handler(len, buf);
417 return HandleNodes(buf, {subtags.first, subtags.second});
421 for (
const auto &tag : subtags) {
422 if (tag.id !=
std::byteswap(
id) || std::visit(type_visitor{}, tag.handler) != type)
continue;
423 return std::visit(evaluate_visitor{buf}, tag.handler);
426 GrfMsg(2,
"StaticGRFInfo: unknown type/id combination found, type={:c}, id={:x}", type,
id);
441 if (!
HandleNode(type,
id, buf, subtags))
return false;
458template <>
void GrfActionHandler<0x14>::SafetyScan(
ByteReader &) { }
459template <>
void GrfActionHandler<0x14>::LabelScan(
ByteReader &) { }
460template <>
void GrfActionHandler<0x14>::Init(
ByteReader &) { }
461template <>
void GrfActionHandler<0x14>::Reserve(
ByteReader &) { }
462template <>
void GrfActionHandler<0x14>::Activation(
ByteReader &) { }
constexpr enable_if_t< is_integral_v< T >, T > byteswap(T x) noexcept
Custom implementation of std::byteswap; remove once we build with C++23.
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).
std::string_view ReadString()
Read a NUL-terminated string.
uint8_t ReadByte()
Read a single byte (8 bits).
Functions related to debugging.
static bool ChangeGRFParamType(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'TYPE' to set the typeof a parameter.
bool(* BranchHandler)(ByteReader &)
Type of callback function for branch nodes.
static bool ChangeGRFParamLimits(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'LIMI' to set the min/max value of a parameter.
static bool ChangeGRFNumUsedParams(size_t len, ByteReader &buf)
Callback function for 'INFO'->'NPAR' to set the number of valid parameters.
static constexpr AllowedSubtags _tags_info[]
Action14 tags for the INFO node.
static bool ChangeGRFURL(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'URL_' to set the newgrf url.
bool(* DataHandler)(size_t, ByteReader &)
Type of callback function for binary nodes.
static bool ChangeGRFParamDescription(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'PARAM'->param_num->'DESC' to set the description of a parameter.
static bool ChangeGRFMinVersion(size_t len, ByteReader &buf)
Callback function for 'INFO'->'MINV' to the minimum compatible version of the NewGRF.
static bool ChangeGRFParamDefault(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'DFLT' to set the default value.
static bool ChangeGRFParamValueNames(ByteReader &buf)
Callback function for 'INFO'->'PARA'->param_num->'VALU' to set the names of some parameter values (ty...
static bool HandleParameterInfo(ByteReader &buf)
Callback function for 'INFO'->'PARA' to set extra information about the parameters.
static GRFParameterInfo * _cur_parameter
The parameter which info is currently changed by the newgrf.
static bool HandleNodes(ByteReader &buf, std::span< const AllowedSubtags > tags)
Handle the contents of a 'C' choice of an Action14.
static bool ChangeGRFName(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'NAME' to add a translation to the newgrf name.
bool(* TextHandler)(uint8_t, std::string_view str)
Type of callback function for text nodes.
static constexpr AllowedSubtags _tags_root[]
Action14 root tags.
static void StaticGRFInfo(ByteReader &buf)
Handle Action 0x14.
static bool ChangeGRFParamMask(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'MASK' to set the parameter and bits to use.
static bool SkipUnknownInfo(ByteReader &buf, uint8_t type)
Try to skip the current node and all subnodes (if it's a branch node).
static bool ChangeGRFDescription(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'DESC' to add a translation to the newgrf description.
static bool ChangeGRFPalette(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PALS' to set the number of valid parameters.
static bool ChangeGRFVersion(size_t len, ByteReader &buf)
Callback function for 'INFO'->'VRSN' to the version of the NewGRF.
static bool ChangeGRFParamName(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'PARAM'->param_num->'NAME' to set the name of a parameter.
static bool HandleNode(uint8_t type, uint32_t id, ByteReader &buf, std::span< const AllowedSubtags > subtags)
Handle the nodes of an Action14.
static bool ChangeGRFBlitter(size_t len, ByteReader &buf)
Callback function for 'INFO'->'BLTR' to set the blitter info.
static constexpr AllowedSubtags _tags_parameters[]
Action14 parameter tags.
NewGRF buffer reader definition.
GRFParameterType
The possible types of a newgrf parameter.
@ PTYPE_UINT_ENUM
The parameter allows a range of numbers, each of which can have a special name.
@ PTYPE_END
Invalid parameter type.
GRFPalette
Information that can/has to be stored about a GRF's palette.
@ GRFP_GRF_UNSET
The NewGRF provided no information.
@ GRFP_BLT_UNSET
The NewGRF provided no information or doesn't care about a 32 bpp blitter.
@ GRFP_GRF_WINDOWS
The NewGRF says the Windows palette can be used.
@ GRFP_GRF_DOS
The NewGRF says the DOS palette can be used.
@ GRFP_GRF_ANY
The NewGRF says any palette can be used.
@ GRFP_BLT_MASK
Bitmask to only get the blitter information.
@ GRFP_BLT_32BPP
The NewGRF prefers a 32 bpp blitter.
@ GRFP_GRF_MASK
Bitmask to get only the NewGRF supplied information.
NewGRF internal processing state.
static void AddGRFTextToList(GRFTextList &list, uint8_t langid, std::string_view text_to_add)
Add a new text to a GRFText list.
Header of Action 04 "universal holder" structure and functions.
std::vector< GRFText > GRFTextList
A GRF text with a list of translations.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
Information about one grf parameter.