Need for Speed чит-файл №2

======================================================================
THE UNOFFICIAL NEED FOR SPEED FILE FORMAT SPECIFICATIONS - Version 0.2
======================================================================

A - GAMEDATA directory
==================

A.1 GAMEDATA\CONFIG\PATHS.DAT
-------------------------

This file contains 18 null-terminated strings of 80 characters each
(total 1440 bytes), describing the paths where NFS looks for its files.
For minimum install, here are the contents (with hex offset):

000 gamedata/config/ 2D0 F:\simdata\misc\
050 gamedata/savegame/ 320 F:\simdata\trackfam\
0A0 F:\frontend\speech\ 370 F:\simdata\slides\
0F0 F:\simdata\soundbnk\ 3C0 F:\simdata\carFams\
140 F:\frontend\music\ 410 F:\simdata\soundbnk\
190 F:\frontend\art\ 460 F:\simdata\carspecs\
1E0 gamedata/modem/ 4B0 F:\simdata\dash\
230 F:\frontend\movielow\ 500 F:\simdata\misc\
280 gamedata/replay/ 550 F:\frontend\show\

Note that simdata\soundbnk and simdata\misc are present twice.
Also note that in the CD-ROM, directories whose name starts with a 'G'
correspond to the German version of the game. Don't know why the car
dashboards had to be translated, though :)

Modify these entries if you want to copy some of the CD files to your hard
disk, for example if you want to modify them. Remember that modifying the
files can be hazardous, and that because the file formats are not fully
known it is better to modify an existing file than to create one from scratch.

A.2 GAMEDATA\SAVEGAME\*.SAV
-----------------------

These are the tournament save files (840 bytes each).

