Page 1 of 1
Articulated vehicle nfo code problem
Posted: 19 Jun 2007 21:14
by FooBar
Hi all,
I'm trying to create my own articulated tram set and I figured I should start figuring out the nfo code bit.
For a start I decoded
hirotram.grf to see what's in there.
Using the GRF Specs (TTDP Wiki) I was able to figure out every bit and piece until I ran into this bunch:
Code: Select all
32 * 14 02 01 12 81 0C 00 FF 01 03 80 11 11 BB 00
33 * 20 02 01 11 81 40 80 FF 00 03 02 AA 00 00 00 12 00 01 01 CC 00
34 * 14 02 01 10 81 10 00 FF 01 50 80 01 02 FF 80
35 * 14 02 01 09 81 10 00 FF 01 49 80 01 01 11 00
36 * 18 02 01 08 81 0C 00 FF 02 09 00 33 33 10 00 16 16 11 00
Looks like a VarAction2 for RoadVehicles to me, but that's about it. Leaving it out of my grf didn't help, so I put it back in. Of course that didn't work either because I was replacing a different vehicle and also changed some cargoIDs. After reverting back those changes it worked. But copying stuff from other people doesn't work for me, so:
Could anyone explain to me (bit by bit) what those five lines of code do?
Any help is appreciated. If anyone needs more information, let me know.
Thanks in advance.
Posted: 19 Jun 2007 23:06
by OzTrans
All back to front ...
Code: Select all
36 * 18 02 01 08 81 0C 00 FF 02 09 00 33 33 10 00 16 16 11 00
processing call backs, 33-set sound effect goto sprite 35, 16-articulated vehicle build goto sprite 34, otherwise goto sprite 33.
Code: Select all
35 * 14 02 01 09 81 10 00 FF 01 49 80 01 01 11 00
determines the sound effect for 01-start vehicle = sound 0x49, for all other sounds terminate the callback by going to sprite 33, eventually ending up with a real sprite and thus terminating the callback.
Code: Select all
34 * 14 02 01 10 81 10 00 FF 01 50 80 01 02 FF 80
articulated vehicle build, add 2 more vehicles with ID 0x50 to the initial one, you have just bought. You now have a tram made up of 3 parts.
Code: Select all
33 * 20 02 01 11 81 40 80 FF 00 03 02 AA 00 00 00 12 00 01 01 CC 00
How the tram is to look, for every group of 3 tram parts, for the first one use sprite-ID AA, the second one goto sprite 32 (to set vehicle length first) and the 3rd one use sprite-ID CC.
Code: Select all
32 * 14 02 01 12 81 0C 00 FF 01 03 80 11 11 BB 00
while in callback mode set vehicle length for middle tram to 5/8th, to display use sprite-ID BB.
I hope this helps ...
Posted: 20 Jun 2007 09:02
by FooBar
It does help. Thanks for your trouble.
I should be able to use it in my own grf but still don't understand what every single byte does. NewGRF spec doesn't help much.
Could you (or someone else) please help me explaining every byte in those lines?
See setup below for things I do understand. Please add missing explanations or correct where I'm wrong. If I knew coding nfo was this hard, I probably wouldn't have started in the first place
Code: Select all
36 * 18 02 01 08 81 0C 00 FF 02 09 00 33 33 10 00 16 16 11 00
02 - Action2
01 - Road Vehicle
08 - Set ID
81 - Callback (?)
0C - Callback type 0C (?)
00 FF - Some Word value
02 - Number of properties to change
09 - Goto setID
00 -
33 - For sound (callback 33)
33 - Twice (?)
10 - Goto setID
00 -
16 - For articulated vehicles (callback 16)
16 - Twice (?)
11 - Goto setID in other cases
00 -
Code: Select all
35 * 14 02 01 09 81 10 00 FF 01 49 80 01 01 11 00
02 - Action2
01 - Road Vehicle
09 - Set ID
81 - Callback (?)
10 - Callback type 10 (?)
00 FF - Some Word value
01 - Number of properties to change
49 - Change sound
80 -
01 - For starting vehicles
01 -
11 - Goto set ID 11 in other cases
00 -
Code: Select all
34 * 14 02 01 10 81 10 00 FF 01 50 80 01 02 FF 80
02 - Action2
01 - Road Vehicle
10 - Set ID
81 - Callback (?)
10 - Callback type 10 (?)
00 FF - Some Word value
01 - Number of properties to change
50 - Vehicle ID
80 -
01 - Add one vehicle (?)
02 - Add another one (?)
FF - Stop adding vehicles
80 - Reverse vehicle (?)
Code: Select all
33 * 20 02 01 11 81 40 80 FF 00 03 02 AA 00 00 00 12 00 01 01 CC 00
02 - Action2
01 - Road Vehicle
11 - Set ID
81 - Callback (?)
40 - Callback type 40 (?)
80 FF - Some Word value
00 -
03 -
02 -
AA - Use setID AA
00 -
00 -
00 -
12 - Goto setID 12
00 -
01 -
01 -
CC - Use setID CC
00 - End callback
Code: Select all
32 * 14 02 01 12 81 0C 00 FF 01 03 80 11 11 BB 00
02 - Action2
01 - Road Vehicle
12 - Set ID
81 - Callback (?)
0C - Callback type 0C (?)
00 FF - Some Word value
01 - Number of properties to change
03 - 5/8th of length
80 -
11 -
11 -
BB - use setID BB
00 - End callback
I'd really appreciate if someone could fill in the gaps and/or correct any mistakes. Thank you!
Posted: 20 Jun 2007 09:26
by PikkaBird
FooBar wrote:NewGRF spec doesn't help much.
Of course it does.
I'll correct one of your translations of var action 2s for you, but it's nothing you couldn't have got from the wiki.
Code: Select all
35 * 14 02 01 09 81 10 00 FF 01 49 80 01 01 11 00
02 - Action2 (Correct)
01 - Road Vehicle (Correct)
09 - Set ID (Correct)
81 - Callback (Wrong. Variable action 2 type 81 (check one byte of a variable of this vehicle))
10 - Callback type 10 (Wrong. Check variable 10 (extra callback info))
00 FF - Some Word value (Wrong, two byte values. Shift the variable 0 bits, AND the variable with FF)
01 - Number of properties to change (Wrong. Number of ranges to check.)
49 - Change sound ("49 80" is a callback result. Var 2 results are word values)
80 -
01 - (for range 01 ...
01 - ... to 01) - which for this var in this callback means when starting vehicle, yes.
11 - Goto set ID 11 in other cases
00 - (correct, although this is a word value so the 00 is part of this too)
Posted: 20 Jun 2007 09:26
by XeryusTC
A callback sprite is defined by setting the variable to 0C, the 00 FF (the ones you call "some word value" are right-shift and and-mask, there is no need to shift on callbacks, and you want to keep all bytes. Callback 16 (as found in your first codeblock) is defined as the range of the var. action 2.
Note that everywhere where the variable isn't 0C that it isn't a callback sprite, you can find that in the
documentation of var. action 2.
Posted: 20 Jun 2007 10:16
by FooBar
Thanks for the help, guys! This really should get me going. I appreciate it.
PikkaBird wrote:Of course it does.
For me it didn't. Maybe I didn't know where to look. I guess I'm just too n00b-ish on this subject to get all the required information from there.

Posted: 20 Jun 2007 21:10
by FooBar
Well, me again
First of all: everything worked out great. I've added some more vehicles to my set (actually some grey boxes since I haven't drawn real sprites yet). I also managed to create a 5-piece tram, but that's where one (hopefully last) question arised.
(I'm using 'piece' here because I don't know the English word for one section of an articulated vehicle)
It's all about this line:
Code: Select all
118 * 20 02 01 11 81 40 80 FF 00 05 04 AA 00 00 00 BB 00 01 01 BB 00 02 02 BB 00 03 03 CC 00
118 * 20 02 01 11 81 40 80 FF 00 - First part is all clear now.
05 - I just added two because I wanted two extra pieces to my tram.
04 - Same here.
AA 00 - Use setID AA.
00 00 - For tram piece 1.
BB 00 - Use set ID BB.
01 01 - For tram piece 2.
BB 00 - Use set ID BB.
02 02 - For tram piece 3.
BB 00 - Use set ID BB.
03 03 - For tram piece 4.
CC 00 - Use set ID CC for the last piece.
Please (again) correct me where I'm wrong
What really bothers me are those two 05 04 bytes.
Thanks for your trouble.
Posted: 20 Jun 2007 21:44
by Lakie
Surely this does what you want?
Code: Select all
118 * 20 02 01 11 81 40 80 FF 00 05 02 AA 00 00 00 BB 00 01 03 CC 00
Rather than checking each value for if it is BB, it just makes anything between vehicle 2 and 4 use sprites from BB.
80 FF - No bitmask and modulus
00 05 - Modulus of 5 (ie, it will repeat the patten every 5 vehicles)
AA 00 00 00 - sprite to use if first vehicle, (ie. vehicle 1)
BB 00 01 04 - Sprites to use for any vehicle between 2 and 4, (ie. vehicles 2, 3, 4)
CC 00 - Fallback sprites, in this case the last vehicles sprites, (ie. vehicle 5).
[Edit] Also notice the number of bytes in that sprite is more than you specify, it should be 28.
Hope that helps,
~ Lakie
Posted: 21 Jun 2007 07:37
by FooBar
Thanks a lot! I'm learning every day.
And it did exactly what I wanted. At least at the graphical end of the game
But I see now why your approach is much better. I guess my approach is only good if I want five different sprites for my tram.
About those bytes in a pseudosprite... I'm really starting to wonder why you have to specify those. It could also be ottd being not so picky about that specification. It didn't complain about me setting the first sprite to zero either

