Site Tools


documentation:file_formats:games:nfs

The unofficial 3DO Need for Speed files format specifications by Versus (vas.1987), 2021 (version 0.9). Based on

THE UNOFFICIAL NEED FOR SPEED FILE FORMAT SPECIFICATIONS - Version 0.2
Copyright © 1995-96, Denis AUROUX (MXK) - auroux@clipper.ens.fr

And OpenNFS1 project by Jeff Harris. https://github.com/jeff-1amstudios/OpenNFS1
_

Note that all data is BIG ENDIAN.

A) CAR FILES
Car files are located at: DriveData\CarData.

*.WrapFam – car’s exterior view: 3D model + textures
*.bigdashfam – car’s interior view
*.bigSpecsFam – car’s specs
*.digitalfam – speedometer digits
*.dashFam – not used?
*.dashConstants – not used?
*.TDDyn - not used?
*.TireR – not used?
*.TireF - not used?
*.spec - not used?
*.carSlideArt - not used?

All files with *.WrapFam extension are cars 3D exterior model with textures. Each file represents a single car.

These files are 'wwww' files containing four chunks.

The file structure is the following: first a 24-byte header, then four
chunks.

The header format is the following:

offsetlengthdata
004'wwww'
0x0444 (number of chunks)
0x0840x18 (offset of the first chunk)
0x0C4offset of the second chunk
0x104offset of the third chunk
0x144offset of the fourth chunk

The first, second and the third chunks correspond to different LODs of the car (from Lowres to Highres), each one consists of two subchunks. These subchunks are ORI3 (describe how the car is to be drawn (position and orientation of each car element) and SHPM (provide the bitmaps referenced by the ORI3 chunks). Note that the offsets specified in the bitmap directories are relative to the 'SHPM' header.


The fourth chunk has the size 0x1DC. It somehow affects car dynamics during crashes or some other situations. If all these chunk bytes are set to 0, car starts spinning with increased speed after the crash. I tested it also on a traffic car. Sometimes it moves to the opposite direction, sometimes just not moving. Charts below shows values representation within the most of the chunk data except chunk’s header.

Each chunk except 4th have ‘wwww’ header with 2 subchunks: ‘ORI3’ and ‘SHPM’. ’ORI3’ chunk is for 3D object geometry, ‘SHPM’ chunk is for object’s textures.

B)
A 3DO 'ORI3' chunk consists of a header followed by six blocks. Block numbering refers from PC-files version (see PC NFS file format specifications mentioned above). If block number is present in PC version, it has the same purpose is in 3DO version. Block numbers which doesn’t exists in PC version have unique 3DO format. Blocks numbering doesn’t matter anything.

\\  The header has length 120 (0x78) bytes and the following structure:
offsetlengthdata
004'ORI3'
0x044chunk length in bytes
0x0840x1F4
0x0C40
0x104size of block 8 in 12-byte records
0x144offset of block 8 = 0x78
0x1840
0x1C40x280 All player cars have 0x280 value, traffic cars may have different values or 0x280. Doesn’t affect any performance (?)
0x204size of block 10 in 24-byte records
0x244offset of block 10
0x288identifier string
0x304Equals value on 0x20 offset (block 10 size)
0x3440
0x3840
0x3C4offset to blank 8 bytes (0). Equals to offset 0x44 and 0x48
0x4040
0x444offset to blank 8 bytes (0). Equals to offset 0x3C and 0x48
0x484offset to blank 8 bytes (0). Equals to offset 0x3C and 0x44
0x4C40
0x5040x78
0x544size of block 5 in 28-byte records
0x584offset of block 5
0x5C4size of block 11 in 4-byte records. Equals block 10’s size * 2 (block 10 size is on 0x20 offset). Multiplying by 2 is for car files only. Common 3D objects in track files doesn’t multiply by 2 and doesn’t have a draw order section (block 11)
0x604offset of block 11
0x644Size of block 6 in 12-byte records (“smok”). Equals 0 or 1. 1 – player car. 0 – traffic car
0x684offset of block 6 (“smok”). Equals value on offset 0x70 minus 0xC. If “smok” is missing, value on offset 0x68 equals what is on 0x70 offset. Equals chunk length in bytes as on 0x04 offset for common 3D objects in track files. For traffic cars it points to ‘bott’ section, length = 0xC
0x6C4size of block 7 in 12-byte records. Equals 0 for common 3D objects in track files
0x704offset of block 7. Equals chunk length in bytes as on 0x04 offset for common 3D objects in track files
0x744??? 0x120, 0x128, 0x130, 0x118 (Wagon.WrapFam car and common 3D objects in *_PKT_000)

Fifth block (28-byte records):

offsetlengthdata
008identifier string ('NON-SORT', 'inside', 'surface', 'outside')
0x0840x8 for 'NON-SORT' or 0x1 for the others
0x0C4number of polygons
0x104polygon sum data (see description by individual ('NON-SORT', etc.) sections below)
0x1440
0x1840

And as for every type of entry:

'NON-SORT':

offsetlengthdata
008identifier string ('NON-SORT')
0x0840x08
0x0C4equals block’s 10 size (total number of polygons)
0x1040
0x1440
0x1840

'inside':

offsetlengthdata
008identifier string ('inside')
0x0841
0x0C4number of polygons for ???
0x104equals block’s 10 size
0x1440
0x1840

'surface':

offsetlengthdata
008identifier string ('surface')
0x0841
0x0C4number of polygons for ???
0x104equals block’s 10 size + number of polygons from ‘inside’ = XXX
0x1440
0x1840

'outside':

offsetlengthdata
008identifier string ('outside')
0x0841
0x0C4number of polygons for ???
0x104equals XXX + number of polygons from 'surface'
0x1440
0x1840

Total number of polygons in 'NON-SORT' equals sum in other sections:
'NON-SORT' = 'inside' + 'surface' + 'outside'.

Identifier string ‘outside’ and 0x0C offset affects rear tires draw order? 0x3 – rear right disappears, 0x2 – front right and rear right disappears, 0x1 two rear wheels and front right disappears, .
Changes in 0x10 offset changes polygons that doesn’t draw.

The sixth block:

offsetlengthdata
008identifier string (‘smok’)
0x084zero or 0x1F (Ferrari only). Doesn’t affect any performance

The seventh block consists of 12-byte records and describes tires, smoke and car lights:

offsetlengthdata
008identifier string (rt_rear, rt_frnt, bklr, lt_rear, lt_frnt, bkll)
0x084texture index

Texture indexes referenced from records in block 10 and block 11th. Texture index shows that wheel or back light will be displayed on the polygon number defined in block 10.

Smoke effect under the wheel will be displayed on drifting, accelerating and braking in the place where texture is shown.

rt_rear – right rear wheel

rt_frnt – right front wheel

bklr – back light right

lt_rear – left rear wheel

lt_frnt – left front wheel

bkll - back light left

Cop’s car only:

LOD 1:

lfc0 - ?????

lrc0 - ?????

LOD 2, 3:

lfr0 – ?????

lfl0 – ?????

hlr0 – ?????

hll0 – ?????

lrl0 – ?????

lrr0 - ?????

bkl0 – ?????

bkr0 - ?????

The eighth block consists of 12-byte records which describe the position in space of each vertex (using signed long integers, centered at (0,0,0)).

offsetlengthdata
004x coord. (x axis is lateral)
0x044z coord. (z axis is vertical, z increases when going up)
0x084y coord. (y axis is longitudinal, increases when going forward)

The tenth block consists of 24-byte records and describes the polygons that are used to draw the car:

offsetlengthdata
001polygon property. 0 - quadrangle, 1 - triangle, 4 – wheels (inside car textures)
0x011? 0xBF (Ferrari 512, Mazda RX7, Toyota Supra) or 0xDF (Lamborgini, Corvette ZR1, Dodge Viper) or 0xEF (Porsche 911, ANSX) or 0xCD (common 3D objects in scenery) or 0x1F (All ? traffic cars)
0x0210
0x031polygon flag (render order?)
0x044Index number. Max = block 10 size
0x084vertex 1 number
0x0C4vertex 2 number
0x104vertex 3 number
0x144vertex 4 number

Polygon flag may be equal:

0x10 – one sided render?,

0x12 – one-sided render, but flipped normals

0x13 - two-sided render,

0x50 – one-sided render,

0x52 – one-sided render, but flipped normals,

0x51 – two-sided render (outside in fifth block??),

0x53 – two-sided render.

Polygon flag may depend on fifth block? Two-sided renders over all polygons. You may edit only last number to test difference in game (0x*0, 0x*1, 0x*2, 0x*3)??. May be it’s a remainder check here when I try to divide it by 3.

The eleventh block

There are two parts in this block. First part is a sequence of 32-bit integers from 0 to block 10’s size (0, 0x1, 0x2, 0x3 …). Second part has the same size as a first one and also has a 32-bit ints, but their order is different. This order is a draw order for the polygons where the last int shows above all polygons in the game.

C)

SHPM chunk (textures for the car)

These store the different bitmaps.

The 16-byte header format is the following:

offsetlengthdata
004'SHPM'
0x044length of the file in bytes
0x084number of objects in the directory
0x0C4'SPoT'

This header is followed by the directory entries, each consisting of a 4-byte identifier string, and a 4-byte offset inside the file pointing to the beginning of the corresponding data.

offsetlengthdata
004identifier string (‘0004’, ‘whl0’, etc.)
0x044offset to texture data relative to SHPM

4-byte identifier string may have the following names.

'0000 ', ' 0001 ', ' 0002'… - car’s textures.

'bkl1' – car back lights texture,

‘whl0’ – non-rotating wheels,

‘whl1’ –rotating wheels (animation type 1),

‘whl2’ –rotating wheels (animation type 2),

'bitf' – Rear car view, moderate distance,

'bitr' – Rear car view, closest distance just before switching to 3D car model,

'bits' – Rear car view, smallest pic and most far,

'mapv' – Small car image for the map (while paused),

'!ori' – see section C.1.

Traffic cars only. There are different palettes for one car, selected randomly by the game engine during gameplay.

'plt0' – palette 1,

'plt1' – palette 2,

'plt2' – palette 3,

'plt3' – palette 4,

Cop’s car only:

LOD1: ‘ lfr1’, ‘lfl1’, ‘lfl1’, ‘lrl2’, ‘lrl1’, ‘lrr1’, ‘lrr2’ – flashing lights textures

LOD2: ‘ lfr1’, ‘lfl1’, ‘lrl1’, ‘lrl2’, ‘lrr1’, ‘lrr2’ – flashing lights textures

LOD3: ‘ lfr1’, ‘lfl1’, ‘lrl1’, ‘lrl2’, ‘lrr1’, ‘lrr2’ – flashing lights textures

Each directory entry in SHPM ('0000', '0001 ', '0002'…) points to a cel (CCB) block with the following structure. Note that there’s no CCB, PDAT, PLUT headers in the block.

16-byte header:

offsetlengthdata
0020x400 – (CCB and PLUT headers type 1) 0x840 – (CCB and PLUT headers type 2) ???, 0x5FF – (CCB and PLUT headers type 3, traffic) ???, 0x500 – (CCB and PLUT headers type 3, traffic SASCO) ???
0x022local offset to the 32-color palette
0x042width of the bitmap in pixels
0x062height of the bitmap in pixels
0x0840 PREAMBLE word? CCB FLAGS? for player cars, non-zero for traffic cars
0x0C20x32
0x0E20x32
0x10variousbitmap cel data

Palette has the following structure:

offsetlengthdata
001620 00 00 00 00 20 00 02 00 20 00 00 00 00 00 00
0x1064palette data. 2 bytes per color

In order to make a correct cel file we must to complete all the headers.

CCB headers (type 1)

43 43 42 20 00 00 00 50 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 34 D3 49 24 00 00 00 00 00 00 00 08 00 00 00 2050 44 41 54 00 00 01 08

… … Pixel data

50 4C 55 54 00 00 00 4C 00 00 00 20

… … Palette data

Bold numbers are width and height, underlined is the size of pixel data with PDAT header (+8 bytes!). For more information, see 3DO SDK (PLUT, PDAT, CCB headers).

CCB headers (type 2) ???

C.1)

'!ori' entry within the SHPM chunk is a texture selector for all polygons. N of entries = block 10th size.

This block has the header and entries.

Header size is 0x40:

offsetlengthdata
0040x60 00 00 00
0x0414
0x052Block 10 size (see ‘ORI3’ structure) multiplied by 2 plus 12
0x0750
0x0C40x32 00 32 00
0x1041
0x144Polygon quantity. Same as block’s 10 size (see ‘ORI3’ structure)
0x188‘DEFAULT.’ identifier string
0x204Polygon quantity. Same as block’s 10 size (see ‘ORI3’ structure)
0x2441
0x2840
0x2C40x00 00 00 B0
0x3040
0x3440x00 00 01 08
0x3840x00 00 01 08
0x3C40

This block describes the link between the texture numbers in block 10 and

the textures stored in the SHPI chunk.

Each of the entries after ‘!ori’ header consists of 8-byte records and describes the polygon’s texture selector from block 10:

offsetlengthdata
004Index number from block 10(see ‘ORI3’ structure)
0x044Texture index selector from SHPM header. Pointer to ‘0000’, ‘0001’, etc.

D)

TRACKS

TRACKs are consisting of two files located at:

\DriveData\DriveArt and at: \DriveData\tracks

D.1) DriveData\DriveArt\ files. These files contains scenery textures, horizon textures, object textures, 3D objects and textures.

The file structure is the following: first a 24-byte header, then chunks.

The header format is the following:

offsetlengthdata
0 4 'wwww'
0x04 4 Equals 5(number of chunks)
0x08 4 0x1C (offset of the first chunk)
0x0C 4 offset of the second chunk
0x10 4 offset of the third chunk
0x14 4 offset of the fourth chunk
0x18 4 offset of the fifth chunk

First 'wwww', then the number of chunks (as a long integer), then the offsets of each chunk header (long integers).

The *_PKT_000 file itself is a 'wwww' file containing five chunks. The first chunk corresponds to the background bitmaps, making up the terrain and the road, while the second chunk is devoted to foreground bitmaps (road signs, etc…). Each of these two chunks is itself in 'wwww' format, containing sub-chunks. Note that the offsets of the sub-chunks listed in the headers are relative to the beginning of the chunks.

This type of files consists of 5 chunks:

Scenery textures - 1st chunk

Object textures - 2nd chunk

3D objects - 3rd chunk

Horizon textures - 4th chunk (bottom)

Horizon textures - 5th chunk (top)

Al1_PKT_000 – Alpine, segment 1

Al2_PKT_000 – Alpine, segment 2

Al3_PKT_000 – Alpine, segment 3

Cl1_PKT_000 – Coastline, segment 1

Cl2_PKT_000 – Coastline, segment 2

Cl3_PKT_000 – Coastline, segment 3

Cy1_PKT_000 – City, segment 1

Cy2_PKT_000 – City, segment 2

Cy3_PKT_000 – City, segment 3

First chunk contain the bitmaps that are used for displaying the corresponding track segment. They make use of the 'wwww' file format, using the usual header. The first chunk starts with a ‘wwww’ header, which contains offsets to ‘wwww’ subchunks. All subchunks have 0x24 CCB entries. Texture numbers from ‘TRKD’ block refers to a corresponding entry number in the first ‘wwww’ header. Then it translates to the subchunk ‘wwww’ header. There are some texture LODs within subchunk, located at different offsets.

