Skip to content

Latest commit

 

History

History
279 lines (210 loc) · 7.41 KB

ROFLFormat.adoc

File metadata and controls

279 lines (210 loc) · 7.41 KB

ROFL Format

This document could be written mainly thanks to the following projects:

Note
  • Positions and sizes are in bytes.

  • Values are in little endian.

  • Strings are NOT null-terminated.

File structure overview

Table 1. Representation of a file with 3 Chunks and 2 Keyframes

BIN Header

JSON Metadata

Payload Header

Payload

Segments headers

Segments data (encrypted)

Header Chunk 1

Header Chunk 2

Header Keyframe 1

Header Chunk 3

Header Keyframe 2

Chunk 1

Chunk 2

Keyframe 1

Chunk 3

Keyframe 2

Sections

Sections

Sections

Sections

Sections

A file’s overall structure is the following:

POS SIZE FORMAT DESCRIPTION

0

288

BIN Header

The base file Header

288

A

Base JSON

The game’s metadata for quick overviews

288+A

34+X (66)

Payload Header

The game’s binary information header

322+A+X

? (until EOF)

Payload

The actual game data

BIN Header

Start at position 0 in file

POS SIZE FORMAT DESCRIPTION

0

4

RIOT

Magic constant string

4

2

?

constant 0 bytes with unknown usage, part of magic ?

6

256

HEX

Data signature

262

2

u16

BIN Header size

264

4

u32

File size

268

4

u32

JSON Metadata offset from file start

272

4

u32

JSON Metadata size

276

4

u32

Payload header offset from file start

280

4

u32

Payload header size

284

4

u32

Payload offset from payload header start

JSON Metadata

The JSON Metadata section is an UTF-8 JSON String that contains metadata on the game. Note that most actual information is in the statsjson json string attribute.

Caution
The String is NOT null-terminated
Table 2. Base JSON attributes
KEY FORMAT DESCRIPTION

.gameLength

Integer

Game duration in milliseconds

.gameVersion

String

Patch version the game was played with

.lastGameChunkId

Integer

Last chunk’s ID

.lastKeyFrameId

Integer

Last keyframe’s ID

.statsJson

String

Stringified JSON statistics on the game to parse before use

Table 3. Stats JSON attributes
KEY FORMAT DESCRIPTION

Payload Header

The header’s position is provided in the BIN header

POS SIZE FORMAT DESCRIPTION

0

8

u64

Match ID

8

4

u32

Match duration in ms

12

4

u32

Keyframes count

16

4

u32

Chunk count

20

4

u32

Last chunk’s ID

24

4

u32

First chunk’s ID

28

4

u32

Keyframe interval

32

2

u16

Encryption key length

34

X

String

Encryption key (current length is always 32 bytes)

Payload

Hereafter, we use Segment to talk about a data range that may either be a Chunk or a Keyframe.

The payload’s position is provided in the BIN header. The payload runs until EOF and each of its data segment is encrypted with the encryption key.

POS SIZE FORMAT DESCRIPTION

0

17*n

Segment Header

Segment Headers (n is the total number of segments)

17*n

?

Chunk/Keyframe

Encrypted Segments whose size and position relative to the header list’s end is provided in the segment header

Payload Segment Header

The payload starts with chunk count + keyframe count Segment headers whose structure is the following :

POS SIZE FORMAT DESCRIPTION

0

4

u32

Segment ID

4

1

u8

Segment type (Chunk = 1, Keyframe = 2)

5

4

u32

Segment data Length

9

4

u32

Associated Chunk ID (Keyframes only, is 0 with chunks)

13

4

u32

Segment data offset (from end of segment headers)

Segment data

Note

From here, all information is speculative and needs to be verified before usage.

Any game update may invalidate this information

Payload data’s sub-sections are split in two parts :

  • One header section

  • One data section whose length is provided in the section header

Decryption

To read a segment, get the Encryption Key and the game’s ID as a string as well as the segment’s data, then:

  • Base64 decode the encryption key string

  • Use Blowfish to decrypt the decoded encryption key with the game ID string as the key (and remove the padding whose length is provided in the last byte of the decrypted data)

  • Use Blowfish to decrypt the segment data with the decrypted encryption key (and remove the padding whose length is provided in the last byte of the decrypted data)

  • Use Gzip to unpack the decrypted segment data

Pseudocode
### Variables
# game_id = "5000000000"
# encryption_key = "Ezyoyu7dqcDbGXsVV6Vg1vAkiuFuirFD"
# segment_encrypted_data = [...]
### Functions
# byte[] blowfish_decrypt(byte encrypted_data[], byte key[], bool remove_padding)
# byte[] gunzip(byte compressed_data[])

raw_encryption_key = base64_decode(encryption_key)
chunk_key = blowfish_decrypt(raw_encryption_key, game_id, true)
segment_zipped_data = blowfish_decrypt(segment_encrypted_data, chunk_key, true)
segment_data = gunzip(segment_zipped_data)

Payload segment sections map

Each section of a segment’s data has a varying-size header determined by its first byte and an optional varying-size data section.

Table 4. Section header+data short view

Configuration byte (1 byte)

Game time (1/4 bytes)

Data Length (1/4 bytes)

Type (2 bytes ?)

Parameters (1/4 bytes)

Data (? bytes)

Table 5. Types map
ID Loading Chunk Loading Keyframe Game Chunk Game Keyframe Note

1

X

X

TODO

Segment’s data structure

Table 6. Section header+data extended view
POS SIZE FORMAT DESCRIPTION

0

1

u8

Header configuration byte H

1

4 if H & 0x80 == 0, else 1

f32 else u8

Game time, either absolute (f32, in s) or relative to last section (u8, in ms)

Varying

4 if H & 0x10 == 0, else 1

u8 else u32

Section’s data’s length

Varying

2 if H & 0x40 == 0, else 0

u16 else None

Section’s data’s type (equals last section’s type if absent)

Varying

4 if H & 0x20 == 0, else 1

u32 else u8

Section’s type’s parameters

Varying

?

Variable

Section’s data

Sections tables

Interaction Pings

Current version: ID = 397 [141,1]

Table 7. Generic ping (len = 15)

POS

SIZE

FORMAT

DESCRIPTION

0

2

?

Ping config ?

2

4

f32

Ping position X

6

4

f32

Ping position Y

10

?

?

Inject specifics here

END

5

?

= [246, 176, 176, 176, 112] (Player ID (4 bytes) + specifier ?)

Table 8. Untargeted pings (1 specific byte)

POS

SIZE

FORMAT

DESCRIPTION

0

1

u8

Ping type ID

Table 9. Unit ping (5 specific bytes)

POS

SIZE

FORMAT

DESCRIPTION

0

1

u8

Ping type ID

1

4

u32

Target unit’s ID

Information ping

Information pings are pings performed from the TAB menu

Table 10. Information ping

POS

SIZE

FORMAT

DESCRIPTION

Targetting pings

Information pings are pings used to target neutral objectives such as gromp , herald, drake, …​

Table 11. Item shop ping

POS

SIZE

FORMAT

DESCRIPTION

Table 12. Ping IDs

ID

Ping