GRF: Add second success indicator mechanism for feature tests and ID mappings
This commit is contained in:
@@ -81,8 +81,21 @@
|
||||
If the test is successful, the bit is set (to 1), otherwise the bit is cleared (to 0).<br />
|
||||
The bit number MUST be in the range: 4 ≤ bit number ≤ 31. These bits can be assumed to be 0 on implementations which do not support this feature test mechanism.<br />
|
||||
Global variable 0x9D can then be tested by using a standard <a href="https://newgrf-specs.tt-wiki.net/wiki/Action7">Action 7 or 9</a>, or a standard <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2">Variational Action 2</a>.<br />
|
||||
If this field is omitted, no bit is set or cleared, and the test is not observable.
|
||||
If this field is omitted, no bit is set or cleared, and the test is not observable (unless the SVAL chunk is used).
|
||||
</p>
|
||||
<h4 id="FTST-SVAL">Feature Set Global Variable 0x91 Success Test Value: C "FTST" -> B "SVAL"</h4>
|
||||
<p>Within an FTST chunk, the SVAL binary (type B) field contains a 32 bit value which can be tested using the mechanism below. This is 4 bytes.<br />
|
||||
If the test is successful, the value is added to a list of successful result values which can be checked using the mechanism below.<br />
|
||||
If the test is unsuccessful, no action is taken.<br />
|
||||
The value must be > 0, a value of 0 has no effect.</p>
|
||||
<p>To check if the test succeeded (the value has been added to the list of successful result values), use <a href="https://newgrf-specs.tt-wiki.net/wiki/Action7">Action 7 or 9</a>.<br />
|
||||
The parameter to test is global variable 0x91 (this always has a value of 0, equivalent to the case where the test has failed, if this feature test mechanism is not present).<br />
|
||||
The condition-type to use is: 02 (\7=, equality) to jump if the value is in the list (the test succeeded), or 03 (\7!, inequality) to jump if the value is not in the list (the test did not succeed).<br />
|
||||
The value in the Action 7 or 9 must match the value specified in this SVAL chunk.
|
||||
</p>
|
||||
<p>If this field is omitted, the test is not observable (unless the SETP chunk is used).</p>
|
||||
<p>This chunk and the associated test mechanism requires the feature name: <font face="monospace">feature_test</font>, version 2.<br />
|
||||
Using this chunk instead or as well as SETP allows observing the result of more than 28 feature tests.</p>
|
||||
<br />
|
||||
<h4 id="FTST-example">Example NFO:</h4>
|
||||
<pre>
|
||||
@@ -134,6 +147,9 @@
|
||||
Global variable 0x8D can then be tested by using a standard <a href="https://newgrf-specs.tt-wiki.net/wiki/Action7">Action 7 or 9</a>, or a standard <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2">Variational Action 2</a>.<br />
|
||||
If this field is omitted, no bit is set or cleared.
|
||||
</p>
|
||||
<h4 id="A0PM-SVAL">Success Indicator Global Variable 0x91 Test Value: C "A0PM" -> B "SVAL"</h4>
|
||||
<p>This behaves identically to the <a href="#FTST-SVAL">C "FTST" -> B "SVAL"</a> case, above</p>
|
||||
<p>This chunk and the associated test mechanism requires the feature name: <font face="monospace">property_mapping</font>, version 2.</p>
|
||||
<h4 id="A0PM-FLBK">Fallback Mode: C "A0PM" -> B "FLBK"</h4>
|
||||
<p>Within an A0PM chunk, the FLBK binary (type B) field contains the fallback mode. This is 1 byte.<br />
|
||||
The fallback mode may take the following values:
|
||||
@@ -656,6 +672,9 @@
|
||||
If this is not specified, a value of 0 is assumed.</p>
|
||||
<h4 id="A2VM-SETT">Success Indicator Global Variable 0x8D Bit: C "A2VM" -> B "SETT"</h4>
|
||||
<p>This behaves identically to the <a href="#A0PM-SETT">C "A0PM" -> B "SETT"</a> case, above</p>
|
||||
<h4 id="A2VM-SVAL">Success Indicator Global Variable 0x91 Test Value: C "A2VM" -> B "SVAL"</h4>
|
||||
<p>This behaves identically to the <a href="#FTST-SVAL">C "FTST" -> B "SVAL"</a> case, above</p>
|
||||
<p>This chunk and the associated test mechanism requires the feature name: <font face="monospace">variable_mapping</font>, version 3.</p>
|
||||
<h4 id="A2VM-VPRM">Replacement parameter: C "A2VM" -> B "VPRM"</h4>
|
||||
<p>Within an A2VM chunk, the VPRM binary (type B) field contains the Variational Action 2 parameter value (as in 60+X variables) to use on the mapped variable. This is 4 bytes.<br />
|
||||
If this is not specified, a value of 0 is assumed.<br />
|
||||
@@ -805,6 +824,9 @@
|
||||
It is possible to override existing type IDs, however this use is not recommended.</p>
|
||||
<h4 id="A5TM-SETT">Success Indicator Global Variable 0x8D Bit: C "A5TM" -> B "SETT"</h4>
|
||||
<p>This behaves identically to the <a href="#A0PM-SETT">C "A0PM" -> B "SETT"</a> case, above</p>
|
||||
<h4 id="A5TM-SVAL">Success Indicator Global Variable 0x91 Test Value: C "A5TM" -> B "SVAL"</h4>
|
||||
<p>This behaves identically to the <a href="#FTST-SVAL">C "FTST" -> B "SVAL"</a> case, above</p>
|
||||
<p>This chunk and the associated test mechanism requires the feature name: <font face="monospace">action5_type_id_mapping</font>, version 2.</p>
|
||||
<h4 id="A5TM-FLBK">Fallback Mode: C "A5TM" -> B "FLBK"</h4>
|
||||
<p>This behaves identically to the <a href="#A0PM-FLBK">C "A0PM" -> B "FLBK"</a> case, above</p>
|
||||
<h4 id="A5TM-example">Example NFO:</h4>
|
||||
@@ -879,6 +901,9 @@
|
||||
At the time of writing known existing feature IDs include the values: 0x00 - 0x13 (inclusive) and 0x48.</p>
|
||||
<h4 id="FIDM-SETT">Success Indicator Global Variable 0x8D Bit: C "FIDM" -> B "SETT"</h4>
|
||||
<p>This behaves identically to the <a href="#A0PM-SETT">C "A0PM" -> B "SETT"</a> case, above</p>
|
||||
<h4 id="FIDM-SVAL">Success Indicator Global Variable 0x91 Test Value: C "FIDM" -> B "SVAL"</h4>
|
||||
<p>This behaves identically to the <a href="#FTST-SVAL">C "FTST" -> B "SVAL"</a> case, above</p>
|
||||
<p>This chunk and the associated test mechanism requires the feature name: <font face="monospace">feature_id_mapping</font>, version 2.</p>
|
||||
<h4 id="FIDM-FLBK">Fallback Mode: C "FIDM" -> B "FLBK"</h4>
|
||||
<p>This behaves identically to the <a href="#A0PM-FLBK">C "A0PM" -> B "FLBK"</a> case, above</p>
|
||||
<h4 id="FIDM-example">Example NFO:</h4>
|
||||
|
@@ -7643,6 +7643,13 @@ static void SkipIf(ByteReader *buf)
|
||||
|
||||
default: grfmsg(1, "SkipIf: Unsupported GRF condition type %02X. Ignoring", condtype); return;
|
||||
}
|
||||
} else if (param == 0x91 && (condtype == 0x02 || condtype == 0x03) && cond_val > 0) {
|
||||
const std::vector<uint32> &values = _cur.grffile->var91_values;
|
||||
/* condtype 0x02: skip if test result found
|
||||
* condtype 0x03: skip if test result not found
|
||||
*/
|
||||
bool found = std::find(values.begin(), values.end(), cond_val) != values.end();
|
||||
result = (found == (condtype == 0x02));
|
||||
} else {
|
||||
/* Tests that use 'param' and are not GRF ID checks. */
|
||||
uint32 param_val = GetParamVal(param, &cond_val); // cond_val is modified for param == 0x85
|
||||
@@ -9212,6 +9219,7 @@ struct GRFFeatureTest {
|
||||
uint16 min_version;
|
||||
uint16 max_version;
|
||||
uint8 platform_var_bit;
|
||||
uint32 test_91_value;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
@@ -9219,6 +9227,7 @@ struct GRFFeatureTest {
|
||||
this->min_version = 1;
|
||||
this->max_version = UINT16_MAX;
|
||||
this->platform_var_bit = 0;
|
||||
this->test_91_value = 0;
|
||||
}
|
||||
|
||||
void ExecuteTest()
|
||||
@@ -9228,7 +9237,16 @@ struct GRFFeatureTest {
|
||||
if (this->platform_var_bit > 0) {
|
||||
SB(_cur.grffile->var9D_overlay, this->platform_var_bit, 1, has_feature ? 1 : 0);
|
||||
grfmsg(2, "Action 14 feature test: feature test: setting bit %u of var 0x9D to %u, %u", platform_var_bit, has_feature ? 1 : 0, _cur.grffile->var9D_overlay);
|
||||
}
|
||||
if (this->test_91_value > 0) {
|
||||
if (has_feature) {
|
||||
grfmsg(2, "Action 14 feature test: feature test: adding test value 0x%X to var 0x91", this->test_91_value);
|
||||
include(_cur.grffile->var91_values, this->test_91_value);
|
||||
} else {
|
||||
grfmsg(2, "Action 14 feature test: feature test: not adding test value 0x%X to var 0x91", this->test_91_value);
|
||||
}
|
||||
}
|
||||
if (this->platform_var_bit == 0 && this->test_91_value == 0) {
|
||||
grfmsg(2, "Action 14 feature test: feature test: doing nothing: %u", has_feature ? 1 : 0);
|
||||
}
|
||||
if (this->feature != nullptr && this->feature->observation_flag != GFTOF_INVALID) {
|
||||
@@ -9296,12 +9314,25 @@ static bool ChangeGRFFeatureSetPlatformVarBit(size_t len, ByteReader *buf)
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Callback function for 'FTST'->'SVAL' to add a test success result value for checking using global variable 91. */
|
||||
static bool ChangeGRFFeatureTestSuccessResultValue(size_t len, ByteReader *buf)
|
||||
{
|
||||
if (len != 4) {
|
||||
grfmsg(2, "Action 14 feature test: expected 4 bytes for 'FTST'->'SVAL' but got " PRINTF_SIZE ", ignoring this field", len);
|
||||
buf->Skip(len);
|
||||
} else {
|
||||
_current_grf_feature_test.test_91_value = buf->ReadDWord();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Action14 tags for the FTST node */
|
||||
AllowedSubtags _tags_ftst[] = {
|
||||
AllowedSubtags('NAME', ChangeGRFFeatureTestName),
|
||||
AllowedSubtags('MINV', ChangeGRFFeatureMinVersion),
|
||||
AllowedSubtags('MAXV', ChangeGRFFeatureMaxVersion),
|
||||
AllowedSubtags('SETP', ChangeGRFFeatureSetPlatformVarBit),
|
||||
AllowedSubtags('SVAL', ChangeGRFFeatureTestSuccessResultValue),
|
||||
AllowedSubtags()
|
||||
};
|
||||
|
||||
@@ -9326,6 +9357,7 @@ struct GRFPropertyMapAction {
|
||||
std::string name;
|
||||
GRFPropertyMapFallbackMode fallback_mode;
|
||||
uint8 ttd_ver_var_bit;
|
||||
uint32 test_91_value;
|
||||
uint8 input_shift;
|
||||
uint8 output_shift;
|
||||
uint input_mask;
|
||||
@@ -9342,6 +9374,7 @@ struct GRFPropertyMapAction {
|
||||
this->name.clear();
|
||||
this->fallback_mode = GPMFM_IGNORE;
|
||||
this->ttd_ver_var_bit = 0;
|
||||
this->test_91_value = 0;
|
||||
this->input_shift = 0;
|
||||
this->output_shift = 0;
|
||||
this->input_mask = 0;
|
||||
@@ -9376,6 +9409,9 @@ struct GRFPropertyMapAction {
|
||||
if (this->ttd_ver_var_bit > 0) {
|
||||
SB(_cur.grffile->var8D_overlay, this->ttd_ver_var_bit, 1, success ? 1 : 0);
|
||||
}
|
||||
if (this->test_91_value > 0 && success) {
|
||||
include(_cur.grffile->var91_values, this->test_91_value);
|
||||
}
|
||||
if (!success) {
|
||||
if (this->fallback_mode == GPMFM_ERROR_ON_DEFINITION) {
|
||||
grfmsg(0, "Error: Unimplemented mapped %s: %s, mapped to: 0x%02X", this->descriptor, str, this->prop_id);
|
||||
@@ -9427,6 +9463,9 @@ struct GRFPropertyMapAction {
|
||||
if (this->ttd_ver_var_bit > 0) {
|
||||
SB(_cur.grffile->var8D_overlay, this->ttd_ver_var_bit, 1, success ? 1 : 0);
|
||||
}
|
||||
if (this->test_91_value > 0 && success) {
|
||||
include(_cur.grffile->var91_values, this->test_91_value);
|
||||
}
|
||||
if (!success) {
|
||||
if (this->fallback_mode == GPMFM_ERROR_ON_DEFINITION) {
|
||||
grfmsg(0, "Error: Unimplemented mapped %s: %s, feature: %s, mapped to: %X", this->descriptor, str, GetFeatureString(this->feature), this->prop_id);
|
||||
@@ -9471,6 +9510,9 @@ struct GRFPropertyMapAction {
|
||||
if (this->ttd_ver_var_bit > 0) {
|
||||
SB(_cur.grffile->var8D_overlay, this->ttd_ver_var_bit, 1, success ? 1 : 0);
|
||||
}
|
||||
if (this->test_91_value > 0 && success) {
|
||||
include(_cur.grffile->var91_values, this->test_91_value);
|
||||
}
|
||||
if (!success) {
|
||||
grfmsg(2, "Unimplemented mapped %s: %s, feature: %s, mapped to 0", this->descriptor, str, GetFeatureString(this->feature));
|
||||
}
|
||||
@@ -9502,6 +9544,9 @@ struct GRFPropertyMapAction {
|
||||
if (this->ttd_ver_var_bit > 0) {
|
||||
SB(_cur.grffile->var8D_overlay, this->ttd_ver_var_bit, 1, success ? 1 : 0);
|
||||
}
|
||||
if (this->test_91_value > 0 && success) {
|
||||
include(_cur.grffile->var91_values, this->test_91_value);
|
||||
}
|
||||
if (!success) {
|
||||
if (this->fallback_mode == GPMFM_ERROR_ON_DEFINITION) {
|
||||
grfmsg(0, "Error: Unimplemented mapped %s: %s, mapped to: %X", this->descriptor, str, this->prop_id);
|
||||
@@ -9625,6 +9670,19 @@ static bool ChangePropertyRemapSetTTDVerVarBit(size_t len, ByteReader *buf)
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Callback function for >'SVAL' to add a success result value for checking using global variable 91. */
|
||||
static bool ChangePropertyRemapSuccessResultValue(size_t len, ByteReader *buf)
|
||||
{
|
||||
GRFPropertyMapAction &action = _current_grf_property_map_action;
|
||||
if (len != 4) {
|
||||
grfmsg(2, "Action 14 %s mapping: expected 4 bytes for '%s'->'SVAL' but got " PRINTF_SIZE ", ignoring this field", action.descriptor, action.tag_name, len);
|
||||
buf->Skip(len);
|
||||
} else {
|
||||
action.test_91_value = buf->ReadDWord();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Callback function for ->'RSFT' to set the input shift value for variable remapping. */
|
||||
static bool ChangePropertyRemapSetInputShift(size_t len, ByteReader *buf)
|
||||
{
|
||||
@@ -9706,6 +9764,7 @@ AllowedSubtags _tags_fidm[] = {
|
||||
AllowedSubtags('FTID', ChangePropertyRemapFeatureId),
|
||||
AllowedSubtags('FLBK', ChangePropertyRemapSetFallbackMode),
|
||||
AllowedSubtags('SETT', ChangePropertyRemapSetTTDVerVarBit),
|
||||
AllowedSubtags('SVAL', ChangePropertyRemapSuccessResultValue),
|
||||
AllowedSubtags()
|
||||
};
|
||||
|
||||
@@ -9727,6 +9786,7 @@ AllowedSubtags _tags_a0pm[] = {
|
||||
AllowedSubtags('PROP', ChangePropertyRemapPropertyId),
|
||||
AllowedSubtags('FLBK', ChangePropertyRemapSetFallbackMode),
|
||||
AllowedSubtags('SETT', ChangePropertyRemapSetTTDVerVarBit),
|
||||
AllowedSubtags('SVAL', ChangePropertyRemapSuccessResultValue),
|
||||
AllowedSubtags()
|
||||
};
|
||||
|
||||
@@ -9751,6 +9811,7 @@ AllowedSubtags _tags_a2vm[] = {
|
||||
AllowedSubtags('VMSK', ChangePropertyRemapSetOutputMask),
|
||||
AllowedSubtags('VPRM', ChangePropertyRemapSetOutputParam),
|
||||
AllowedSubtags('SETT', ChangePropertyRemapSetTTDVerVarBit),
|
||||
AllowedSubtags('SVAL', ChangePropertyRemapSuccessResultValue),
|
||||
AllowedSubtags()
|
||||
};
|
||||
|
||||
@@ -9771,6 +9832,7 @@ AllowedSubtags _tags_a5tm[] = {
|
||||
AllowedSubtags('TYPE', ChangePropertyRemapTypeId),
|
||||
AllowedSubtags('FLBK', ChangePropertyRemapSetFallbackMode),
|
||||
AllowedSubtags('SETT', ChangePropertyRemapSetTTDVerVarBit),
|
||||
AllowedSubtags('SVAL', ChangePropertyRemapSuccessResultValue),
|
||||
AllowedSubtags()
|
||||
};
|
||||
|
||||
|
@@ -357,6 +357,7 @@ struct GRFFile : ZeroedMemoryAllocator {
|
||||
|
||||
uint32 var8D_overlay; ///< Overlay for global variable 8D (action 0x14)
|
||||
uint32 var9D_overlay; ///< Overlay for global variable 9D (action 0x14)
|
||||
std::vector<uint32> var91_values; ///< Test result values for global variable 91 (action 0x14, only testable using action 7/9)
|
||||
|
||||
uint32 observed_feature_tests; ///< Observed feature test bits (see: GRFFeatureTestObservationFlag)
|
||||
|
||||
|
@@ -16,11 +16,11 @@
|
||||
|
||||
/** Action14 feature list */
|
||||
extern const GRFFeatureInfo _grf_feature_list[] = {
|
||||
GRFFeatureInfo("feature_test", 1),
|
||||
GRFFeatureInfo("property_mapping", 1),
|
||||
GRFFeatureInfo("variable_mapping", 2),
|
||||
GRFFeatureInfo("feature_id_mapping", 1),
|
||||
GRFFeatureInfo("action5_type_id_mapping", 1),
|
||||
GRFFeatureInfo("feature_test", 2),
|
||||
GRFFeatureInfo("property_mapping", 2),
|
||||
GRFFeatureInfo("variable_mapping", 3),
|
||||
GRFFeatureInfo("feature_id_mapping", 2),
|
||||
GRFFeatureInfo("action5_type_id_mapping", 2),
|
||||
GRFFeatureInfo("action0_station_prop1B", 1),
|
||||
GRFFeatureInfo("action0_station_disallowed_bridge_pillars", 1),
|
||||
GRFFeatureInfo("varaction2_station_var42", 1),
|
||||
|
Reference in New Issue
Block a user