- Offset 0 : your name (null-terminated string followed by zeros)
- Offset 28 : 'Opponent' (")
- Offset EC : 'Player 2' (")
- Offset 114 : 'Opponent 2' (")
- Offset 1D8 : name of the tournament (")
- Offset 20A : 'REPLAY.RPL' (")
- Offsets 23C-26F : ???
- Offset 270 : name of the tournament (")
- Offsets 30E-337 : ???
- Offsets 338, 33A, 33C, 33E, 340, 342, 344 : these contain 01 if the
corresponding race has been won, otherwise 00. The first three bytes
are for open-road races, while the other correspond to closed tracks.
For instance, in order to access the bonus track, save a tournament,
then set all these bytes to 01 except 33E to 00 (Rusty Springs), then
reload the tournament and win Rusty Springs. The odd offsets 339 to 345
are zeros.
- Offsets 346-347 : ???

The other offsets contains zeros.

A.3 GAMEDATA\CONFIG\CONFIG.DAT
--------------------------

This file (25552 bytes) contains all the relevant configuration data
(current car, track, display & sound options, ...), as well as the current
scores (best times, top speeds, laps, ...). It also describes whether you
have access to the bonus track and the bonus car, etc...
Anybody got anything more detailed to put here ?


B - SIMDATA directory
=================

B.1 SIMDATA\CARSPECS\*.PBS
----------------------

These files (one per player car) describe the car performance.
Usually, installing these files to the hard disk (by editing PATHS.DAT)
makes Need for Speed inoperable (no acceleration is possible) because the
game modifies SIMDATA\CARSPECS\BY_R&T. However this can be prevented by
making the check file read-only (run ATTRIB +R BY_R&T).

Note that copying one of these files on top of another one will affect the
car performance and handling, but not the engine sound. So if the max rpm's
of the two engines are not the same, the sound can get badly altered because
the correct sound sample is not available.

These files are somehow compressed, because by modifying a single byte in
the file one can reach various results such as : an instant system crash ;
a car that materializes under the road and cannot move, with 11 gears (!) ;
a car without front wheels, that keeps spinning at its initial position...

B.2 SIMDATA\DASH\*.FMM
------------------

These small files (two per player car, corresponding to the hi-res and
low-res dashboards) describe the shape of the car's windshield in each
display resolution. The files are slightly different for 320x200 and 640x480.

a) Low-res .FMMs (*DL.FMM) :

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

The header format is the following :

offset len data
------ --- ----
00 4 'wwww'
04 4 4 (number of chunks)
08 4 18h (offset of the first chunk)
0C 4 offset of the second chunk
10 4 offset of the third chunk
14 4 offset of the fourth chunk

The chunks in low-res .FMMs have the following header (22 bytes) :

offset len data
------ --- ----
00 4 'BAMF'
04 2 length of the chunk in bytes, minus two
06 4 ? (usually equals 10000h or 8000h : maybe an image size)
0A 2 maximum "length" value in the chunk's records
0C 4 ? (usually equals 10000h or 8000h : maybe an image size)
10 4 ? (usually equals 10000h or 8000h : maybe an image size)
14 2 number of records in the chunk (length minus 18h, div 8)

This header is in each chunk immediately followed by the 8-byte records.
Each record has the following structure :

offset len data
------ --- ----
00 4 baddr
04 2 vaddr
06 2 length

The last record is followed by a 16-bit value (purpose unknown).

The vaddr and length values are interpreted as follows : starting from
address "vaddr" in video memory (i.e. of the form 320y+x for pixel (x,y)),
"length" pixels do not belong to the dashboard, and must instead be drawn
because they correspond to screen portions where the player must see the
road through the windshield.
The baddr field corresponds to an internal buffer offset, describing
where the data to be displayed at "vaddr" are to be found in the buffer
where NFS draws the view.

- The first chunk corresponds to high detail : vaddr and baddr are equal,
and each line corresponds to 320 bytes in the buffer (every pixel is stored).

- The second chunk corresponds to medium detail : each line corresponds to
320 bytes in the buffer, but only half of the pixels are stored, thus only
the first 160 bytes contain relevant data, the following 160 being unused.
To vaddr=320y+x corresponds baddr=320y+(x>>1) : the horizontal resolution
is decreased.

- The third chunk corresponds to low detail : two consecutive lines have the
same baddr values, and these two lines correspond to 320 bytes in the buffer.
As before, only half of these 320 bytes are used. Only a quarter of the
pixels are stored. vaddr=320y+x corresponds to baddr=320.(y>>1)+(x>>1) :
both horizontal and vertical resolutions are decreased.

- The fourth chunk corresponds to the interlaced mode : only half of the
screen lines are referenced ; as in low detail, two screen lines correspond
to 320 bytes, half of which are unused. vaddr=320y+x still corresponds to
baddr=320.(y>>1)+(x>>1), but only the even-numbered lines are present.

b) Hi-res .FMMs (*DH.FMM) :

The chunk format is slightly different because the video memory is now
segmented in several 64K pages. (Note that the values at offsets 06, 0C and
10 in the chunk header are now larger, e.g. 40000h and 10000h)

Offset 14h in the chunk now contains, instead of the total number of records
in the chunk, only the number of records that correspond to the first page
of video memory (i.e. the first 64K). It is followed by the corresponding
records.
After these records, another 16-bit value describes the number of records
that are located in the second page of video memory (the following 64K);
the records for the second page follow (note that the 32-bit baddr values
at last become useful ; only the 16 last bits of the vaddr are stored,
since it is known to be located in the second page).
The chunk continues with the following pages, until the number of records
for a given page is zero. This zero value is followed by a 16-bit value
(purpose unknown) as in the low-res files.

The four chunks correspond respectively to high, medium, low and interlaced
detail levels, as described above (but the lines are now each 640 pixels
long ; when not in high resolution, only 320 of the 640 bytes are used).

B.3 SIMDATA\DASH\*.FSH
------------------

These store the different bitmaps that make up the dashboard.
The 16-byte header format is the following :
                               
offset len data
------ --- ----
00 4 'SHPI'
04 4 length of the file in bytes
08 4 number of objects in the directory
0C 4 directory identifier string

The directory identifier is 'GIMX' in .FSH dashboard files.

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.

Each entry in the directory represents a piece of the dashboard.
There are gaps between the directory and the first bitmap, and between
consecutive bitmaps (significance unknown).

Each directory entry points to a bitmap block with the following structure :

offset len data
------ --- ----
00 1 7Bh
01 3 size of the block (= width x length + 10h)
04 2 width of the bitmap in pixels
06 2 heigth of the bitmap in pixels
08 4 ?
0C 2 x position to display the bitmap
0E 2 y position to display the bitmap
10 w.h bitmap data : 1 byte per pixel

Note that the object called 'dash' in the directory takes the whole screen
(320x200 or 640x480, at position x=0, y=0)."

The various objects, depending on their 4-letter identifier, represent :
the dashboard itself, the steering wheel in various positions, the radar
detector lights, the gauges, and also pieces of the steering wheel to redraw
over the gauges when necessary. Note that value FF in the bitmaps stands for
the background : this is useful when a bitmap is drawn on top of another one.

Also note that some SHPI bitmap directories contain entries that actually
describe the palette to be used with the bitmaps. Typically, entries with
names like '!PAL', and with bitmap dimension 256x3, correspond to palettes.
The palette data consists of 256 3-byte records, each record containing the
red, green and blue components of the corresponding color (1 byte each).

B.4 SIMDATA\CARFAMS\*.CFM
---------------------

These files describe the exterior look of the cars during the race. There
seem to be two different kinds of files :
- full CFMs that can be used to describe any car
- restricted CFMs that can only describe traffic or opponents - note that
yourself and your head-to-head opponent must have full CFMs, whereas
"single race" opponents can be either full or restricted CFMs.

a) Full CFMs on the CD :
Standard cars : ANSX.CFM, CZR1.CFM, DVIPER.CFM, F512TR.CFM, LDIABL.CFM,
MRX7.CFM, P911.CFM, TSUPRA.CFM, TRAFFC.CFM (Warrior)
More or less bugged previous versions of these cars :
F512M.CFM, P911T.CFM, WARIOR.CFM, WARRIOR.CFM

b) Restricted CFMs on the CD :
Vans/jeeps/pickups : JEEP.CFM, PICKUP.CFM, RODEO.CFM, VANDURA.CFM
Station-wagons : AXXESS.CFM, WAGON.CFM
Usual cars : BMW.CFM, JETTA.CFM, LEMANS.CFM, SUNBIRD.CFM
Sports cars : CRX.CFM, PROBE.CFM
The cop's car : COPMUST.CFM
Restricted versions of the player cars (loaded for single race opponents):
MANSX.CFM, MCZR1.CFM, MDVIPER.CFM, MF512TR.CFM, MLDIABL.CFM,
MMRX7.CFM, MP911.CFM, MTSUPRA.CFM, MTRAFFC.CFM
Bugged versions of the player cars :
LDIABLO.CFM, MF512M.CFM, MP911T.CFM, TESTA.CFM

These files are 'wwww' files containing four chunks. The header is as in
.FMM files (see B.2). The first and second chunk correspond to high-detail
car structure, while the third and fourth chunk correspond to low-detail.

The first and third chunks have header 'ORIP', and describe how the car is
to be drawn (position and orientation of each car element). The second
and fourth chunks are 'SHPI' bitmap directories (see B.3), with directory
identifier 'WRAP'. They provide the bitmaps referenced by the ORIP chunks.
Note that the offsets specified in the bitmap directories are relative to the
'SHPI' header.

An 'ORIP' chunk consists of a header followed by nine blocks.
The header has length 112 (70h) and the following structure :

offset len data
------ --- ----
00 4 'ORIP'
04 4 chunk length in bytes
08 4 2BCh (=700)
0C 4 0
10 4 size of block 8 in 12-byte records
14 4 ? the previous minus 10h
18 4 offset of block 8 in the ORIP (in bytes)
1C 4 size of block 2 in 8-byte records
20 4 offset of block 2
24 4 size of block 1 in 12-byte records
28 4 offset of block 1 (=70h)
2C 12 identifier string
38 4 size of block 3 in 20-byte records
3C 4 offset of block 3
40 4 size of block 4 in 20-byte records
44 4 offset of block 4
48 4 size of block 5 in 28-byte records
4C 4 offset of block 5
50 4 offset of block 9
54 4 size of block 6 in 12-byte records
58 4 offset of block 6
5C 4 size of block 7 in 12-byte records
60 4 offset of block 7
64 4 0
68 4 70h
6C 4 0

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

offset len data
------ --- ----
00 1 83h for triangle, 84h for quadrangle, 8Ch when quadrangle/null
01 1 ?
02 1 texture number
03 1 ?
04 4 polygon offset for pol1
08 4 polygon offset for pol2

The texture number corresponds to a record position in block 3, which is
converted to one of the textures in the SHPI chunk that follows the ORIP.
The polygon offsets correspond to positions in the last block, where the
polygons are listed consecutively (first pol2 and then pol1, for each record).
The first polygon has pol2 starting at 0. (The polygon offsets are given
in 4-byte units). In the last block, vertices belonging to a pol1 are
expanded to 3D points by lookup in block 8, while vertices belonging to a
pol2 are expanded to 2D points by lookup in block 2. The portion of the
relevant texture corresponding to pol2 is mapped onto the 3D polygon pol1.

When the first byte is 83h, pol1=pol2+3 and next polygon's pol2 equals pol1+3.
When it is 84h, pol1=pol2+4 and next pol2 equals pol1+4. When it is 8Ch,
pol1=pol2 and next pol2 equals pol1+4.

The second block is made of 8-byte records, which describe the (x,y)
coordinates inside the textures referenced by pol2.

offset len data
------ --- ----
00 4 x coordinate
04 4 y coordinate

Third block (20-byte records):

offset len data
------ --- ----
00 8 identifier string 1
08 4 identifier string 2
0C 8 ? 00 00 00 81 F5 00 00 00

This block describes the link between the texture numbers of block 1 and
the textures stored in the SHPI chunk. Identifier string 2, when non-void,
corresponds to one of the SHPI directory entries.

Fourth block (20-byte records):

offset len data
------ --- ----
00 8 identifier string ('left_tur', 'right_tu')
08 4 number of vertices
0C 4 polygon offset (in block 9)
10 4 ?

Fifth block (28-byte records):

offset len data
------ --- ----
00 12 identifier string ('NON-SORT', 'inside', 'surface', 'outside')
0C 4 ?
10 4 polygon offset (in block 9)
14 4 number of vertices
18 4 0

Sixth and seventh blocks (12-byte records):

offset len data
------ --- ----
00 8 identifier string
08 4 ?

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

offset len data
------ --- ----
00 4 x coord. (x axis is lateral)
04 4 z coord. (z axis is vertical, z increases when going up)
08 4 y coord. (y axis is longitudinal, increases when going forward)

The last block is a succession of long integers, each representing a vertex
number. This block describes the vertices each polygon consists of, and is
referenced by the index tables of the first, fourth and fifth blocks. Each
vertex number referenced in a pol1 polygon is converted to a point in space
using block 8, while each vertex number referenced in a pol2 polygon is
converted to a position in a texture bitmap using block 2.

B.5 SIMDATA\MISC\*.QFS, SIMDATA\SLIDES\*.QFS, ...
---------------------------------------------

This seems to be EAC's favorite bitmap format... Basically, it is similar
to the .FSH files described in B.3, however the data are now compressed
using some kind of Huffman algorithm. Outside of this compression thing,
the file still contains a 'SHPI' header, and a directory. The directory
itself is much shorter than in the dashboard FSH's : usually one entry
(the bitmap itself), sometimes two (when a palette is specified).
The big trouble is in finding the details of the decompression algorithm.

The directory header is 'LN32', indicating 32768-color mode. (see C.2).

B.6 SIMDATA\MISC\*.TRI
------------------

Don't know why these are in the MISC directory... they are quite important
indeed ! 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 SIMDATA\TRACKFAM.

Their structure is fairly complex, so I recommend you play with the files
in order to get acquainted with their subtleties. The information contained
in this section was used to develop the first NFS track editor, called
TRACKED, and available at the following URL :

http://www.eleves.ens.fr:8080/home/auroux/nfs/tracked.zip

In order to understand the structure of TRI 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.

a) TRI files begin with 12F8h bytes of headers and index tables. These are
as follows :

offset len data
------ --- ----
00 4 ?
04 8 ?
0C 4 x coordinate of the first node
10 4 z coordinate of the first node
14 4 y coordinate of the first node
18 4 ?
1C 4 ?
20 4 ?
24 4 length of the scenery data (in bytes : 554h per record)
28 4 ?
2C 960h first index table
98C 960h second index table

The first index table is a succession of 32-bit offsets. It follows an
arithmetic progression by 548h as a general rule. This means the first
value is 0, followed by 548h, A90h, etc... On closed tracks, when the
end is reached, the offsets start again with 0, 548h, A90h, etc...
(so that the end of a lap is connected with the beginning of the following
one !). 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, since there are no 548h-byte structures in the file.

The second index table is also a succession of 32-bit offsets, but these
offsets are inside the TRI file. This one follows an arithmetic progression
by 554h. It corresponds to the offsets of the successive records for
scenery data, which starts at offset 1B000h in the scenery file. So this
table starts with 1B000h, 1B554h, 1BAA8h, etc... until the end of the
TRI file is reached. It is filled to 600 entries with zero values.

b) The virtual road data follows, and is constituted of 36-byte records
(one for each node). The first record is at offset 12F8h, and the last
allowed record is at offset 16468h (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 :

offset len data
------ --- ----
00 1 a0
01 1 a1
02 1 a2
03 1 a3
04 1 b0
05 1 b1
06 1 b2
07 1 b3
08 4 x coordinate
0C 4 z coordinate
10 4 y coordinate
14 2 slope
16 2 slant-A
18 2 orientation
1A 2 0
1C 2 y-orientation
1E 2 slant-B
20 2 x-orientation
22 2 0

- a0,a1,a2,a3 are 8-bit values whose purpose is unknown : possibly the
width of the road on each side ?

- b0,b1,b2,b3 are 8-bit values of unknown purpose.

- 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.

c) The objects data comes next. There are first several distinct zones,
many of which seem to be unused (?) :

