diff options
author | Peter Nelson <peter1138@openttd.org> | 2021-06-04 12:31:00 +0100 |
---|---|---|
committer | PeterN <peter@fuzzle.org> | 2021-06-12 08:05:59 +0100 |
commit | 40cec34836a694e7388a4421d746e5238a57b608 (patch) | |
tree | ad5149e167a4f01b6dcf70f11905fca5f9dfa830 | |
parent | f1328db063fe0808a55e7ed76304491b84916146 (diff) | |
download | openttd-40cec34836a694e7388a4421d746e5238a57b608.tar.xz |
Change: Skip creating a RealSpriteGroup when there is only one result.
This avoids checking RSG for empty sets every time they are evaluated.
This might alter behaviour in cases of a malformed NewGRF file.
-rw-r--r-- | src/newgrf.cpp | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 318c5e8ea..1432c0660 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -109,7 +109,7 @@ public: int skip_sprites; ///< Number of pseudo sprites to skip before processing the next one. (-1 to skip to end of file) /* Currently referenceable spritegroups */ - SpriteGroup *spritegroups[MAX_SPRITEGROUP + 1]; + const SpriteGroup *spritegroups[MAX_SPRITEGROUP + 1]; /** Clear temporary data before processing the next file in the current loading stage */ void ClearDataForNextFile() @@ -4982,7 +4982,7 @@ static void NewSpriteGroup(ByteReader *buf) * otherwise it specifies a number of entries, the exact * meaning depends on the feature * V feature-specific-data (huge mess, don't even look it up --pasky) */ - SpriteGroup *act_group = nullptr; + const SpriteGroup *act_group = nullptr; uint8 feature = buf->ReadByte(); if (feature >= GSF_END) { @@ -5163,24 +5163,53 @@ static void NewSpriteGroup(ByteReader *buf) return; } - assert(RealSpriteGroup::CanAllocateItem()); - RealSpriteGroup *group = new RealSpriteGroup(); - group->nfo_line = _cur.nfo_line; - act_group = group; - grfmsg(6, "NewSpriteGroup: New SpriteGroup 0x%02X, %u loaded, %u loading", setid, num_loaded, num_loading); - for (uint i = 0; i < num_loaded; i++) { + if (num_loaded + num_loading == 1) { + /* Avoid creating 'Real' sprite group if only one option. */ uint16 spriteid = buf->ReadWord(); - group->loaded.push_back(CreateGroupFromGroupID(feature, setid, type, spriteid)); - grfmsg(8, "NewSpriteGroup: + rg->loaded[%i] = subset %u", i, spriteid); + act_group = CreateGroupFromGroupID(feature, setid, type, spriteid); + grfmsg(8, "NewSpriteGroup: one result, skipping RealSpriteGroup = subset %u", spriteid); + break; + } + + std::vector<uint16> loaded; + std::vector<uint16> loading; + + for (uint i = 0; i < num_loaded; i++) { + loaded.push_back(buf->ReadWord()); + grfmsg(8, "NewSpriteGroup: + rg->loaded[%i] = subset %u", i, loaded[i]); } for (uint i = 0; i < num_loading; i++) { - uint16 spriteid = buf->ReadWord(); - group->loading.push_back(CreateGroupFromGroupID(feature, setid, type, spriteid)); - grfmsg(8, "NewSpriteGroup: + rg->loading[%i] = subset %u", i, spriteid); + loading.push_back(buf->ReadWord()); + grfmsg(8, "NewSpriteGroup: + rg->loading[%i] = subset %u", i, loading[i]); + } + + if (std::adjacent_find(loaded.begin(), loaded.end(), std::not_equal_to<>()) == loaded.end() && + std::adjacent_find(loading.begin(), loading.end(), std::not_equal_to<>()) == loading.end() && + loaded[0] == loading[0]) + { + /* Both lists only contain the same value, so don't create 'Real' sprite group */ + act_group = CreateGroupFromGroupID(feature, setid, type, loaded[0]); + grfmsg(8, "NewSpriteGroup: same result, skipping RealSpriteGroup = subset %u", loaded[0]); + break; + } + + assert(RealSpriteGroup::CanAllocateItem()); + RealSpriteGroup *group = new RealSpriteGroup(); + group->nfo_line = _cur.nfo_line; + act_group = group; + + for (uint16 spriteid : loaded) { + const SpriteGroup *t = CreateGroupFromGroupID(feature, setid, type, spriteid); + group->loaded.push_back(t); + } + + for (uint16 spriteid : loading) { + const SpriteGroup *t = CreateGroupFromGroupID(feature, setid, type, spriteid); + group->loading.push_back(t); } break; |