Datasheet: Difference between revisions

From ZeldaMods (Link's Awakening)
Jump to navigation Jump to search
imported>Leoetlino
imported>Leoetlino
(→‎Field: fix Field::Type storage type)
Line 70: Line 70:
=== Field ===
=== Field ===
<syntaxhighlight lang="c++">
<syntaxhighlight lang="c++">
enum class Type : u16 {
enum class Type : u8 {
   Struct = 0,
   Struct = 0,
   Bool = 1,
   Bool = 1,

Revision as of 08:57, 13 April 2020

Datasheet
File format
Magic gsht
Endianness little
Version 1
This article is about the file format in general. For actual values, check the game RomFS.

GSHT (G?sheet) is a custom Grezzo binary serialization file format that is used to store structured, strongly typed data. GSHT documents are called datasheets.

A datasheet contains structure type information followed by arrays of structures. Optionally, one of the structure fields may be declared as a key field, in which case the contents are treated as a dictionary/mapping rather than a array.

Format

Documents are little endian and their sizes are always rounded up to be a multiple of 0x10.

Pointers are encoded as absolute offsets and relocated when the document is loaded by the game.

Header

Offset Type Description
0x0 char[4] Magic (gsht)

After pointer relocation, the magic is set to GSHT.

0x4 int Version (must be 1)
0x8 u32 ? Some kind of hash? (unused [check])
0xC u8 Bool type size (must be 1)
0xD u8 Pointer size (must be 8)
0xE u8 ?[check]
0x10 const char* Name (must be non-null)
0x18 u32 Number of root fields
0x1C u32 Number of fields in total
0x20 Value* Values
0x28 u32 Number of values
0x2C u32 Size of each value

The header is immediately followed by the root fields (a Field[num_root_fields] array).

Field

enum class Type : u8 {
  Struct = 0,
  Bool = 1,
  Int = 2,
  Float = 3,
  String = 4,
};

enum class Flag : u16 {
  IsNullable = 1 << 0,
  IsArray = 1 << 1,
  IsKey = 1 << 2,
  b3 = 1 << 3,  // unknown
  IsEnum = 1 << 4,
  b5 = 1 << 5,  // unknown
};
Offset Type Description
0x0 const char* Name (must be non-null)
0x8 const char* Type name (must be non-null)
0x10 Field::Type Type
0x11 u8 ?[check]
0x12 Field::Flag Flags
0x14 u16 Offset of this field in the value structure
0x16 u16 Size of this field in the value structure

For strings and arrays, this is always 0x10.

0x18 u16 Size of the data

For strings and inline types (inline structs, ints, floats, bools), this is the same as the size in the value structure.

0x1A u16 [For structs] Number of fields
0x20 Field* [For structs] Fields
0x28 Field* Parent (filled in during parsing; always 0xdeadbeefdeadbeef when serialized)

Fields must be properly aligned to 0x30 byte boundaries.

Key fields cannot be arrays or Nullable types.

Key fields must be of type String or Int.

Value

Combining all the root fields gives a structure (in the sense of a C or C++ structure). That structure is called a Value in this documentation.

Field data serialization
Type Serialized data format
Nullable<T> (non-strings) struct { T* data; } (nullptr if no value)
Array<T> struct { T* data; u32 size; } (aligned to 0x10 bytes[check])
Struct struct { Fields...; }
Bool bool (1-byte)
Int s32
Float f32
String struct { const char* data; u32 length; } (aligned to 0x10 bytes)

For empty strings that are Nullable, data is nullptr and length is 0. Empty strings that are not Nullable have a 0 length but still point to a null byte.

Usage in Link's Awakening

Datasheets are extensively used to configure game logic and to store miscellaneous data. They are located in rom:/region_common/datasheets and their file extension is .gsheet.

Text versions of datasheets are available in the leoetlino/la-re-notes repository on GitHub.