Save file format (ASE)

From ARK Wiki
Jump to navigation Jump to search

This page documents the custom save file format used by ARK: Survival Evolved in .ark files, and is intended for anyone who wants to learn or wants to read the save files directly. The .ark files contain the current world state, including creatures, inventories, items, built structures, and foliage state. It is a binary file with multiple segments, and there are currently eleven versions of the format numbered 1 through 11. This page focuses on version 9.

To understand all of this you need a basic knowledge of binary files, and a basic understanding of number representations in memory (floating point numbers, integers, etc.).

The basic flow to read the data of the Ark save file is as follows:

Segments

File header

The header is located right at the start of the file, and contains information such as segment addresses, save count and total play time.

How the file header looks on a version 9 file
Name Type Length Description
File version int16 2 bytes The save file version number.
Binary Data Offset int32 4 bytes This is the file offset in which the Embedded Binary Data starts
Unknown int32 4 bytes This seems to be unused data (all test read 0)
Name Table Offset int32 4 bytes This is the offset at which the name table begins.
Object data segment offset int32 4 bytes This is the offset at which serialised object data (properties) begins.
Game time float 4 bytes This section stores the in-game time.
Save count int32 4 bytes This section stores how many times the file has been saved

Binary Data Names Object

To read this table you need to read the String Data into the Object as many times as it was specified on the Array Length

Name Type Length Description
Array length Int32 2 bytes This tells us how many Strings are contained in this Array
String Data String Unknown bytes The size of these objects is unknown as data is read on the fly

Name table

Concept

"Names" are a concept in Unreal Engine, which (within the engine) allows for efficient string comparisons (only indexes or hashes (calculated internally) need to be compared instead of the entire string) and lower memory usage around highly reoccurring text. Names are composed of two pieces:

  • A central string table (which this segment is), which in a binary file is specific to the file and merged into a global one shared by all objects in the engine at runtime;
  • And references to that table, which consist of an int32 table index and a int32 instance number.

A non-zero instance number is appended (decremented by one) to the string preceded by a single underscore.

A common "use case" for names are object and asset names, paths, property names and types, and other strings which may appear often.

Serialised format

This segment begins at the offset found in the header.

Name Type Length Description
Array length int32 4 bytes This tells us how many strings are contained within the table.
Entries string[] Null-terminated sequence of strings, the number of which is determined by the fore-mentioned array length field.

Embeded Binary Data Object

The use of this data is unknown, we will read an array of arrays, containing Int32 numbers. First we will read the Array Length and do a loop that many times, on each of these loops we will:

Read the next 4 bytes as Int32 and loop that many times reading each time another Int32 value into the SubArray.

Name Type Length Description
Array Length Int32 4 bytes This tells us how many Arrays are contained in this Array
SubArray Length Int32 4 bytes This tells us how many Strings are contained in this Array
Int32 Data Int32 SubArray Length * 4 bytes Int32 numbers on the array

Unknown Data Object

This is some unknown data object, we need to read it correctly in case Ark uses it at some point

Name Type Length Description
Array Length Int32 4 bytes This tells us how many Arrays are contained in this Array
Unknown Number Int32 4 bytes This is an unknown number which appears to be some kind of flags
Unknown Object Count Int32 4 bytes This is an unknown number which appears to tells us an object count
String Data String Unknown bytes Some Unknown String Data

Object metadata table

This is the primary segment that acts as an index of all game world objects contained within the file.

Name Type Length Description
Array length Int32 4 bytes This tells us how many entries are within this table.
Entries
Name Type Length Description
GUID uint8[16] 16 bytes The GUID (globally unique identifier) of the object. It is, however, not guaranteed to be unique.
Class name Name 8 bytes The name of the class this object is an instance of.

Noted be, that this is only the class name and not a full path. ARK does not store any more information about the object's type.

Is item? bool 4 bytes This defines if the object is an item
Class Names Array Length Int32 4 Bytes The amount of Ark Class Objects contained on this array
Class Name Ark Class Object 8 Bytes This data Repeats itself the Amount specified in Class Names Array Length
From Data file Boolean Object 4 Bytes A boolean that tells if it's from Data File (Unknown meaning)
Data File Index Int32 4 Bytes The Index of the Data file (Unknown meaning)
Location Data Available Boolean Object 4 Bytes This specifies if there's location data available, only if this is true the Next 24 bytes exist, otherwise the information does not exist and should be skipped
Position Data Location Data Object 24 Bytes This data is only available if the previous Location Data Available was true, otherwise we should skip reading these 24 bytes.
Data offset Int32 4 Bytes This tells us the Offset of the Properties on which to start reading the properties of the object.
Unknown Integer Int32 4 Bytes Unknown integer which appeaars to always be 0 (It may be simply a 4 byte long NUL)

