Difference between revisions of "Action7"

From GRFSpecs
Jump to navigationJump to search
m (Reverted edits by Pm-bot (Talk) to last revision by Orudge)
m (Bot: Automated text replacement (--= +==))
Line 1: Line 1:
   
  +
== Introduction ==
'''''Conditionally skip sprites or jump to label'''''
 
   
 
=Action 7 & Action 9=
 
=Action 7 & Action 9=
Line 6: Line 6:
 
Conditionally skip sprites or jump to label
 
Conditionally skip sprites or jump to label
   
-=Description=-
+
==Description==
   
These two actions allow you to skip a specified number or all following sprites in this .grf file.  This can be used to have, for example, climate-specific graphics, patch-version checks and error messages, and deactivating in the presence of other active .grf files.
+
These two actions allow you to skip a specified number or all following sprites in this .grf file. This can be used to have, for example, climate-specific graphics, patch-version checks and error messages, and deactivating in the presence of other active .grf files.
   
-=Format=-
+
==Format==
   
 
The data looks as follows:
 
The data looks as follows:
   
<pre>-+&lt;sprite-number&gt; * &lt;length&gt; <nowiki><nowiki>[07/09]</nowiki></nowiki> &lt;variable&gt; &lt;varsize&gt; &lt;condition-type&gt; &lt;value&gt; &lt;num-sprites&gt;+-</pre>
+
<pre>-+<sprite-number> * <length> [07/09] <variable> <varsize> <condition-type> <value> <num-sprites>+-</pre>
   
||'''Element'''|[[GRFActionsDetailed|'''Size''']]|'''Description'''
+
!'''Element'''!![[GRFActionsDetailed!!'''Size''']]!!'''Description'''
   
  +
|-
&lt;sprite-number&gt;|dec|A sequential sprite number
 
  +
|<sprite-number>||dec||A sequential sprite number
   
  +
|-
&lt;length&gt;|dec|The total number of bytes in the action
 
  +
|<length>||dec||The total number of bytes in the action
   
  +
|-
07/09|B|Action type. &nbsp;In this case, 07 or 09
 
  +
|07/09||B||Action type. In this case, 07 or 09
   
  +
|-
&lt;variable&gt;|B|Which variable to base the decision on
 
  +
|<variable>||B||Which variable to base the decision on
   
  +
|-
&lt;varsize&gt;|B|How many bytes to read from the variable
 
  +
|<varsize>||B||How many bytes to read from the variable
   
  +
|-
&lt;condition-type&gt;|B|What condition to check
 
  +
|<condition-type>||B||What condition to check
   
  +
|-
&lt;value&gt;|V|Value to compare with (size equals &lt;varsize&gt;)
 
  +
|<value>||V||Value to compare with (size equals <varsize>)
   
  +
|-
&lt;num-sprites&gt;|B|How many sprites to skip||
 
  +
|<num-sprites>||B||How many sprites to skip
  +
|}
   
-=Filling in the terms=-
+
==Filling in the terms==
   
 
===sprite-number===
 
===sprite-number===
Line 56: Line 65:
 
Here's a table showing this whole action 7/9 issue:
 
Here's a table showing this whole action 7/9 issue:
   
||Action to skip|with 7|with 9|notes
+
!Action to skip!!with 7!!with 9!!notes
   
  +
|-
0 (new props)|yes|yes|
 
  +
|0 (new props)||yes||yes||
   
  +
|-
1 (sprite blk)|yes|yes|
 
  +
|1 (sprite blk)||yes||yes||
   
  +
|-
2 (cargo ID)|n/a*|no|* skip the corresponding action 3 instead
 
  +
|2 (cargo ID)||n/a*||no||* skip the corresponding action 3 instead
   
  +
|-
3 (veh ID map)|yes*|no|* can't skip a livery override without skipping the main engine action 3 as well
 
  +
|3 (veh ID map)||yes*||no||* can't skip a livery override without skipping the main engine action 3 as well
   
  +
|-
4 (veh names)|yes|no|
 
  +
|4 (veh names)||yes||no||
   
  +
|-
5 (sprite blk)|yes|yes|
 
  +
|5 (sprite blk)||yes||yes||
   
  +
|-
6 (apply param)|n/a*|yes|* &quot;yes&quot; since 2.0.1 alpha 51
 
  +
|6 (apply param)||n/a*||yes||* "yes" since 2.0.1 alpha 51
   
  +
|-
7 (skip sprite)|yes|yes|
 
  +
|7 (skip sprite)||yes||yes||
   
  +
|-
8 (GRF ID)|yes|yes|
 
  +
|8 (GRF ID)||yes||yes||
   
  +
|-
9 (skip sprite)|yes*|yes|* not during initialization, of course
 
  +
|9 (skip sprite)||yes*||yes||* not during initialization, of course
   
  +
|-
A (repl.sprite)|yes|yes|
 
  +
|A (repl.sprite)||yes||yes||
   
  +
|-
B (error msg)|yes|yes|
 
  +
|B (error msg)||yes||yes||
   
  +
|-
C (NOP)|yes|yes|
 
  +
|C (NOP)||yes||yes||
   
  +
|-
D (set param)|yes*|yes|* not if parameter will be used in action 6 (except for 2.0.1 alpha 51 and higher)
 
  +
|D (set param)||yes*||yes||* not if parameter will be used in action 6 (except for 2.0.1 alpha 51 and higher)
   
  +
|-
E (deact.GRFs)|yes|yes|
 
  +
|E (deact.GRFs)||yes||yes||
   
  +
|-
F (town names)|n/a|yes|
 
  +
|F (town names)||n/a||yes||
   
  +
|-
10 (goto labels)|n/a|no|
 
  +
|10 (goto labels)||n/a||no||
   
  +
|-
11 (sound fx)|n/a|no|
 
  +
|11 (sound fx)||n/a||no||
   
  +
|-
12 (glyphs)|yes|yes|
 
  +
|12 (glyphs)||yes||yes||
   
  +
|-
13 (translate)|yes|yes|
 
  +
|13 (translate)||yes||yes||
   
  +
|-
14 (static info)|n/a|n/a| ||
 
  +
|14 (static info)||n/a||n/a||
  +
