Final Fantasy XV

Mods

Unlocking Ansel allows to me to do things like this: https://youtu.be/sAaBgAHh7L0

Final Fantasy XV Benchmark

Disable ALSR
Memory offsets will not change if you restart the game. Useful for Cheat Engine.
Offset 486 from 96 to 32
Defeat the anti-debugger
The game normally closes when a debugger is attached. This will prevent that anti-debugging feature.
Offset 3535807 from 133 to 51
Offset 3535827 from 133 to 51
Ansel anywhere
Allows to use Nvidia Ansel anywhere: during cutscenes, loading screens and even CGI movies!
Offset 46009569 from 0 to 127

Final Fantasy XV Windows Demo

Disable ALSR
Memory offsets will not change if you restart the game. Useful for Cheat Engine.
Offset 478 from 96 to 32
Defeat the anti-debugger
The game normally closes when a debugger is attached. This will prevent that anti-debugging feature.
Offset 3707039 from 133 to 51
Offset 3707059 from 133 to 51
Ansel anywhere
Allows to use Nvidia Ansel anywhere: during cutscenes, loading screens and even CGI movies!
Offset 46234849 from 0 to 127

EXML data and scripting format

The Luminous Engine uses a data container called EXML, which is the extension of those files. An EXML is no more than a XML file serialized in binary for faster loading. Two versions of EXML exists: XMB used by Episode Duscae and Platinum Demo, XMB2 used by the complete game.

XMB: Final Fantasy XV Episode Duscae, Final Fantasy XV Platinum Demo

This format has been cracked by Xeeynamo for both reading and writing. The code can be found on GitHub.

The format is straight forward to read. You start from the RootElement, get Elements[RootElement] (that we will call e) and you can start to read the name of the root node element with Names[e.NameTableOffset] and its attributes from Attributes[AttributeTableIndex[[e.AttributeTableIndex]] to Attributes[AttributeTableIndex[[e.AttributeTableIndex + e.AttributeCount - 1]] and its child elements from Elements[ElementTableIndex[[e.ElementTableIndex]] to Elements[ElementTableIndex[[e.ElementTableIndex + e.ElementCount - 1]]. Recursively, each child element will be the new e.
Each attribute has its own value, that can be obtained using Variants[currentAttribute.VariantOffset]. The same can be said for the Element, but only when currentElement.ElementCount is 0 (leaf node). When an Element or an Attribute does not contain a value, the VariantOffset will point to a Variant[k] where its NameStringOffset points to a string with length = 0.
The described algorithm can be found in Xmb.Read.cs.

Once readed, the output looks like the following (reading ctrl_cmn_text_icon.exml): sample

Xmb.Header structure
OffsetTypeNameDescription
0x00uint32_tMagic CodeFixed to 584D 4200 (or "XMB\0")
0x04uint32_tUnusedAlways set to 0
0x08Xmb.EntryElementsA descriptor for the ElementTable
0x10Xmb.EntryAttributesA descriptor for the AttributeTable, which contains all the possible XML Attribute entries
0x18Xmb.EntryNamesA descriptor for the NameTable, where a series of null-terminated string are stored
0x20Xmb.EntryElementTableIndexesA descriptor for the ElementTableIndex, which contains indices between 0 and Elements.Count
0x28Xmb.EntryAttributeTableIndexesA descriptor for the AttributeTableIndex, which contains indices between 0 and Attributes.Count
0x30Xmb.EntryVariantsA descriptor for the VariantTable
0x38uint32_tElementRootContains an index between 0 and Elements.Count that represents the offset for the Element that acts as XML Root Node
0x3Cuint32_tUnusedAlways set to 0
0x40uint32_tUnusedAlways set to 0
0x44uint32_tUnusedAlways set to 0
0x48uint32_tUnusedAlways set to 0
Elements.OffsetXmb.ElementTable[Elements.Count]ElementTableContains all the possible XML Element entries, avoiding duplicates (up to the compiler)
Attributes.OffsetXmb.AttributeTable[Attributes.Count]AttributeTableContains all the possible XML Attribute entries, avoiding duplicates (up to the compiler)
Variants.OffsetXmb.VariantTable[Variants.Count]VariantTableContains all the possible values for both Elements and Attributes, avoiding duplicates (up to the compiler)
Names.Offsetchar[TableNames.Count]NamesData of names used from the different tables
ElementTableIndices.Offsetuint32_t[ElementTableIndices.Count]ElementTableIndex[]Contains values between 0 and Elements.Count, used to hold a list of Element for an Element node
AttributeTableIndices.Offsetuint32_t[AttributeTableIndices.Count]AttributeTableIndex[]Contains values between 0 and Attributes.Count, used to hold a list of Attribute for an Element

Xmb.Entry structure
OffsetTypeNameDescription
0x00uint32_tOffsetWhere the data is located, starting from the beginning of the file
0x04uint32_tCountThe number of items in the array

Xmb.ElementTable structure
OffsetTypeNameDescription
0x00uint64_tReservedThe game uses it to store a pointer to the parser itself. Always set to 0
0x08uint32_tAttributeTableIndexOffset to the Attribute Table, which contains an array of indices
0x0Cuint32_tAttributeCountThe number of consecutive attributes starting from AttributeTableIndex
0x10uint32_tElementTableIndexOffset to the Element Table, which contains an array of indices
0x14uint32_tElementCountThe number of consecutive attributes starting from ElementTableIndex
0x18uint32_tNameStringOffsetOffset to Name Table, starting from NameTable.Offset. Holds the name of the Element.
0x1Cuint32_tVariantOffsetOffset to Variant Table, starting from VariantTable.Offset. Gives an optional string representation for the element's value.

Xmb.AttributeTable structure
OffsetTypeNameDescription
0x00uint64_tReservedThe game uses it to store a pointer to the parser itself. Always set to 0
0x08uint32_tNameStringOffsetOffset to Name Table, starting from NameTable.Offset. Holds the name of the Attribute.
0x0Cuint32_tVariantOffsetOffset to Variant Table, starting from VariantTable.Offset. Gives an optional string representation for the attribute's value.

Xmb.VariantTable structure
OffsetTypeNameDescription
0x00ValueTypeTypeDescribes what is the value type of the entry
0x04uint32_tNameStringOffsetOffset to Name Table, starting from NameTable.Offset. Holds the name of the Attribute.
0x08byte[16]DataThe data itself; VariantTable.Type will describe how the data should be interpreted

ValueType
ValueNameDescription
1GenericCan be anything. Not quite sure on how this is used
2BoolThe value is a boolean
3SignedThe value is a int32_t, which the upper bit (little endian) is the sign flag
4UnsignedThe value is a uint32_t
5FloatThe value is a float IEEE 754
6Vector2Vector of 2 float IEEE 754 values
7Vector3Vector of 3 float IEEE 754 values
8Vector4Vector of 4 float IEEE 754 values

XMB2: Final Fantasy XV PS4 / Xbox One / Windows Edition

The structure of XMB2 is very different from XMB. AFAIK, it has not been cracked yet. I would like to work on this after completely reversing the XMB format. One of my objective is to import the asset from Episode Duscae and Platinum Demo into Final Fantasy XV Windows Edition.