offset len data
------ --- ----
16478 708h 3-byte records (there are 600... as many as scenery blocks ?)
16B80 4 40h (?)
16B84 4 3E8h = 1000 (size of the main block in records)
16B88 4 'OBJS'
16B8C 4 428Ch (total length of the remaining blocks)
16B90 400h 16-byte records (unknown purpose)
16F90 4 ?
16F94 3E80h object data : 1000 records of 16 bytes (one per object)
1AE14 1ECh 0

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

offset len data
------ --- ----
00 4 reference node
04 1 bitmap number
05 1 flip
06 4 flags (unknown purpose)
0A 2 relative x coordinate
0C 2 relative z coordinate
0E 2 relative y coordinate

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 perpendi-
cular 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.

The bitmap number corresponds to a texture in the corresponding .FAM file
(see B.8). The relevant bitmaps are in the second chunk of the .FAM file.
Two cases can occur :

- closed tracks : the second chunk is a 'wwww' structure containing a
single subchunk which is in turn a SHPI directory where the entry corres-
ponding to bitmap #n is called "nn00" where nn is n written in decimal.
(e.g. bitmap #18 is "1800"). Furthermore the object called "!pal" or "!PAL",
when it exists, is the corresponding palette (256 3-byte entries) ; FFh is
transparent.

- open roads : the second chunk contains a subchunk per bitmap, and each
subchunk is a SHPI containing at least the object "0000" (the bitmap), and
possibly a palette ("!pal" or "!PAL"). Object #n is then the bitmap "0000"
in the subchunk #n (the first subchunk is #0).

One must add to these 2D objects (plain bitmaps) the 3D objects described
in the fourth chunk of the .FAM file. They usually correspond to numbers
above the last 2D object ; however it happens, in closed tracks, that some
of the 3D objects are given numbers inside the range used by 2D objects.
In that case, the numbers describing 2D objects are shifted upwards.
(i.e. the bitmap "4400" corresponds to object #45 or #46). This phenomenon
apparently does not occur for open roads, where the 3D objects always follow
the 2D objects.

Furthermore, certain consecutive bitmaps represent successive states of an
animated object. In that case, the game will display successively the
relevant bitmaps. Note that if the second bitmap is given instead of the
first, the animation does not occur.

d) The scenery data starts at offset 1B000h. It is made up of records of
size 554h, each corresponding to four nodes in the virtual road. The
records are consecutive and the last record ends the .TRI file.
Each record has the following structure :

offset len data
------ --- ----
000 4 'TRKD'
004 4 548h = length of the record contents
008 4 number of this record (0 for the first, then 1, etc...)
00C 2 ?
00E 10 textures
018 12 reference point
024 12 ?
030 12 point A0
03C 12 point A1
... .. ........
09C 12 point A9
0A8 12 point A10
0B4 12 ?
0C0 12 point B0
0CC 12 point B1
... .. ........
12C 12 point B9
138 12 point B10
144 12 ?
150 12 point C0
15C 12 point C1
... .. ........
1BC 12 point C9
1C8 12 point C10
1D4 12 ?
1E0 12 point D0
1EC 12 point D1
... .. ........
24C 12 point D9
258 12 point D10
264 12 ?
270 12 ?
27C 12 point E0
288 12 point E1
... .. ........
2E8 12 point E9
2F4 12 point E10
300 516 ? unused (room for 43 points)
504 80 ? unused

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, consti-
tuting 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 :

E10---E9---E8---E7---E6---E0---E1---E2---E3---E4---E5 node 4n+4
| | | | | || | | | | |
| | | | | || | | | | |
D10 D9 D8 D7 D6 D0 D1 D2 D3 D4 D5 node 4n+3
| T | T | T | T | T || T | T | T | T | T |
| | | | | || | | | | |
C10 C9 C8 C7 C6 C0 C1 C2 C3 C4 C5 node 4n+2
| 10 | 9 | 8 | 7 | 6 || 1 | 2 | 3 | 4 | 5 |
| | | | | || | | | | |
B10 B9 B8 B7 B6 B0 B1 B2 B3 B4 B5 node 4n+1
| | | | | || | | | | |
| | | | | || | | | | |
A10---A9---A8---A7---A6---A0---A1---A2---A3---A4---A5 node 4n
^
the nodes are here |

The texture numbers are converted to bitmaps in the first chunk of the
.FAM file (see B.8). There are two different cases :

- closed tracks : the first chunk is a 'wwww' structure which contains a
single subchunk which is in turn a SHPI bitmap directory, possibly with a
palette '!PAL' or '!pal'. There is also often a bitmap called 'ga00' or
'GA00' (unknown interpretation). The names have the structure "xxls", where
xx is a decimal value indicating the texture group, l is 'A', 'B' or 'C',
and s indicates a scale ('0' is the largest, while '3'&'4' are very small).
The various scales are here to speed up the texture-mapping algorithm,
anyway the only texture that is always present is with s=0.
The xx and l values correspond to a texture number n in the following way :
n=3xx if l='A', 3xx+1 if l='B' and 3xx+2 if l='C'. Note that there are holes
in the numbering : many numbers do not have a bitmap.
Examples : bitmap "03C0" corresponds to texture #11 (3x3+2) at the largest
scale; bitmap "14A1" corresponds to texture #42 (3x14) at the second scale
available.

- open roads : the first chunk contains a subchunk per texture group (i.e.
the xx value is now the number of the subchunk, starting with 0). Each
subchunk is a SHPI directory containing potentially a palette, and bitmaps
labelled "l00s", where l is 'A','B' or 'C' and s is the scale.
As before, n=3xx if l='A', 3xx+1 if l='B', 3xx+2 if l='C', and there are
holes in the numbering.
Examples : texture #11 at scale '0' is now the bitmap "C000" in subchunk #3.
Texture #42 at scale '1' is now the bitmap called "A001" in subchunk #14.

B.7 SIMDATA\SOUNDBNK\*.BNK
----------------------

These file store the sound samples for the engines, the crashes, etc...
The filenames ending with 'W' correspond to 16-bit sound, while 'B' stands
for 8-bit sound. Logically, 'S' should stand for stereo and 'M' for mono,
but it seems that, at least for cars, the file that gets loaded in 8-bit
mono mode is the one whose name ends with 'SB'. I don't know why. I'm
beginning to think that EAC recruited Microsoft programmers ;-)

