TD files

td files
each represents an area of 512 tiles by 512 tiles

-00026+00027.td
+00002+00021.td

67108864 = 8192 * 8192

512 tiles * 16 patches/tile = 8192 patches
each patch is 128m by 128m

depth 0 entire globe
divide in half by 6 times to get to depth 6
which is a 512 tiles square

-00022+00026.td
tdx tdz “.td”
x 11264 to 11775 from 512tdx to 512(tdx+1)-1
y 13312 to 13823 from 512 tdz to 512*(tdz+1)-1

world composed of 64 by 64 large TD tiles,
-32 to -1 and 0 to 31

depth tiles
0 32768
1 16384
2 8192
3 4096
4 2048
5 1024
6 512
7 256
8 128
9 64
10 32
11 16
12 8
13 4
14 2
15 1

td files start path in quad tree at depth 6 based on td_idx.dat

SIMISA@@@@@@@@@@JINX0D0t______

terrain_desc (
terrain_desc_size ( 67108864 )
Depth ( 6 )
terrain_desc_tiles (
TdFile ( -19 22 )
TdFile ( -1 21 )
TdFile ( 2 21 )
)
)

n number of decimal characters in tile name
if tile name starts with “-” then
depth = 2n-1 if tile name starts with “_” then depth = 2n

when converting tile name to tile numbers
if depth is odd then right shift two bits and discard

tile name to tile numbers
input: tile name
output: tile x, tile z, depth

tile numbers to tile name
input: tile x, tile z, depth
output: tile name

limit of tile numbers
minimum: -2^(depth-1)
maximum: 2^(depth-1)-1
example:
depth 5
minimum: -32
maximum: 31

TD file format

Hello,

here is the structure of the TD-file as far as it is known to me:

A TD-file (*.td,*.tdl) is connected with a tile-definition of 512×512 length. The position of this tile is shown within the filename.

The file starts with a header of 54 bytes, which contain:
– the file-id (+cr/lf)
– 3 length-values (datalength at pos 50, datalength+5 at pos. 45, datalength+14 at pos. 36)
– some (for me) unknown values

The next byte represents the 4 sub-tiles of this tile (length: 256×256). It shows, if the tile is ‘divided’ (first 4 bits) or populated (second 4 bits).
If none of the first 4 bits is set, the file ends here. Then it describes 4 tiles of length 256×256, which may be populated.

If one (or more) of the first 4 bits is set, this tile is divided and the next byte represents, the FIRST of these sub-tiles. It shows, if this tile is divided into subtiles of length 128×128 or if it is populated. The above scheme is used to signal this.

This procedure continues until sub-tiles of length 1×1 are reached, which cannot be further divided, or until a controlbyte is reached, where none of the first 4 bits is set.

Then, the second of the sub-tiles is processed in the same way. (one level higher)

This continues until all defined sub-tiles of various length are processed. Then, all bytes of the file should be processed, too.

I hope this will help you.

regards
CarlosHR

PS.
The 4 subtiles are processed (from-> to): upper/left, lower/left, lower/right, upper/right

Using the Simis Editor at http://jgrmsts.codeplex.com/ I was able to complete the format of TD files.

/* File format information */
FILE = :terrain_desc .
FILE_NAME = “Tile Definition” .
FILE_EXT = “td” .
FILE_TYPE = “d” .
FILE_TYPE_VER = “1” .

/* Base types */
terrain_desc_tiles ==> :uint {:byte} .

/* Format types */
terrain_desc ==> :terrain_desc_tiles .

EOF /* End of file */

The following are defined in coreids.tok:
SIDDEF(SID_TERRAIN_DESC, “terrain_desc”)
SIDDEF(SID_TERRAIN_DESC_FLAGS, “terrain_desc_flags”)
SIDDEF(SID_TERRAIN_DESC_SIZE, “terrain_desc_size”)
SIDDEF(SID_TERRAIN_DESC_TILES, “terrain_desc_tiles”)

SID_TERRAIN_DESC = 0x84
SID_TERRAIN_DESC_TILES = 0x87

Using the documentation for the binary format at http://twpol.dyndns.org/weblog/2010/05/10/01

32 byte header
4 byte identifier for SID_TERRAIN_DESC
4 byte length
1 byte length for null string
4 byte identifier for SID_TERRAIN_DESC_TILES
4 byte length
1 byte length for null string
4 byte :uint count of bytes
variable number of bytes describing division and population of tiles

Source: TD file – TrainSim.Com

Validate global tsection.dat

Errors

Track shapes that use an undefined track section

Track shape names must be unique.

Warnings

Track shapes that have two track sections start at the same location but missing MainRoute

Curved track sections are defined as a pair with negative angle followed by positive angle.

Junction track shapes were the two paths use the same track sections. One example is A1tYPnt10dMnl.s

TrackShape ( 217
FileName ( A1tYPnt10dMnl.s )
NumPaths ( 2 )
SectionIdx ( 2 0 0 0 0 183 175 )
SectionIdx ( 2 0 0 0 0 183 176 )
ManualJunctionShape ( )
)

Information

Track shapes that share the same definition of track sections.

Track shapes that do not have a shape file.

