A plain number is assumed to be in hexadecimal. A number prefixed with a plus (+) or minus (-) sign is assumed to be in decimal. A number prefixed with 0x is in hexadecimal. (This is the convention used by the SoftICE debugger.)
The following rules hold for most of the custom labels (that is, those that do not have one of IDA's automatic prefixes like byte_):
| b | byte |
|---|---|
| w | word |
| d | doubleword |
| s | structure |
| x | untyped |
| v | variably accessed |
| p | pointer (the following letter(s), if any, indicate type of location pointed to) |
| f | far pointer |
| a | array (the preceding letter(s) indicate member type; if used alone, it's an ASCII string) |
I'm trying to stick to TT's original conventions when naming things (vehicle, vehicle type, station etc.), as long as it's not confusing. The only consistent difference is, where TT uses the term square, I use tile (it's more specific).
Note: Just because I say object and class don't assume it has something to do with object-oriented programming (OOP). The analogy is too weak to be useful.
Both TTO and TTD code is clearly divided into several abstraction classes. Each class is identified by an integer number (the class ID), or by a corresponding class offset (more on this later). An object such as a tile or a vehicle also contains the ID of the class it belongs to; this is referred to simply as the class of the object.
There are the following classes in the TTD simulation engine:
Classes 0 to A are used for landscape tiles (squares). The class of a tile is stored in the upper nibble of the respective byte in the _landscape4 array (accessed in DOS versions of TTD via the FS segment register, loaded with the value taken from the wLandscape4Selector variable).
More specifically:
Classes 10 to 15 are used for vehicles (and pseudo-vehicles). The class of a vehicle is stored in the first byte of the vehicle structure.
A class offset is the class ID multiplied by 8; for instance, if the class ID of an object is 5, its class offset is 28 (hex). Class offsets are useful because some arrays (including the main array of handler tables, see below) are indexed by a class offset. The procedure GetTileTypeHeightInfo returns the class offset of a tile in the BX register.
TTO classes are slightly different:
The main TT simulation engine communicates with subroutines belonging to various classes via handlers. A typical handler calling sequence looks like this:
ppOpClass0.CALL [EBP+XX]. The offset XX is called the operation offset in this document.The following table lists the operation offsets, and what I know or guess of their meaning and calling conventions. Note that entry 10 is not guaranteed to point to anything meaningful if there are no actions in a class. The table applies to TTD; TTO's handlers are similar, but so far I have not verified if their calling conventions are the same or not.
| Operation offset | Name (X = class ID) | Meaning |
|---|---|---|
| Common operations | ||
| 00 | ClassXInitHandler | Initialization routines. AX = 0 when resetting the class data, AX = 1 when starting a new game or scenario. |
| 04 | ClassXFunctionHandler | Various class-specific functions. EBX holds the number of the function to be called, other registers are function-specific. |
| 08 | TextTypeXXHandler |
Text handlers. EAX holds the text ID with bits +11..+15 (TTO: +10..+15) masked off, EDI points to the buffer the expanded text will be placed in. Usually, these handlers jump through TextHandler@@ProcessString to expand special codes in the string (which means they may be called recursively).
|
| 0C | ClassXTickProc |
A routine called once every simulation tick, enabled selectively for some classes (see the procedure DoAllTickProcs).
|
| 10 | ClassXActionHandler |
Action (e.g., construction or destruction) handlers, called within
AX and CX hold the precise X and Y coordinates, respectively, of the point on the landscape (typically the north corner of a tile) where the operation is to be performed. Registers EDX, EDI and the upper 24 bits of EBX are action-specific. Also, additional action-specific parameters may be passed through the text reference stack (
All these handlers return the cost of the operation in EBX. If the operation is not possible, EBX = 0x80000000 is returned and |
| Operations defined only for vehicle classes (10..15 for TTD, 20..26 for TTO) | ||
| 14 | ClassXVehTickProc |
This handler is invoked once every simulation tick for each vehicle (pointed to by EDI) by the procedure |
| 18 | ClassXMouseClickVeh | This handler is invoked when the player clicks on a vehicle on the landscape. EDI points to the vehicle. |
| 1C | VehicleClassDailyProc |
This is the daily vehicle processing routine (see |
| Operations defined only for landscape classes (0..A for TTD, 0..B for TTO) | ||
| 14 | ClassXGroundAltCorrection |
These handlers are invoked by the procedure Return: DL = corrected altitude, DH = 1 if the location is under a bridge, 0 otherwise. AX and CX must be kept untouched. |
| 18 | ClassXClearTile |
These handlers are invoked when an attempt to clear a tile is taken. AX, CX, BL are as for the operation 10 (action) handlers, DL, DH and DI are as returned by |
| 1C | ClassXDrawLand |
These handlers collect sprites to be displayed for a given tile. Registers as returned by |
| 20 | ClassXPeriodicProc |
Called by PeriodicProc256Tiles every +256 ticks for each tile, these handlers are for things like growing of grass and trees. EBX holds the XY index of the tile.
|
| 24 | ClassXRouteMapHandler | These handlers are called to determine in which directions a vehicle can travel on a tile. EDI holds the tile's XY index, AX = 0, 2 or 4 to get railway, road and water routes, respectively. Return a map of routes in EAX. |
| 28 | ClassXVehEnterLeave | These handlers are called when a vehicle tries to move on a tile (DL=0), or leaves a tile (DL=1). EDI points to the vehicle, EBX holds the XY index of the tile. Return updated (if necessary) XY index in BX, plus some flags in the upper word of EBX (bit 31 set = movement not possible). |
| 2C | ClassXMouseClick |
These handlers are called every time the player clicks on a tile with the normal (arrow) cursor. EDI holds the XY index of the tile, AL and CL hold the precise X and Y coordinates wihtin the tile, DL and DH are as returned by GetTileTypeHeightInfo for the tile. Return AL = 0 if nothing happened, 1 if something has been activated.
|
| 30 | ClassXAnimationHandler |
These handlers are called every tick for animated tiles (see AnimateTileObjects). EBX holds the XY index of the tile to be animated.
|
| 34 | ClassXQueryHandler | This operation is invoked to query a tile. EDI holds the XY index of the tile.
|
| 38 | ClassXSellHandler | This operation is invoked for all tiles when a company goes bankrupt or is taken over, to change the ownership of tiles owned by it. EBX holds the XY index of the tile being sold, DL = ID of the original company, DH = ID of the company that takes it over or FF if the original company is being just sold off. |