|}
   
 
Yes=safe to skip
 
Yes=safe to skip
Line 108: Line 139:
 
===variable===
 
===variable===
   
This sets the variable to base the decision on. &nbsp;It can be either one of the GRF parameters (see [[Action6|action 6]]), or a built-in patch variable. &nbsp;If it's a GRF parameter that wasn't specified in the newgrf(w).cfg file, or variable 88 with a GRFID that doesn't exist, the action 7 or 9 is ignored and no sprites are skipped, the only exception being condition type 0A which will skip the sprites if the GRFID doesn't exist as well.
+
This sets the variable to base the decision on. It can be either one of the GRF parameters (see [[Action6|action 6]]), or a built-in patch variable. If it's a GRF parameter that wasn't specified in the newgrf(w).cfg file, or variable 88 with a GRFID that doesn't exist, the action 7 or 9 is ignored and no sprites are skipped, the only exception being condition type 0A which will skip the sprites if the GRFID doesn't exist as well.
   
||'''Variable'''|[[GRFActionsDetailed|'''Size''']]|'''Description'''
+
!'''Variable'''!![[GRFActionsDetailed!!'''Size''']]!!'''Description'''
   
  +
|-
81|B|current year (count from 1920, max. 2175 even with eternalgame)
 
  +
|81||B||current year (count from 1920, max. 2175 even with eternalgame)
   
  +
|-
83|B|Current climate: 00 = temp, 01 = arctic, 02 = trop, 03 = toyland
 
  +
|83||B||Current climate: 00 = temp, 01 = arctic, 02 = trop, 03 = toyland
   
  +
|-
84|D|[[GrfLoadingStages|GRF loading stage]], see below
 
  +
|84||D||[[GrfLoadingStages|GRF loading stage]], see below
   
  +
|-
85|B|[[TTDPatchFlags|TTDPatch flags]]: only for bit tests
 
  +
|85||B||[[TTDPatchFlags|TTDPatch flags]]: only for bit tests
   
  +
|-
86|B|Road traffic side: bit 4 clear=left, set=right
 
  +
|86||B||Road traffic side: bit 4 clear=left, set=right
   
  +
|-
88|4*B|Checks specified GRFID (see condition-types below)
 
  +
|88||4*B||Checks specified GRFID (see condition-types below)
   
  +
|-
8B|D|TTDPatch version, see below
 
  +
|8B||D||TTDPatch version, see below
   
  +
|-
8D|B|TTD version, 0=DOS, 1=Windows
 
  +
|8D||B||TTD version, 0=DOS, 1=Windows
   
  +
|-
8E|B|Y-Offset for train sprites
 
  +
|8E||B||Y-Offset for train sprites
   
  +
|-
8F|4*B|Rail track type cost factors
 
  +
|8F||4*B||Rail track type cost factors
   
  +
|-
92|B|Game mode, 0 in title screen, 1 in game and 2 in editor
 
  +
|92||B||Game mode, 0 in title screen, 1 in game and 2 in editor
   
  +
|-
93|D|Tile refresh offset to left
 
  +
|93||D||Tile refresh offset to left
   
  +
|-
94|D|Tile refresh offset to right
 
  +
|94||D||Tile refresh offset to right
   
  +
|-
95|D|Tile refresh offset upwards
 
  +
|95||D||Tile refresh offset upwards
   
  +
|-
96|D|Tile refresh offset downwards
 
  +
|96||D||Tile refresh offset downwards
   
  +
|-
9A|D|Has always all bits set; you can use this to make unconditional jumps
 
  +
|9A||D||Has always all bits set; you can use this to make unconditional jumps
   
  +
|-
9D|D|TTD Platform, 0=TTDPatch, 1=OpenTTD
 
  +
|9D||D||TTD Platform, 0=TTDPatch, 1=OpenTTD
   
  +
|-
A1|D|OpenTTD version, see below.
 
  +
|A1||D||OpenTTD version, see below.
   
  +
|-
A2|D|Difficulty level: 00= easy, 01=medium, 02=hard, 03=custom, since r12449 for OpenTTD and r1857 for TTDPatch
 
  +
|A2||D||Difficulty level: 00= easy, 01=medium, 02=hard, 03=custom, since r12449 for OpenTTD and r1857 for TTDPatch
   
  +
|-
A3|D|Current date(4); long format, since r13376 in OpenTTD and r2048 in TTDPatch
 
  +
|A3||D||Current date(4); long format, since r13376 in OpenTTD and r2048 in TTDPatch
   
  +
|-
A4|D|Current year(4); long format, year zero based since r13376 in OpenTTD and r2048 in TTDPatch||
 
  +
|A4||D||Current year(4); long format, year zero based since r13376 in OpenTTD and r2048 in TTDPatch
  +
|}
   
 
Note 1: All other parameter values greater than 80 (hexadecimal) are reserved and must not be used in action 7 or 9.
 
Note 1: All other parameter values greater than 80 (hexadecimal) are reserved and must not be used in action 7 or 9.
Line 164: Line 217:
 
Variable 84 is a BYTE variable up to TTDPatch 2.5r1220. Its lower byte (bits 0..7) are 0 for the post-load and GRF initialization stages and 01 for all other stages. The remaining bits are a bitmask, and including the lower byte have the following meaning:
 
Variable 84 is a BYTE variable up to TTDPatch 2.5r1220. Its lower byte (bits 0..7) are 0 for the post-load and GRF initialization stages and 01 for all other stages. The remaining bits are a bitmask, and including the lower byte have the following meaning:
   
||Bit|Meaning
+
!Bit!!Meaning
   
  +
|-
0|Set after the &quot;Initialization&quot; stage completes
 
  +
|0||Set after the "Initialization" stage completes
   
  +
|-
1..7|Always clear
 
  +
|1..7||Always clear
   
  +
|-
8|Set during the &quot;Reserve&quot; stage only
 
  +
|8||Set during the "Reserve" stage only
   
  +
|-
9|Set during the &quot;Activate&quot; stage only
 
  +
|9||Set during the "Activate" stage only
   
  +
|-
10|Set during the &quot;Test&quot; stage only||
 
  +
|10||Set during the "Test" stage only
  +
