VarAction2: Add support for more varaction2 types

Add CB failure and deterministic relative types
This commit is contained in:
Jonathan G Rennison
2023-03-14 17:57:30 +00:00
parent 48d602962f
commit 5718730d68
24 changed files with 282 additions and 50 deletions

View File

@@ -5789,6 +5789,17 @@ static void ProcessDeterministicSpriteGroupRanges(const std::vector<Deterministi
}
}
static VarSpriteGroupScopeOffset ParseRelativeScopeByte(byte relative)
{
VarSpriteGroupScopeOffset var_scope_count = (GB(relative, 6, 2) << 8);
if ((relative & 0xF) == 0) {
SetBit(var_scope_count, 15);
} else {
var_scope_count |= (relative & 0xF);
}
return var_scope_count;
}
/* Action 0x02 */
static void NewSpriteGroup(ByteReader *buf)
{
@@ -5819,6 +5830,16 @@ static void NewSpriteGroup(ByteReader *buf)
* we do not need to delete anything if there is an exception from the
* ByteReader. */
/* Decoded sprite type */
enum SpriteType {
STYPE_NORMAL,
STYPE_DETERMINISTIC,
STYPE_DETERMINISTIC_RELATIVE,
STYPE_DETERMINISTIC_RELATIVE_2,
STYPE_RANDOMIZED,
STYPE_CB_FAILURE,
};
SpriteType stype = STYPE_NORMAL;
switch (type) {
/* Deterministic Sprite Group */
case 0x81: // Self scope, byte
@@ -5827,7 +5848,73 @@ static void NewSpriteGroup(ByteReader *buf)
case 0x86: // Parent scope, word
case 0x89: // Self scope, dword
case 0x8A: // Parent scope, dword
stype = STYPE_DETERMINISTIC;
break;
/* Randomized Sprite Group */
case 0x80: // Self scope
case 0x83: // Parent scope
case 0x84: // Relative scope
stype = STYPE_RANDOMIZED;
break;
/* Extension type */
case 0x87:
if (HasBit(_cur.grffile->observed_feature_tests, GFTOF_MORE_VARACTION2_TYPES)) {
byte subtype = buf->ReadByte();
switch (subtype) {
case 0:
stype = STYPE_CB_FAILURE;
break;
case 1:
stype = STYPE_DETERMINISTIC_RELATIVE;
break;
case 2:
stype = STYPE_DETERMINISTIC_RELATIVE_2;
break;
default:
grfmsg(1, "NewSpriteGroup: Unknown 0x87 extension subtype %02X for feature %s, handling as CB failure", subtype, GetFeatureString(feature));
stype = STYPE_CB_FAILURE;
break;
}
}
break;
default:
break;
}
switch (stype) {
/* Deterministic Sprite Group */
case STYPE_DETERMINISTIC:
case STYPE_DETERMINISTIC_RELATIVE:
case STYPE_DETERMINISTIC_RELATIVE_2:
{
VarSpriteGroupScopeOffset var_scope_count = 0;
if (stype == STYPE_DETERMINISTIC_RELATIVE) {
var_scope_count = ParseRelativeScopeByte(buf->ReadByte());
} else if (stype == STYPE_DETERMINISTIC_RELATIVE_2) {
uint8 mode = buf->ReadByte();
uint8 offset = buf->ReadByte();
bool invalid = false;
if ((mode & 0x7F) >= VSGSRM_END) {
invalid = true;
}
if (HasBit(mode, 7)) {
/* Use variable 0x100 */
if (offset != 0) invalid = true;
}
if (invalid) {
grfmsg(1, "NewSpriteGroup: Unknown 0x87 extension subtype 2 relative mode: %02X %02X for feature %s, handling as CB failure", mode, offset, GetFeatureString(feature));
act_group = NewCallbackResultSpriteGroupNoTransform(CALLBACK_FAILED);
break;
}
var_scope_count = (mode << 8) | offset;
}
byte varadjust;
byte varsize;
@@ -5839,13 +5926,22 @@ static void NewSpriteGroup(ByteReader *buf)
group->feature = feature;
if (_action6_override_active) group->sg_flags |= SGF_ACTION6;
act_group = group;
group->var_scope = HasBit(type, 1) ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF;
switch (GB(type, 2, 2)) {
default: NOT_REACHED();
case 0: group->size = DSG_SIZE_BYTE; varsize = 1; break;
case 1: group->size = DSG_SIZE_WORD; varsize = 2; break;
case 2: group->size = DSG_SIZE_DWORD; varsize = 4; break;
if (stype == STYPE_DETERMINISTIC_RELATIVE || stype == STYPE_DETERMINISTIC_RELATIVE_2) {
group->var_scope = (feature <= GSF_AIRCRAFT) ? VSG_SCOPE_RELATIVE : VSG_SCOPE_SELF;
group->var_scope_count = var_scope_count;
group->size = DSG_SIZE_DWORD;
varsize = 4;
} else {
group->var_scope = HasBit(type, 1) ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF;
switch (GB(type, 2, 2)) {
default: NOT_REACHED();
case 0: group->size = DSG_SIZE_BYTE; varsize = 1; break;
case 1: group->size = DSG_SIZE_WORD; varsize = 2; break;
case 2: group->size = DSG_SIZE_DWORD; varsize = 4; break;
}
}
const VarAction2AdjustInfo info = { feature, GetGrfSpecFeatureForScope(feature, group->var_scope), varsize };
@@ -5962,9 +6058,7 @@ static void NewSpriteGroup(ByteReader *buf)
}
/* Randomized Sprite Group */
case 0x80: // Self scope
case 0x83: // Parent scope
case 0x84: // Relative scope
case STYPE_RANDOMIZED:
{
assert(RandomizedSpriteGroup::CanAllocateItem());
RandomizedSpriteGroup *group = new RandomizedSpriteGroup();
@@ -5975,7 +6069,7 @@ static void NewSpriteGroup(ByteReader *buf)
if (HasBit(type, 2)) {
if (feature <= GSF_AIRCRAFT) group->var_scope = VSG_SCOPE_RELATIVE;
group->count = buf->ReadByte();
group->var_scope_count = ParseRelativeScopeByte(buf->ReadByte());
}
uint8 triggers = buf->ReadByte();
@@ -6005,8 +6099,12 @@ static void NewSpriteGroup(ByteReader *buf)
break;
}
case STYPE_CB_FAILURE:
act_group = NewCallbackResultSpriteGroupNoTransform(CALLBACK_FAILED);
break;
/* Neither a variable or randomized sprite group... must be a real group */
default:
case STYPE_NORMAL:
{
switch (feature) {
case GSF_TRAINS: