This code makes some assumptions that you won't want to make if you are implementing this. It's purely part of a proof-of-concept that I eventually determined was impossible and thus, abandoned.
/*
* @author: Chavo
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Chavoland.vHost.API.Util;
namespace Chavoland.vHost.Plugin.Util
{
class Statstring
{
private static short mapWidth = 0x0074;
private static short mapHeight = 0x0074;
public static byte[] CreateStatString(string hostName, string mapPath, uint mapCRC)
{
DataBuffer data = new DataBuffer();
try
{
if (mapPath.Length > 0 && hostName.Length > 0)
{
data.InsertByte(0x02); // game speed = fast
data.InsertByte(0x48); // teams together, visibility = map default
data.InsertByte(0x06); // lock teams
data.InsertByte(0x40); // refs
data.InsertByte(0x00); // unknown
//data.InsertByteArray(UNKNOWN);
data.InsertInt16(mapWidth);
data.InsertInt16(mapHeight);
data.InsertUInt32(mapCRC);
data.InsertCString(mapPath);
data.InsertCString(hostName);
data.InsertByte(0);
return EncodeStatString(data.GetData());
}
}
catch (Exception ex){}
return new byte[0];
}
public static byte[] EncodeStatString(byte[] data)
{
int i;
byte mask;
List<byte> list;
try
{
mask = 1;
list = new List<byte>();
for (i = 0; i < data.Length; i++)
{
if (data[i] % 2 == 0) // even
list.Add((byte) (data[i] + 1));
else // odd
{
list.Add(data[i]);
mask = (byte)(mask | (1 << (i % 7) + 1));
}
if ((i % 7) == 6 || i == (data.Length - 1))
{
list.Insert(list.Count - 1 - (i % 7), mask);
mask = 1;
}
}
return list.ToArray();
}
catch (Exception ex)
{
return new byte[0];
}
}
public static byte[] DecodeStatString(byte[] code)
{
int i;
byte mask;
List<byte> list;
try
{
i = 0;
list = new List<byte>();
if (code == null || code.Length == 0)
{
return new byte[0];
}
mask = code[0];
while (i < code.Length && code[i] != 0)
{
if ((i % 8) == 0)
{
mask = code[i];
}
else
{
if ((mask & (1 << (i % 8))) == 0)
{
list.Add((byte) (code[i] - 1));
}
else
{
list.Add(code[i]);
}
}
i++;
}
return list.ToArray();
}
catch (Exception ex)
{
return new byte[0];
}
}
}
}
But ya, I'm not sure I can explain it much more simply than for.rest's quote. The encoding just takes 7 byte chunks of existing data, increments the even bytes and marks those increments those in a corresponding 1-byte bitfield that is appended to that modified 7-byte chunk to make a 8-byte chunk. Decoding is just as straightfoward.