Anarchy Online
Advertisement

The message[]

The message consists of the following parts:

[Bytes 1-2] - This tells the client that its the start of a message that needs to be converted. Its always '~&'. [Bytes 3-7] - This is the first ID [Bytes 8-12] - This is the second ID [Bytes 13-n] - If the string needs some arguments they are placed here. The format of these arguments looks like this:

[datatype][length][data]

datatype (1 byte) - 's' = string, 'i' = integer .. there might be more here (like maybe 'd' for double) but im not sure. length (1 byte) - This is the length of the data including the length char (so its length of data + 1). data ('length-1' bytes) - This is the actual argument data.

The last byte of the message is '~', this is the stop-char.

The ID's[]

The client use these ID's to retrieve the real message from the database. Before we can start looking in the db for these id's we need to convert them to a 4

byte value which is done like this:

Each ID-byte can hold values 33 to 117 so the first thing we need to do is subtract 33 from each byte so we get values 0 to 84. Now we just calculate the decimal value of these 5 bytes, this can be done with the following formula:

Decimal value = (byte1 * (85^4)) + (byte2 * (85^3)) + (byte3 * (85^2)) + (byte4 * (85^1)) + (byte5 * (85^0))

TNow lets get the 4 bytes from this value.. i wrote a little function to do it for me:

$Byte1 = intval($decimal_value / pow(256,3)); $rest = $id_decimal - $Byte1*pow(256,3);

$Byte2 = intval($rest / pow(256,2)); $rest = $rest - $Byte2*pow(256,2);

$Byte3 = intval($rest / pow(256,1)); $Byte4 = $rest - $Byte3*pow(256,1);

The ID's in the database is stored in reversed byte order so $byte4 here is the most significant byte.

The databases[]

text.mdb and ctext.ldb - Both these files can be used to retrieve the real message, not exactly sure why there is 2 different files.

ctext.ldb[]

This one was quite easy to understand. It's structure looks like this: [Byte 1-4] - This is the header ('MLDB'). [byte 5-n] - This is the messages stored like this:

First 4 bytes = First ID Next 4 bytes = Second ID Next 4 bytes = String length Next 'length' bytes = Message.

Note. The length is also stored in reversed byte order so make sure you reverse it

text.mdb[]

This one was a bit harder to understand, i don't think i fully understand it yet but i know how to pull messages from it.

Structure: [Byte 1-8] - Header ('MMDB' + 4 bytes that might not really be a part of the header) After the header comes a list of the first ID's and a position in the file where the second ID can be found. The first ID and fileposition are stored like this: [First ID (4 bytes)][Fileposition (4 bytes)]...

Now lets seek down to the position of the second ID. Same thing here 2 chunks of 4 byte values but the second chunk here contains the fileposition of the message. [Second ID (4 bytes)][Fileposition (4 bytes)]...

Seeking down to the message...

Now all we gotta do is read the message and be happy . I don't think the length of the string is stored anywhere but all strings ends with chr(0) so its no biggie.

The string we get here is a formatting string so it might contain '%s', '%d' and so on... So just use the arguments from the original message and use sprintf($formatting_string, $arg1,$arg2...) to get the real string

Quellen[]

Advertisement