Also remember that the 8 bit sound samples are signed data. If you plan to
use WAV files as samples, don't forget to change this.

The file format is the following :

- the first 512 bytes contain 128 long integers, which are either zero if
the corresponding sample is not present, or the offset of a sample header.
Car files contain four samples with header offsets 200h, 248h, 290h and 2D8h,
declared at offsets 04, 08, 0C and 80h respectively. The two first samples
are the engine sound, the third is the car horn, the fourth is the sound
that gets produced when you change gears.

- each sample header consists of 72 bytes (48h). The format is the following:

offset len data
------ --- ----
00 4 ? flags (for 8-bit car sounds, these are 1, 2, 4000h and 10h)
04 4 header's offset + 28h (i.e. offset of the 'EACS' marker)
08 4 ? (0 for cars)
0C 4 ? (0 for cars except gear change)
10 4 ? (0 for cars)
14 1 ?
15 1 ? (80h for cars)
16 1 ? (0 for cars)
17 1 ?
18 4 ? (7F40h for cars)
1C 4 ? (0 for cars)
20 4 ? (0 for cars)
24 4 ? (0 for cars)
28 4 'EACS'
2C 4 3E80h (sampling rate : 16 kHz)
30 1 8/16 bit flag : 1 for 8-bit, 2 for 16-bit
31 1 mono/stereo flag : 1 for mono, 2 for stereo
32 1 ? (0 for cars)
33 1 ? (FFh for cars)
34 4 beginning of the repeat loop (in samples : 1, 2 or 4 bytes)
38 4 length of the repeat loop (in samples)
3C 4 length of the sound (in samples)
40 4 offset of the raw sound data in the .BNK file
44 4 ? (0 for cars)