Functions

Validate a global tsection.dat file

Create a new trimmed file that only includes tracks that have a shape file.

Terrain files and elevations

Terrain files of type .t contain elevation and texture information. The structure and elevation data for normal size tiles:

terrain (
terrain_samples (
terrain_nsamples ( 256 )
terrain_sample_floor ( 934.403 )
terrain_sample_scale ( 0.00239484 )
terrain_sample_size ( 8 )
terrain_sample_ybuffer ( -01a186e8_y.raw )
terrain_sample_ebuffer ( -01a186e8_e.raw )
terrain_sample_nbuffer ( -01a186e8_n.raw )
)

And for lo tiles:

terrain (
terrain_samples (
terrain_nsamples ( 64 )
terrain_sample_floor ( 742.356 )
terrain_sample_scale ( 0.0241534 )
terrain_sample_size ( 256 )
terrain_sample_ybuffer ( _01a184_y.raw )
terrain_sample_ebuffer ( _01a184_e.raw )
terrain_sample_nbuffer ( _01a184_n.raw )
)

The tiles are a 2-dimensional grid of terrain_nsamples. The size of sample is terrain_sample_size in meters. The terrain_sample_ybuffer is an array of 2-byte unsigned integer in meters.

For normal tiles there are 256 by 256 samples each 8 meters, so the tile size is 2048 meters square. With each sample at 2 byte the file size is 131,072.

For lo tiles there are 64 by 64 samples each 256 meters, so the tile size is 16,384 meters square. With each sample at 2 bytes the file size is 8,192 bytes

When _y.raw has a value of 0 the elevation is terrain_sample_floor. To calculate the elevation at a sample multiply by terrain_sample_scale adding terrain_sample_floor. The maximum elevation is 65,536 times terrain_sample_scale plus terrain_sample_floor. The two bytes are in little endian order.

The name of the _y.raw file is in terrain_sample_ybuffer. Lo tiles have shorter names because they are earlier in the quad tree. Each quad tree division adds two bits to the file name of the tile as each division splits a tile into four parts.

Which tiles are split and selected is encoded in TD and TDL files in the TD directory.

The lo tiles will only be displayed in MSTS when mountains are active in the route definition file (.trk) with Mountains ( 00000001 ),

Converting between world and tile file names

World files have names with two numbers such as w-012489+014772.w and tile files have encoded names such as -01a4d768.t.

Code to convert world to tile file names

    function WorldNameToTileName(world)
      Dim x,z
      Dim tile
      if len(world) = 15 then
        x = mid(world,2,7)
        z = mid(world,9,7)
        If IsNumeric(x) And IsNumeric(z) then
          tile = WorldNamesToTileName(x,z)
        end if
      end if
      WorldNameToTileName = tile
    end function
    function WorldNamesToTileName (x,z)
      dim tile
      dim m
      dim wx,wz
      dim qx,qz,q
      dim i

      tile = 0
      m = 1
      wx = CInt(x) + 16384
      wz = CInt(z) + 16384
      for i = 0 to 14
        m = m * 4
        qx = wx and 1
        wx = CInt(wx \ 2)
        qz = wz and 1
        wz = CInt(wz \ 2)
        if qx = 1 then
          if qz = 1 then
            q = 1
          else
            q = 2
          end if
        else
          if qz = 1 then
            q = 0
          else
            q = 3
          end if
        end if
        tile = tile + (m * q)
      next
      WorldNamesToTileName = "-" & Right("0000000" & LCase(Hex(tile)),8)
    end Function

Code to convert tile to world file name

function TileNameToWorldName(sTileName)
    on error resume next
    dim x
    dim z
    dim m
    dim sTile
    dim tile
    dim q ' quandrant encoded in two bits NW=0, NE=1, SE=2, SW=3
    dim i
    dim sWorldName

    if left(sTileName,1) = "-" and len(sTileName) = 11 then
        sTile = mid(sTileName,2,8)
        tile = CLng("&h" & sTile) ' error occurs if file name includes non-hex characters
        if Err.Number = 0 then
            x = -16384
            z = -16384
            m = 1
            for i = 0 to 14
                tile = CLng(tile \ 2) ' shift 2 bits right
                tile = CLng(tile \ 2)
                q = tile and 3 ' extract right 2 bits
                if q = 1 or q = 2 then ' east quads NE and SE
                    x = x + m
                end if
                if q = 0 or q = 1 then ' north quads NW and NE
                    z = z + m
                end if
                m = m * 2
            next
            sWorldName = "w"
            if x < 0 then
                sWorldName = sWorldName & "-"
            else
                sWorldName = sWorldName & "+"
            end if
            sWorldName = sWorldName & right("00000" & Abs(x), 6)
            if z < 0 then
                sWorldName = sWorldName & "-"
            else
                sWorldName = sWorldName & "+"
            end if
            sWorldName = sWorldName & right("00000" & Abs(z), 6)
        else
            sWorldName = "ERROR: Invalid character in tile name."
            Err.Clear
        end if
    else
        sWorldName = "ERROR: Not a fully divided tile."
    end if
    TileNameToWorldName = sWorldName
end function