|}
   
 
Variable 8B has the following format: MMmrbbbb (though encoded in little endian as bb bb mr MM)
 
Variable 8B has the following format: MMmrbbbb (though encoded in little endian as bb bb mr MM)
   
||Element|Meaning|Value
+
!Element!!Meaning!!Value
   
  +
|-
MM|major|First number of the TTDPatch version
 
  +
|MM||major||First number of the TTDPatch version
   
  +
|-
m|minor|Second number of the TTDPatch version
 
  +
|m||minor||Second number of the TTDPatch version
   
  +
|-
r|revision|Third number of the TTDPatch version*
 
  +
|r||revision||Third number of the TTDPatch version*
   
  +
|-
bbbb|build|Alpha/beta version number times ten (up to an including 2.5 beta 5), SVN revision (from 2.5 beta 5 r418 on)||
 
  +
|bbbb||build||Alpha/beta version number times ten (up to an including 2.5 beta 5), SVN revision (from 2.5 beta 5 r418 on)
  +
|}
   
 
Examples
 
Examples
   
||Version|Variable 8B|Elements
+
!Version!!Variable 8B!!Elements
   
  +
|-
1.9.1 alpha 50|019101F4| MM=01, m=9, r=1, bbbb=50*10=01F4
 
  +
|1.9.1 alpha 50||019101F4|| MM=01, m=9, r=1, bbbb=50*10=01F4
   
  +
|-
2.0 beta 4|02040028|MM=02, m=0, r=4*, bbbb=4*10=0028
 
  +
|2.0 beta 4||02040028||MM=02, m=0, r=4*, bbbb=4*10=0028
   
  +
|-
2.0 final|02070046|MM=02, m=0, r=7*, bbbb=70=0046
 
  +
|2.0 final||02070046||MM=02, m=0, r=7*, bbbb=70=0046
   
  +
|-
2.0 rev 1|02070050|MM=02, m=0, r=7*, bbbb=80=0050
 
  +
|2.0 rev 1||02070050||MM=02, m=0, r=7*, bbbb=80=0050
   
  +
|-
2.0.1 alpha 3|020A001E|MM=02, m=0, r=10*, bbbb=3*10=001E
 
  +
|2.0.1 alpha 3||020A001E||MM=02, m=0, r=10*, bbbb=3*10=001E
   
  +
|-
2.5 beta 2|02500014|MM=02, m=5, r=0, bbbb=2*10=0014
 
  +
|2.5 beta 2||02500014||MM=02, m=5, r=0, bbbb=2*10=0014
   
  +
|-
2.5 rev631|02500631|MM=02, m=5, r=0, bbbb=631=0631||
 
  +
|2.5 rev631||02500631||MM=02, m=5, r=0, bbbb=631=0631
  +
|}
   
<nowiki><nowiki>*</nowiki></nowiki> For 2.0, r=7 and for 2.0.1 series, r=10 due to an oversight which used r=1..4 for 2.0 beta 1..4.
+
* For 2.0, r=7 and for 2.0.1 series, r=10 due to an oversight which used r=1..4 for 2.0 beta 1..4.
   
 
To detect versions from 2.5 rev419 and up correctly, check that var. 8B is 02500419 or higher, or replace 0419 with the actual required revision (using the revision number as hex digits). Because SVN revisions are shared with other patch branches, it is important to check the actual patch version as well as the SVN revision.
 
To detect versions from 2.5 rev419 and up correctly, check that var. 8B is 02500419 or higher, or replace 0419 with the actual required revision (using the revision number as hex digits). Because SVN revisions are shared with other patch branches, it is important to check the actual patch version as well as the SVN revision.
Line 212: Line 284:
 
Variable A1 has the following format: Mmrbbbbb (though encoded in little endian as bb bb rb Mm). This variable has only a usefull meaning when variable 9D is 1 (OpenTTD). This variable can be used since OpenTTD r11330.
 
Variable A1 has the following format: Mmrbbbbb (though encoded in little endian as bb bb rb Mm). This variable has only a usefull meaning when variable 9D is 1 (OpenTTD). This variable can be used since OpenTTD r11330.
   
||Element|Meaning|Value
+
!Element!!Meaning!!Value
   
  +
|-
M|major|First number of the OpenTTD version
 
  +
|M||major||First number of the OpenTTD version
   
  +
|-
m|minor|Second number of the OpenTTD version
 
  +
|m||minor||Second number of the OpenTTD version
   
  +
|-
r|revision|Third number of the OpenTTD version
 
  +
|r||revision||Third number of the OpenTTD version
   
  +
|-
bbbbb|build|Subversion revision of a build leading towards a release. When a final release is done 80000h is set.||
 
  +
|bbbbb||build||Subversion revision of a build leading towards a release. When a final release is done 80000h is set.
  +
|}
   
 
The presence of 80000h (bit 19 set) means that a release always has a higher version number than any builds leading to that release.
 
The presence of 80000h (bit 19 set) means that a release always has a higher version number than any builds leading to that release.
Line 226: Line 303:
 
Examples
 
Examples
   
||Version|Variable A1|Elements
+
!Version!!Variable A1!!Elements
   
  +
|-
0.6.0 r11330|06002C42|M=0, m=6, r=0, bbbbb=11330=2C42
 
  +
|0.6.0 r11330||06002C42||M=0, m=6, r=0, bbbbb=11330=2C42
   
  +
|-
0.6.0 (release)|06080000|M=0, m=6, r=0, bbbbb=0=80000 (due to release)||
 
  +
|0.6.0 (release)||06080000||M=0, m=6, r=0, bbbbb=0=80000 (due to release)
  +
|}
   
 
===varsize===
 
===varsize===
   
