# C4Group Dateispezifikation

**URL:** https://forum.clonkspot.org/t/c4group-dateispezifikation/1422
**Category:** Hilfestellung
**Created:** [5. November 2020 um 22:45 UTC](https://forum.clonkspot.org/t/c4group-dateispezifikation/1422 "2020-11-05T22:45:33Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![Funni](https://forum.clonkspot.org/user_avatar/forum.clonkspot.org/funni/32/74_2.png) [@Funni](https://forum.clonkspot.org/u/Funni)
#### Post date: [5. November 2020 um 22:45 UTC](https://forum.clonkspot.org/t/c4group-dateispezifikation/1422/1 "2020-11-05T22:45:33Z")

</div>

Nachfolgend die Spezifikation für C4Group-Dateien. Das Original ist [hier](https://web.archive.org/web/20170920201255/https://wiki.nosebud.de/wiki/C4Group) 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](https://web.archive.org/web/20170920201255/https://wiki.nosebud.de/wiki/Szenario) (c4s), [Rundenordner](https://web.archive.org/web/20170920201255/https://wiki.nosebud.de/wiki/Rundenordner) (c4f), [Objektdefinitionen](https://web.archive.org/web/20170920201255/https://wiki.nosebud.de/wiki/Objektdefinition) (c4d) usw.

Gruppendateien können im Entwicklermodus des [Menüsystems](https://web.archive.org/web/20170920201255/https://wiki.nosebud.de/wiki/Frontend) 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:

```auto
for position = 0 to Datenlänge - 2 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#

> ****
>
> ```cs
> 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

> ****
>
> ```auto
> 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

> ****
>
> ```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

> ****
>
> ```php
> /**
> * 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

> ****
>
> ```javascript
> 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](https://en.wikipedia.org/wiki/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](https://en.wikipedia.org/wiki/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.**
