Jump to content

Decompiling the beta


coffeetable

Recommended Posts

Instructions for decompiling the beta:

  1. Go download and install ILSpy: http://ilspy.net/
  2. Run it, then use it to open "Steam\SteamApps\common\Pillars of Eternity - Public Beta\PillarsOfEternity_Data\Managed\Assembly-CSharp.dll"
  3. You can now explore the decompiled code via the "Assembly-CSharp" node in the tree on the left. Thanks to this being C#, it's pretty readable. Most of Obsidian's work is in the "-" subnode, indicating the global namespace.
  4. Optional: to export the code from the tool, click on the Assembly-CSharp node in the tree, then File->Save Code. It'll create a .csproj which can be loaded using Visual Studio, or you can just poke around with the text editor of your choice.

This thread can be for discussing anything you come across. Be warned, there are obviously gonna be a lot of spoilers in there.

 

If any of the Obsidian programmers happen across this: how did CharacterStats.cs and StatusEffects.cs come about? I know some of it is bloat from the compiler, but both are north of 4,000 lines. Do all games look like this internally? How do you debug them?

Edited by coffeetable
  • Like 2
Link to comment
Share on other sites

Did you get a bunch of errors in PE_StreamTile.cs, in the LoadTexturesAsync() method? It's all mangled...

 

Edit: I'm using ILSpy, and saved the code.

 

Example of what I'm talking about:

[DebuggerHidden]
    private IEnumerator LoadTexturesAsync(string levelName, LevelInfo levelInfo)
    {
        PE_StreamTile.<LoadTexturesAsync>c__Iterator2B <LoadTexturesAsync>c__Iterator2B = new PE_StreamTile.<LoadTexturesAsync>c__Iterator2B();
        <LoadTexturesAsync>c__Iterator2B.levelName = levelName;
        <LoadTexturesAsync>c__Iterator2B.<[DebuggerHidden] private IEnumerator LoadTexturesAsync(string levelName, LevelInfo levelInfo) { PE_StreamTile.<LoadTexturesAsync>c__Iterator2B <LoadTexturesAsync>c__Iterator2B = new PE_StreamTile.<LoadTexturesAsync>c__Iterator2B(); <LoadTexturesAsync>c__Iterator2B.levelName = levelName; <LoadTexturesAsync>c__Iterator2B.<$>levelName = levelName; <LoadTexturesAsync>c__Iterator2B.<>f__this = this; return <LoadTexturesAsync>c__Iterator2B; }gt;levelName = levelName;
        <LoadTexturesAsync>c__Iterator2B.<>f__this = this;
        return <LoadTexturesAsync>c__Iterator2B;
    }

 

Also tried dotpeek, got other (different) manglings...

Telerik JustDecompiler, no love either...

 

How'd you guys get this to build?

Edited by PrimeHydra

Ask a fish head

Anything you want to

They won't answer

