Skip to content
This repository has been archived by the owner on May 23, 2022. It is now read-only.

File Format Documentation

Arves100 edited this page Nov 9, 2020 · 10 revisions

File Format Specification

Notes

  • Library used: Granny 2.1.0.3, Granny 2.4.0.10 (Metin2)
  • Target File Format: 6
  • The CRC32 is stored in Big Endian, and it should be from the beginning of Sector 0 to all the file (It should not include Header and File Information)

Header (32 bytes)

struct Header {
	uint32_t magic[4];
	uint32_t size;        // Size of the header
	uint32_t format;      // Seems always 0
	uint32_t reserved[2]; // Seems always 0
};

If the magic matches "B8 67 B0 CA F8 6D B1 0F 84 72 8C 7E 5E 19 00 1E", the file is in Little Endian. If the magic matches "CA B0 67 B8 0F B1 6D F8 7E 8C 72 84 1E 00 19 E5" (each 4 bytes are swapped) then the file is in Big Endian.

Format must be 0 otherwise the file is threated as unregonized.

The next 8 bytes are unknown.

File Information

First 4 bytes is the File Format version.

Next 4 bytes tells us the total file size.

The next 4 bytes tells us the CRC32, which is Big endian. CRC is computed from the end of the file to the header size?

Next 4 byte is the Header size.

The next 4 bytes is the Sector count.

The next 8 bytes are a reference for something.

Same the next 8 bytes are a reference for something.

Next 4 bytes is the Tag, which might be used to tell specific information of the GR2 file or the version. All the tags starts from 0x8000000. If the tag is 0x800000F then the file is invalid!

Next 16 bytes: ?

In file format 7, there are 16 extra unknown bytes.

Sector information

struct Section_header {
	uint32_t compression; // 0: no compression, 1: Oodle0, 2: Oodle1
	uint32_t data_offset; // From the start of the file
	uint32_t data_size;   // In bytes
	uint32_t decompressed_size; // In bytes
	uint32_t alignment;         // Seems always 4
	uint32_t first16bit;        // Stop0 for Oodle1
	uint32_t first8bit;         // Stop1 for Oodle1
	uint32_t relocations_offset;
	uint32_t relocations_count;
	uint32_t marshallings_offset;
	uint32_t marshallings_count;
};

Compression types:

  • 0 = No compression
  • 1 = Oodlee 0
  • 2 = Oodlee 1
  • 3 = Bitknit
  • 4 = Bitknit 2

(Relocations are called Fixup in Granny2)

Reference data

4 byte the sector number.

4 bytes the position of the data in the sector.

Fixup data

4 byte an offset.

4 byte the sector to apply.

4 byte an offset.

It seems that it apply something to the sector specified in the structure, but it's unknown what this function precicely does

Marshall data

4 unknown bytes

4 byte an offset

4 byte the sector to apply

4 byte an offset

It seems that it apply something to the sector specified in the structure, but it's unknown what this function precicely does, it's only applied when the Header file is Big Endian but the sectors are Little Endian. (Which theorically, it can't happen on a BE file, unless compression magic)