For GRF parameters, this is the same as &lt;param-size&gt; in [[Action6#param%2Dsize|action 6]]. For built-in variables, it depends on the variable, see the above table.
+
For GRF parameters, this is the same as <param-size> in [[Action6#param%2Dsize|action 6]]. For built-in variables, it depends on the variable, see the above table.
   
 
For bit tests, this size is ignored. Value must be a BYTE for bit tests, no matter what the size of the variable being tested.
 
For bit tests, this size is ignored. Value must be a BYTE for bit tests, no matter what the size of the variable being tested.
Line 244: Line 324:
 
There are several conditions you can choose from to test against. This has an escape sequence for each valid value. See [[GRFActionsDetailed#Byte_order|the discussion of escape sequences]] for further information on escape sequences in general. For your convenience they are summed up in yet another table:
 
There are several conditions you can choose from to test against. This has an escape sequence for each valid value. See [[GRFActionsDetailed#Byte_order|the discussion of escape sequences]] for further information on escape sequences in general. For your convenience they are summed up in yet another table:
   
||'''Condition type'''|'''Escape'''|'''Description'''
+
!'''Condition type'''!!'''Escape'''!!'''Description'''
   
  +
|-
00|\71|Test for bit given by value being set
 
  +
|00||\71||Test for bit given by value being set
   
  +
|-
01|\70|Test for bit given by value being clear
 
  +
|01||\70||Test for bit given by value being clear
   
  +
|-
02|\7=|Parameter is equal to value
 
  +
|02||\7=||Parameter is equal to value
   
  +
|-
03|\7!|Parameter is not equal to value
 
  +
|03||\7!||Parameter is not equal to value
   
  +
|-
04|\7&lt;|Parameter is less than value
 
  +
|04||\7<||Parameter is less than value
   
  +
|-
05|\7&gt;|Parameter is greater than value
 
  +
|05||\7>||Parameter is greater than value
   
  +
|-
06|\7G|GRF ID (see [[Action8|action 8]]) is active (for variable 88 only)
 
  +
|06||\7G||GRF ID (see [[Action8|action 8]]) is active (for variable 88 only)
   
  +
|-
07|\7g|GRF ID is not active (for variable 88 only)
 
  +
|07||\7g||GRF ID is not active (for variable 88 only)
   
  +
|-
08|\7gG|GRF ID is not active yet but will be activated (variable 88 only)
 
  +
|08||\7gG||GRF ID is not active yet but will be activated (variable 88 only)
   
  +
|-
09|\7GG|GRF ID is or will be active (variable 88 only)
 
  +
|09||\7GG||GRF ID is or will be active (variable 88 only)
   
  +
|-
0A|\7gg|GRF ID is not nor will it be active (variable 88 only)
 
  +
|0A||\7gg||GRF ID is not nor will it be active (variable 88 only)
   
  +
|-
0B|\7c|Cargo type is not available (variable is ignored; value is the label)*
 
  +
|0B||\7c||Cargo type is not available (variable is ignored; value is the label)*
   
  +
|-
0C|\7C|Cargo type is available (variable is ignored; value is the label)*
 
  +
|0C||\7C||Cargo type is available (variable is ignored; value is the label)*
   
  +
|-
0D| |Rail type label is not defined (variable is ignored; value is the label)**
 
  +
|0D|| ||Rail type label is not defined (variable is ignored; value is the label)**
   
  +
|-
0E| |Rail type label is defined (variable is ignored; value is the label)**||
 
  +
|0E|| ||Rail type label is defined (variable is ignored; value is the label)**
  +
|}
   
 
Note that for the characters, a capital letter means available, and a lowercase character means not available. For the two character GRFid sequences, the first character is its current state, and the second is its future state.
 
Note that for the characters, a capital letter means available, and a lowercase character means not available. For the two character GRFid sequences, the first character is its current state, and the second is its future state.
   
<nowiki><nowiki>*</nowiki></nowiki> Prior to r11358, OTTD will skip these checks with variable 88.
+
* Prior to r11358, OTTD will skip these checks with variable 88.
   
<nowiki><nowiki>**</nowiki></nowiki> Only in OpenTTD since r15418.
+
** Only in OpenTTD since r15418.
   
 
The tests for variable 88 depend on the current [[GrfLoadingStages|GRF Loading Stage]], the order GRFs are loaded, and of course whether they are present or were disabled (by themself or by other GRFs). Consider two GRFs A and B (loaded in that order):
 
The tests for variable 88 depend on the current [[GrfLoadingStages|GRF Loading Stage]], the order GRFs are loaded, and of course whether they are present or were disabled (by themself or by other GRFs). Consider two GRFs A and B (loaded in that order):
   
  +
|-
<pre>~pp~Condition | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Initialisation &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Reservation/Activation &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| Tested GRF &nbsp; |
 
  +
|<pre>~pp~Condition || Initialisation || Reservation/Activation || Tested GRF ||
   
  +
|-
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp;A testing for B &nbsp; &nbsp;| &nbsp; &nbsp;B testing for A &nbsp; &nbsp;| &nbsp; &nbsp;A testing for B &nbsp; &nbsp;| &nbsp; &nbsp;B testing for A &nbsp; &nbsp;| not present &nbsp;|
 
  +
| || A testing for B || B testing for A || A testing for B || B testing for A || not present ||
   
  +
|-
----------+-----------------------+-----------------------+-----------------------+-----------------------|--------------|
 
  +
|----------+-----------------------+-----------------------+-----------------------+-----------------------||--------------||
   
  +
|-
06 &nbsp;\\7G &nbsp; | always false &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| always false &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| always false &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| A not disabled? &nbsp; &nbsp; &nbsp; | always false |
 
  +
|06 \\7G || always false || always false || always false || A not disabled? || always false ||
   
  +
|-
07 &nbsp;\\7g &nbsp; | always true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | always true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | always true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | A disabled? &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | always false |
 
  +
|07 \\7g || always true || always true || always true || A disabled? || always false ||
   
  +
|-
08 &nbsp;\\7gG &nbsp;| always false &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| A not (yet) disabled? | B not (yet) disabled? | always false &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| always false |
 
  +
|08 \\7gG || always false || A not (yet) disabled? || B not (yet) disabled? || always false || always false ||
   
  +
|-
09 &nbsp;\\7GG &nbsp;| always false &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| A not (yet) disabled? | B not (yet) disabled? | A not disabled? &nbsp; &nbsp; &nbsp; | always false |
 
  +
|09 \\7GG || always false || A not (yet) disabled? || B not (yet) disabled? || A not disabled? || always false ||
   
  +
|-
0A &nbsp;\\7gg &nbsp;| B (already) disabled? | A (already) disabled? | B (already) disabled? | A disabled? &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | always true &nbsp;|~/pp~</pre>
 
  +
|0A \\7gg || B (already) disabled? || A (already) disabled? || B (already) disabled? || A disabled? || always true ||~/pp~</pre>
   
If the tested GRF is not present, conditions 06 to 09 always evaluate to &quot;false&quot;. For condition 0A &quot;disabled&quot; and &quot;not present&quot; are the same, i.e. it always evaluates to &quot;true&quot;.
+
If the tested GRF is not present, conditions 06 to 09 always evaluate to "false". For condition 0A "disabled" and "not present" are the same, i.e. it always evaluates to "true".
   
 
===value===
 
===value===
   
This term is what the variable is compared to. Its size is given by &lt;varsize&gt;.
+
This term is what the variable is compared to. Its size is given by <varsize>.
   
 
For bit tests (condition types 00 or 01), it must always be a single BYTE for bit tests and specifies the bit to test.
 
For bit tests (condition types 00 or 01), it must always be a single BYTE for bit tests and specifies the bit to test.
Line 318: Line 422:
 
===num-sprites===
 
===num-sprites===
   
This element sets how many sprites will be skipped if the condition is true. &nbsp;If num-sprites is zero, the entire rest of the .grf file will be skipped, otherwise exactly that many sprites will be skipped. If this causes action 8 to be skipped, the .grf file will be deemed inactive.
+
This element sets how many sprites will be skipped if the condition is true. If num-sprites is zero, the entire rest of the .grf file will be skipped, otherwise exactly that many sprites will be skipped. If this causes action 8 to be skipped, the .grf file will be deemed inactive.
   
 
If the condition is false, processing continues at the following sprite.
 
If the condition is false, processing continues at the following sprite.
   
Starting from TTDPatch 2.0.1 alpha 49, it is possible to jump to a certain position in the grf file by defining labels with [[Action10|action 10]]. &nbsp;If num-sprites is the number of a label defined somewhere in the file, then processing of the grf file resumes with the sprite following the label, instead of skipping that many sprites. This is the only way to skip more than 255 sprites at once.
+
Starting from TTDPatch 2.0.1 alpha 49, it is possible to jump to a certain position in the grf file by defining labels with [[Action10|action 10]]. If num-sprites is the number of a label defined somewhere in the file, then processing of the grf file resumes with the sprite following the label, instead of skipping that many sprites. This is the only way to skip more than 255 sprites at once.
   
 
Since 2.0.1 alpha 70, duplicate labels are fully supported. The jump will always be to the first matching label that follows. If no matching label follows, the first matching label in the file will be used instead.
 
Since 2.0.1 alpha 70, duplicate labels are fully supported. The jump will always be to the first matching label that follows. If no matching label follows, the first matching label in the file will be used instead.
Line 328: Line 432:
 
Note that it is generally not safe to skip backwards, i.e. to an earlier position. While the patch will happily do that, you will get strange results if certain actions are repeated. Only action 0, 6, 7, 9, C and D are reasonably safe to execute more than once.
 
Note that it is generally not safe to skip backwards, i.e. to an earlier position. While the patch will happily do that, you will get strange results if certain actions are repeated. Only action 0, 6, 7, 9, C and D are reasonably safe to execute more than once.
   
-=Example=-
+
==Example==
   
 
Let's start with an easy Action 7:
 
Let's start with an easy Action 7:
Line 336: Line 440:
 
What does this Action 7 tells TTDPatch to do with the fictional .grf file?
 
What does this Action 7 tells TTDPatch to do with the fictional .grf file?
   
||'''Byte'''|'''Meaning'''
+
!'''Byte'''!!'''Meaning'''
   
  +
|-
47|&lt;sprite-number&gt;
 
  +
|47||<sprite-number>
   
  +
|-
6|&lt;length&gt; of the action in bytes; start counting at 07 (&lt;action&gt;)
 
  +
|6||<length> of the action in bytes; start counting at 07 (<action>)
   
  +
|-
07|&lt;action&gt;: sets this pseudo-sprite to function as action 7
 
  +
|07||<action>: sets this pseudo-sprite to function as action 7
   
  +
|-
83|&lt;variable&gt; 83 refers to the 4 different climates
 
  +
|83||<variable> 83 refers to the 4 different climates
   
  +
|-
01|&lt;varsize&gt;: amount of bytes to compare; a single byte for the climate
 
  +
|01||<varsize>: amount of bytes to compare; a single byte for the climate
   
  +
|-
03|&lt;condition-type&gt; 03 means skip if the variable is not equal to the &lt;value&gt;
 
  +
|03||<condition-type> 03 means skip if the variable is not equal to the <value>
   
  +
|-
00|&lt;value&gt; 00 equals temperate climate for this variable
 
  +
|00||<value> 00 equals temperate climate for this variable
   
  +
|-
00|&lt;num-sprites&gt; 00 means to skip the whole .grf file if the condition is true, i.e. for all climates except temperate in this case||
 
  +
|00||<num-sprites> 00 means to skip the whole .grf file if the condition is true, i.e. for all climates except temperate in this case
  +
|}
   
 
Therefore, this action 7 skips the rest of the file if it is being loaded in a climate other than the temperate climate.
 
Therefore, this action 7 skips the rest of the file if it is being loaded in a climate other than the temperate climate.
   
-=Patch version check=-
+
==Patch version check==
   
 
Due to action 7 being skipped during initalization, and action B severity bit 7 not working before 2.0.1 alpha 66, the best way to check for the required patch version is the following sequence:
 
Due to action 7 being skipped during initalization, and action B severity bit 7 not working before 2.0.1 alpha 66, the best way to check for the required patch version is the following sequence:
   
<pre>~pp~ &nbsp; // Check for 2.0.1 alpha 57, skip action B if present
+
<pre>~pp~ // Check for 2.0.1 alpha 57, skip action B if present
   
1 * 9 &nbsp; &nbsp; &nbsp; 09 8B 04 05 39 02 0A 02 01
+
1 * 9 09 8B 04 05 39 02 0A 02 01
   
&nbsp; // Abort with fatal action B if not (during its first activation)
+
// Abort with fatal action B if not (during its first activation)
   
2 * 19 &nbsp; &nbsp; &nbsp;0B 03 1F 00 32 2E 30 2E 31 20 61 6C 70 68 61 20 35 37 00
+
2 * 19 0B 03 1F 00 32 2E 30 2E 31 20 61 6C 70 68 61 20 35 37 00
   
&nbsp; // Action 8
+
// Action 8
   
3 * ... &nbsp; &nbsp; 08 06 ...
+
3 * ... 08 06 ...
   
&nbsp; // Skip rest of file if not 2.0.1 alpha 57,
+
// Skip rest of file if not 2.0.1 alpha 57,
   
&nbsp; // to prevent meaningless &quot;invalid sprite&quot; errors
+
// to prevent meaningless "invalid sprite" errors
   
4 * 9 &nbsp; &nbsp; &nbsp; 09 8B 04 04 3A 02 0A 02 00~/pp~</pre>
+
4 * 9 09 8B 04 04 3A 02 0A 02 00~/pp~</pre>
   
This way the GRF Status entry shows the proper error message as well as the correct name and description because the action 8 is still being processed during initialization, and all unknown sprites are skipped so that the &quot;invalid sprites&quot; error message is not shown first (or else it would become the permanent message shown in the GRF Status Window).
+
This way the GRF Status entry shows the proper error message as well as the correct name and description because the action 8 is still being processed during initialization, and all unknown sprites are skipped so that the "invalid sprites" error message is not shown first (or else it would become the permanent message shown in the GRF Status Window).
   
-=Unconditional jump=-
+
==Unconditional jump==
   
 
Var 9A always has all bits set, so to make an unconditional jump you can use a bit test:
 
Var 9A always has all bits set, so to make an unconditional jump you can use a bit test:
   
<pre>~pp~1 * 7 &nbsp; 07 9A 01 00 00 01~/pp~ resp.
+
<pre>~pp~1 * 7 07 9A 01 00 00 01~/pp~ resp.
   
~pp~1 * 7 &nbsp; 07 9A 01 \\71 00 01~/pp~</pre>
+
~pp~1 * 7 07 9A 01 \\71 00 01~/pp~</pre>
   
 
What this does is that it checks if bit 0 from the first byte of variable 9A is set (which it always is), so the sprite which you put after this action 7 is always skipped.
 
What this does is that it checks if bit 0 from the first byte of variable 9A is set (which it always is), so the sprite which you put after this action 7 is always skipped.

Revision as of 22:10, 14 June 2011

Introduction

Action 7 & Action 9

Conditionally skip sprites or jump to label

Description

These two actions allow you to skip a specified number or all following sprites in this .grf file. This can be used to have, for example, climate-specific graphics, patch-version checks and error messages, and deactivating in the presence of other active .grf files.

Format

The data looks as follows:

-+<sprite-number> * <length> [07/09] <variable> <varsize> <condition-type> <value> <num-sprites>+-

!Element!!GRFActionsDetailed!!'''Size'''!!Description

|- |<sprite-number>||dec||A sequential sprite number

|- |<length>||dec||The total number of bytes in the action

|- |07/09||B||Action type. In this case, 07 or 09

|- |<variable>||B||Which variable to base the decision on

|- |<varsize>||B||How many bytes to read from the variable

|- |<condition-type>||B||What condition to check

|- |<value>||V||Value to compare with (size equals <varsize>)

|- |<num-sprites>||B||How many sprites to skip |}

Filling in the terms

sprite-number

The current sprite number.

length

The total number of bytes in this action 7 or 9.

action

The type of action this pseudo-sprites defines. It is either 07 or 09, depending if you are using action 7 or action 9.

Both have identical format, the only difference is whether sprites will be skipped during the initialisation of the TTDPatch graphics system, or only when the .grf file becomes active.

Action 9 is always executed, both during initialisation and activation, but action 7 is executed only during activation.

Depending on the action(s) you want to skip, you cannot always use both actions. If in doubt, use action 7 except to skip an action 6 or F. You must not skip an action 2 at all unless skipping the entire rest of the file. Instead, skip the action 3 that refers to it.

Here's a table showing this whole action 7/9 issue:

!Action to skip!!with 7!!with 9!!notes

|- |0 (new props)||yes||yes||

|- |1 (sprite blk)||yes||yes||

|- |2 (cargo ID)||n/a*||no||* skip the corresponding action 3 instead

|- |3 (veh ID map)||yes*||no||* can't skip a livery override without skipping the main engine action 3 as well

|- |4 (veh names)||yes||no||

|- |5 (sprite blk)||yes||yes||

|- |6 (apply param)||n/a*||yes||* "yes" since 2.0.1 alpha 51

|- |7 (skip sprite)||yes||yes||

|- |8 (GRF ID)||yes||yes||

|- |9 (skip sprite)||yes*||yes||* not during initialization, of course

|- |A (repl.sprite)||yes||yes||

|- |B (error msg)||yes||yes||

|- |C (NOP)||yes||yes||

|- |D (set param)||yes*||yes||* not if parameter will be used in action 6 (except for 2.0.1 alpha 51 and higher)

|- |E (deact.GRFs)||yes||yes||

|- |F (town names)||n/a||yes||

|- |10 (goto labels)||n/a||no||

|- |11 (sound fx)||n/a||no||

|- |12 (glyphs)||yes||yes||

|- |13 (translate)||yes||yes||

|- |14 (static info)||n/a||n/a|| |}

Yes=safe to skip

No=not safe to skip, will break the grf file or TTDPatch

N/A=not applicable; it won't break anything, but it won't actually be skipped either (in other words, its definitions will continue to be used)

variable

This sets the variable to base the decision on. It can be either one of the GRF parameters (see action 6), or a built-in patch variable. If it's a GRF parameter that wasn't specified in the newgrf(w).cfg file, or variable 88 with a GRFID that doesn't exist, the action 7 or 9 is ignored and no sprites are skipped, the only exception being condition type 0A which will skip the sprites if the GRFID doesn't exist as well.

!Variable!!GRFActionsDetailed!!'''Size'''!!Description

|- |81||B||current year (count from 1920, max. 2175 even with eternalgame)

|- |83||B||Current climate: 00 = temp, 01 = arctic, 02 = trop, 03 = toyland

|- |84||D||GRF loading stage, see below

|- |85||B||TTDPatch flags: only for bit tests

|- |86||B||Road traffic side: bit 4 clear=left, set=right

|- |88||4*B||Checks specified GRFID (see condition-types below)

|- |8B||D||TTDPatch version, see below

|- |8D||B||TTD version, 0=DOS, 1=Windows

|- |8E||B||Y-Offset for train sprites

|- |8F||4*B||Rail track type cost factors

|- |92||B||Game mode, 0 in title screen, 1 in game and 2 in editor

|- |93||D||Tile refresh offset to left

|- |94||D||Tile refresh offset to right

|- |95||D||Tile refresh offset upwards

|- |96||D||Tile refresh offset downwards

|- |9A||D||Has always all bits set; you can use this to make unconditional jumps

|- |9D||D||TTD Platform, 0=TTDPatch, 1=OpenTTD

|- |A1||D||OpenTTD version, see below.

|- |A2||D||Difficulty level: 00= easy, 01=medium, 02=hard, 03=custom, since r12449 for OpenTTD and r1857 for TTDPatch

|- |A3||D||Current date(4); long format, since r13376 in OpenTTD and r2048 in TTDPatch

|- |A4||D||Current year(4); long format, year zero based since r13376 in OpenTTD and r2048 in TTDPatch |}

Note 1: All other parameter values greater than 80 (hexadecimal) are reserved and must not be used in action 7 or 9.

Note 2: The value of variable 88 can only be tested with the GRFID tests.

Note 3: The tile refresh offsets are available from 2.0.1 alpha 39. See Action D for more details on their use.

Note 4: OpenTTD doesn't report the current date and year but the date and year the game was loaded. The reason lies in the fact that it was seen that use of this variable leads to desyncs in network games.

Variable 84 is a BYTE variable up to TTDPatch 2.5r1220. Its lower byte (bits 0..7) are 0 for the post-load and GRF initialization stages and 01 for all other stages. The remaining bits are a bitmask, and including the lower byte have the following meaning:

!Bit!!Meaning

|- |0||Set after the "Initialization" stage completes

|- |1..7||Always clear

|- |8||Set during the "Reserve" stage only

|- |9||Set during the "Activate" stage only

|- |10||Set during the "Test" stage only |}

Variable 8B has the following format: MMmrbbbb (though encoded in little endian as bb bb mr MM)

!Element!!Meaning!!Value

|- |MM||major||First number of the TTDPatch version

|- |m||minor||Second number of the TTDPatch version

|- |r||revision||Third number of the TTDPatch version*

|- |bbbb||build||Alpha/beta version number times ten (up to an including 2.5 beta 5), SVN revision (from 2.5 beta 5 r418 on) |}

Examples

!Version!!Variable 8B!!Elements

|- |1.9.1 alpha 50||019101F4|| MM=01, m=9, r=1, bbbb=50*10=01F4

|- |2.0 beta 4||02040028||MM=02, m=0, r=4*, bbbb=4*10=0028

|- |2.0 final||02070046||MM=02, m=0, r=7*, bbbb=70=0046

|- |2.0 rev 1||02070050||MM=02, m=0, r=7*, bbbb=80=0050

|- |2.0.1 alpha 3||020A001E||MM=02, m=0, r=10*, bbbb=3*10=001E

|- |2.5 beta 2||02500014||MM=02, m=5, r=0, bbbb=2*10=0014

|- |2.5 rev631||02500631||MM=02, m=5, r=0, bbbb=631=0631 |}

  • For 2.0, r=7 and for 2.0.1 series, r=10 due to an oversight which used r=1..4 for 2.0 beta 1..4.

