- How I Decompile -

Posts 1–10 of 10 · Page 1 of 1
- How I Decompile -
Since many people have asked me this, this is how I decompile the assembly..

Quote Originally Posted by MrBlueSL
Well for decompiling, I used NetBeans dotPeek 1.1 to decompile everything, which at first has a ton of errors.
I then went over every class file (.cs) with ILSpy (As in I selected the Class file in ILSpy's assembly viewer) and copied the code into the class files generated by dotPeek.

So in all sense, I just used dotPeek to create the solution, and project file.

Example: Main.cs (The one that was made by dotPeek) has a lot of errors... okay, so I select that class in Visual Studios, and Ctrl-A select all the code. Delete it. Now I go over to ILSpy, select Main.cs in the assembly viewer there, select main.cs and wait for it to decompile, then when that's finished, Ctrl-A all the code that was decompiled, and copy/paste it into the Main.cs we recently deleted all the code it. Continue this for all class files, except Item.cs (Look below for Item.cs)



For Item.cs, the part that crashes ILSpy is just -public void SetDefaults(int Type, bool noMatCheck = false)-
So to fix this, all you really need to do is go over every method, EXCEPT the one above, and copy/paste the code into the proper method in your source..
I'm sure this is all confusing the way I explained it, but I'm happy to explain more if needed.
Thanks sir! Dotpeek really fucks up the code to nearly make it unfixable.(As i told before in other threads non existant items, no map, no health and manabar etc.)
I'll try this tomorrow.
Quote Originally Posted by infinest View Post
Thanks sir! Dotpeek really fucks up the code to nearly make it unfixable.(As i told before in other threads non existant items, no map, no health and manabar etc.)
I'll try this tomorrow.
I've noticed dotPeek tends to delete brackets too. Even though it doesn't hurt the source in most cases, it just looks ugly.

I'm glad to have helped!
And again, Thank You very much!
ILSpy crashes on that specific method of Item.cs due to a stack overflow; it uses recursion to traverse Else If chains, and that specific method has an Else If chain over a thousand elements long.

That crash can be prevented by adjusting ILSpy's Stack; assuming you have Visual Studio 2010 installed, you can use the Editbin.exe utility (found in Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin) to change ILSpy's stack to a larger value. I used "editbin /stack:10485760 Z:\ILSpy\ILSpy.exe" (or, in other words, increased the stack from it's 1MB default to 10MB) and was able to decompile Item.cs .

There is one snag, though: the way those else if constructs are nested, the places with higher indentation in the resulting file have over a thousand tabs before the actual code. Makes editing a pain.
Quote Originally Posted by RoKFenris View Post
ILSpy crashes on that specific method of Item.cs due to a stack overflow; it uses recursion to traverse Else If chains, and that specific method has an Else If chain over a thousand elements long.

That crash can be prevented by adjusting ILSpy's Stack; assuming you have Visual Studio 2010 installed, you can use the Editbin.exe utility (found in Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin) to change ILSpy's stack to a larger value. I used "editbin /stack:10485760 Z:\ILSpy\ILSpy.exe" (or, in other words, increased the stack from it's 1MB default to 10MB) and was able to decompile Item.cs .

There is one snag, though: the way those else if constructs are nested, the places with higher indentation in the resulting file have over a thousand tabs before the actual code. Makes editing a pain.
I couldn't find editbin in that location. Would I have to download it?
I didn't have it either. Seems you need to install Visual C++ to populate that directory.
Well, I have installed the full Visual Studio Express suite, so it might be only available when the C++ part of the suite is installed.

I've been toying with attempting to increase the stack in the source code of ILSpy itself, but up to now without success. Or, rather, the stack size seems to be somewhat random when I increase it in the Thread calls in the source code. And I don't know the code well enough to rewrite the function that is giving a stack overflow error.

BTW, I might have something interesting for those that are up to compiling their own ILSpy. To add support to else if constructions in ILSpy, removing the absurd amount of indentation we get in some files, in the file NRefactory\ICSharpCode.NRefactory.CSharp\OutputVis itor\CSharpOutputVisitor.cs, find:

Code:
			if (!ifElseStatement.FalseStatement.IsNull) {
				WriteKeyword(IfElseStatement.ElseKeywordRole);
				WriteEmbeddedStatement(ifElseStatement.FalseStatement);
			}
and change to:

Code:
			if (!ifElseStatement.FalseStatement.IsNull) {
				WriteKeyword(IfElseStatement.ElseKeywordRole);
				BlockStatement blockFalse = ifElseStatement.FalseStatement as BlockStatement;
				if (blockFalse != null && blockFalse.Statements.Count == 1) {
					var node = blockFalse.Statements.ElementAt(0) as IfElseStatement;
					if (node != null) {
						StartNode(blockFalse);
						node.AcceptVisitor(this);
						EndNode(blockFalse);
					} else WriteEmbeddedStatement(ifElseStatement.FalseStatement);
				} else WriteEmbeddedStatement(ifElseStatement.FalseStatement);
			}
I'm now trying now to get ILSpy to fix the casting errors on it's own; ILSpy is currently unaware that bitwise and arithmetic operators result in int types when used on bytes, which is why it doesn't add the needed casts. Fixing is not as easy as discovering the reason, though.
Just found a way to make ILSpy generate the byte and short casts. Net result, there are only 4 errors in the whole decompiled code, and the game worked after fixing just those 4 (and removing the Steam requirement). The side effect is that operators such as +=, which do work without casting in C#, are decompiled to something like "b = (byte)(b + 1)".

If anyone wants to try the same changes, open the ICSharpCode.Decompiler\ILAst\TypeAnalysis.cs in the ILSpy source, then change:

Code:
		TypeReference DoInferTypeForExpression(ILExpression expr, TypeReference expectedType, bool forceInferChildren = false)
		{
			switch (expr.Code) {
					#region Logical operators
to:

Code:
		TypeReference DoInferTypeForExpression(ILExpression expr, TypeReference expectedType, bool forceInferChildren = false)
		{
			TypeReference tempType = null;
			switch (expr.Code) {
					#region Logical operators
About 250 lines below in the same method, change:

Code:
					#region Arithmetic instructions
				case ILCode.Not: // bitwise complement
				case ILCode.Neg:
					return InferTypeForExpression(expr.Arguments.Single(), expectedType);
				case ILCode.Add:
					return InferArgumentsInAddition(expr, null, expectedType);
				case ILCode.Sub:
					return InferArgumentsInSubtraction(expr, null, expectedType);
				case ILCode.Mul:
				case ILCode.Or:
				case ILCode.And:
				case ILCode.Xor:
					return InferArgumentsInBinaryOperator(expr, null, expectedType);
				case ILCode.Add_Ovf:
					return InferArgumentsInAddition(expr, true, expectedType);
				case ILCode.Sub_Ovf:
					return InferArgumentsInSubtraction(expr, true, expectedType);
				case ILCode.Mul_Ovf:
				case ILCode.Div:
				case ILCode.Rem:
					return InferArgumentsInBinaryOperator(expr, true, expectedType);
				case ILCode.Add_Ovf_Un:
					return InferArgumentsInAddition(expr, false, expectedType);
				case ILCode.Sub_Ovf_Un:
					return InferArgumentsInSubtraction(expr, false, expectedType);
				case ILCode.Mul_Ovf_Un:
				case ILCode.Div_Un:
				case ILCode.Rem_Un:
					return InferArgumentsInBinaryOperator(expr, false, expectedType);
				case ILCode.Shl:
to:
Code:
					#region Arithmetic instructions
				case ILCode.Not: // bitwise complement
				case ILCode.Neg:
					tempType = InferTypeForExpression(expr.Arguments.Single(), expectedType);
					return (GetInformationAmount(tempType) == 16) ? typeSystem.Int32 : ((GetInformationAmount(tempType) == 8) ? typeSystem.Int32 : tempType);
				case ILCode.Add:
					tempType = InferArgumentsInAddition(expr, null, expectedType);
					return (GetInformationAmount(tempType) == 16) ? typeSystem.Int32 : ((GetInformationAmount(tempType) == 8) ? typeSystem.Int32 : tempType);
				case ILCode.Sub:
					tempType = InferArgumentsInSubtraction(expr, null, expectedType);
					return (GetInformationAmount(tempType) == 16) ? typeSystem.Int32 : ((GetInformationAmount(tempType) == 8) ? typeSystem.Int32 : tempType);
				case ILCode.Mul:
				case ILCode.Or:
				case ILCode.And:
				case ILCode.Xor:
					tempType = InferArgumentsInBinaryOperator(expr, null, expectedType);
					return (GetInformationAmount(tempType) == 16) ? typeSystem.Int32 : ((GetInformationAmount(tempType) == 8) ? typeSystem.Int32 : tempType);
				case ILCode.Add_Ovf:
					tempType = InferArgumentsInAddition(expr, true, expectedType);
					return (GetInformationAmount(tempType) == 16) ? typeSystem.Int32 : ((GetInformationAmount(tempType) == 8) ? typeSystem.Int32 : tempType);
				case ILCode.Sub_Ovf:
					tempType = InferArgumentsInSubtraction(expr, true, expectedType);
					return (GetInformationAmount(tempType) == 16) ? typeSystem.Int32 : ((GetInformationAmount(tempType) == 8) ? typeSystem.Int32 : tempType);
				case ILCode.Mul_Ovf:
				case ILCode.Div:
				case ILCode.Rem:
					tempType = InferArgumentsInBinaryOperator(expr, true, expectedType);
					return (GetInformationAmount(tempType) == 16) ? typeSystem.Int32 : ((GetInformationAmount(tempType) == 8) ? typeSystem.Int32 : tempType);
				case ILCode.Add_Ovf_Un:
					tempType = InferArgumentsInAddition(expr, false, expectedType);
					return (GetInformationAmount(tempType) == 16) ? typeSystem.Int32 : ((GetInformationAmount(tempType) == 8) ? typeSystem.Int32 : tempType);
				case ILCode.Sub_Ovf_Un:
					tempType = InferArgumentsInSubtraction(expr, false, expectedType);
					return (GetInformationAmount(tempType) == 16) ? typeSystem.Int32 : ((GetInformationAmount(tempType) == 8) ? typeSystem.Int32 : tempType);
				case ILCode.Mul_Ovf_Un:
				case ILCode.Div_Un:
				case ILCode.Rem_Un:
					tempType = InferArgumentsInBinaryOperator(expr, false, expectedType);
					return (GetInformationAmount(tempType) == 16) ? typeSystem.Int32 : ((GetInformationAmount(tempType) == 8) ? typeSystem.Int32 : tempType);
				case ILCode.Shl:
Here is a modified ILSpy which has a bandaid that fixes crashing when decompiling Terraria.


This contains FlattenElseIf which transforms most "else { if }" into "else if { }".
Also ILSpy's StackReserve was increased to allow decompiling a large number of if statements.
github.com/bladecoding/ILSpy/releases
Posts 1–10 of 10 · Page 1 of 1

Post a Reply

Similar Threads

Tags for this Thread

None

Need help?