B.8 SIMDATA\TRACKFAM\*.FAM
----------------------

These files contain the bitmaps that are used for displaying the correspon-
ding track or track segment. They make use of the 'wwww' file format, using
the usual header (see B.2) : first 'wwww', then the number of chunks (as a
long integer), then the offsets of each chunk header (long integers).

The .FAM file itself is a 'wwww' file containing four 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. In the open road .FAM's, the chunks are very
subdivided and contain many small subchunks, while in the closed tracks,
there is only one big subchunk.

Now the subchunks in each of the first two chunks are themselves 'SHPI'
bitmap directories (see B.3), whose elements are a palette and several
bitmaps. Keep in mind that the offsets in the directories are relative to
the beginning of the subchunk (i.e. the 'SHPI' header).

The third chunk of the .FAM file is a SHPI file describing the horizon :
the SHPI directory contains two entries, one for the palette and one for
the bitmap itself.

The fourth chunk describes the three-dimensional objects in the scenery.
It is a 'wwww' structure, containing a subchunk per object. Now each of
these subchunks is quite similar to a .CFM file (see B.4) : it is itself a
'wwww' structure containing two subsubchunks ! The first subsubchunk is an
'ORIP' structure describing the shape of the object, while the second is
a 'SHPI' structure containing the bitmaps referenced by the 'ORIP' part.

