# HG changeset patch # User frosch # Date 2018-03-11 15:08:51 # Node ID 4149c4b18e2417b234f6df5ee5de30880d5522cf # Parent 609bd20432371498e8c3f0bbbc7fc4d0ba71ea94 (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. diff --git a/src/newgrf.cpp b/src/newgrf.cpp --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -4698,6 +4698,8 @@ static void NewSpriteGroup(ByteReader *b 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 bounds; @@ -4711,10 +4713,11 @@ static void NewSpriteGroup(ByteReader *b std::vector 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 *b std::vector 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 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -252,7 +252,7 @@ const SpriteGroup *DeterministicSpriteGr 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 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -174,7 +174,8 @@ struct DeterministicSpriteGroup : Sprite VarSpriteGroupScope var_scope; DeterministicSpriteGroupSize size; uint num_adjusts; - byte num_ranges; + uint num_ranges; + bool calculated_result; DeterministicSpriteGroupAdjust *adjusts; DeterministicSpriteGroupRange *ranges; // Dynamically allocated