Properties Object

This is one of the most "fun" parts to read data from. To create this object we will fill it with an array of the objects we read from the file, first we need to sum the Ark File Header Object's Properties Block Offset with the Game Object's Properties Offset and begin reading from there, until we reach a Class Name named "None"

Name Type Length Description
Class Name Ark Class Object 8 Bytes Class name of the property if the Result is "None" we need to stop reading at the end of this property.
Properties Content Property Object Unknown Bytes If the Previous Class Name was not "None" then we begin to read the contents of the property accordingly
Unknown Integer Int32 4 Bytes Unknown integer which appeaars to always be 0 (It may be simply a 4 byte long NUL)
Extra Data Extra Data Object Unknown Bytes Sometimes there's extra data at the end of the properties, you should save this data because it may contain important information.

Property Object

After reading the property's Class Name you need to read the data according to it's classification:

BoolProperty Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value PropertyBoolean 1 Bytes The boolean Value

ByteProperty Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read, Funny enough this sometimes does not tell us the exact size of bytes to read.
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value UInt8 Or Ark Class Object Or Raw Bytes 1, 8 or Unknown Bytes If Length is 1 read as UInt8, If Length is 8 then Read as a Ark Class Object followed with a value of another Ark Class Object, If the Length is different read as Raw Bytes.

FloatProperty Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value Float 4 Bytes The Float Value

DoubleProperty Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value Double 8 Bytes The Double Value

IntProperty Object

This is read the same as Int32Property Object

Int8Property Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value Int8 1 Byte The Signed Int8 Value

UInt8Property Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value UInt8 1 Byte The Unsigned UInt8 Value

Int16Property Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value Int16 2 Bytes The Signed Int16 Value

UInt16Property Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value UInt16 2 Bytes The Unsigned UInt16 Value

Int32Property Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value Int32 4 Bytes The Signed Int32 Value

UInt32Property Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value UInt32 4 Bytes The Unsigned UInt32 Value

Int64Property Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value Int64 8 Bytes The Signed Int64 Value

UInt64Property Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value UInt64 8 Bytes The Unsigned UInt64 Value

NameProperty Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
Value Ark Class Object 8 Bytes The Ark Class Name Object

ObjectProperty Object

Name Type Length Description
Length Int32 4 Bytes Length in bytes of the data to read
Index Int32 4 Bytes Index of the data read (Used on some properties that repeat themselves multiple times)
ID Int32 4 Bytes This is an ID of some sort (Unknown use)
Value Int32 Or Ark Class Object 4 or 8 Bytes If the Length is 8 then Read the Int32 value, if it's 12 read the Ark Class Object as Value

StructProperty Object

ArrayProperty Object

PropertyText Object

StrProperty Object

Ark Class Object

When reading an Ark Class Object you need to read always 8 bytes, and when an index is defined (more than 0) you need to append that index at the name of the class, so if you have your Name Table Object and in position #72 you have PrimalItem_WeaponEmptyCryopod_C (Note: There's no position 0 on the Name Table Object) it means that if your index = 1 you need to append _0 at the end making it PrimalItem_WeaponEmptyCryopod_C_0 and if your index=135 then you need to append _134.

Name Type Length Description
ID Int32 4 Bytes The corresponding ID on Name Table Object
Index Int32 4 Bytes The index of this Name, the game takes the Names and represents them with a _INDEX at the end, if this number is 0 we do not append a _0 to the name, we leave the original name as is, if we find a 1 or more in this value we need to start counting from 0, which means that Index=1 is Append=_0

Data Types

Below are the data types and how to read them accordingly.

String

Name Type Length Description
String Length Int32 4 bytes This tells us how many bytes to read
String Data String String Length bytes Read this data as a string, keep in mind the last character will be a 0x00 NUL character.

Bool

Read 32Bit (4 Byte) In which the least significant bit indicates true

Double

Read 64Bit (8 Byte) Double Number

Float

Read 32Bit (4 Byte) Float Number

Int8

Read 8Bit (1 Byte) Signed Integer

UInt8

Read 8Bit (1 Byte) Unsigned Integer

Int16

Read 16Bit (2 Byte) Signed Integer

UInt16

Read 16Bit (2 Byte) Unsigned Integer

Int32

Read 32Bit (4 Byte) Signed Integer

UInt32

Read 32Bit (4 Byte) Unsigned Integer

Int64

Read 64Bit (8 Byte) Signed Integer

UInt64

Read 64Bit (8 Byte) Unsigned Integer

PropertyBoolean

Read 8Bit (1 Byte) In which the least significant bit indicates true.