If you didn't catch everything, don't worry... look at NFSVIEW.PAS (see D.1)


C - FRONTEND directory
==================

C.1 FRONTEND\ART\*.QFS, FRONTEND\SHOW\*.QFS : see B.5
---------------------------------------

C.2 FRONTEND\ART\*.INV
------------------

These files describe how to reduce the palette from hi-color mode to 256
colors. The corresponding .QFS files (compressed SHPI bitmaps) have directory
identifier 'LN32', indicating the bitmaps are in 32768-color mode (each
red, blue and green component is coded on 5 bits (0 to 31), and the 15 bits
describing the color are stored in a 16-bit word). Since many video cards do
not support these modes, information is provided for palette reduction to
256-color modes. This information is partly stored as a palette object in the
QFS file, describing the RGB components of the 256 colors. In order to help
Need for Speed with the palette conversion, the .INV file (length 32768 bytes)
stores, for each 15-bit value, which palette entry is relevant.

Displaying the 'LN32' bitmaps in 256-color is thus done by first expanding
the .QFS file, then setting the specified palette, and converting each
15-bit pixel in the bitmap to the 8-bit value located at the corresponding
offset in the .INV file.

C.3 FRONTEND\MUSIC\*.ASF
--------------------

These files contain the music for the front end. The 40-byte header is as
follows (note a consistency with the EACS structures described in B.7) :