To detect versions from 2.5 rev419 and up correctly, check that var. 8B is 02500419 or higher, or replace 0419 with the actual required revision (using the revision number as hex digits). Because SVN revisions are shared with other patch branches, it is important to check the actual patch version as well as the SVN revision.

Variable A1 has the following format: Mmrbbbbb (though encoded in little endian as bb bb rb Mm). This variable has only a usefull meaning when variable 9D is 1 (OpenTTD). This variable can be used since OpenTTD r11330.

!Element!!Meaning!!Value

|- |M||major||First number of the OpenTTD version

|- |m||minor||Second number of the OpenTTD version

|- |r||revision||Third number of the OpenTTD version

|- |bbbbb||build||Subversion revision of a build leading towards a release. When a final release is done 80000h is set. |}

The presence of 80000h (bit 19 set) means that a release always has a higher version number than any builds leading to that release.

Examples

!Version!!Variable A1!!Elements

|- |0.6.0 r11330||06002C42||M=0, m=6, r=0, bbbbb=11330=2C42

|- |0.6.0 (release)||06080000||M=0, m=6, r=0, bbbbb=0=80000 (due to release) |}

varsize

For GRF parameters, this is the same as <param-size> in action 6. For built-in variables, it depends on the variable, see the above table.

For bit tests, this size is ignored. Value must be a BYTE for bit tests, no matter what the size of the variable being tested.

