Settlers 2:Next Generation (Finished)
-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Settlers 2:Next Generation (Finished)
I could need some help with the files of The Settlers 2:Next Generation. It doesn't seem to be archives, so I don't know if this is the right forum.
The devs seem to use compression/encryption on each file.
I've attached 2 of them. One must be a normal texture, the other one the credits text. The files always start with this ...rc00 header, but the rest is different.
Can somebody help me? Is this any known compression/encryption algorithm or is it own code?
A german demo is available here:
http://www.giga.de/tv/gigagamespc/00132 ... er_2_demo/
EDIT: Get some decryption code below.
The devs seem to use compression/encryption on each file.
I've attached 2 of them. One must be a normal texture, the other one the credits text. The files always start with this ...rc00 header, but the rest is different.
Can somebody help me? Is this any known compression/encryption algorithm or is it own code?
A german demo is available here:
http://www.giga.de/tv/gigagamespc/00132 ... er_2_demo/
EDIT: Get some decryption code below.
You do not have the required permissions to view the files attached to this post.
Last edited by Rheini on Mon Jun 11, 2007 6:32 pm, edited 1 time in total.
-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
The international version of this game seems to be called Settlers 2: 10th Anniversary.
A demo can be found here: http://www.3dgamers.com/games/settlers2ng/downloads/
A demo can be found here: http://www.3dgamers.com/games/settlers2ng/downloads/
- Deniz Oezmen
- VIP member