offset len data
------ --- ----
00 4 '1SNh'
04 4 ?
08 4 'EACS'
0C 4 3E80h (sampling rate 16 kHz)
10 1 2 (16-bit mode flag)
11 1 2 (stereo mode flag)
12 1 ? (0 usually)
13 1 ? (0 usually)
14 4 length of the wave data (expressed in 4-byte samples)
18 4 beginning of the repeat loop (in samples)
1C 4 length of the repeat loop (in samples)
20 4 0 (the start offset is not specified : should be 28h)
24 4 ?

Signed 16-bit stereo wave data follows.

C.4 FRONTEND\SPEECH\*.EAS
---------------------

These file contain the speeches, as an EACS structure (see B.7 and C.3).
The 32-byte header is now as follows :

offset len data
------ --- ----
00 4 'EACS'
04 4 3E80h (sampling rate 16 kHz)
08 1 1 (8-bit mode flag)
09 1 1 (mono mode flag)
0A 1 ? (0 usually)
0B 1 ? (FFh usually)
0C 4 length of wave data (expressed in 1-byte units)
10 4 FFFFFFFFh (no repeat loop)
14 4 0 (no repeat length)
18 4 20h (offset of the wave data)
1C 4 ?

Signed 8-bit mono wave data follows.


D - Appendix
========

