header YouTube
Clonk Livestream auf Twitch.tv!

Clonkspot

C4Group Dateispezifikation

Nachfolgend die Spezifikation für C4Group-Dateien. Die Kopie des Originals ist hier zu finden, damit aber eine Weiterentwicklung der Dokumentation möglich ist, schreibe ich das hier noch einmal nieder.


C4Group ist der Name des Gruppendatei-Formats, in dem die Spieldaten von Clonk gepackt sind, also Szenarien (c4s), Rundenordner (c4f), Objektdefinitionen (c4d) usw.

Gruppendateien können im Entwicklermodus des Menüsystems geöffnet, bearbeitet, entpackt und gepackt oder zerlegt werden.

Aufbau

C4Group-Dateien haben folgenden Aufbau:
  • GZIP-Header (mit geänderten Magic Bytes 0x1e und 0x8c)
  • Deflate-komprimierter Datenbereich.
  • GZIP-Footer (CRC32 und unkomprimierte Länge)

Header

Der Datenbereich beginnt mit dem 204 Byte langen Header des Hauptordners (root) der Gruppendatei. Jeder Ordner innerhalb einer Gruppendatei beginnt mit seinem Header, der Informationen über ihn liefert. Er ist auf folgende Weise verschlüsselt:
for position = 0 to Datenlänge - 1 step 3
    Vertausche(puffer[position], puffer[position + 2])
next
for position = 0 to Datenlänge - 1
    puffer[position] = puffer[position] xor 0xED
next

Beispielimplementierungen Verschlüsselung

In C#

void MemScramble(byte[] buffer)
{
	int i;
	byte tmp;
	for (i = 0; i < buffer.Length; i++)
		buffer[i] ^= 237;
	for (i = 0; (i + 2) < buffer.Length; i += 3)
	{
		tmp = buffer[i];
		buffer[i] = buffer[i + 2];
		buffer[i + 2] = tmp;
	}
}

In C

void mem_scramble(char* data, unsigned int length) {
   for(char* ptr = data; ptr < data + length; ptr += 3) {
       char tmp = *ptr; *ptr = *(ptr + 2) ^ 0xED; *(ptr + 2) = tmp ^ 0xED;
       *(ptr + 1) ^= 0xED;
   }
   for(unsigned int i = length % 3; i>0; i--)
       data[length - i] ^= 0xED;
}

In Python

def mem_scramble(data : bytes) -> bytes:
    data = bytearray(data)
    i = 0
    while (i + 2) < len(data):
        data[i], data[i + 2] = data[i + 2], data[i]
        i += 3
    i = 0
    while i < len(data):
        data[i] = data[i] ^ 0xED
        i += 1
    return bytes(data)

In PHP5

/**
 * Decrypts the group header
 * @param $data
 */
function memScramble(array &$data) {
    for($i = 0; $i < count($data); $i++) {
        $data[$i] ^= 237;
    }
    for($i = 0; ($i + 2) < count($data); $i += 3) {
        $tmp = $data[$i];
        $data[$i] = $data[$i + 2];
        $data[$i + 2] = $tmp;
    }
}

In Node.js

let memScramble = function(chunk) {
    for(let i = 0; i < chunk.length; i += 3) {
        [chunk[i], chunk[i + 2]] = [chunk[i+2], chunk[i]];
    }
    for(let i = 0; i < chunk.length; i++) {
        chunk[i] ^= 0xED;
    }
}

Aufbau des Headers

Offset (in Bytes) Größe (in Bytes) Datentyp Beschreibung (Clonk Rage) Beschreibung (OpenClonk) Beschreibung (LegacyClonk)
0 25 String Muss RedWolf Design GrpFolder sein.
25 3 - Reserviert
28 4 Integer Versionsnummer 1. Muss 1 sein.
32 4 Integer Versionsnummer 2. Muss 2 sein.
36 4 Integer Anzahl der Unterordner und Dateien.
40 32 String Name des Autors. Reserviert
72 32 - Reserviert Reserviert
104 4 time_t (Integer) Erstellungsdatum Reserviert
108 4 Integer 1234567 falls die Gruppe ein Originalpaket ist, oder ein beliebiger anderer Wert andernfalls. Reserviert
112 92 - Reserviert Reserviert

Aufbau des Inhaltsverzeichnisses

Offset (in Bytes) Größe (in Bytes) Datentyp Beschreibung (Clonk Rage) Beschreibung (OpenClonk) Beschreibung (LegacyClonk)
0 257 String Dateiname
257 3 - Reserviert
260 4 Integer Gibt an, ob die Datei gepackt ist. Sollte 1 sein. Reserviert
264 4 Boolean 0 wenn der Eintrag eine Datei ist, 1 wenn es sich um einen Ordner handelt.
268 4 Integer Dateigröße
272 4 - Reserviert
276 4 Integer Abstand des Dateiinhalts vom Ende des Inhaltsverzeichnisses.
280 4 time_t (Integer) Datum der letzten Modifikation. Reserviert
284 1 Byte 0: Keine Prüfsumme vorhanden.
1: Prüfsumme des Dateiinhalts.
2: Prüfsumme über Dateiinhalt und Dateiname.
285 4 Unsigned Integer CRC32-Prüfsumme.
289 1 Byte Gibt an ob die Datei ausführbar ist. (Wird nur unter Linux benötigt)
0: Nicht ausführbar
1-255: Ausführbar
290 26 - Reserviert

Hiernach folgt der Deflate-komprimierte Datenbereich.

Nachteile

C4Group ist ein progressiv komprimiertes Format, d.h. wenn eine Datei entpackt werden soll, muss die C4Group-Datei vom Anfang bis zu der angefragten Datei entpackt werden. Dadurch werden auch nicht benötigte Dateien entpackt, die dann wieder verworfen werden. Außerdem muss die C4Group-Datei jedesmal zurück an den Anfang springen, wenn eine Datei angefragt wird, die vor der aktuellen Leseposition liegt.

Changelog

Datum Art der Änderung Änderung
1998-05-30T00:00:00Z added C4Group new magic (load old/new, save new), file version 1.2.
1998-12-22T00:00:00Z added C4Group creation stamp
1999-05-23T00:00:00Z added C4Group::EntryTime
2004-03-28T00:00:00Z added Automatic contents checksum creation and caching.
2006-05-13T00:00:00Z changed C4Group: use file names for crc, too.
2006-07-25T00:00:00Z changed C4Group: Calc new-style CRC32 of entries using entry filename instead of group filename.

PS: Dies ist ein Wikipost. Damit ist jedem angemeldeten Nutzer das Bearbeiten dieses Posts möglich.