gbin.md (3522B)
1 GBIN and GSTR 2 ============= 3 4 GBIN (stored inside `.gbin` files in SYSTEM/database, and inside `.cl3`s) and 5 GSTR (stored in `.gstr` files in SYSTEM/database) are quite similar. All 6 integers are little-endian. 7 8 The sections described below (Header/Footer, Type descriptor, Struct and String 9 table) are aligned to 16 bytes in GBIN, but unaligned in GSTR... 10 11 Header/Footer 12 ------------- 13 14 ```c++ 15 struct HeaderFooter 16 { 17 char magic[3]; 18 char endian; 19 uint16_t field_04; // always 1 20 uint16_t field_06; // always 0 21 uint32_t field_08; // always 16 22 uint32_t field_0c; // always 4 23 uint32_t flags; 24 uint32_t struct_offset; 25 uint32_t struct_count; 26 uint32_t struct_size; 27 uint32_t types_count; 28 uint32_t types_offset; 29 uint32_t field_28; // ?? 30 uint32_t string_offset; 31 uint32_t field_30; // 0 or 4 32 uint32_t padding[3]; // always 0 33 }; 34 sizeof(HeaderFooter) == 0x40 35 ``` 36 37 In GSTR the above struct is a header, at the beginning of the file, magic string 38 is `GST`. In GBIN it's a footer (so it starts at `EOF-sizeof(HeaderFooter)`), 39 and the magic is `GBN`... Endian is denoted by `endian`, if `L` means 40 little-endian and `B` means big-endian. 41 42 `flags` is 1 if there's any string stored in the file (see Type descriptor 43 below), 0 otherwise. `struct_offset` is 0 in GBIN and 0x40 in GSTR files (but 44 other values should work too). Offsets are relative to the beginning of the 45 file. 46 47 Type descriptor 48 --------------- 49 50 This file contains a list of some structure. However the structure is actually 51 defined inside the file, so you can figure out the types of each fields. 52 53 ```c++ 54 struct TypeDescriptor 55 { 56 uint16_t type; 57 uint16_t offset; 58 }; 59 sizeof(TypeDescriptor) == 4; 60 ``` 61 62 They start at `header.types_offset`, and there's `header.types_count` of them. 63 They're sorted into ascending order by `offset`. Each entry describes a field 64 inside the struct, `offset` is an offset from the beginning of the struct. The 65 valid values for `type` are: 66 67 ```c++ 68 enum Type 69 { 70 UINT32 = 0, 71 UINT8 = 1, 72 UINT16 = 2, 73 FLOAT = 3, 74 STRING = 5, 75 }; 76 ``` 77 78 `UINT16`, and `UINT32` are standard 16 bit and 32 bit integers (not sure if 79 they're signed or unsigned though, probably the format makes no difference 80 between them), `FLOAT` is a standard 32 bit float (as used by x86 CPUs). 81 82 `UINT8` is a bit special: it's normally a single byte, but can also mean a fixed 83 length zero terminated string. They both end up as `type=1`. This editor 84 currently uses a heuristic: if the offset of the next entry is this entry's 85 offset + 1 (taking aligning into account), it's probably a single byte, 86 otherwise a fixed length string. 87 88 `STRING` is a 32 bit integer, an offset into the string table. Sometimes it'll 89 be -1 (0xffffffff), that's an invalid string (maybe NULL pointer originally?). 90 91 The fields are aligned: `UINT32`, `FLOAT` and `STRING` are aligned to 4 bytes 92 and `UINT16` to 2 bytes. 93 94 Struct 95 ------ 96 97 The structs start at `header.struct_offset` and there are `header.struct_count` 98 of them. Every struct is `header.struct_size` bytes length, the fields are 99 described by the type descriptor. 100 101 102 String table 103 ------------ 104 105 This is optional, it only exists if `header.flags == 1`. It starts at 106 `header.string_offset`. Each contains a bunch of zero terminated strings 107 sequentially, and referenced inside `STRING` type fields. 108 109 There's an optimization in the original files: if the same string appears 110 multiple times, it's only stored once in the table, the identical `STRING` 111 fields will get the same offset.