Since r1384 it is possible to set this to 8 bytes with Variable 88 thus allowing the use of a bit mask. This is useful for if only a few bits change over several grfs.

condition-type

There are several conditions you can choose from to test against. This has an escape sequence for each valid value. See the discussion of escape sequences for further information on escape sequences in general. For your convenience they are summed up in yet another table:

!Condition type!!Escape!!Description

|- |00||\71||Test for bit given by value being set

|- |01||\70||Test for bit given by value being clear

|- |02||\7=||Parameter is equal to value

|- |03||\7!||Parameter is not equal to value

|- |04||\7<||Parameter is less than value

|- |05||\7>||Parameter is greater than value

|- |06||\7G||GRF ID (see action 8) is active (for variable 88 only)

|- |07||\7g||GRF ID is not active (for variable 88 only)

|- |08||\7gG||GRF ID is not active yet but will be activated (variable 88 only)

|- |09||\7GG||GRF ID is or will be active (variable 88 only)

|- |0A||\7gg||GRF ID is not nor will it be active (variable 88 only)

|- |0B||\7c||Cargo type is not available (variable is ignored; value is the label)*

|- |0C||\7C||Cargo type is available (variable is ignored; value is the label)*

|- |0D|| ||Rail type label is not defined (variable is ignored; value is the label)**

