summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfrosch <frosch@openttd.org>2018-03-11 15:08:51 +0000
committerfrosch <frosch@openttd.org>2018-03-11 15:08:51 +0000
commit55a503e6f225a3c1dba3dbc1effa7e0d6942dd96 (patch)
treec60b80c025c69edbfa919518d81b84c354fcbe7f
parentc6eb633d189f12fa3dd95243a5dcc021cb0e930b (diff)
downloadopenttd-55a503e6f225a3c1dba3dbc1effa7e0d6942dd96.tar.xz
(svn r27989) -Fix (r27985): VA2 optimisation failed in various special cases:
- nvar=0 is meant to return the calculated result. - Missing references resolve to NULL and got identified with the default result. - Missing 'break' broke overlapping cases. - Splitting into non-overlapping cases could result in more than 256 cases.
-rw-r--r--src/newgrf.cpp7
-rw-r--r--src/newgrf_spritegroup.cpp2
-rw-r--r--src/newgrf_spritegroup.h3
3 files changed, 8 insertions, 4 deletions
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
index 41d719591..d06d1c40a 100644
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -4698,6 +4698,8 @@ static void NewSpriteGroup(ByteReader *buf)
group->default_group = GetGroupFromGroupID(setid, type, buf->ReadWord());
group->error_group = ranges.size() > 0 ? ranges[0].group : group->default_group;
+ /* nvar == 0 is a special case -- we turn our value into a callback result */
+ group->calculated_result = ranges.size() == 0;
/* Sort ranges ascending. When ranges overlap, this may required clamping or splitting them */
std::vector<uint32> bounds;
@@ -4711,10 +4713,11 @@ static void NewSpriteGroup(ByteReader *buf)
std::vector<const SpriteGroup *> target;
for (uint j = 0; j < bounds.size(); ++j) {
uint32 v = bounds[j];
- const SpriteGroup *t = NULL;
+ const SpriteGroup *t = group->default_group;
for (uint i = 0; i < ranges.size(); i++) {
if (ranges[i].low <= v && v <= ranges[i].high) {
t = ranges[i].group;
+ break;
}
}
target.push_back(t);
@@ -4723,7 +4726,7 @@ static void NewSpriteGroup(ByteReader *buf)
std::vector<DeterministicSpriteGroupRange> optimised;
for (uint j = 0; j < bounds.size(); ) {
- if (target[j]) {
+ if (target[j] != group->default_group) {
DeterministicSpriteGroupRange r;
r.group = target[j];
r.low = bounds[j];
diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp
index 8f44ef9c5..a5d689bbf 100644
--- a/src/newgrf_spritegroup.cpp
+++ b/src/newgrf_spritegroup.cpp
@@ -252,7 +252,7 @@ const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) con
object.last_value = last_value;
- if (this->num_ranges == 0) {
+ if (this->calculated_result) {
/* nvar == 0 is a special case -- we turn our value into a callback result */
if (value != CALLBACK_FAILED) value = GB(value, 0, 15);
static CallbackResultSpriteGroup nvarzero(0, true);
diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h
index b2e764599..6adf7c2ac 100644
--- a/src/newgrf_spritegroup.h
+++ b/src/newgrf_spritegroup.h
@@ -174,7 +174,8 @@ struct DeterministicSpriteGroup : SpriteGroup {
VarSpriteGroupScope var_scope;
DeterministicSpriteGroupSize size;
uint num_adjusts;
- byte num_ranges;
+ uint num_ranges;
+ bool calculated_result;
DeterministicSpriteGroupAdjust *adjusts;
DeterministicSpriteGroupRange *ranges; // Dynamically allocated