Hello, some of you have have seen me around the site lately picking up some C++ knowledge. I have been reading a book (brief history). I am trying to get involved in dev work for a community I help out. So i took up C++. My assignment has been to take some C# code (approx 2k lines, not gonna show it all) and figure out how it works. Basically it is a patcher. It patches an exe file by reading all the bytes into a byte [] in C# and altering some parts to it. Then it re-writes it all into a new exe file.

I understand how most of the program works and where the changes occur. My question is I am trying to interpret the program by changing some things around into C++. Basically I want to be able to implement the C# code that occurs into C++ code instead. I don't know of any binary functions or a good place to read up on them for C++, I just kept googling things that i didn't understand in C#, but have yet to find a good place to read about it in C++. Here is an idea of what I am working with. (I only provided about 10% of the actual coding)

If this needs to be moved into the C# section instead then feel free to move it. I just want to learn about some Binary functions for C++ so i can do this in C++ instead and be able to manipulate it as I need to. Ty :)

static public void PatchDrsRefInExe(byte[] exe, byte[] temp, string newInterfaceDrsName, Patch patch)
        {
            // Set InterfaceDrsPosition to temp variable drsPos
            var drsPos = patch.InterfaceDrsPosition;
            // If exe[0] != 'i', throw an error
            if (exe[drsPos] != 'i')
                throw new FatalError(@"Didn't find interfac.drs reference at expected location. Wrong exe.");

            // Convert into ASCII standard and store in newBytes
            var newBytes = Encoding.ASCII.GetBytes(newInterfaceDrsName);
            // For each variable in newBytes set exe[drsPos] = # of times through (e.g. starts @ 0, goes up)
            /*************************Change coding exists here*********************************************/
            int i = 0;
            foreach (var byt in newBytes)
            {
                exe[drsPos] = byt; // Set each byte into array byte type called exe
                drsPos++; //  Increment drsPos
                temp[i] = byt; // Record bytes being written  
                using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\Program Files (x86)\Microsoft Games\Age of Empires II\Info.txt", true))
                {
                    file.WriteLine(temp[i]);
                }
                i++;
            }
        }
