The nfo/grf Technical Reference

GRF Resource Management

Preventing conflicts with limited resources



Introduction

Since 2.0.1 alpha 51, it has been possible to use action D to participate in cooperative resource management.

This feature is useful for avoiding resource conflicts between grf files. A file may query the available resources, check whether certain IDs are available, and/or mark them as reserved. Then, an action 6 will enter the actual values in the appropriate action entries, for example action 0 or 3 for vehicles, and action A for sprites. Alternatively, one can use another action D to set variable 99 and have it adjust the IDs of the relevant actions appropriately.

If the requested resources are not available, the grf file will be deactivated and be shown with an orange colour in the GRF Status Window, as well as a message indicating the type of resource that was not available. Note that previously allocated resources will not be freed if this happens, therefore you must first check that all of the resources are available before reserving any of them. This means if you have more than one type of resource that is required, you need two action D entries for each type, first one action D for each type using the "check" or "find" operation, after all of which follow the action D entries for each type using the "reserve" or "mark" operation.

This type of action D is ignored during initialisation (because the resources are not initialised yet either), and the target parameter will be set to 0 in that case.

Notes:

This resource management is cooperative. That means that grf files that do not use it can still access all IDs, and TTDPatch will never know about it. Only those grf files that use this resource management will "know" of each other and can be sure not to use conflicting resources. If another grf file then uses a "reserved" ID without telling TTDPatch via an action D, there is nothing that will prevent it from doing so.


Format

<sprite-number> * <length> 0D <target> 00 <GRM-op> FE FF <feature> <count>

ElementSizeDescription
0DBDefines action 0D
<target>BTarget parameter. See also below.
00BAssignment
<GRM-op>BResource operation to perform. See below.
FEBDefines a special variable access
FFBPrevent conflicts with ReadingOtherGRFParameters
<feature>BFeature to operate on. See below.
<count>WNumber of IDs to operate on.

For the check, mark, no-fail check, and get-owner operations, <target> must contain the first ID to be operated on.


Description

<GRM-op>


The following operations are available:

NumberEscapeOperationResultMeaning
00\DRReserveFirst found IDfind available resource ID and mark as in use
01\DFFindFirst found IDfind available resource ID but do not mark
02\DCCheck(none)check whether given resources (ID stored in the <target> variable) are available
03\DMMark(none)check that the given resources are available, and if so mark as in use
04\DnFNo-fail Find(see below)like "Find", but does not deactive the grf if no IDs found
05\DnCNo-fail Check(see below)like "Check", but does not deactive the grf if there is a conflict
06\DOGet OwnerGRF-ID of ownerRetrieve GRFID that has reserved the given ID (or 0 if not reserved)

Action D returns its result (if any) in the given <target> parameter. If the result is marked as "(none)" in the above table, the <target> parameter is not modified.

The "reserve" and "find" operations will try to find a contiguous block of <count> entries, and store the first number in the target parameter of the action D. If not enough entries can be found, the grf file is deactivated.

The "check" and "mark" operations use the value stored in the target parameter of the action D, and check/mark the block of <count> entries starting from that number. If not all entries are available, the grf file is deactivated.

The no-fail versions work exactly like their regular counterparts, but they set the <target> parameter to -1 (FFFFFFFF) if the resources are unavailable, which can be checked with action 7 afterwards. They do not deactivate the grf file. If successful, they do nothing. They are useful if the file wants to voluntarily skip certain modifications in case other files have changed them already.

Typically, the "reserve" or "find" operations will be used for files that modify only a few vehicles. For (mostly) complete sets, the "check" and "mark" operations are more useful, because it is often not feasible to remap the IDs of an entire set, so these operations will simply make sure that all needed IDs are available.

For each feature, multiple "find" operations will check for different size blocks, but will always return the same base entry number, so "find" should only be called once for each feature.

Note:

Each operation also has a corresponding escape sequence, as listed. See the discussion of escape sequences for further information on escape sequences in general.


<feature>


The following features and feature/GRM-op combinations are supported:

FeatureReserveFindCheckMarkGetNotes
00 (trains)
0
0
X
X
X
01 (road vehicles)
0
0
X
X
X
02 (ships)
0
0
X
X
X
03 (aircraft)
0
0
X
X
X
08 (general sprites)
X
X
*
*
-
0B (cargos)
-
-
X
X
X
see below

0 = unsafe, the IDs may change when loading game
X = safe to use
* = safe but useless
- = do not use

Note:

For newcargos, IDs 00..1F refer to the cargo IDs themselves (e.g. ID 0B is available in the temperate climate, and 0C..1F in all climates), whereas IDs 20..3F refer to the bit number from prop. 08 plus 20 (e.g. ID 2D, being bit number 0D=fruit, is available in all climates except tropical). You need to check and mark both ID types for correct operation.