summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Nelson <peter1138@openttd.org>2021-06-04 12:31:00 +0100
committerPeterN <peter@fuzzle.org>2021-06-12 08:05:59 +0100
commit40cec34836a694e7388a4421d746e5238a57b608 (patch)
treead5149e167a4f01b6dcf70f11905fca5f9dfa830
parentf1328db063fe0808a55e7ed76304491b84916146 (diff)
downloadopenttd-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.cpp55
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;