neptools

Modding tools to Neptunia games
git clone https://git.neptards.moe/neptards/neptools.git
Log | Files | Refs | Submodules | README | LICENSE

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.