/* * This file is part of OpenTTD. * 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. * 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. * 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 . */ /** @file newgrf_internal.h NewGRF internal processing state. */ #ifndef NEWGRF_INTERNAL_H #define NEWGRF_INTERNAL_H #include "../newgrf.h" #include "../newgrf_commons.h" #include "../newgrf_config.h" #include "../spriteloader/sprite_file_type.hpp" #include "newgrf_bytereader.h" /** Possible return values for the GrfChangeInfoHandler functions */ enum ChangeInfoResult : uint8_t { CIR_SUCCESS, ///< Variable was parsed and read CIR_DISABLED, ///< GRF was disabled due to error CIR_UNHANDLED, ///< Variable was parsed but unread CIR_UNKNOWN, ///< Variable is unknown CIR_INVALID_ID, ///< Attempt to modify an invalid ID }; /** GRF feature handler */ template struct GrfChangeInfoHandler { static ChangeInfoResult Reserve(uint first, uint last, int prop, ByteReader &buf); static ChangeInfoResult Activation(uint first, uint last, int prop, ByteReader &buf); }; /** GRF action handler */ template struct GrfActionHandler { static void FileScan(ByteReader &buf); static void SafetyScan(ByteReader &buf); static void LabelScan(ByteReader &buf); static void Init(ByteReader &buf); static void Reserve(ByteReader &buf); static void Activation(ByteReader &buf); }; static constexpr uint MAX_SPRITEGROUP = UINT8_MAX; ///< Maximum GRF-local ID for a spritegroup. /** Temporary data during loading of GRFs */ struct GrfProcessingState { private: /** Definition of a single Action1 spriteset */ struct SpriteSet { SpriteID sprite; ///< SpriteID of the first sprite of the set. uint num_sprites; ///< Number of sprites in the set. }; /** Currently referenceable spritesets */ std::map spritesets[GSF_END]; public: /* Global state */ GrfLoadingStage stage; ///< Current loading stage SpriteID spriteid; ///< First available SpriteID for loading realsprites. /* Local state in the file */ SpriteFile *file; ///< File of currently processed GRF file. GRFFile *grffile; ///< Currently processed GRF file. GRFConfig *grfconfig; ///< Config of the currently processed GRF file. uint32_t nfo_line; ///< Currently processed pseudo sprite number in the GRF. /* Kind of return values when processing certain actions */ int skip_sprites; ///< Number of pseudo sprites to skip before processing the next one. (-1 to skip to end of file) /* Currently referenceable spritegroups */ std::array spritegroups{}; /** Clear temporary data before processing the next file in the current loading stage */ void ClearDataForNextFile() { this->nfo_line = 0; this->skip_sprites = 0; for (uint i = 0; i < GSF_END; i++) { this->spritesets[i].clear(); } this->spritegroups = {}; } /** * Records new spritesets. * @param feature GrfSpecFeature the set is defined for. * @param first_sprite SpriteID of the first sprite in the set. * @param first_set First spriteset to define. * @param numsets Number of sets to define. * @param numents Number of sprites per set to define. */ void AddSpriteSets(uint8_t feature, SpriteID first_sprite, uint first_set, uint numsets, uint numents) { assert(feature < GSF_END); for (uint i = 0; i < numsets; i++) { SpriteSet &set = this->spritesets[feature][first_set + i]; set.sprite = first_sprite + i * numents; set.num_sprites = numents; } } /** * Check whether there are any valid spritesets for a feature. * @param feature GrfSpecFeature to check. * @return true if there are any valid sets. * @note Spritesets with zero sprites are valid to allow callback-failures. */ bool HasValidSpriteSets(uint8_t feature) const { assert(feature < GSF_END); return !this->spritesets[feature].empty(); } /** * Check whether a specific set is defined. * @param feature GrfSpecFeature to check. * @param set Set to check. * @return true if the set is valid. * @note Spritesets with zero sprites are valid to allow callback-failures. */ bool IsValidSpriteSet(uint8_t feature, uint set) const { assert(feature < GSF_END); return this->spritesets[feature].find(set) != this->spritesets[feature].end(); } /** * Returns the first sprite of a spriteset. * @param feature GrfSpecFeature to query. * @param set Set to query. * @return First sprite of the set. */ SpriteID GetSprite(uint8_t feature, uint set) const { assert(IsValidSpriteSet(feature, set)); return this->spritesets[feature].find(set)->second.sprite; } /** * Returns the number of sprites in a spriteset * @param feature GrfSpecFeature to query. * @param set Set to query. * @return Number of sprites in the set. */ uint GetNumEnts(uint8_t feature, uint set) const { assert(IsValidSpriteSet(feature, set)); return this->spritesets[feature].find(set)->second.num_sprites; } }; extern GrfProcessingState _cur; struct GRFLocation { uint32_t grfid; uint32_t nfoline; GRFLocation(uint32_t grfid, uint32_t nfoline) : grfid(grfid), nfoline(nfoline) { } bool operator <(const GRFLocation &other) const { return this->grfid < other.grfid || (this->grfid == other.grfid && this->nfoline < other.nfoline); } bool operator ==(const GRFLocation &other) const { return this->grfid == other.grfid && this->nfoline == other.nfoline; } }; using GRFLineToSpriteOverride = std::map>; extern std::map> _grm_sprites; extern GRFLineToSpriteOverride _grf_line_to_action6_sprite_override; extern GrfMiscBits _misc_grf_features; void SetNewGRFOverride(uint32_t source_grfid, uint32_t target_grfid); GRFFile *GetCurrentGRFOverride(); std::span GetCargoTranslationTable(const GRFFile &grffile); CargoTypes TranslateRefitMask(uint32_t refit_mask); void SkipBadgeList(ByteReader &buf); std::vector ReadBadgeList(ByteReader &buf, GrfSpecFeature feature); void MapSpriteMappingRecolour(PalSpriteID *grf_sprite); TileLayoutFlags ReadSpriteLayoutSprite(ByteReader &buf, bool read_flags, bool invert_action1_flag, bool use_cur_spritesets, int feature, PalSpriteID *grf_sprite, uint16_t *max_sprite_offset = nullptr, uint16_t *max_palette_offset = nullptr); bool ReadSpriteLayout(ByteReader &buf, uint num_building_sprites, bool use_cur_spritesets, uint8_t feature, bool allow_var10, bool no_z_position, NewGRFSpriteLayout *dts); GRFFile *GetFileByGRFID(uint32_t grfid); GRFError *DisableGrf(StringID message = {}, GRFConfig *config = nullptr); void DisableStaticNewGRFInfluencingNonStaticNewGRFs(GRFConfig &c); bool HandleChangeInfoResult(const char *caller, ChangeInfoResult cir, uint8_t feature, uint8_t property); uint32_t GetParamVal(uint8_t param, uint32_t *cond_val); void GRFUnsafe(ByteReader &); void InitializePatchFlags(); #endif /* NEWGRF_INTERNAL_H */