Confused about callback results
Moderator: Graphics Moderators
- UnicycleBloke
- Engineer
- Posts: 72
- Joined: 30 Aug 2011 14:39
- Location: Cambridge, England
Confused about callback results
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
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
Re: Confused about callback results
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.UnicycleBloke wrote: ↑25 Nov 2019 10:14I was under the impression that they would invoke a function call at runtime
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.
- UnicycleBloke
- Engineer
- Posts: 72
- Joined: 30 Aug 2011 14:39
- Location: Cambridge, England
Re: Confused about callback results
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...
I guess I should build OTTD and see this in action...
- planetmaker
- OpenTTD Developer
- Posts: 9432
- Joined: 07 Nov 2007 22:44
- Location: Sol d
Re: Confused about callback results
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.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...
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).
OpenTTD: manual | online content | translations | Wanted contributions and patches
#openttdcoop: blog | wiki | public server | DevZone | NewGRF web translator
DevZone - home of the free NewGRFs: OpenSFX | OpenMSX | OpenGFX | Swedish Rails | OpenGFX+ Trains|RV|Industries|Airports|Landscape | NML
- UnicycleBloke
- Engineer
- Posts: 72
- Joined: 30 Aug 2011 14:39
- Location: Cambridge, England
Re: Confused about callback results
OK. Thanks, both. It's much clearer now.
- andythenorth
- Tycoon
- Posts: 5658
- Joined: 31 Mar 2007 14:23
- Location: Lost in Music
Re: Confused about callback results
If you have more questions there's always irc https://wiki.openttd.org/IRC_channel
Hit and miss whether you'll get useful answers but eh
Hit and miss whether you'll get useful answers but eh
FIRS Industry Replacement Set (released) | HEQS Heavy Equipment Set (trucks, industrial trams and more) (finished)
Unsinkable Sam (ships) (preview released) | CHIPS Has Improved Players' Stations (finished)
Iron Horse ((trains) (released) | Termite (tracks for Iron Horse) (released) | Busy Bee (game script) (released)
Road Hog (road vehicles and trams) (released)
Unsinkable Sam (ships) (preview released) | CHIPS Has Improved Players' Stations (finished)
Iron Horse ((trains) (released) | Termite (tracks for Iron Horse) (released) | Busy Bee (game script) (released)
Road Hog (road vehicles and trams) (released)
Re: Confused about callback results
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")UnicycleBloke wrote: ↑25 Nov 2019 10:14The 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.
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)
Who is online
Users browsing this forum: No registered users and 18 guests