Second chunk (object textures) has a usual ‘wwww’headerpointingatCCBentries.

The third chunk describes the three-dimensional objects in the scenery.

It is a 'wwww' structure, containing a subchunks.

First ‘wwww’ header defines a number of 3D objects stored in the 3rd chunk.

Second ‘wwww’ header defines three LODs of the current object, defined in the first ‘wwww’ header. Usually ‘ORI3’ sections in all LODs are equal. Difference is only in texture resolution and texture size, of course.

Each LOD entry from the second chunk is a third ‘wwww’ header consist of the two subchunks (ORI3 and SHPM).

Each of these 3D objects is quite similar to a car file (For 3D objects format see car file format: section A) : it is itself a 'wwww' structure containing two subsubchunks! The first subsubchunk is an 'ORI3' structure describing the shape of the object, while the second is a 'SHPM' structure containing the bitmaps referenced by the 'ORI3' part.

‘ORI3’ header for common 3D objects see below.

offsetlengthdata
004'ORI3'
0x044chunk length in bytes
0x0840x1F4
0x0C40
0x104size of block 8 in 12-byte records
0x144offset of block 8 = 0x78
0x1840
0x1C40x280
0x204size of block 10 in 24-byte records
0x244offset of block 10
0x288identifier string
0x304equals 0x20 offset (block 10 size)
0x3440
0x3840
0x3C4offset to blank 8 bytes (0). Equals to offset 0x44 and 0x48
0x4040
0x444offset to blank 8 bytes (0). Equals to offset 0x3C and 0x48
0x484offset to blank 8 bytes (0). Equals to offset 0x3C and 0x44
0x4C40
0x5040x78
0x544size of block 5 in 28-byte records
0x584offset of block 5
0x5C4size of block 11 in 4-byte records. Equals block 10’s size (block 10 size is on 0x20 offset). Common 3D objects in track files doesn’t have a draw order section (as for cars in the second part of block 11)
0x604offset of block 11
0x644Size of block 6 in 12-byte records. Equals 0 for common 3D objects
0x684offset of block 6. Value on offset 0x68 equals what is on 0x70 offset. Equals chunk length in bytes as on 0x04 offset for common 3D objects in track files
0x6C4size of block 7 in 12-byte records. Equals 0 for common 3D objects in track files because block 7 doesn’t apply
0x704offset of block 7. Equals chunk length in bytes as on 0x04 offset for common 3D objects in track files because block 7 doesn’t apply
0x744??? 0x120 or 0x118

Identifier string on 0x28 offset tells us which LOD is it. For example,

*T2000 – less-detailed model, fair textures

*T1000 – medium detailed model, better textures

*T0000 – full-detailed model, full-sized textures.

‘SHPM’ is reduced in comparsion with car files.

SHPM chunk (textures for the 3D object)

These store the different bitmaps.

The 16-byte header format is the following:

offsetlengthdata
004'SHPM'
0x044length of the file in bytes
0x084number of objects in the directory
0x0C4'SPoT'

This header is followed by the directory entries, each consisting of a 4-byte identifier string, and a 4-byte offset inside the file pointing to the beginning of the corresponding data.

offsetlengthdata
004identifier string (‘0001’, ‘0002’, etc.)
0x044offset to texture data relative to SHPM

4-byte identifier string may have the following names.

'0000 ', ' 0001 ', ' 0002'… - object’s textures.

'!ori' – see section C.1).

To make a correct cel file from SHPM entry you must complete all the CCB headers (type 1), see C).

The fourth and fifth chunk of the *_PKT_000 file is a SHPM file describing the horizon.

Fourth chunk is for the horizon’s bottom, fifth chunk is for the horizon’s top.

Each chunk contains six CCB entries with ‘wwww’ header.

D.2)</font> <font inherit/inherit;;inherit;;inherit>\DriveData\tracks. These files contains track’s geometry, objects size and location and virtual road for the game engine.

al1.trk – Alpine, segment 1

al2.trk – Alpine, segment 2

al3.trk – Alpine, segment 3

cl1.trk – Coastline, segment 1

cl2.trk – Coastline, segment 2

cl3.trk – Coastline, segment 3

cy1.trk – City, segment 1

cy2.trk – City, segment 2

cy3.trk – City, segment 3

In order to understand the structure of TRK files you have to know that a

track is the superposition of three structures:

- first, a 'virtual road' : this is a sequence of points in space,

which will be called 'nodes'. These points correspond to successive

positions along the track, and all the cars have to pass near each of

these positions. During the game, the virtual road is invisible, but

you have to stay close to it.

- second, the scenery : this is a collection of points in space, which

will be called 'vertices', together with textures which are mapped onto

the polygons defined by consecutive vertices. These textures are used

to draw the road, the roadside and part of the landscape. Thus it is

of course preferable that the scenery remain close to the virtual road !

- and last, the objects : points in space together with bitmaps, which

are used for road signs, buildings, trees, etc… Some of them are

plain 2D bitmaps, but others have a more sophisticated polygonal 3D

structure.

The 3D coordinates x,y,z will always be used with the following meaning :

- x is an axis which is transversal to the starting line. Positive x values

correspond to points which are on the right of the starting position.

(i.e. if you start looking to the north, x points to the east)