(I use ottd for debugging my grf because it restarts quicker than ttdp; and I have to restart a lot). If patch needs the grf to be error free it's up to me to make sure it is. I don't want an ottd-only thingy. Everybody should be able to enjoy it (when it's finished, ofcourse

).
Thanks again for your great help.
Posted: 21 Jun 2007 15:22
by PikkaBird
FooBar wrote:About those bytes in a pseudosprite... I'm really starting to wonder why you have to specify those.
I believe the latest versions of GRFCodec can automatically correct the sprite numbers/lengths during encoding.
Posted: 21 Jun 2007 17:21
by FooBar
And so it does. Sprite numbers and sprite lengths get set to their correct value. Only sprite 0 (with the total number of sprites in the grf) remains unchanged. Either way, this saves a lot of time. In the future I'm gonna set all sprite numbers to 1, same with sprite lengths
I also noticed something strange.
When I set this action4:
Code: Select all
113 * 36 04 01 7F 01 3F "RET RegioCitadis (Series 2000)" 00
Encode the file, decode it again (using grfcodec 0.9.10), it ends up like this:
Code: Select all
113 * 36 04 01 7F 01 "?RET RegioCitadis (Series 2000)" 00
The reference to road vehicle 3F is lost and a question mark is added to the beginning of the text string. Is that normal behaviour or a bug in grfcodec?
Posted: 21 Jun 2007 17:41
by PikkaBird
It's both normal behaviour and a bug.

