C#, Code, Unreal Engine 4

Unreal Engine 4 , blueprints or C++?

Unreal Engine 4 is probably one of the most powerful and widespread engines in the industry right now.

For artists it’s easy to see why , it has some very good rendering capabilities, has great functionality with substance painter and is very easy to create new shaders in with its very robust node-based approach.

Programmers new to UE4 however are not always sure how they should feel about UE4. Sure , the blueprint system seems like a nice idea , but can I really do everything I want in it?

Most programmers have a certain fear of the blueprint system at first because they feel like it limits them to what they can do. It also isn’t exactly very freeform at first. Sure , it’s easy to grasp , but very hard to actually implement complex systems in. Atleast , that’s what they think.

As a programmer myself however , i understand all these questions and had them myself at first. Coming from unity , this gives you the idea that you can write everything you want very easily, as it’s totally code-based. Blueprints however are also very powerful , and not should not be underestimated. It’s actually very easy and possible to create a fully working FPS with an inventory etc. without even touching a single line of code in UE4. And all that , thanks to the power of blueprints.

An added benefit of blueprints , is that they can be made extremely readable and it’s a lot easier for the artists on your project to try and code ( or at least understand ) something themselves. This , because it is  essentially the same node-based system as the way in which they create their shaders in UE4.

And when you are a small team , it can be very helpful if an artist ca roughly code one of his ideas and then just let you refine and actually implement this feature.

Therefore , I highly recommend leaving the C++ code on the side and at least trying some code in UE4 blueprints. You’ll be amazed at what it can do.

I’ll be making another blogpost containing some actual examples of me using this system to great effect in the near future.

Stay tuned!

 

 

C#, Code, Diablo 2

Understanding the diablo 2 save file format / Part 3

Now , for the third and final part , let’s look into the checksum a bit , i’ll try to keep my code simple and short this time , so you don’t get a headache while trying to read this post 😉

On a sidenote , this contains a lot of bitshifting etc. which is not ideal to write in c#, but verything should still be straightforward enough to translate into another language. 🙂

The checksum is actually pretty simple , first of all , you set the checksum bits to 0. ( they are bytes 12-15 )

character.BinaryStream[12] = 0x00;
character.BinaryStream[13] = 0x00;
character.BinaryStream[14] = 0x00;
character.BinaryStream[15] = 0x00;

Now for the checksum algorithm. This one is also fairly simple. All you have to do is add up all the bytes one by one and everytime you add a byte , you bitshift the sum 1 spot to the left. You do however have to make sure to carry over the highest bit( most bitshifting operators do not do this , so we have to do it manually ) , as we do not want this value to get lost , so we actually just rotate our sum around 1 bit everytime we add another value.

uint checksum = 0;            

for (int i = 0; i < character.BinaryStream.Count(); i++)
{
 byte thisByte = character.BinaryStream[i];

 uint carry = 0;
 if ((checksum & (1 << 31)) != 0)
   {
    carry = 1;
   }

checksum = unchecked (unchecked(checksum << 1) + character.BinaryStream[i]) + unchecked(carry) ;
}

And now , we just have to get the checksum back in the 4 bytes!

 byte[] intbytearray = BitConverter.GetBytes(checksum);
character.BinaryStream[12] = intbytearray[0];
character.BinaryStream[13] = intbytearray[1];
character.BinaryStream[14] = intbytearray[2];
character.BinaryStream[15] = intbytearray[3];

If all went well , you should now be able to read in files ,save them out , and still be able to play them !

C#, Code, Diablo 2

Understanding the diablo 2 save file format / Part 2

This time , we’ll be taking a look at how to read in the statistics bit of the d2 save file. First of all , we’ll need to establish how we will be reading in this part , I suggest copying this part in a separate bit/bool array for easier reading seeing as this is not byte aligned anymore.

First, we check out the length of the statsheader by looking at the location of the skills header . We also know for sure that the statsheader starts at 767 due to the fact that all files are formatted identical up untill this point.

int statstart = 767;

for (int i = 765; i < fileSize; i++)
{
    if (fileStream[i] == 'i')
    {
        if (fileStream[i + 1] == 'f')
        {
            skillHeaderStart = i;
        }
    }
}
int statlength = skillHeaderStart - statstart;

Now , let’s put the statsblock in an array of bools for easier reading ( so we dont have to skip over to another byte everytime )

List statBitStream = new List();

for (var i = 0; i < statlength; i++) // Getting the statlist in a bit array
{
  for (var j = 0; j < 8; j++)
  {
    var bit = GetBit(fileStream[statstart + i], j);
    statBitStream.Add(bit);
  }
}

private static bool GetBit(byte b, int position) // position in range 0-7
{
 return (b & (1 << position)) != 0;
}

Now that we have gotten individual bits in an array , let’s try reading them , and converting our values. The values always have an “id” part and a “value” part , the id part always consists of 9 bits and contains values between 0 and 15 ( meaning there are at maximum only 16 stats contained in this block ) . The size value part’s size however , depends on the particular id.

Now , for id’s and their values’ size :

private int StatIdToBitCount(int id)
        {

            int bitCount;
            switch (id)
            {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                    bitCount = 10;
                    break;
                case 5:
                    bitCount = 8;
                    break;
                case 6:
                case 7:
                case 8:
                case 9:
                case 10:
                case 11:
                    bitCount = 21;
                    break;
                case 12:
                    bitCount = 7;
                    break;
                case 13:
                    bitCount = 32;
                    break;
                case 14:
                case 15:
                    bitCount = 25;
                    break;
                default:
                    // UNKNOWN BITCOUNT
                    bitCount = 1;
                    break;
            }
            return bitCount;
        }

With this out of the way , our program will recognise the amount of bits he has to read for the value of our particular stat. You will notice i did some weird shenanigans to properly read in the values ( namely multiplying the bits times 2^x depending on the bit position )

int streamIndex = 0;
bool doLoop = true;

while (doLoop)
{
    var id = 0;
    if (streamIndex + 9 > statBitStream.Count()) // stop when end of stream is reached;
    {
        doLoop = false;
        break;
    }

    for (int j = 0; j  statBitStream.Count() -StatIdToBitCount(id)) 
// stop when end of stream is reached;
    {
        doLoop = false;
        break;
    }

    uint valueForStat = 0;

    for (int d = 0; d < StatIdToBitCount(id); d++) // Add bits to the valueforstat
    {
        int addedvalue = 1;

        if (d == 0)
        {
            if (statBitStream[streamIndex + d]) { addedvalue = 1; }
            else
            {
                addedvalue = 0;
            }
        }
        else
        {
         for (int i = 0; i  statBitStream.Count()) 
// stop when end of stream is reached;
        {
        doLoop = false;
        }
}

This post is mainly a big wall of code , it may be rather ugly to read . But I do find it important for people so they can see how they would go about translating the information about a binary file into actual code that reads this.

So , that was it for now , next post , and probably the last about the d2s file , will be about manipulating the checksum so you can actually save your file and play your manipulated save in the game.