ARCH3D.BSA is a NumberRecord (0x0200) BSA file, containing 10251 (0x280B) records. Each record describes a single 3D object/mesh.

3D Object RecordsEdit

The following description has been tested on all the 3D Objects contained in Arch3D.BSA and appears to be sound. There are two records which have some problems (offsets 0x008B8D58 and 0x013274C6) and don't follow the known format of the other 10249 records. They have a large section of repeating bytes just after the 3D object header and their Data2 section is not the standard. These records could very well be corrupt or not used or of a special, undiscovered, format.

Each BSA record contains the information for one 3D object. Note that each record appears to be similar to the .3D file format used in Battlespire. One difference is that here the .3D files are contained in one big file, while in Battlespire they are in individual files. Records range from 212 to 81394 bytes in size.

A 3D Object Record normally has the following sections:

3D Object Header
Always the first 64 bytes in each 3D Object Record.
This provides offsets to reference the other sections of the record.
PointList
The Point Structures which define the 3D Object Record's geometry are stored here.
PlaneList
The Plane Structures which define the 3D Object Record's geometry are stored here.
Plane Structures refer to elements of the PointList.
NormalList
The Normals for each Plane Structure are stored here.
PlaneDataList
Each Plane Structure implies a 24 byte value, stored here.
ObjectDataList
Each 3D Object Record refers to zero or more ObjectData Structures, stored here.

Two records contain a block of repeating bytes of unknown purpose not referenced within their 3D Object Record Header.


3D Object HeaderEdit

Each 3D Object is described by a header, which is always the first 64 bytes of the 3D Object Record. This header reports the 3D Object's Version (necessary for interpreting the 3D Object's geometry), number and location of Point structures Plane, etc.

3D Object Record Header Structure
Offset Type Name Description
0-3 String (7-bit ASCII) Version Appears to be a version number. The value is not null-terminated. Most of the records report "v2.7", though 135 report "v2.6" and 9 report "v2.5". The "v2.5" records require special care when decoding their geometry (see below).
4-7 Int32 PointCount The count of Point Structures in the 3D Object's PointList. All records must report at least 3 for their PointCount field. Values should not be negative.
8-11 Int32 PlaneCount The count of Plane Structures in the 3D Object's PlaneList. All records must report at least 1 for their PlaneCount field. Values should not be negative.
12-15 Int32 Radius The radius of the mesh, which is the maximum distance of any point in the PointList from the origin (0, 0, 0).
16-23 UInt64 NullValue1 Always 0x0000000000000000.
24-27 Int32 PlaneDataOffset The offset relative to the 3D Object Record for the 3D Object's PlaneDataList. The position of the PlaneDataList would simply be (RecordStartPosition + PlaneDataOffset).
28-31 Int32 ObjectDataOffset The offset relative to the 3D Object Record for the 3D Object's ObjectDataList. The position of the ObjectDataList would simply be (RecordStartPosition + ObjectDataOffset).
32-35 Int32 ObjectDataCount The count of ObjectData elements in the 3D Object Record's ObjectDataList.
36-39 UInt32 Unknown2 Unknown purpose.
40-47 UInt64 NulValue2 Always 0x0000000000000000
48-51 Int32 PointListOffset The offset relative to the 3D Object Record for the 3D Object's PointList. The position of the PointList would simply be (RecordStartPosition + PointListOffset).
52-55 Int32 NormalListOffset The offset relative to the 3D Object Record for the 3D Object's NormalList. The position of the NormalList would simply be (RecordStartPosition + NormalListOffset). There is a Normal element for each Plane element, associated by ordinal; that is to say the first Normal is associated with the first Plane.
56-59 UInt32 Unknown3 Unknown purpose.
60-63 Int32 PlaneListOffset The offset relative to the 3D Object Record for the 3D Object's PlaneList. The position of the PlaneList would simply be (RecordStartPosition + PlaneListOffset).

PointList SectionEdit

This section is a contiguous list of PointCount Point structures.

Point StructureEdit

Each Point structure is an Int32 triplet:

PointList Point Structure elements
Offset Type Description
0-3 Int32 X
4-7 Int32 Y
8-11 Int32 Z

While the PointList Section is usually adjacent to the Object Header Section, there are two files where the PointList Section begins some distance after the Object Header Section.

PlaneList SectionEdit

The PlaneList Section contains PlaneCount Plane Structure elements describing the geometry of the 3D Object Record. This includes the necessary points to describe the geometry, as well as the necessary texture information to display the object.

Each Plane Structure is described by her own header, followed by three or more PlanePoint structures.

