• Welcome to Valhalla Legends Archive.
 

[C#]CheckRevision

Started by shout, November 24, 2004, 02:01 PM

Previous topic - Next topic

shout

I am trying to create a check revison algorithum... but it does not give the correct values. I am using the string "A=153298715 B=515653871 C=630933526 4 A=A+S B=B^C C=C^A A=A^B" (which I got from packetlogging brood war), and when I use mine ( from iago's Java) I get 0x44c0733a, but with BNLS I get 0xff887946.

Here is my code (sorry for lack of comments):

private static uint[] hashcodes = new uint[] { 0xE7F4CB62, 0xF6A14FFC,0xAA5504AF,0x871FCDC2,0x11BF6A18,0xC57292E6,0x7927D27E,0x2FEC8733 };

public static uint CheckRevision(string VersionString, string[] FileNames, string client, int mpqNum)
{
char[] Operations = new char[4];
ulong[] Values = new ulong[4];
int[] opDest = new int[4];
int[] opSrc1 = new int[4];
int[] opSrc2 = new int[4];

SeperateVerString(VersionString, Operations, Values, opDest, opSrc1, opSrc2);

Values[0] ^= hashcodes[mpqNum];

for (int i = 0; i < 3; i++)
{
FileStream fileStream = new FileStream(FileNames[i],FileMode.Open, FileAccess.Read);
FileInfo fileInfo = new FileInfo(FileNames[i]);
int fileLength = (int)fileInfo.Length;
byte[] Buffer = new byte[4];
int roundedLength = (fileLength / 1024) * 1024;

for (int j = 0; j < roundedLength; j += 4)
{
fileStream.Read(Buffer, 0, 4);
Values[3] = BitConverter.ToUInt32(Buffer, 0);
for (int k = 0; k < 4; k++)
{
switch (Operations[k])
{
case '+':
Values[opDest[k]] = Values[opSrc1[k]] + Values[opSrc2[k]];
break;
case '-':
Values[opDest[k]] = Values[opSrc1[k]] - Values[opSrc2[k]];
break;
case '^':
Values[opDest[k]] = Values[opSrc1[k]] ^ Values[opSrc2[k]];
break;
default:
break;
}
}
}
}
return (uint)Values[2];
}

private static void SeperateVerString(string VersionString, char[] Operations, ulong[] Values, int[] opDest, int[] opSrc1, int[] opSrc2)
{
char equals = '=';
char space = ' ';
string[] verString = VersionString.Split(space);
string[] values = new string[4];
string[] tmp = new string[2];

for (int i = 0; i < 4; i++)
{
values[i] = verString[i];
}

for (int i = 0; i < 3; i++)
{
tmp = values[i].Split(equals);
Values[i] = (ulong)int.Parse(tmp[1]);
}

for (int i = 0; i < 3; i++)
{
opDest[i] = getNum((char)verString[i + 4][0]);
opSrc1[i] = getNum((char)verString[i + 4][2]);
opSrc2[i] = getNum((char)verString[i + 4][4]);
Operations[i] = verString[i + 4][3];
}
}


Don't ask why I put the chars in a variable in SeperateVerString but I did so oh well.

And just for good measure, iago's code:


/*
* CheckRevision.java
*
* Created on March 10, 2004, 9:05 AM
*/

package bot.bnet.util;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import java.nio.channels.FileChannel;

import java.nio.MappedByteBuffer;
import java.nio.ByteOrder;

import java.util.StringTokenizer;

import timer.Timer;

/**
*
* @author  iago
*/
public class CheckRevision
{
    private static final int hashcodes[] = { 0xE7F4CB62, 0xF6A14FFC, 0xAA5504AF, 0x871FCDC2, 0x11BF6A18, 0xC57292E6, 0x7927D27E, 0x2FEC8733 };
   
    /** This class simply does the version check on the three main files.
    */
    public static int checkRevision(String versionString, String[] files, int mpqNum) throws FileNotFoundException, IOException
    {
        // First, parse the versionString to name=value pairs and put them
        // in the appropriate place
        int[] values = new int[4];
       
        int[] opValueDest = new int[4];
        int[] opValueSrc1 = new int[4];
        char[] operation = new char[4];
        int[] opValueSrc2 = new int[4];
       
        // Break this apart at the spaces
        StringTokenizer s = new StringTokenizer(versionString, " ");
        int currentFormula = 0;
        while(s.hasMoreTokens())
        {
            String thisToken = s.nextToken();
            // As long as there is an '=' in the string
            if(thisToken.indexOf('=') > 0)
            {
                // Break it apart at the '='
                StringTokenizer nameValue = new StringTokenizer(thisToken, "=");
                if(nameValue.countTokens() != 2)
                    return 0;
               
                int variable = getNum(nameValue.nextToken().charAt(0));
               
                String value = nameValue.nextToken();
               
                //System.out.println((int)variable + " = " + value);
               
                // If it starts with a number, assign that number to the appropriate variable
                if(Character.isDigit(value.charAt(0)))
                {
                    values[variable] = Integer.parseInt(value);
                }
                else
                {
                    opValueDest[currentFormula] = variable;
                   
                    opValueSrc1[currentFormula] = getNum(value.charAt(0));
                    operation[currentFormula] = value.charAt(1);
                    opValueSrc2[currentFormula] = getNum(value.charAt(2));
                   
                    currentFormula++;
                }
            }
        }
       
        // Now we actually do the hashing for each file
        // Start by hashing A by the hashcode
        values[0] ^= hashcodes[mpqNum];
       
        for(int i = 0; i < files.length; i++)
        {
            Timer thisFile = new Timer();
           
            File currentFile = new File(files[i]);
           
            int roundedSize = (int)((currentFile.length() / 1024) * 1024);
           
            // Load the file into memory
            FileInputStream input = new FileInputStream(new File(files[i]));
            MappedByteBuffer file = input.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, roundedSize);
            file.order(ByteOrder.LITTLE_ENDIAN);
            file.load();
           
            //System.out.println("Processing " + currentFile.toString() + " (" + (roundedSize/4) + " DWords)");
            //System.out.print("Processing " + currentFile.toString() + "........");
           
            for(int j = 0; j < roundedSize; j += 4)
            {
                values[3] = file.getInt(j);
                //values[3]  = (file.get() & 0xFF) |
                //            ((file.get() & 0xFF) << 8) |
                //            ((file.get() & 0xFF) << 16) |
                //            ((file.get() & 0xFF) << 24);
                               
                for(int k = 0; k < currentFormula; k++)
                {
                    switch(operation[k])
                    {
                        case '+':
                            values[opValueDest[k]] = values[opValueSrc1[k]] + values[opValueSrc2[k]];
                            break;
                           
                        case '-':
                            values[opValueDest[k]] = values[opValueSrc1[k]] - values[opValueSrc2[k]];
                            break;
                           
                        case '^':
                            values[opValueDest[k]] = values[opValueSrc1[k]] ^ values[opValueSrc2[k]];
                            break;
                           
                        default:
                            return 0;
                    }
                }
            }
           
            //System.out.println(thisFile.getTime() + "ms.");
        }
        //System.out.println(Integer.toHexString(values[0]));
        //System.out.println(Integer.toHexString(values[1]));
        //System.out.println(Integer.toHexString(values[2]));
        return values[2];
    }

    private static int getNum(char c)
    {
        c = Character.toUpperCase(c);
        if(c == 'S')
            return 3;
        else
            return c - 'A';
    }
   
    public static void main(String args[]) throws Exception
    {
        String[] files = { "/home/iago/Projects/Java/bot/starcraft.exe",
                            "/home/iago/Projects/Java/bot/storm.dll",
                            "/home/iago/Projects/Java/bot/battle.snp" } ;
        long totalTime = 0;
        final int MAX = 100;
        long min = -1;
        long max = -1;
        for(int i = 0; i < MAX; i++)
        {
            int val1 = (int) (Math.random() * (double)Integer.MAX_VALUE);
            int val2 = (int) (Math.random() * (double)Integer.MAX_VALUE);
            int val3 = (int) (Math.random() * (double)Integer.MAX_VALUE);
       
            String testString = "A=" + val1 + " B=" + val2 + " C=" + val3 + " 4 A=A^S B=B-C C=C+A A=A+B";

                           
            Timer checkRevision = new Timer();
            checkRevision(testString, files, 6);
            long elapsed = checkRevision.getTime();
            System.out.println("checkRevision took " + elapsed + "ms.");
            totalTime += elapsed;
           
            if(elapsed < min || min == -1)
                min = elapsed;
            if(elapsed > max || max == -1)
                max = elapsed;
        }
       
        System.out.println("For " + MAX + "runs:");
        System.out.println("Total time: " + totalTime + "ms");
        System.out.println("Average time: " + (totalTime / MAX) + "ms");
        System.out.println("Min time: " + min + "ms");
        System.out.println("Max time: " + max + "ms");
       
        //System.out.println(Integer.toHexString(a));
    }
}


Mephisto

Immediately looking at your switch statement I see that you're not doing as you should.  In the case of xor, you're adding, same with the case of subtraction, you still add.

shout

#2
LOL... I am so FUCKING STUPID!!!

** Hits head on keyboard **

(Crying)Stupid, stupid, stupid...

Fixed that.

Now I get 0xab919d86.

I guess I will have to go through the grueling task of installing java on my machine... **sigh**

It seems although my SeperateVerString method is faulty. I shall fix it.

MyndFyre

Quote from: shout on November 24, 2004, 02:14 PM
I guess I will have to go through the grueling task of installing java on my machine... **sigh**

Or maybe you could just fix it and get it right...?
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

shout

#4
It was more so I could tell exactly what iago's code was doing.

Well, anyway, it works now. It's kind of ugly and it may only work with SC/BW

public class CheckRevision
{
private static bool SeperateVerString(string VersionString, char[] Operations, ulong[] Values, int[] opDest, int[] opSrc1, int[] opSrc2)
{
string[] verString = VersionString.Split(' '); //Split the string at the spaces
string[] NumericASValues = new string[4]; //The A=320842304 and so fourth

for (int i = 0; i != 4; i++) //Puts the string values into an array
{
NumericASValues[i] = verString[i];
}

string[] tmpstr = new string[2]; //Temp storage for split string of values
for (int i = 0; i != 3; i++)
{
tmpstr = NumericASValues[i].Split('='); //Splits the string at the =
Values[i] = ulong.Parse(tmpstr[1]); //Parses values into ulongs
}
Values[3] = 4;

for (int i = 0; i != 4; i++)
{
opDest[i] = getNum((char)verString[i + 4][0]); //Gets the destination for the calculation
opSrc1[i] = getNum((char)verString[i + 4][2]); //Gets the first source for the calculation
opSrc2[i] = getNum((char)verString[i + 4][4]); //Gets the 2nd source for the calculation
Operations[i] = verString[i + 4][3]; //Gets the operator for the calculation
}
return true;
}
private static uint[] hashcodes = new uint[] { 0xE7F4CB62, 0xF6A14FFC,0xAA5504AF,0x871FCDC2,0x11BF6A18,0xC57292E6,0x7927D27E,0x2FEC8733 };

public static uint CheckRevision(string VersionString, string[] FileNames, string client, int mpqNum)
{
char[] Operations = new char[4];
ulong[] Values = new ulong[4];
int[] opDest = new int[4];
int[] opSrc1 = new int[4];
int[] opSrc2 = new int[4];

SeperateVerString(VersionString, Operations, Values, opDest, opSrc1, opSrc2);

Values[0] ^= hashcodes[mpqNum];

for (int i = 0; i < 3; i++)
{
FileStream fileStream = new FileStream(FileNames[i],FileMode.Open, FileAccess.Read);
FileInfo fileInfo = new FileInfo(FileNames[i]);
int fileLength = (int)fileInfo.Length;
byte[] Buffer = new byte[4];
int roundedLength = (fileLength / 1024) * 1024;

for (int j = 0; j < roundedLength; j += 4)
{
fileStream.Read(Buffer, 0, 4);
Values[3] = BitConverter.ToUInt32(Buffer, 0);
for (int k = 0; k < 4; k++)
{
switch (Operations[k])
{
case '+':
Values[opDest[k]] = Values[opSrc1[k]] + Values[opSrc2[k]];
break;
case '-':
Values[opDest[k]] = Values[opSrc1[k]] - Values[opSrc2[k]];
break;
case '^':
Values[opDest[k]] = Values[opSrc1[k]] ^ Values[opSrc2[k]];
break;
default:
break;
}
}
}
}
return (uint)Values[2];
}
private static int getNum(char c)
{
c = char.ToUpper(c);
if(c == 'S')
{
return 3;
}
else
{
return c - 'A';
}
}
}