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
}