Difference between revisions of "Team17 compression"

From Worms Knowledge Base

Jump to: navigation, search
m (History: internal link correction)
m (Decompression Routine: change coding style - does this look better?)
Line 8: Line 8:
  
 
== Decompression Routine ==
 
== Decompression Routine ==
 
+
public static bool Decompress(BinaryReader b, ref byte[] dStream)
    public static bool Decompress(BinaryReader b, ref byte[] dStream)
+
{
    {
+
    int cmd;
        int cmd;
+
    int output = 0; //offset of next write
        int output = 0; //offset of next write
+
    while ((cmd = b.ReadByte()) != -1)
        while ((cmd = b.ReadByte()) != -1)
+
    { //read a byte
        { //read a byte
+
        if ((cmd & 0x80) == 0) //command: 1 byte (color)
            if ((cmd & 0x80) == 0) //command: 1 byte (color)
+
            dStream[output++] = (byte)cmd;
            {
+
        } else {
                dStream[output++] = (byte)cmd;
+
            int arg1 = (cmd >> 3) & 0xF; //arg1=bits 2-5
            }
+
            int arg2 = b.ReadByte();
            else
+
            if (arg2 == -1)
            {
+
                return false;
                int arg1 = (cmd >> 3) & 0xF; //arg1=bits 2-5
+
            arg2 = ((cmd << 8) | arg2) & 0x7FF; //arg2=bits 6-16
                int arg2 = b.ReadByte();
+
            if (arg1 == 0) {
                if (arg2 == -1) { return false; }
+
                if (arg2 == 0) //command: 0x80 0x00
                arg2 = ((cmd << 8) | arg2) & 0x7FF; //arg2=bits 6-16
+
                    return false;
                if (arg1 == 0)
+
                int arg3 = b.ReadByte();
                {
+
                if (arg3 == -1)
                    if (arg2 == 0) { return false; } //command: 0x80 0x00
+
                    return false;
                    int arg3 = b.ReadByte();
+
                output = CopyData(output, arg2, arg3 + 18, ref dStream); //command: 3 bytes
                    if (arg3 == -1) { return false; }
+
            } else {
                    output = CopyData(output, arg2, arg3 + 18, ref dStream); //command: 3 bytes
+
                output = CopyData(output, arg2 + 1, arg1 + 2, ref dStream); //command: 2 bytes
                }
+
            }
                else
+
        }
                {
+
    }
                    output = CopyData(output, arg2 + 1, arg1 + 2, ref dStream); //command: 2 bytes
+
    return true;
                }
+
}
            }
+
        }
+
public static int CopyData(int dOffset, int cOffset, int Repeat, ref byte[] dStream)
        return true;
+
{
    }
+
    for (; Repeat > 0; Repeat--)
 
+
        dStream[dOffset] = dStream[dOffset++ - cOffset];
    public static int CopyData(int dOffset, int cOffset, int Repeat, ref byte[] dStream)
+
    return dOffset;
    {
+
}
        for (; Repeat > 0; Repeat--)
+
        {
+
            dStream[dOffset] = dStream[dOffset++ - cOffset];
+
        }
+
        return dOffset;
+
    }
+

Revision as of 02:57, 5 June 2010

The majority of Team17's unique graphic file formats are stored with their image data compressed into 1 or more data streams. The exact compression algorithm used has not been made public knowledge.

History

It is presumed that Fudge Boy was the first one to reverse engineer Team17's compression algorithm. He used this knowledge to create two very popular and important programs, the WA directory editor and The Fiddler. However, he never released his information about Team17's compression to the public.

Many years passed before it was again reverse engineered, this time by acme_pjz. On June 12, 2008 he released his findings to the public. Very shortly thereafter, Pisto revised acme_pjz's decompression code and re-released the improvements to the public.

Decompression Routine

public static bool Decompress(BinaryReader b, ref byte[] dStream)
{
    int cmd;
    int output = 0;  //offset of next write
    while ((cmd = b.ReadByte()) != -1)
    {  //read a byte
        if ((cmd & 0x80) == 0) {  //command: 1 byte (color)
            dStream[output++] = (byte)cmd;
        } else {
            int arg1 = (cmd >> 3) & 0xF;  //arg1=bits 2-5
            int arg2 = b.ReadByte();
            if (arg2 == -1)
                return false;
            arg2 = ((cmd << 8) | arg2) & 0x7FF;  //arg2=bits 6-16
            if (arg1 == 0) {
                if (arg2 == 0)  //command: 0x80 0x00
                    return false;
                int arg3 = b.ReadByte();
                if (arg3 == -1)
                    return false;
                output = CopyData(output, arg2, arg3 + 18, ref dStream);  //command: 3 bytes
            } else {
                output = CopyData(output, arg2 + 1, arg1 + 2, ref dStream);  //command: 2 bytes
            }
        }
    }
    return true;
}

public static int CopyData(int dOffset, int cOffset, int Repeat, ref byte[] dStream)
{
    for (; Repeat > 0; Repeat--)
        dStream[dOffset] = dStream[dOffset++ - cOffset];
    return dOffset;
}
Personal tools