static public void PatchResolutions(byte[] exe, byte[] temp, int oldWidth, int oldHeight, int newWidth, int newHeight, Patch patch)
        {
            // Create the map so, that originally larger resolutions stay larger even after patching. They _may_ become invalid though.
            // This is necessary to keep the internal (in AoE) if > else if > else if > code working.

            // Create empty dictionary
            var hmap = new Dictionary<int, int>();

            // Make an array with the possible widths
            var existingWidths = new[] { 800, 1024, 1280, 1600 };

            // take newWidth and store in temp variable
            var wshift = newWidth;

            // For each variable in existingeWidths (provided above)
            // If variable is equal to oldWidth, set hmap[w] equal to the newWidth
            // else if it is greater then oldwidth, set hmap[w] equal to 1 + newWidth (using incrmenter)
            foreach (var w in existingWidths)
            {
                if (w == oldWidth)
                    hmap[w] = newWidth;
                else if (w > oldWidth)
                    hmap[w] = ++wshift;
            }

            // Create empty dictionary
            // Do same as above but for vertical instead of horizontal
            var vmap = new Dictionary<int, int>();
            var existingHeights = new[] { 600, 768, 1024, 1200 };
            var hshift = newHeight;
            foreach (var h in existingHeights)
            {
                if (h == oldHeight)
                    vmap[h] = newHeight;
                else if (h > oldHeight)
                    vmap[h] = ++hshift;
            }

            // Display information from dictionaries
            foreach (var pair in hmap)
                UserFeedback.Trace(string.Format(@"Horizontal {0} => {1}", pair.Key, pair.Value));

            foreach (var pair in vmap)
                UserFeedback.Trace(string.Format(@"Vertical {0} => {1}", pair.Key, pair.Value));

            // For each variable in patch (Patch class) sub items
            //int i = 50000;
            foreach (var item in patch.Items)
            {
                // Possible invalid location
                if (item.Pos >= exe.Length)
                {
                    UserFeedback.Warning(@"Error in input: Invalid location {0:X8}. [NOT PATCHED]", item.Pos);
                    continue;
                }

                // Set temp variable oldValue to ReverenceValue (words[1])
                var oldValue = item.ReferenceValue;

                // New int varaible
                int newValue;

                // Contains() returns bool value, therefore hor, ver are bool types
                // Returns true if words[2] from item class contains the following:
                var hor = item.Type.Contains("H");
                var ver = item.Type.Contains("V");

                // If a number is used for both horizontal and vertical
                //  prefer the one that we are patching.
                // Both are true
                if (hor && ver)
                {
                    if (oldWidth == oldValue) // so if we have 1024 HV, and are patching 1024x768, we'd ignore the V, and use the H
                        ver = false;
                    else
                        hor = false; // Else we will use the V
                }

                // If one of the two are true:
                Trace.Assert(hor || ver);

                // If ver is true, then map = vmap
                // Else: map = hmap
                // Determining which map to use
                // vmap and hmap are the dictionaries from above
                var map = ver ? vmap : hmap;

                // oldValue is the key, and newValue is the value assigned to that key
                // Only goes if it can't find the old value
                if (!map.TryGetValue(oldValue, out newValue))
                    newValue = oldValue;

                if (item.Type.Contains("H") && item.Type.Contains("V"))
                    UserFeedback.Trace(string.Format(@"{0} HV: Mapping to {1}", oldValue, newValue));

                // Create 4 new variables with (int) type
                // Remmeber: item.Pos is words[0] e.g. 001E3897 converted to decimal (1980567)
                // So it would be 1980567, 1980568, 1980569, 1980570
                // Then converting it to (int)
                /********************************Coding Change occurs starting here ****************************************/
                var ob0 = (int)exe[item.Pos];
                var ob1 = (int)exe[item.Pos + 1];
                var ob2 = (int)exe[item.Pos + 2];
                var ob3 = (int)exe[item.Pos + 3];

                // Single | means if the previous condition is true, the others won't be checked
                var orgValue = ob0 | ob1 << 8 | ob2 << 16 | ob3 << 24;

                // If words[2] equals "dv" or "dH" then do the following:
                // If needed use an offset to fix error
                // Return data mismatch, meaning file is not properly patched (e.g. 1.0c instead of 1.0e)
                if (item.Type.Equals("dV") || item.Type.Equals("dH"))
                {
                    var expectedOrgValue = item.Parameter;
                    if (expectedOrgValue == 0)
                    {
                        UserFeedback.Warning(
                            string.Format(
                                "{0} action is safer if you mention the expected orgValue. Encountered {1} @ {2:X8}",
                                item.Type, orgValue, item.Pos));
                    }
                    else
                    {
                        if (expectedOrgValue != orgValue)
                        {
                            UserFeedback.Warning(string.Format(
                                                     @"{0} action expected value mismatch: {1} expected, {2} encountered @ {3:X8} [NOT PATCHED]",
                                                     item.Type,
                                                     expectedOrgValue, orgValue, item.Pos));
                            continue;
                        }
                    }

                    var offset = newValue - oldValue;
                    newValue = orgValue + offset;
                }
                // If origValue doesnt equal to oldValue (words[1])
                // Return data mismatch, meaning file is not properly patched (e.g. 1.0c instead of 1.0e)
                else
                {
                    if (orgValue != oldValue)
                    {
                        UserFeedback.Warning(string.Format(
                                                 @"{0} action expected value mismatch: {1} expected, {2} encountered @ {3:X8} [NOT PATCHED]",
                                                 item.Type,
                                                 oldValue, orgValue, item.Pos));
                        continue;
                    }
                }

                // convert back to byte format
                var b0 = (byte)(newValue & 0xFF);
                var b1 = (byte)((newValue >> 8) & 0xFF);
                var b2 = (byte)((newValue >> 16) & 0xFF);
                var b3 = (byte)((newValue >> 24) & 0xFF);
                //UserFeedback.Trace(String.Format("b0 = {0}", b0));

                /***************************************Changing code occurs here **********************************************/
                exe[item.Pos] = b0;
                exe[item.Pos + 1] = b1;
                exe[item.Pos + 2] = b2;
                exe[item.Pos + 3] = b3;
                //temp[i] = b0;
                //temp[i + 1] = b1;
                //temp[i + 2] = b2;
                //temp[i + 3] = b3;
                //i++;
                //i++;
                //i++;
                //i++;
            }  // End of for each for Items
        }

Recommended Answers

All 6 Replies

Basically I want to be able to implement the C# code that occurs into C++ code instead.

Your question is a bit vague...
Do you want to execute C++ code from this C# program so that you can replace it 'in small parts'? If yes... don't even try.

What I think you mean is that you want some ideas on how to write / modify binary files in C++?

This is a good way to learn things though... so what I would do:
- Look at all the major classes in the C# code, it's probably a good idea to stick to roughly the same design in C++.
- Start a new C++ Project :P (don't copy any code from C#).
- Bit by bit start to implement what the C# code is doing, like(I'm guessing here):
* Read the file
* Try some random stuff, like searching in the file, changing something hard-coded etc.
* Write the file

Some things you need to know:
If you want to read a binary file, you need to open the file in 'binary' mode, look up ios::binary in fstream.
Then you just read the entire file in an array, modify what you need and write it back.


If you have any more specific questions (easier for us than kind of guessing what you mean ;)) - please do ask.

My more specific question is where can I read about the C++ functions? Haha i thought I said it up above, maybe I didn't I want to be able to do anything that I need to do to this file in C++ instead of C# if I need to. So i have absolutely no idea what library that I should be reading about for C++. Can someone direct me to the right place? Haha

Google basically... if you want general information about C++ there are many good books, there is a sticky on this forum with a few good suggestions.

I THINK there are converters for C# to C++ as well, they won't do a good job on big chunks of code, but may help if you need a few functions 'translated'.

I don't know wat to google for, I have been reading a book, but I am not sure the Input/Output chapter covers everything I will need to know.

but I am not sure the Input/Output chapter covers everything I will need to know.

Any reasonable book should cover all that you need about file i/o for this task. Basically, you just need to be know how to read and write bytes (or sequences of bytes). Dictionary<int, int> would be std::map<int,int> ; read up on std::map<>.

An array of bytes would be byte[] a std::vector<unsigned char> (preferably) or just a plain C-style array; read up on std::vector<>

Ty for the info :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.