GRFCodec isn't perfect at working out what it should translate into a quoted string, and what it should leave as hex bytes.
Posted: 21 Jun 2007 17:52
by FooBar
I see. So 3F is just the hex code for a question mark.
Interesting 'feature'

Posted: 21 Jun 2007 18:59
by DaleStan
FooBar wrote:About those bytes in a pseudosprite... I'm really starting to wonder why you have to specify those.
Hysterical raisins. It used to be that grfcodec could not determine for itself the length of a pseudosprite, but grfcodec has gotten more intelligent. Just leave the sprite number as -1 and the size as 0, and grfcodec will be happy. GRFCodec will object to any other incorrect values.
FooBar wrote:It didn't complain about me setting the first sprite to zero either
grfcodec 0.9.9 and later will complain if the first sprite is not correct. Or you could just use NFORenum, which will silently make it right. (And the sprite numbers and sprite lengths too.)
If configured correctly (read the readmes) NFORenum is also capable of correctly quoting action 4s, so the 3F is put back in hex.
Posted: 21 Jun 2007 20:52
by FooBar
Thanks for your reply.
FooBar wrote:It didn't complain about me setting the first sprite to zero either
Here I was referring to OTTD. At the time of that post I didn't know GRFCodec corrected sprite numbers and lengths automatically and I figured it had something to do with the game, not the codec.
I'm gonna see what value NFORenum can prove.
I also noticed GRFCodec did complain about not setting sprite 0 indeed. It outputted something like "Found 116 more sprites than sprite 0".