|- |0E|| ||Rail type label is defined (variable is ignored; value is the label)** |}

Note that for the characters, a capital letter means available, and a lowercase character means not available. For the two character GRFid sequences, the first character is its current state, and the second is its future state.

  • Prior to r11358, OTTD will skip these checks with variable 88.
    • Only in OpenTTD since r15418.

The tests for variable 88 depend on the current GRF Loading Stage, the order GRFs are loaded, and of course whether they are present or were disabled (by themself or by other GRFs). Consider two GRFs A and B (loaded in that order):

|-

|

~pp~Condition ||                Initialisation                 ||             Reservation/Activation            || Tested GRF   ||

|-
|         ||    A testing for B    ||    B testing for A    ||    A testing for B    ||    B testing for A    || not present  ||

|-
|----------+-----------------------+-----------------------+-----------------------+-----------------------||--------------||

|-
|06  \\7G   || always false          || always false          || always false          || A not disabled?       || always false ||

|-
|07  \\7g   || always true           || always true           || always true           || A disabled?           || always false ||

|-
|08  \\7gG  || always false          || A not (yet) disabled? || B not (yet) disabled? || always false          || always false ||

|-
|09  \\7GG  || always false          || A not (yet) disabled? || B not (yet) disabled? || A not disabled?       || always false ||