D.1 NFSVIEW.PAS
-----------

{NFS file viewer : recurse into 'wwww' structures and view 'SHPI' bitmaps}

uses crt;
var f:file;
scr:array[0..199,0..319] of byte absolute $A000:0;
pal:array[0..767] of byte;
s:string[5];

procedure setpalette; assembler;
asm
mov dx,3c8h
xor cl,cl
mov si,offset pal
cld
@bcl:
mov al,cl
out dx,al
inc dx
lodsb
out dx,al
lodsb
out dx,al
lodsb
out dx,al
dec dx
inc cl
jnz @bcl
end;

function st(x:longint):string;
var s:string[20];
begin
str(x,s);
st:=s;
end;

procedure viewshpi(pre:string;off:longint); {process a SHPI}
var ni,i:integer;
w,h,xp,yp,y:word;
l:longint;
foundpal:boolean;
begin
seek(f,off+8);
blockread(f,ni,2);
writeln(pre,'SHPI ',ni,' bitmaps'#10#13'Looking for a palette...');
foundpal:=false;
for i:=0 to ni-1 do begin {look for a palette}
seek(f,off+20+8*i);
blockread(f,l,4);
seek(f,off+l+4);
blockread(f,w,2);
blockread(f,h,2);
if (w=256) and (h=3) then begin
blockread(f,pal,8);
blockread(f,pal,768);
foundpal:=true;
end;
end;
if foundpal then writeln('Found !') else writeln('No palette.');
readkey;
asm
mov ax,13h
int 10h
end;
if foundpal then setpalette;
for i:=0 to ni-1 do begin {display the bitmaps}
fillchar(scr,64000,0);
seek(f,off+20+8*i);
blockread(f,l,4);
seek(f,off+l+4);
blockread(f,w,2);
blockread(f,h,2);
blockread(f,l,4);
blockread(f,xp,2);
blockread(f,yp,2);
if (w<>256) or (h<>3) then begin
if (xp+w>320) or (yp+h>200) then begin yp:=0; xp:=0; end;
for y:=yp to yp+h-1 do
blockread(f,scr[y,xp],w);
readkey; end;
end;
asm
mov ax,3
int 10h
end;
end;

procedure viewwwww(pre:string;off:longint); {process a wwww block}
var n,i:integer;
l:longint;
s:string[5];
begin
seek(f,off+4);
blockread(f,n,2);
for i:=1 to n do begin {process each chunk}
seek(f,off+4+4*i);
blockread(f,l,4);
s[0]:=#4;
seek(f,off+l);
blockread(f,s[1],4); {read 4-char id}
if s='wwww' then
viewwwww(pre+'chunk '+st(i)+'/'+st(n)+' sub',off+l)
else if s='SHPI' then
viewshpi(pre+'chunk '+st(i)+'/'+st(n)+' ',off+l)
else begin
writeln(pre,'chunk ',i,'/',n,' unrecognized header ',s);
readkey;
end;
end;
end;

begin
if paramcount=0 then begin
writeln('Need For Speed wwww/SHPI Viewer 1.0 (c) Denis Auroux 1995');
writeln('Syntax : NFSVIEW filename'#10#13);
exit;
end;
clrscr;
assign(f,paramstr(1));
reset(f,1);
s[0]:=#4;
blockread(f,s[1],4); {read 4-char id}
if s='wwww' then viewwwww('',0)
else if s='SHPI' then viewshpi('',0)
else writeln('Unrecognized header ',s,#10#13);
close(f);
end.