Daggerfall:MAPS.BSA

MAPS.BSA is a Name Record (0x0100) BSA file containing the overland data for 62 regions of the game. The file contains 4 different record types. Each described region has one of each record type associated with it, for a total of 248 distinct records within the file. Within each of the region's associated records, all navigable settlements, dungeons, shrines, etc are listed and described.

Each described region has 4 records associated with it. Records are all named in 7-bit ASCII string DOS8.3 format. The 3 character record extension is the ASCII representation of the region's decimal number, with leading 0's. Ex: Daggerfall (0x11) is identified by records ending with "017", such as "MAPPITEM.017". The leading 8 characters indicate the specific type of record:

MapNames

These records simply lists the names of all navigable locations within the region, stored as an array of 7-bit ASCII strings.

MapTable

These records describe the coarse GPS data, and type of the navigable locations within the region.

MapPItem

These records describe the exterior of each navigable location within the region.

MapDItem

These records describe the dungeon interiors of each navigable location within the region.

Ex: "MAPNAMES.005" is the list of the names of all navigable places within Dwynnen.

This type of record contains the count of all navigable locations within the record's associated region, immediately followed by the names of all navigable locations within the record's associated region.

The first four bytes are the count of name elements as an UInt32, referred to as LocationCount. This record is variably sized, but must always be 4 + ( 32 * LocationCount ) bytes long.

Immediately following this count are the actual names of all the navigable locations for the record's associated region, each 32 characters wide, stored as a null-terminated, 7-bit ASCII string. There are exactly LocationCount elements.

These records report the GPS location data, as well as the type of the described location, for each navigable location within the record's associated region. Each record consists of a contiguous list of MapTable structures. Each MapTable structure is 17 bytes long in size.

There are exactly MapNames.LocationCount elements in the contained list, and each indexed record is the same location as in the map names.

MapTable Element structure

Offset

Type

Name

Description

0-3

Int32

MapId

This numeric ID is used to associate values MapTable elements with LocationRecordElement elements. Each LocationExterior value must be described by a MapTable value. The first 20 bits of this field matches the first 20 bits of a LocationExterior.ExteriorData.MapId value; Simply match ( LocationExterior.ExteriorData.MapId & 0x000fffff ) with ( MapTable.MapId & 0x000fffff ). Those values must be stored in increasing order.

The upper bits contain the location index. It must correspond to a position of MapTable element in the array.

4-7

UInt32

LongitudeType

This field is actually the combination of the location's Longitude and type. Decoding instructions are below.

8-11

UInt16

LatitudeType

The location's latitude (see below).

12

UInt8

Flavor

If this location is one of four kinds of dungeons, this field controls its discovery message (add 500 to obtain the string index). Otherwise, unknown.

13-16

UInt32

Services

A bitfield representing which guilds, temples, and shops found in the location.

The remaining two types of records (MapPItem and MapDItem) each use a common base format for their root data, described here. Each record consists of a contiguous list of the data for all the navigable locations for that record's associated region. Since not all locations have dungeons, Location Exterior Data Records may contain more elements than Dungeon Interior Data Records.

The base format, LocationRecordElement, is variably-sized. It consists of a DoorHeader, immediately followed by a contiguous list of zero or more Door elements, immediately followed by a LocationRecordElementHeader with its ObjectHeader.

Immediately following the DoorHeader is a contiguous list of Door elements, DoorCount in count, each 6 bytes long.

Door structure

Offset

Type

Name

Description

0-1

UInt16

BuildingDataIndex

This is a valid index to an element within the LocationExterior.BuildingData array, or 0xffff which indicates this Door is not associated with an element of the BuildingData array. This places a maximum count of BuildingData elements at 0x7fff.

2

UInt8

NullValue

This value is always 0x00.

3

UInt8

Mask

This value is a mask of some type. The specific purpose is presently unknown.

The LocationRecordElementHeader immediately follows the ObjectHeader. Each LocationRecordElementHeader structure is 48 bytes long.

LocationRecordElementHeader structure

Offset

Type

Name

Description

0-31

7-bit ASCII string

LocationName

Reports the NULL-terminated name of the location, but may not always exactly match the values in the MapNames record for the region. This value is used when displaying the name of a location when entering it. The fast travel map uses the MapNames record for display.

Each MapPItem record begins with a list of UInt32 values with MapNames.LocationCount elements. This is a list of offsets to the LocationExterior structures for each location. These values are relative to the end of the list, so adding (LocationCount * 4) to the offset locates the actual record. One offset may be greater than a subsequent one; no data order is presumed.

At each offset indicated, a LocationExterior structure is present, which includes all fields from the LocationRecordElement and some data of its own.

Immediately following the LocationRecordElement, is a contiguous list of BuildingData structures. Each BuildingData is 26 bytes long. BuildingData structures are associated with buildings within a settlement, such as a tavern.

BuildingData structure

Offset

Type

Name

Description

0-1

UInt16

NameSeed

This field is used as a seed value for generating the building's name.

2-9

UInt64

NullValue1

Should always be 0x0000000000000000.

10-17

UInt64

NullValue2

Should always be 0x0000000000000000.

18-19

UInt32

FactionId