|-
|0A  \\7gg  || B (already) disabled? || A (already) disabled? || B (already) disabled? || A disabled?           || always true  ||~/pp~

If the tested GRF is not present, conditions 06 to 09 always evaluate to "false". For condition 0A "disabled" and "not present" are the same, i.e. it always evaluates to "true".

value

This term is what the variable is compared to. Its size is given by <varsize>.

For bit tests (condition types 00 or 01), it must always be a single BYTE for bit tests and specifies the bit to test.

For conditions 0B, 0C, 0D and 0E the value specifies directly the cargo/railtype label; it is no index into a translation table.

For conditions 0B and (since 2.0.1 alpha 72) 0C, the variable given is ignored (but must be a valid variable nonetheless), the varsize must be 4 and the value must be the cargo label to check for. If no cargo with this label is defined in case of condition 0B, the given number of sprites are skipped. For condition 0C, the sprites are skipped if the cargo label has been defined. Both tests work irrespective of the order of .grf files in newgrf(w).cfg; the cargo is considered to be available even if it is defined by a later grf file. For this to work correctly, you must not skip a cargo definition with conditions 0B or 0C.

The same holds for conditions 0D and 0E wrt. railtypes and their reservation.

Since r1384, setting varsize to 8, changes value slightly, the first 4 bytes are the value (generalised grfid), and the next 4 bytes are a bit mask for the grfids to check. Please note you should make sure any masked bits are also not in the grfid to check, as value to check against is not currently masked.

num-sprites

This element sets how many sprites will be skipped if the condition is true. If num-sprites is zero, the entire rest of the .grf file will be skipped, otherwise exactly that many sprites will be skipped. If this causes action 8 to be skipped, the .grf file will be deemed inactive.

If the condition is false, processing continues at the following sprite.

Starting from TTDPatch 2.0.1 alpha 49, it is possible to jump to a certain position in the grf file by defining labels with action 10. If num-sprites is the number of a label defined somewhere in the file, then processing of the grf file resumes with the sprite following the label, instead of skipping that many sprites. This is the only way to skip more than 255 sprites at once.

Since 2.0.1 alpha 70, duplicate labels are fully supported. The jump will always be to the first matching label that follows. If no matching label follows, the first matching label in the file will be used instead.

Note that it is generally not safe to skip backwards, i.e. to an earlier position. While the patch will happily do that, you will get strange results if certain actions are repeated. Only action 0, 6, 7, 9, C and D are reasonably safe to execute more than once.

Example

Let's start with an easy Action 7:

-+ 47 * 6 07 83 01 03 00 00+-

What does this Action 7 tells TTDPatch to do with the fictional .grf file?

!Byte!!Meaning

|- |47||<sprite-number>

|- |6||<length> of the action in bytes; start counting at 07 (<action>)

|- |07||<action>: sets this pseudo-sprite to function as action 7

|- |83||<variable> 83 refers to the 4 different climates

|- |01||<varsize>: amount of bytes to compare; a single byte for the climate

|- |03||<condition-type> 03 means skip if the variable is not equal to the <value>

|- |00||<value> 00 equals temperate climate for this variable

|- |00||<num-sprites> 00 means to skip the whole .grf file if the condition is true, i.e. for all climates except temperate in this case |}

Therefore, this action 7 skips the rest of the file if it is being loaded in a climate other than the temperate climate.

Patch version check

Due to action 7 being skipped during initalization, and action B severity bit 7 not working before 2.0.1 alpha 66, the best way to check for the required patch version is the following sequence:

~pp~   // Check for 2.0.1 alpha 57, skip action B if present

1 * 9       09 8B 04 05 39 02 0A 02 01

  // Abort with fatal action B if not (during its first activation)

2 * 19      0B 03 1F 00 32 2E 30 2E 31 20 61 6C 70 68 61 20 35 37 00

  // Action 8

3 * ...     08 06 ...

  // Skip rest of file if not 2.0.1 alpha 57,

  // to prevent meaningless "invalid sprite" errors

4 * 9       09 8B 04 04 3A 02 0A 02 00~/pp~

This way the GRF Status entry shows the proper error message as well as the correct name and description because the action 8 is still being processed during initialization, and all unknown sprites are skipped so that the "invalid sprites" error message is not shown first (or else it would become the permanent message shown in the GRF Status Window).

Unconditional jump

Var 9A always has all bits set, so to make an unconditional jump you can use a bit test:

~pp~1 * 7   07 9A 01 00 00 01~/pp~ resp.

~pp~1 * 7   07 9A 01 \\71 00 01~/pp~

What this does is that it checks if bit 0 from the first byte of variable 9A is set (which it always is), so the sprite which you put after this action 7 is always skipped.