Confused about callback results

Discussions about the technical aspects of graphics development, including NewGRF tools and utilities.

Moderator: Graphics Moderators

Post Reply
User avatar
UnicycleBloke
Engineer
Engineer
Posts: 63
Joined: 30 Aug 2011 14:39
Location: Cambridge, England

Confused about callback results

Post by UnicycleBloke »

I would be grateful for any assistance in understanding 1-2-3 chains better. In particular, I am puzzled by the use of callback results. I've tried to make sense of the NewGRF specs, and had a look through some of the OTTD source. This may be the wrong forum, but the context is that I am working on (yet another) decompiler for GRFs, because I am curious about what NML does under the hood, which makes me curious about how GRFs work in detail.

This is what I think I know:

- Action01 defines sprite sets. Each set a collection of images of the same train (say) in the same state, but in different orientations. When these are loaded into OTTD, each image is given a unique SpriteID.

- Action02, in its various forms (basic, variable, random) is used to construct a whole tree of decisions which are made in terms of the current state of the game (by testing variable values). The leaves of the tree are Action01 sprite sets. The tree is walked (potentially frequently) at runtime in order to select the particular SpriteIDs that are used for our train (or whatever) at any given time.

- Action03 associates the root of some Action02 tree with a particular type of game object, such as our train. The same tree could be used for multiple trains (or whatever).

Does that sound about right so far? I might have some details wrong, but it seems to make sense, and I can see that the decision trees allow a great deal of flexibility over what is actually drawn, giving variations depending on cargo type, cargo amount, time of year, day of the week, or whatever you like.

The thing that has me puzzled is what callback results mean in this context. I was under the impression that they would invoke a function call at runtime, but they appear to be just numbers which are returned. I can see in the source code that each callback result in a VarAction02 is used to create an object in the tree of other Action02 objects, which just returns the value they were given. Are they supposed to be a direct reference to a SpriteID, or something else? It seems that they can be used to return string IDs or other things, and this seems at odds with the goal of finding a sprite to draw.

I guess they could be used for other decisions, such as the current name of an item (say), but this was not clear from the specs. I was particularly confused to see examples in VarAction02s in which some ranges return other Action02 set ids, and some ranges return callback results.

Can anyone explain what's going on?

Thanks very much.


Al

User avatar
PikkaBird
Graphics Moderator
Graphics Moderator
Posts: 5472
Joined: 13 Sep 2004 13:21
Location: The Moon
Contact:

Re: Confused about callback results

Post by PikkaBird »

UnicycleBloke wrote:
25 Nov 2019 10:14
I was under the impression that they would invoke a function call at runtime
Callbacks are not invoked, but run on set triggers (the vehicle moves, the track type changes, a processing loop happens, etc) - which is why some intensive callbacks need to be explicitly turned on by a bit switch, to avoid running them unnecessarily for vehicles/objects which don't require them.

When the callback runs, it walks the action 2 tree until it reaches a callback result or a callback failure (eg a real graphic). Variable 0C (callback ID) is checked to return particular results (or follow particular branches of the tree) for different callbacks.

User avatar
UnicycleBloke
Engineer
Engineer
Posts: 63
Joined: 30 Aug 2011 14:39
Location: Cambridge, England

Re: Confused about callback results

Post by UnicycleBloke »

Right, thanks. I got myself confused about how graphics and callbacks are integrated. If I've understood you, the process of obtaining graphics is really just another callback, whose return value is a SpriteID. I wasn't seeing that. So... the Action02 tree is walked for *every* enabled callback, of which (potentially) only some are about finding images? A VarAction02 in the tree can switch on the current callback index, and this is where graphics and non-graphics are apparently mixed in the result ranges? Sorry if these are silly questions.

I guess I should build OTTD and see this in action...

User avatar
planetmaker
OpenTTD Developer
OpenTTD Developer
Posts: 9412
Joined: 07 Nov 2007 22:44
Location: Sol d

Re: Confused about callback results

Post by planetmaker »

UnicycleBloke wrote:
25 Nov 2019 12:03
Right, thanks. I got myself confused about how graphics and callbacks are integrated. If I've understood you, the process of obtaining graphics is really just another callback, whose return value is a SpriteID. I wasn't seeing that. So... the Action02 tree is walked for *every* enabled callback, of which (potentially) only some are about finding images? A VarAction02 in the tree can switch on the current callback index, and this is where graphics and non-graphics are apparently mixed in the result ranges? Sorry if these are silly questions.

I guess I should build OTTD and see this in action...
Yes, quite. The graphics callback is the default callback and has to provide a sprite ID in return. For other cases the callback result has to be some value (or also sprite) - what or which depends on the actual callback.

Thus in NML all callbacks are registered in the 'graphics' block of an item: https://newgrf-specs.tt-wiki.net/wiki/N ... hics_block - it can be argued that 'graphics' might be a bit mis-named and 'callbacks' would be the better name, when you also determine speed, weight etc in this block (if you wish to have it depend on situation).

User avatar
UnicycleBloke
Engineer
Engineer
Posts: 63
Joined: 30 Aug 2011 14:39
Location: Cambridge, England

Re: Confused about callback results

Post by UnicycleBloke »

OK. Thanks, both. It's much clearer now.


Eddi
Tycoon
Tycoon
Posts: 7456
Joined: 17 Jan 2007 00:14

Re: Confused about callback results

Post by Eddi »

UnicycleBloke wrote:
25 Nov 2019 10:14
The thing that has me puzzled is what callback results mean in this context. I was under the impression that they would invoke a function call at runtime, but they appear to be just numbers which are returned.
on the lowest level possible, a regular (spriteset) result is a value between 0x0000 and 0x7FFF, and a callback result is between 0x8000 and 0xFFFF (with the highest bit not being part of the result value, just treated as a flag indicating "callback result")

when the game expects a callback result, but gets a spriteset, it gets treated as a special "callback failed" result. the primary use of that is being backward compatible with GRFs that were written before a specific callback was introduced. (some callbacks do not have extra flags to enable them, those are only added for performance reasons)
You might not exactly be interested in Ferion, but if you are, have fun :)

Post Reply

Return to “NewGRF Technical Discussions”

Who is online

Users browsing this forum: No registered users and 3 guests