For the most part, writing NFO code, especially VarAction2 chains, is done by trial-and-error until it works. To help with this process, TTDPatch and OpenTTD provide various debugging tools.
OpenTTD nightly versions from r19723 and up include multiple newgrf debugging tools, including 'inspect' and a sprite aligner. OpenTTD newgrf debugging tools are described in the OpenTTD manual: OpenTTD NewGRF debugging
TTDPatch nightly versions from r663 and up include a sort of GRF debugger that displays what is going on.
To activate the debugger, use the sign cheat "Cht: grfdebug 1 [<feature> [<id> [<callback>]]]".
The "1" is there to activate the debugger. This creates a file "grfdebug.log" (deleting any existing version first) to which all following debug information is written. The optional feature, id and callback values specify what to log. If specified, only the given feature, id and callback are logged. Note that the values have to be entered in decimal, despite being hex everywhere else. When a value is missing or is equal to 255, it is not checked for a match. If the cheat fails due to "invalid parameter", it means the file "grfdebug.log" could not be created, possibly because a file of the same name exists but is not writable. If it fails with "unknown cheat", the given version does not have the GRF debugger built in (only nightly versions have it, not releases because it slows down graphics processing a little even when not used).
For instance, "Cht: grfdebug 1 1 255 18" logs callback 12 (load amount, decimal 18) for all road vehicles.
Due to the logging the game will become very slow when the debugger is active, so it is best to enable it in paused mode only, and to only briefly unpause if necessary. To trigger redrawing the graphics that are currently on the screen, press "t" (transparent mode) once. Otherwise, if the graphics in question are shown in a window, moving that window a small amount will also trigger redrawing them and call any callbacks necessary to display it.
When the problematic graphics have been displayed, turn off the debugger again with "Cht: grfdebug". This closes the "grfdebug.log" file, which may then be examined for the following entries. For help in interpreting the debug lines, DaleStan has written a  to parse the "grfdebug.log" file into a more descriptive text file.
GET cccciiff <GRFID>
Written at the start when determining the sprite/callback result for feature ff, ID ii in callback cccc (callback is 0 if none, or 1 when determining random triggers). The given GRFID is the one owning the action 3 in question.
ACT2 <sprite> 00000000
When processing a regular, random or VarAction2. The sprite number is the sprite number in the .NFO file minus one, given in hex.
RND <value> <rndbits>
In a random action 2, the random value is <value> with <rndbits> being the bits used to choose the next action 2.
VAR <value> <adjusted>
In a VarAction2, the variable value has been computed as <value>, and <adjusted> will be used after shift/and/add/mod/div adjustments were applied. Note that this is a DWORD value, but only the BYTE/WORD part will be used depending on the VarAction2 type.
RSLT <result> 00000000
A callback result has been computed. When not in a callback, this causes the sprite determination to fail and default sprites to be used.
SPRT <sprite> 00000000
A sprite number has been computed. When in a callback, this causes the callback to fail if it isn't following a RSLT line indicating a valid callback result.
Since the value is mapped into TTD's sprite number space, it is not directly related to sprite numbers in the NFO file. To translate the returned sprite number to an action 1 block sprite, it is necessary to have this grf file be loaded first in newgrf(w).cfg. Then the sprite numbers of action 1 blocks will be allocated consecutively starting from the base number (see below) for each feature.
|other||1324 (4900) Note: this includes all features not listed below as well as GRM sprite allocations|
|Road vehicles||6CDC (27868)|
The feature-specific base numbers are only valid if the extended sprite limit is active, otherwise all features use the "other" base number.
For instance, the first sprite block of 32 (20 hex) sprites for a road vehicle would start at sprite 6CDC, then the following sprite block would start at 6CDC+20=6CFC.