Plane Structure elements are contiguous within the PlaneList; that is to say the second Plane Structure immediately follows the first Plane Structure.

Plane Structure HeaderEdit

Each Plane Structure is described by a header. From this data, one can load the Plane's geometry and texture file information.

The 8 byte long header is described as followed:

PlaneHeader
Offset Type Name Description
0 Int8 PlanePointCount The count of PlanePoint structures describing this Plane's geometry.
1 UInt8 Unknown1 Usually 0x00 for most plane records (about 2% are non-zero). Values range from 0x00 to 0xFF although most are repeating values in the 0x00 to 0x40 range.
2-3 UInt16 Texture This is the texture information compressed into a bitfield.
4-7 UInt32 Unkown2 Almost always 0x00000000, 0x00010000, 0x00010001, or 0x00010002 and rarely a wide range of other values. Probably two short values.

Texture StructureEdit

The Texture field in the Plane Header is a bitfield containing the FileIndex and ImageIndex fields compressed into a single UInt16. It can be interpreted as follows:

Texture Structure
Bits Type Field Decode Description
0-6 Int8 ImageIndex ( Texture & 0x7f ) The ordinal index of the image to use in the texture file described by FileIndex.
7-15 Int16 FileIndex ( Texture >> 7 ) The extension of the file to use.

Ex: If ImageIndex were 7, and FileIndex were 214, one would use the eighth image within TEXTURE.214 for the referring Plane Structure.

PlanePoint StructureEdit

Immediately following the Plane Header is a set of PlanePointCount PlanePoint structures. Each structure contains a reference to a Point entry in the Point List Section, as well as the UV coordinates.

The 8 byte structure is as follows:

PlanePoint Structure
Offset Type Name Description
0-3 Int32 PointOffset This is an offset to a Point Structure within the current 3D Object's PointList. The offset is relative to the 3D Object's PointListOffset field. No values should be negative. This field must be interpreted in context of the 3D Object's Version field.
4-5 Int16 U The texture UV's U component for the Point referenced.
6-7 Int16 V The texture UV's V component for the Point referenced.
Interpreting PointOffset
Version Calculation
2.7 PointListOffset + PointOffset
2.6 PointListOffset + PointOffset
2.5 PointListOffset + ( PointOffset * 3)

See UV Texture Coordinates for interpretting Daggerfall UV coordinate values.

NormalList SectionEdit

The NormalList is a PlaneCount set of Point structures, containing the Normals for each Plane structure. Each Point structure element within the NormalList is associated by ordinal to the corresponding Plane Structure; that is to say the first Point structure in the NormalList is the normal for the first Plane structure. Normals are normalized and scaled by 256, so a normal pointing straight down the X axis would be 256 0 0.

PlaneDataList SectionEdit

For each Plane structure, there is a corresponding PlaneData structure within the 3D Object Record's PlaneDataList, by ordinal.

The purpose of the data is currently unknown.

PlaneData Structure
Offset Type Name Description
0-23 Int8[ 24 ] Unknown Unknown purpose

ObjectDataList SectionEdit

There are ObjectDataCount elements of ObjectData Structures within the ObjectDataList. Each ObjectData structure contains zero or more 6 byte long ObjectDataValue elements. The ObjectData elements are contiguous; each immediately follows their predecessor.

Each ObjectData Structure is composed of an ObjectDataHeader Structure, and zero or more ObjectDataValue structures. The ObjectDataValue structures, if present, immediately follow the ObjectDataHeader.

ObjectData Structure HeaderEdit

ObjectDataHeader Structure
Offset Type Name Description
0-15 Int32[ 4 ] Numbers Could be a Point Structure and an Int32 magnitude, but in which order?
16-17 Int16 SubrecordCount The count of the number of ObjectDataValue Structure immediately following.


ObjectDataValueEdit

Each ObjectData Structure contains zero or more ObjectDataValue Structures. An ObjectDataValue structure appears to be a 6 byte field of an unknown purpose.

ObjectDataSubrecord Structure
Offset Type Name Description
0-5 Int8[ 6 ] Value Unknown purpose.

Special ObjectsEdit

The following list of objects (by RecordId) in the ARCH3D file have special mention:

Object 4722 (0x8B8D58)
This v2.6 3D object has a truncated, or different, ObjectDataList which does not conform with the known format.
Object 7614 (0x13274C6)
This v2.7 object has an invalid ObjectDataOffset value (it points to the middle of the PlaneDataList section).

All but 25 of the 10251 records have unique RecordId's. It is not known if the Daggerfall engine loads the first match, or the last match when two or more records collide by RecordId values.