Implement extended NewGRF variable parameter support
This commit is contained in:
@@ -466,7 +466,7 @@
|
|||||||
<br />
|
<br />
|
||||||
<h3 id="variable-mapping">Action 14 - Variable Mapping for Variational Action 2</h3>
|
<h3 id="variable-mapping">Action 14 - Variable Mapping for Variational Action 2</h3>
|
||||||
<p>See <a href="https://newgrf-specs.tt-wiki.net/wiki/Action14">Action 14 Specification</a> and <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2">Variational Action 2 Specification</a> for background information.</p>
|
<p>See <a href="https://newgrf-specs.tt-wiki.net/wiki/Action14">Action 14 Specification</a> and <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2">Variational Action 2 Specification</a> for background information.</p>
|
||||||
<p>The variable mapping mechanism has the feature name: <font face="monospace">variable_mapping</font>, this document describes version 1.</p>
|
<p>The variable mapping mechanism has the feature name: <font face="monospace">variable_mapping</font>, this document describes version 1 (and where indicated, version 2).</p>
|
||||||
<p>Unlike property mappings, it is not necessary to perform a feature test or check a mapping success variable before using a mapped variable.</p>
|
<p>Unlike property mappings, it is not necessary to perform a feature test or check a mapping success variable before using a mapped variable.</p>
|
||||||
<p>Remapped variables are accessed by reading from variable 0x11 using a varadjust shift-num and and-mask which exactly matches that specified in the variable mapping.<br />
|
<p>Remapped variables are accessed by reading from variable 0x11 using a varadjust shift-num and and-mask which exactly matches that specified in the variable mapping.<br />
|
||||||
In the absence of any successful variable mapping, variable 0x11 has all bits set to 0 and attempting to read from it with any shift-num and and-mask value
|
In the absence of any successful variable mapping, variable 0x11 has all bits set to 0 and attempting to read from it with any shift-num and and-mask value
|
||||||
@@ -474,6 +474,9 @@
|
|||||||
<p>Reading a mapped variable on a version of OpenTTD which does not support this variable mapping mechanism or which does not support the requested variable, returns a value of 0.</p>
|
<p>Reading a mapped variable on a version of OpenTTD which does not support this variable mapping mechanism or which does not support the requested variable, returns a value of 0.</p>
|
||||||
<p>If more than one variable mapping is made for the same combination of feature ID, shift-num and and-mask, it is implementation-defined which mapping is used.<br />
|
<p>If more than one variable mapping is made for the same combination of feature ID, shift-num and and-mask, it is implementation-defined which mapping is used.<br />
|
||||||
Each variable mapping SHOULD use a unique combination of feature ID, shift-num and and-mask.</p>
|
Each variable mapping SHOULD use a unique combination of feature ID, shift-num and and-mask.</p>
|
||||||
|
<p>From version 2 of the <font face="monospace">variable_mapping</font> feature name, variable remapping can also be used with variable 0x7B.<br />
|
||||||
|
In this case the parameter of variable 0x7B should be set to 0x11, and the shift and mask fields set the same way in the direct 0x11 variable case.<br />
|
||||||
|
The "VPRM" parameter field is ignored, and the parameter used is the accumulator of the previous adjust part in the usual way for variable 0x7B.</p>
|
||||||
<h4 id="A2VM">Variable Mapping: C "A2VM"</h4>
|
<h4 id="A2VM">Variable Mapping: C "A2VM"</h4>
|
||||||
<p>Each A2VM chunk (type C) describes an individual variable mapping.<br />
|
<p>Each A2VM chunk (type C) describes an individual variable mapping.<br />
|
||||||
Sub-chunks within each A2VM chunk may appear in any order, however each sub-chunk SHOULD only appear ONCE within an individual A2VM chunk.</p>
|
Sub-chunks within each A2VM chunk may appear in any order, however each sub-chunk SHOULD only appear ONCE within an individual A2VM chunk.</p>
|
||||||
@@ -500,6 +503,10 @@
|
|||||||
If this is not specified, a value of 0 is assumed.</p>
|
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>
|
<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>
|
<p>This behaves identically to the <a href="#A0PM-SETT">C "A0PM" -> B "SETT"</a> case, above</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 />
|
||||||
|
Support for this field is indicated by the feature name <font face="monospace">variable_mapping</font>, version 2.</p>
|
||||||
<h4 id="A2VM-example">Example NFO:</h4>
|
<h4 id="A2VM-example">Example NFO:</h4>
|
||||||
<pre>
|
<pre>
|
||||||
// Map station variable "sample_station_variable" with a shift-num of 4 and an and-mask of 0xFF, to reads of variable 0x11 with a shift-num of 1 and an and-mask of 0x2, and set bit 4 of global variable 0x8D if successful
|
// Map station variable "sample_station_variable" with a shift-num of 4 and an and-mask of 0xFF, to reads of variable 0x11 with a shift-num of 1 and an and-mask of 0x2, and set bit 4 of global variable 0x8D if successful
|
||||||
|
@@ -5414,6 +5414,16 @@ static void NewSpriteGroup(ByteReader *buf)
|
|||||||
adjust.variable = remap.id;
|
adjust.variable = remap.id;
|
||||||
adjust.shift_num = remap.output_shift;
|
adjust.shift_num = remap.output_shift;
|
||||||
adjust.and_mask = remap.output_mask;
|
adjust.and_mask = remap.output_mask;
|
||||||
|
adjust.parameter = remap.output_param;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (adjust.variable == 0x7B && adjust.parameter == 0x11) {
|
||||||
|
for (const GRFVariableMapEntry &remap : _cur.grffile->grf_variable_remaps) {
|
||||||
|
if (remap.feature == feature && remap.input_shift == adjust.shift_num && remap.input_mask == adjust.and_mask) {
|
||||||
|
adjust.parameter = remap.id;
|
||||||
|
adjust.shift_num = remap.output_shift;
|
||||||
|
adjust.and_mask = remap.output_mask;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8799,6 +8809,7 @@ struct GRFPropertyMapAction {
|
|||||||
uint8 output_shift;
|
uint8 output_shift;
|
||||||
uint input_mask;
|
uint input_mask;
|
||||||
uint output_mask;
|
uint output_mask;
|
||||||
|
uint output_param;
|
||||||
|
|
||||||
void Reset(const char *tag, const char *desc)
|
void Reset(const char *tag, const char *desc)
|
||||||
{
|
{
|
||||||
@@ -8814,6 +8825,7 @@ struct GRFPropertyMapAction {
|
|||||||
this->output_shift = 0;
|
this->output_shift = 0;
|
||||||
this->input_mask = 0;
|
this->input_mask = 0;
|
||||||
this->output_mask = 0;
|
this->output_mask = 0;
|
||||||
|
this->output_param = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecuteFeatureIDRemapping()
|
void ExecuteFeatureIDRemapping()
|
||||||
@@ -8930,7 +8942,7 @@ struct GRFPropertyMapAction {
|
|||||||
extern const GRFVariableMapDefinition _grf_action2_remappable_variables[];
|
extern const GRFVariableMapDefinition _grf_action2_remappable_variables[];
|
||||||
for (const GRFVariableMapDefinition *info = _grf_action2_remappable_variables; info->name != nullptr; info++) {
|
for (const GRFVariableMapDefinition *info = _grf_action2_remappable_variables; info->name != nullptr; info++) {
|
||||||
if (info->feature == this->feature && strcmp(info->name, str) == 0) {
|
if (info->feature == this->feature && strcmp(info->name, str) == 0) {
|
||||||
_cur.grffile->grf_variable_remaps.push_back({ (uint16)info->id, (uint8)this->feature, this->input_shift, this->output_shift, this->input_mask, this->output_mask });
|
_cur.grffile->grf_variable_remaps.push_back({ (uint16)info->id, (uint8)this->feature, this->input_shift, this->output_shift, this->input_mask, this->output_mask, this->output_param });
|
||||||
success = true;
|
success = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -9162,8 +9174,7 @@ static bool ChangePropertyRemapSetOutputParam(size_t len, ByteReader *buf)
|
|||||||
grfmsg(2, "Action 14 %s mapping: expected 4 bytes for '%s'->'VPRM' but got " PRINTF_SIZE ", ignoring this field", action.descriptor, action.tag_name, len);
|
grfmsg(2, "Action 14 %s mapping: expected 4 bytes for '%s'->'VPRM' but got " PRINTF_SIZE ", ignoring this field", action.descriptor, action.tag_name, len);
|
||||||
buf->Skip(len);
|
buf->Skip(len);
|
||||||
} else {
|
} else {
|
||||||
buf->ReadDWord();
|
action.output_param = buf->ReadDWord();
|
||||||
/* This is not implemented yet, so just do nothing, but still validate that the format is correct */
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -211,6 +211,7 @@ struct GRFVariableMapEntry {
|
|||||||
uint8 output_shift = 0;
|
uint8 output_shift = 0;
|
||||||
uint32 input_mask = 0;
|
uint32 input_mask = 0;
|
||||||
uint32 output_mask = 0;
|
uint32 output_mask = 0;
|
||||||
|
uint32 output_param = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The type of action 5 type. */
|
/** The type of action 5 type. */
|
||||||
|
@@ -18,7 +18,7 @@
|
|||||||
extern const GRFFeatureInfo _grf_feature_list[] = {
|
extern const GRFFeatureInfo _grf_feature_list[] = {
|
||||||
GRFFeatureInfo("feature_test", 1),
|
GRFFeatureInfo("feature_test", 1),
|
||||||
GRFFeatureInfo("property_mapping", 1),
|
GRFFeatureInfo("property_mapping", 1),
|
||||||
GRFFeatureInfo("variable_mapping", 1),
|
GRFFeatureInfo("variable_mapping", 2),
|
||||||
GRFFeatureInfo("feature_id_mapping", 1),
|
GRFFeatureInfo("feature_id_mapping", 1),
|
||||||
GRFFeatureInfo("action5_type_id_mapping", 1),
|
GRFFeatureInfo("action5_type_id_mapping", 1),
|
||||||
GRFFeatureInfo("action0_station_prop1B", 1),
|
GRFFeatureInfo("action0_station_prop1B", 1),
|
||||||
|
@@ -595,7 +595,7 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (adjust.variable >= 0x60 && adjust.variable <= 0x7F) p += seprintf(p, lastof(this->buffer), " (parameter: %X)", adjust.parameter);
|
if ((adjust.variable >= 0x60 && adjust.variable <= 0x7F) || adjust.parameter != 0) p += seprintf(p, lastof(this->buffer), " (parameter: %X)", adjust.parameter);
|
||||||
p += seprintf(p, lastof(this->buffer), ", shift: %X, and: %X", adjust.shift_num, adjust.and_mask);
|
p += seprintf(p, lastof(this->buffer), ", shift: %X, and: %X", adjust.shift_num, adjust.and_mask);
|
||||||
switch (adjust.type) {
|
switch (adjust.type) {
|
||||||
case DSGA_TYPE_DIV: p += seprintf(p, lastof(this->buffer), ", add: %X, div: %X", adjust.add_val, adjust.divmod_val); break;
|
case DSGA_TYPE_DIV: p += seprintf(p, lastof(this->buffer), ", add: %X, div: %X", adjust.add_val, adjust.divmod_val); break;
|
||||||
|
Reference in New Issue
Block a user