- y is an axis which is parallel to the starting line. Positive y values

correspond to points which are ahead of the starting position.

(i.e. y points to the north)

- z is a vertical axis. Positive z values correspond to points higher than

the starting position.

These type of files consists of three chunks: Virtual road, Plain objects, Scenery and fences.

They describe the track itself, including the shape of the road and the position of the scenery items. The objects are referenced by numbers which correspond to entries in the corresponding file in DriveData\DriveArt\.

a) TRK files begin with 0x13B4 bytes of headers and index tables. These are as follows:

offsetlengthdata
0040xE
0x044scenery block number (see D.2.3) of the ending (checkpoint, finish) line + 45. If you want to see what is happening behind the checkpoint line after finish, set:
Alpine, segment 1 – 0x231
Alpine, segment 2 – 0x26B
Alpine, segment 3 – 0x247
Coastline, segment 1 – 0x208
Coastline, segment 2 – 0x1F5
Coastline, segment 3 – 0x1F5
City, segment 1 – 0x208
City, segment 2 – 0x1E1
City, segment 3 – 0x24F
0x0840x60000
0x0C4x coordinate of the first node
0x104z coordinate of the first node
0x144y coordinate of the first node
0x1840
0x1C40
0x2040
0x244length of the scenery data in bytes (All TRKD sections, from first TRKD till the end of file)
0x2841
0x2C0x960first index table
0x98C0x960second index table
0x12EC4??????
0x12F00x80????? third index table. All tracks except Coastline segment 1 have this table filled with 0xFF
0x13700x40????? Filled with zeroes except Coastline segment 1 track
0x13B040x3F

The first index table is a succession of 32-bit offsets. It follows a progression by size of each scenery TRKD entry. This means the first value is 0, followed by block 1 TRKD size, block 2 TRKD size + block 1 TRKD size, etc…

Sometimes this progression interrupts with zero entry when value is greater than 0x1C000???
The table is filled to 960h bytes (600 entries) with zero values. This table is probably only used as a lookup table in memory during the game.

The second index table is also a succession of 32-bit offsets, but these offsets are inside the TRK file. Each offset points to TRKD block (see section D.2.3). It corresponds to the offsets of the successive records for scenery data, which starts at offset 1B000h in the scenery file. It is filled to 600 entries with zero values.


D.2.1) Virtual road section for the 3DO version starts at 0x13B4 finish at 0x16534
b) The virtual road data follows, and is constituted of 36-byte records
(one for each node). The first record is at offset 13B4h, and records ends at offset 16534h (this leaves room for 2400 records, and since a scenery block corresponds to four nodes, both capacities are equal).
The unused records (after the last node) are filled with zero values.
The structure of each record is the following:

offsetlengthdata
001a0
0x011a1
0x021a2
0x031a3
0x041b0
0x051b1
0x061b2
0x071b3
0x084x coordinate
0x0C4z coordinate
0x104y coordinate
0x142slope
0x162slant-A
0x182orientation
0x1A20
0x1C2y-orientation
0x1E2slant-B
0x202x-orientation
0x2220

- a0,a1 are 8-bit values. Those shows width of the road to the left and right verges.
- a2, a3 are 8-bit values. Those are for left and right invisible barriers of the road.

- b0,b1,b2 are 8-bit flags.
b0 – Traffic direction and distance between lanes?
0-forward only, two lanes.
1-forward only, right lane/lanes.
2-forward only, right lane/lanes (may occupy right verge).

b1 – barrier type and sound? Fence distance?
b2 – barrier type and sound? Verge type and sound?
- b3 is 8-bit flag for future use with ParseScenery (Tracknode property). It defines tunnels on the left or on the right, lanes split and rejoin.
b3 = LANE_SPLIT = 0. Used in Alpine, Coastal tracks when the road widens. Vertices should be moved to the right (see scenery block D.2.3).
b3 = LANES_3 = 1(?). Road lanes = 3.
b3 = LANES_2 = 3 (?). Road lanes = 2.
b3 = LANE_REJOIN = 2. Used in Alpine, Coastal tracks when the road narrows. vertices should be moved to the right (see scenery block D.2.3).
b3 = TUNNEL_1 = 4. plays tunnel sound and car textures are faded a bit.
b3 = BRIDGE = 5. plays bridge sound at Alpine 2 track and car textures are not faded. Check flag on other track.
b3 = TUNNEL_2 = 7. plays tunnel sound at Coastal 2 track and car textures are faded a bit (?).
b3 = TUNNEL_3 = 8. Forest at Coastal 3 track and car textures are faded a bit (?).
b3 = TUNNEL_4 = 9. plays bridge sound at Alpine 3 track in tunnels with windows. No car textures fading occurs.


The next properties are interesting! If set, either the last terrain strips on the right or left is detached and placed between the specified points. This is how the tunnels in Coastal and Alpine 3 are constructed.
b3 = RIGHT_TUNNEL_A2_A9 = 7.
b3 = LEFT_TUNNEL_A4_A9 = 9.
b3 = LEFT_TUNNEL_A9_A5 = 13.??


- x, z and y coordinates are signed long values.