- Posts: 185
- Joined: Mon Aug 28, 2006 2:07 pm
- Has thanked: 1 time
- Been thanked: 14 times
- Contact:
-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Here is a code snippet with the most important parts of my quick n dirty tool written in D. Please PM me if you make any optimizations.
Comments and variable names are in German (Learn it or die tryin'
)
The entry point for code analysis is the Entpacken function at the end.
Comments and variable names are in German (Learn it or die tryin'
The entry point for code analysis is the Entpacken function at the end.
Code: Select all
private ubyte[] puffer; /// Hauptpuffer für die Dateidaten
private ubyte[16] basis; /// der 16-Byte Basiswert für pwcrc
/// Die Kopfstruktur einer Siedler2-Datei
struct Kopf {
uint uk; /// seems to belong to the header
uint fcc; /// header
uint datacrc; /// crc32 checksum of decompressed data
uint pwcrc; /// tricky checksum
uint datasize; /// decompressed data size
}
/**
* Ver- oder Entschlüsseln
* Params:
* puffer = Ein- und Ausgabepuffer
*/
void Schlüsseln(ubyte[] puffer)
{
uint x = kopf.pwcrc; // Startwert
BerechneStartwert(x);
Verschlüsselungsfunktion(x); // einmal initial durchlaufen
uint xorgröße = (x & 0x7F) + 0x80; // das ist die Größe des XOR-Schlüssels
byte[256] xorpuffer;
for(int i=0; i<xorgröße; i++)
{
Verschlüsselungsfunktion(x);
xorpuffer[i] = x & 0xFF;
}
for(int i=0; i<puffer.length; i++)
{
puffer[i] = puffer[i] ^ xorpuffer[i%xorgröße];
}
// -----hier beginnt zweite Stufe----
Verschlüsselungsfunktion(x);
xorgröße = ((x & 0x1F) | 0x10) + 1;
for(uint i=0; i<xorgröße; i++)
{
Verschlüsselungsfunktion(x);
xorpuffer[i] = x & 0xFF;
}
Verschlüsselungsfunktion(x);
uint offset = x % puffer.length; // Offset des falschen Bytes im Datenpuffer
Verschlüsselungsfunktion(x);
uint abstand = (x & 0x3FFF) | 0x2000;
for(uint i=offset; i<puffer.length; i+=abstand)
{
puffer[i] ^= xorpuffer[(basis[i % 16] ^ i) % xorgröße];
}
}
/// den 16er Basiswert intialisieren
void InitialisiereBasiswert()
{
this.basis[] = cast(ubyte[]) [0xC9, 0x59, 0x46, 0xCA, 0xD9, 0xF0, 0x4F, 0x0A, 0xA1, 0x00, 0xAA, 0xB8, 0xCB, 0xE8, 0xDB, 0x6B];
}
/**
* berechnet den pwcrc-Wert
*
* muss vor Schlüsseln() aufgerufen werden
* übergeben wird der Dateiname
*/
uint BerechnePwCRC(string dateiname)
{
uint x = crc32(cast(ubyte[])dateiname); // Startwert für die x-Variable
BerechneStartwert(x);
for (uint i=0; i<16; i++)
{
Verschlüsselungsfunktion(x);
basis[i] ^= x & 0xFF;
}
return crc32(basis);
}
/// Berechnet den Startwert der x-Variable
void BerechneStartwert(inout uint x)
{
uint[32] puffer = [12u, 0x17, 0x0A, 0x19, 0x08, 0x1B, 0x06, 0x1D, 0x04, 0x1E, 0x01, 0x16, 0x09, 0x0D, 0x15, 0x00,
0x11, 0x1A, 0x05, 0x0F, 0x12, 0x1C, 0x0B, 0x02, 0x0E, 0x03, 0x18, 0x07, 0x13, 0x10, 0x14, 0x1F];
uint ecx=0;
uint edi=0;
uint edx;
x &= 0x7FFFFFFF;
do
{
edx = 1;
edx <<= ecx & 0xFF;
if (x & edx) // != 0
edi++;
ecx++;
} while(ecx < 0x1F);
if (edi < 8)
{
uint esi = 8;
esi -= edi;
edx =0;
if (esi != 0)
{
uint ebp; // ebp ist nur lokal hier, ist richtig so
do
{
ecx = puffer[edx];
ebp = 1 << (ecx & 0xFF);
x |= ebp;
edx++;
} while(edx < esi);
}
}
if (edi > 24)
{
uint esi = 32;
esi -= edi;
edx = 0;
if (esi != 0)
{
do
{
ecx = puffer[edx];
edi = 1 << (ecx & 0xFF);
edi ^= 0xFFFFFFFF;
x &= edi;
edx++;
} while(edx < esi);
}
}
if (x == 0)
x = 1;
else
x &= 0x7FFFFFFF;
}
/// Hilfsfunktion zu Schlüsseln()
void Verschlüsselungsfunktion(inout uint x)
{
uint oben = (x >> 16) * 0x41A7; // 41A7=16807
uint unten = (x & 0x0FFFF) * 0x41A7;
x = ((oben & 0x7FFF) << 16) + unten;
if (x > 0x7FFFFFFF)
x = (x & 0x7FFFFFFF) + 1;
x += oben >> 15;
if (x > 0x7FFFFFFF)
x = (x & 0x7FFFFFFF) + 1;
}
///
int Entpacken(string dateiname)
{
if (Lesen(dateiname))
return 1;
// Dateinamen herausfiltern
uint index = std.string.rfind(dateiname, cast(dchar) '\\');
if (index != -1)
{
dateiname = dateiname[index+1 .. dateiname.length];
}
InitialisiereBasiswert();
if (dateiname[dateiname.length-3 .. dateiname.length] != "s2m")
{
dateiname = std.string.tolower(dateiname);
if (BerechnePwCRC(dateiname) != kopf.pwcrc)
{
writef("Prüfsumme stimmt nicht überein!\n");
return 2;
}
}
Schlüsseln(puffer); //decrypt
ubyte[] AusPuf;
AusPuf.length = kopf.datasize;
Dekomprimieren(puffer, AusPuf); // LZSS
if (crc32(AusPuf) != kopf.datacrc)
{
writef("crc fehlgeschlagen!\n");
}
// Entpackte Daten in Datei schreiben
std.file.write(dateiname, AusPuf);
return 0;
}-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Re: Settlers 2:Next Generation (Finished)
Attached the S2Tools posted above.
You do not have the required permissions to view the files attached to this post.