This is the FactionId which should be associated with this building, or 0x0000 if no faction should be associated with this building. Valid values for this field are defined by the FACTION.TXT file.

20-23

Int32

ObjectId

This value links to the object representing that building in the game world.

24

UInt8

BuildingType

This indicates the type of the building. Valid values are defined in the Building Type Code enumeration.

25

UInt8

Quality

This specifies the quality of the building, always non-zero and ranges from 1 to 0x14 (20). Divide by 4 to rate on the "rusty-relics…" through "incense burning…" scale.

Appears to be another name for the location, but changing the value has no visible effect on the game.

32-35

Int32

MapId

Since each LocationExterior value must be described by a MapTable value, this field must correspond to a MapTable.LocationId value. The first 20 bits of this field matches the first 20 bits of a MapTable.MapId value; Simply match ( LocationExterior.ExteriorData.MapId & 0x000fffff ) with ( MapTable.MapId & 0x000fffff ).

36-39

UInt32

Unknown1

Unknown Purpose.

40

UInt8

Width

The width of the exterior data. This value may not be 0, and must be less-than-or-equal-to 8.

41

UInt8

Height

The height of the exterior data. This value may not be 0, and must be less-than-or-equal-to 8.

42-45

UInt8[ 4 ]

Unknown2

Unknown Purpose.

46

char

Letter

A letter used in calculation of RMB block names.

47

UInt8

Port

Non zero if it is a port town that sells ships.

48

UInt8

Unknown3

Unknown Purpose.

49-112

UInt8[ 64 ]

BlockIndex

Only the first Width * Height elements will have any meaning. See decoding instructions below.

113-176

UInt8[ 64 ]

BlockNumber

Only the first Width * Height elements will have any meaning. See decoding instructions below.

177-240

UInt8[ 64 ]

BlockCharacter

Only the first Width * Height elements will have any meaning. See decoding instructions below.

241-272

char[ 32 ]

DungeonName

The name of the dungeon associated with this location. All the following dungeon fields are zeroed if there is no dungeon.

243

UInt8

Encounters

An index into the encounter table for this dungeon.

274

UInt8

BlockCount

The number of blocks in the dungeon.

275-283

UInt8[ 9 ]

Unknown4

Unknown Purpose.

284-371

DungeonBlock[ 32 ]

Blocks

Blocks of the dungeon associated with this location. Only BlockCount first elements are valid.

The BlockIndex, BlockNumber, and BlockCharacter arrays all have a fixed size of 64 elements, but only the first Width * Height elements are used; the remainder are ignored. All 64 elements must be read just the same. These values are used to load the appropriate records from the BLOCKS.BSA file, which contains the automap data and are in turn used to load the appropriate meshes and models from ARCH3D.BSA to actually display the scene.

When accessing the block arrays, they should be synchronized. This is to say BlockIndex[ 5 ] should refer to the same Block record as BlockCharacter[ 5 ] and BlockNumber[ 5 ]. If one adds, removes, or reorders any array then one must reorder both of the other arrays to keep them synchronized.

The arrays are stored in west-to-east, south-to-north order. This means index 0 refers to the southwest corner of the location, and index ( Width * Height ) refers to the northeast corner of the location. Locations are not required to be squares (Width is not required to equal Height).

Immediately following the DungeonCount field is a contiguous list of DungeonOffset values. Each value is 8 bytes long. The elements are not required to be in any particular order; That is to say the first element's offset could be higher than the second element's offset.

DungeonOffset structure

Offset

Type

Name

Description

0-3

UInt32

Offset

These offsets refer to the DungeonInterior elements of the record, and all offsets are relative to the end of the offset list.

4-7

UInt32

DungeonObjId

This value is calculated as (LocationExterior.LocationRecordElement.LocationId << 16) + 1.

Each DungeonInterior structure contains a contiguous list of DungeonBlock structures. There are exactly DungeonHeader.BlockCount elements in this list.

DungeonBlock structure

Offset

Type

Name

Description

0

UInt8

X

The X coordinate of the block.

1

UInt8

Z

The Z coordinate of the block.

2-3

UInt16

BlockNumberStartIndex

This is a concatenation of the BlockIndex and BlockNumber values. Decoding instructions follow.

The X and Z fields indicate how the blocks should be arranged in a two-dimensional grid. Dungeons are not required to be uniform such as squares or rectangles. They can contain empty spaces, or have spurs.

This value is used for decoding the string name of the RDB record from BLOCKS.BSA. As of the current patch, bits 8-9 are only necessary for Privateer's Hold (999); all other blocks require only bits 0-7.

10

Bool

IsStartingBlock

This bit is set (1) if this block is the "entrance" block. This is the block where the player starts when entering a dungeon. This bit is reset (0) otherwise. All DungeonInterior records must have one and only one DungeonBlock element with this bit set (1).

11-15

UInt8

BlockIndex

This value is used for decoding the string name of the RDB record from BLOCKS.BSA. Valid values are described in Block Record Indexes.

Immediately following the last DungeonBlock element are ( 128 - ( BlockCount * 4 ) ) bytes of padding. These values are simply padding and can be ignored. This gives each Dungeon a maximum of 32 DungeonBlock elements.