- slope is a value indicating the slope at the current node, i.e. the difference between the z coordinates of two consecutive nodes.
A good approximation is : slope(i) = (z(i+1) - z(i))/152. However, to complicate things, it is stored as a signed 14-bit value, complemented to 4000h. This means -1 is stored as 3FFFh, -2 as 3FFEh, … So in fact you must perform a logical and with 3FFFh before storing !

- slant-A is a value indicating how the road is slanted to the left or to the right (as in the turns in Autumn Valley or Lost Vegas). It is a signed 14-bit value, like slope. The value is positive if the road is slanted to the right, negative if it is slanted to the left.

- slant-B has the same purpose, but is a standard signed 16-bit value. Its value is positive for the left, negative for the right. The approximative relation between slant-A and slant-B is slant-B = -12.3 slant-A (remember that slant-A is 14-bit, though)

- orientation is a 14-bit value, and is equal to 0 for north (increasing y), 1000h for east (increasing x), 2000h for south (decreasing y), 3000h for west (decreasing x), and back to 3FFFh for north.

- y-orientation is a signed 16-bit value, which is proportional to the y coordinate variation. Meanwhile, x-orientation is proportional to the
*opposite* of the x coordinate variation. This means that the couple (-xorientation,yorientation) gives the orientation of the track.
The norm (square root of xorient^2+yorient^2) is usually around 32000 (a little less than 8000h, to avoid numeric overflows), but can fluctuate
with the only condition that (-xor,yor) gives the correct orientation.


D.2.2) Objects startOffset = 0x17050; paramsStart = 0x16C3C;
c) The objects data comes next:

offsetlengthdata
0x165340x7083-byte records for the traffic (there are 600… as many as scenery blocks)
0x16C3C40x40 = Number of 16-bytes entries (object parameters data)
0x16C4040x3E8 = 1000 (size of the main block in records)
0x16C444'OBJS'
0x16C4840x428C (total length of the remaining blocks)
0x16C4C40 ??
0x16C500x40016-byte records (Object parameters data)
0x170500x3E80object data: 1000 records of 16 bytes (one per object)
0x1AED00x1300

0x708 - are a 3-byte records affects traffic cars speed and trigger speed for the cops. If set to zero, forward-moving traffic cars will generate at the distance and will be just standing on the road. If set to 0xFF, forward-moving traffic cars will speed up to approx. 100 mph. These 3-byte records have the following structure:

May be if I’ll set another value on 0x16C3C offset and recalculate others I can extend all object parameters entries?

offsetlengthdata
001Traffic car speed
0x011Cops trigger speed
0x021Traffic car speed

Object parameters data (0x400, 16-byte records) describes width, height of the object, it’s type and a flags. Each record is 16-byte long.

offsetlengthdata
001SceneryFlags (none = 0, animated = 4 (only for PC version)
0x011SceneryType model = 1, bitmap = 4, twosidedbitmap = 6 (two bitmaps, one is turned by 90 degrees)
0x021Resourse ID
0x031Resourse ID2 for 2-sided bitmap object
0x0410
0x051width
0x067?????
0x0D1height
0x0E1?????
0x0F10

These parameters are linked with object data (see below) started from 17050 offset.

The object data itself consists of a 16-byte record per object. The record structure is the following:

offsetlengthdata
004reference node
0x041bitmap number
0x051flip
0x064flags (unknown purpose) ??????
0x0A2relative x coordinate
0x0C2relative z coordinate
0x0E2relative y coordinate

Object data entry for each object must be considered with object’s parameters entry. Object’s bitmap number equals entry number in object’s parameters block. ResourseID, resourseID2 from object’s parameters sections refers to object texture in 2nd chunk *_PKT_000 file using ‘wwww’ header. Number of entry = resourseID (resourseID2) number.

Each object is related to a reference node in the virtual road. The x,z,y
coordinates are then expressed as signed 16-bit values relative to the
coordinates of the reference node. Beware that the axes are simply translated
but not rotated! (i.e. the x and y axes are still pointing east and north)
The objects are sorted in the order of increasing reference nodes.
A reference node value of -1 indicates that the record is unused (i.e. after
the end of the used records). Also note that the coordinates are not
expressed in the same unit as the 32-bit absolute coordinates seen above
(the units are much larger, so that the value fits in 16 bits).

The 8-bit flip value is equal to 0 for an object that is perfectly perpendicular to the track (e.g. a road sign), larger values for objects that are slightly turned, until 64 for an object that is mapped along the track (e.g. an ad on the side of the road), then up to 128 which is the perfectly reversed position (since the objects have no “back”, this is the common way of reversing a road sign for a turn in the other direction), then
up to 192 which is again longitudinal mapping (the other way) and until 255 which is back to the normal position.

D.2.3) Scenery and Fences startOffset = 0x1B000;
d) The scenery data starts at offset 1B000h. It is made up of different sized records, each corresponding to four nodes in the virtual road. The records are consecutive and the last record ends the .TRK file.
Each record has the following structure:

offsetlengthdata
004'TRKD'
0x044length of the record contents (with CCB section)
0x084number of this record (0 for the first, then 1, etc…)
0x0C1????? May be non-zero once on the track and at the last ‘TRKD’ block. Block #1 within TRKD started here. Size = 0x258
0x0D1Fence present. Stores the sides of the road the fence lives, and the textureId to use for it. If the top bit is set, fence on the left exists, if next bit is set, fence is on the right. Both can also be set. The other 6 bits seem to the texture number.
0x0E1010 textures (one byte per texture)
0x1812reference point (A0 point)
0x2412Coordinates? Marker where ends current block sized 0x2DC? End 0x84 sized overlapping. Appears at 0x24 offset, second and the last position – before CCB minus 0x50. It means: CCB – 0x50 – 0x2DC + 0x84 = second these bytes position end.
0x3012point A0
0x3C12point A1
0x9C12point A9
0xA812point A10
0xB412not used?
0xC012point B0
0xCC12point B1
0x12C12point B9
0x13812point B10
0x14412not used?
0x15012point C0
0x15C12point C1
0x1BC12point C9
0x1C812point C10
0x1D412not used?
0x1E012point D0
0x1EC12point D1
0x24C12point D9
0x25812point D10
0x2641? Block #2 within TRKD started here. Block #2 size is 0x258
0x2651fences again
0x26610Textures again
0x27012point E0
0x27C12? Purpose is the same as on 0x24 offset, but values are from????
0x28812point A0 (next TRKD subblock) = E0 point. This offset is a A0 point for the next scenery block. It means, that points data for the current and next block is overlapped. E10 point for the current block (n) ends at 0x30C since A0 point for the next block (n+1) starts at 0x288. Data for the (n+1) block is located between 0x288 and 0x564 offsets. As mentioned before 0x84 bytes for the connected blocks are overlapped. For the (n+1) and (n+2) blocks overlapped by the same way. In other words, points E10-E0, E1-E5 from n block equals A10-A0, A1-A5 points from n+1 block.
Size 0x84 explanation: 11 points total overlapping. X,Y,Z coordinates (4 bytes each) = 12 bytes 1 point. 12*11=132=0x84.
If any of the X or Y or Z values and doesn’t differs a lot with D0 X or Y or Z point and number of this record is more than 100, E0 point is on 27C offset??? And reference point on 0x18 offset is E0 point from (n-1) offset????
0x29412point E1=A1 (n+1)
0x2F412point E9=A9 (n+1)
0x30012point E10=A10 (n+1)
0x30C7032Points for 12 forward-located blocks. See 0x288 offset for more information
0x1E84780Five blocks sized 0x9C (see small blocks structure below).
Rest of the space is filled with zeros
0x219080Block 80. See below for structure. In some cases, there are additional bytes after Block 80:
4F 46 53 54 00 00 00 18 00 00 00 68 00 00 00 B4 00 00 00 D4 00 00 00 EC
(‘OFST’ identifier string, 0x18, 0x68, 0xB4, 0xD4, 0xEC).
0x21E0various sizeCCB texture. Unused space after CCB texture is filled with 0 to fill the modulus (see below).
Size of ‘TRKD’ block must be aligned to 0x1000 or 0x800 offset as the follows. Possible sizes of ‘TRKD’ blocks are: 0x2000, 0x2800, 0x3000, 0x3800, 0x4000, 0x5000, 0x6000, 0xC000, 0x8800, 0xA000 and so on.

Small blocks structure:
There are 5 blocks:
Block 1:

offsetlengthdata
002Equals zero. (Not used)
0x021010 textures (one byte per texture) for the n+1 block
0x0C12Point coords. Purpose is the same as on 0x27C offset, but values are from????
0x1812A0 point for the n+1 block
0x2412A1 point for the n+1 block
0x3012A2 point for the n+1 block
0x3C12A3 point for the n+1 block
0x4812A4 point for the n+1 block
0x5412A5 point for the n+1 block
0x6012A6 point for the n+1 block
0x6C12A7 point for the n+1 block
0x7812A8 point for the n+1 block
0x8412A9 point for the n+1 block
0x9012A10 point for the n+1 block

Block 2:

offsetlengthdata
002Equals zero. (Not used)
0x021010 textures (one byte per texture) for the current block
0x0C12Point coords. Purpose is the same as on 0x27C offset, but values are from????
0x1812A0 point for the current block
0x2412A1 point for the current block
0x3012A2 point for the current block
0x3C12A3 point for the current block
0x4812A4 point for the current block
0x5412A5 point for the current block
0x6012A6 point for the current block
0x6C12A7 point for the current block
0x7812A8 point for the current block
0x8412A9 point for the current block
0x9012A10 point for the current block

Block 3:

offsetlengthdata
002Equals zero. (Not used)
0x021010 textures (one byte per texture) for the n-1 block
0x0C12Point coords. Purpose is the same as on 0x27C offset, but values are from????
0x1812A0 point for the n-1 block
0x2412A1 point for the n-1 block
0x3012A2 point for the n-1 block
0x3C12A3 point for the n-1 block
0x4812A4 point for the n-1 block
0x5412A5 point for the n-1 block
0x6012A6 point for the n-1 block
0x6C12A7 point for the n-1 block
0x7812A8 point for the n-1 block
0x8412A9 point for the n-1 block
0x9012A10 point for the n-1 block

Block 4:

offsetlengthdata
002Equals zero. (Not used)
0x021010 textures (one byte per texture) for the n-2 block
0x0C12Point coords. Purpose is the same as on 0x27C offset, but values are from????
0x1812A0 point for the n-2 block
0x2412A1 point for the n-2 block
0x3012A2 point for the n-2 block
0x3C12A3 point for the n-2 block
0x4812A4 point for the n-2 block
0x5412A5 point for the n-2 block
0x6012A6 point for the n-2 block
0x6C12A7 point for the n-2 block
0x7812A8 point for the n-2 block
0x8412A9 point for the n-2 block
0x9012A10 point for the n-2 block

Block 5:

offsetlengthdata
02Equals zero. (Not used)
0x021010 textures (one byte per texture) for the n-3 block
0x0C12Point coords. Purpose is the same as on 0x27C offset, but values are from????
0x1812A0 point for the n-3 block
0x2412A1 point for the n-3 block
0x3012A2 point for the n-3 block
0x3C12A3 point for the n-3 block
0x4812A4 point for the n-3 block
0x5412A5 point for the n-3 block
0x6012A6 point for the n-3 block
0x6C12A7 point for the n-3 block
0x7812A8 point for the n-3 block
0x8412A9 point for the n-3 block
0x9012A10 point for the n-3 block

Block 80. This block is for CCB reference point, CCB size, CCB position on the screen when car is on the n block.

offsetlengthdata
004Point A0X (block n+12)
0x044Point A0Z (block n+12)
0x084Point A0Y (block n+12)
0x0C4Point A6X (block n+20)
0x104Point A6Z (block n+20)
0x144Point A6Y (block n+20)
0x184Point A0X (block n+22)
0x1C4Point A0Z (block n+22)
0x204Point A0Y (block n+22)
0x2440
0x2840
0x2C40
0x304Cel background position X?
0x344Cel background position Y?
0x384not used ?
0x3C4not used ?
0x404not used ?
0x444not used ?
0x4840x10001
0x4C4CCB size in bytes

Each point is given by three signed 32-bit absolute coordinates (x,z,y as usual). The coordinates are the same as in the virtual road data. The reference point is unused in the game and usually equal to point A0.

The points A0,…,A10 in record #n (starting with 0) correspond to the node #4n (starting with 0) in the virtual road data. B0,…,B10 correspond to node #4n+1, C0…C10 to node #4n+2, D0…D10 to node #4n+3 and E0…E10 to node #4n+4. Thus the points E0…E10 are identical to the points A0…A10 of the following record.

The eleven point series (0 to 10) are arranged as follows: A0-E0 are near the middle of the road, and thus close to the corresponding nodes. A1-E1 are a little to the right, A2-E2 further right, … until A5-E5. A6-E6 are a little to the left, A7-E7 further left, … until A10-E10.(In tunnels, the points A5-E5 and A10-E10 get back to the center, constituting the ceiling).
To each record correspond ten textures (coded at the beginning), each given by a 8-bit value, T1,T2,…,T10. T1 is used between A0-E0 and A1-E1, T2 between A1-E1 and A2-E2, …, T5 between A4-E4 and A5-E5 ; meanwhile, T6 is used between A0-E0 and A6-E6, T7 between A6-E6 and A7-E7, …, T10 between A9-E9 and A10-E10. This is summarized on the following diagram:

точкиscenery-model.jpg

The texture numbers are converted to bitmaps in the first chunk of the *_PKT_000 file (see D.1).

E) Other image files.
There are also many other image files located at: \FrontEnd\Display. These are *.3sh files each containing one or some SHPM chunks (bitmaps).

The 16-byte header format is the following:

offsetlengthdata
004'SHPM'
0x044length of the file in bytes
0x084number of objects in the directory
0x0C4'SPoT'

This header is followed by the directory entries, each consisting of a 4-byte identifier string, and a 4-byte offset inside the file pointing to the beginning of the corresponding data.

offsetlengthdata
004identifier string (‘eal2’, ‘512b’, etc.)
0x044offset to texture data relative to SHPM

4-byte identifier string may have different names.

Each directory entry in SHPM (‘eal2’, '512b’, …) points to a cel (CCB) block with the following structure. Note that there’s no CCB or PDAT headers in the block.

16-byte header:

offsetlengthdata
0020x9600 for CCB headers type 3, or 0x1600 for CCB headers type 3a. Other values possible?
0x0220
0x042width of the bitmap in pixels
0x062height of the bitmap in pixels
0x0840 (?)
0x0C2???
0x0E2???
0x10various sizebitmap cel data

In order to make a correct cel file we must to complete all the headers.
CCB headers (type 3)
43 43 42 20 00 00 00 50 00 00 00 00 7F 6F 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 1F 00 1F 00 80 00 3B D6 00 9E 01 3F 00 00 00 70 00 00 00 31 58 54 52 41 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 50 44 41 54 00 00 18 C8
… … Pixel data

CCB headers (type 3a)
43 43 42 20 00 00 00 50 00 00 00 00 7F 6F 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 1F 00 1F 00 80 00 3B D6 00 9E 01 3F 00 00 01 40 00 00 00 F0 58 54 52 41 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 50 44 41 54 00 02 58 08
… … Pixel data

Bold numbers are width and height, underlined is the size of pixel data with PDAT header (+8 bytes!). For more information, see 3DO SDK (PDAT, CCB headers).

documentation/file_formats/games/nfs.txt · Last modified: 2022/02/15 17:52 by trapexit