(They can't talk)

Link to comment
Share on other sites

Did you get a bunch of errors in PE_StreamTile.cs, in the LoadTexturesAsync() method? It's all mangled...

 

Edit: I'm using ILSpy, and saved the code.

 

Example of what I'm talking about:

[DebuggerHidden]

    private IEnumerator LoadTexturesAsync(string levelName, LevelInfo levelInfo)

    {

        PE_StreamTile.<LoadTexturesAsync>c__Iterator2B <LoadTexturesAsync>c__Iterator2B = new PE_StreamTile.<LoadTexturesAsync>c__Iterator2B();

        <LoadTexturesAsync>c__Iterator2B.levelName = levelName;

        <LoadTexturesAsync>c__Iterator2B.<[DebuggerHidden] private IEnumerator LoadTexturesAsync(string levelName, LevelInfo levelInfo) { PE_StreamTile.<LoadTexturesAsync>c__Iterator2B <LoadTexturesAsync>c__Iterator2B = new PE_StreamTile.<LoadTexturesAsync>c__Iterator2B(); <LoadTexturesAsync>c__Iterator2B.levelName = levelName; <LoadTexturesAsync>c__Iterator2B.<$>levelName = levelName; <LoadTexturesAsync>c__Iterator2B.<>f__this = this; return <LoadTexturesAsync>c__Iterator2B; }gt;levelName = levelName;

        <LoadTexturesAsync>c__Iterator2B.<>f__this = this;

        return <LoadTexturesAsync>c__Iterator2B;

    }

 

Also tried dotpeek, got other (different) manglings...

Telerik JustDecompiler, no love either...

 

How'd you guys get this to build?

That's not really mangling, it's because decompilers are not that smart about some high-level C# features like iterator blocks and async methods, so they show you the transformed code rather than its original high-level form. The DebuggerHidden attributes already tells you that this is almost certainly compiler generated code. The name of this method suggests that it should be an async method, but it returns IEnumerator so I'm not entirely sure. Perhaps async is implemented using enumerators underneath.

 

On that note, it's pretty nice that they are using such state-of-the-art features, it shows some high level of expertise with the language and hints that the code is probably of good quality.

Edited by Zeckul
  • Like 1
Link to comment
Share on other sites

 

Did you get a bunch of errors in PE_StreamTile.cs, in the LoadTexturesAsync() method? It's all mangled...

 

Edit: I'm using ILSpy, and saved the code.

 

Example of what I'm talking about:

[DebuggerHidden]

    private IEnumerator LoadTexturesAsync(string levelName, LevelInfo levelInfo)

    {

        PE_StreamTile.<LoadTexturesAsync>c__Iterator2B <LoadTexturesAsync>c__Iterator2B = new PE_StreamTile.<LoadTexturesAsync>c__Iterator2B();

        <LoadTexturesAsync>c__Iterator2B.levelName = levelName;

        <LoadTexturesAsync>c__Iterator2B.<[DebuggerHidden] private IEnumerator LoadTexturesAsync(string levelName, LevelInfo levelInfo) { PE_StreamTile.<LoadTexturesAsync>c__Iterator2B <LoadTexturesAsync>c__Iterator2B = new PE_StreamTile.<LoadTexturesAsync>c__Iterator2B(); <LoadTexturesAsync>c__Iterator2B.levelName = levelName; <LoadTexturesAsync>c__Iterator2B.<$>levelName = levelName; <LoadTexturesAsync>c__Iterator2B.<>f__this = this; return <LoadTexturesAsync>c__Iterator2B; }gt;levelName = levelName;

        <LoadTexturesAsync>c__Iterator2B.<>f__this = this;

        return <LoadTexturesAsync>c__Iterator2B;

    }

 

Also tried dotpeek, got other (different) manglings...

Telerik JustDecompiler, no love either...

 

How'd you guys get this to build?

That's not really mangling, it's because decompilers are not that smart about some high-level C# features like iterator blocks and async methods, so they show you the transformed code rather than its original high-level form. The DebuggerHidden attributes already tells you that this is almost certainly compiler generated code. The name of this method suggests that it should be an async method, but it returns IEnumerator so I'm not entirely sure. Perhaps async is implemented using enumerators underneath.

 

On that note, it's pretty nice that they are using such state-of-the-art features, it shows some high level of expertise with the language and hints that the code is probably of good quality.

 

Would be nice if I could get it into a compilable form. I know "mangling" might not be the right word. How about uncompilable output? It's the same to my eyes :)

Edited by PrimeHydra

Ask a fish head

Anything you want to

They won't answer

(They can't talk)

Link to comment
Share on other sites

dotPeek 1.1 and ILSpy boast that they can do this, but I haven't tried.

 

Note that Unity code is likely compiled with the mono compiler rather than the "standard" one in Visual Studio, so it's likely that these tools fail because they're only designed to recognize the specific patterns emitted by one specific compiler.

Edited by Zeckul
Link to comment
Share on other sites

I tried with dotpeek, ILSpy, Redgate Reflector as well. The output always had some weird unucompilable stuff in it. Eventually found on their forums that they're not trying to produce compilable code, due to security concerns. Makes sense...but I'm all set with hacking IL, I'll leave that to the hardcore.

Ask a fish head

Anything you want to

They won't answer

(They can't talk)

Link to comment
Share on other sites

×
×
  • Create New...