Recently, a mate of mine asked me to write a few modifications for a game: PC Building Simulator

He wanted things like "Infinite Money" and "Instant Level 20", since he didn't like to grind games. Sure, I get that. I often find myself opening Cheat Engine on many a game when I find the game get's a bit boring.

So I grabbed a copy of PCBS (PC Building Simulator) off Steam and set to work.

The first thing I did was quite simply peruse the directory structure, and I can immediatly see that the game has been created in Unity Engine, which is a .NET based game engine. This makes things a lot simpler, since it is possible to just decompile .NET binaries, or in this case, the .NET libraries that will contain the game logic.

Tools

  1. dnSpy

I'm only going to use dnSpy for this game, since there is no need for any other tools.

Game Structure

The only thing that matters realted to this game, is that unity stores all libraries related to game logic within the <project_name>_Data\Managed folder.
In this case, the .\PCBS_Data\Managed folder.

The contents of said folder are as follows:

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2018/05/04     13:03          13312 ArabicSupport.dll
-a----       2018/05/04     13:02        1699840 Assembly-CSharp-firstpass.dll
-a----       2018/05/04     13:03          18944 Assembly-CSharp.dll
-a----       2018/05/04     13:02         433104 CTNAudio.dll
-a----       2018/05/04     13:03          76752 CTNLayer.dll
-a----       2018/05/04     13:03          66512 CTNVorbis.dll
-a----       2018/05/04     13:03           5632 CursorControl.dll
-a----       2018/05/04     13:03         130048 ES2.dll
-a----       2018/05/04     13:03         184320 Mono.Posix.dll
-a----       2018/05/04     13:02         294912 Mono.Security.dll
-a----       2018/05/04     13:03          11776 MoodkieSecurity.dll
-a----       2018/05/04     13:02        2590208 mscorlib.dll
-a----       2018/05/04     13:03         124928 System.Configuration.dll
-a----       2018/05/04     13:02         297472 System.Core.dll
-a----       2018/05/04     13:02        1679360 System.dll
-a----       2018/05/04     13:03         135168 System.Security.dll
-a----       2018/05/04     13:02        1270272 System.Xml.dll
-a----       2018/05/04     13:03           8704 UnityEngine.AccessibilityModule.dll
-a----       2018/05/04     13:03            609 UnityEngine.AccessibilityModule.dll.mdb
-a----       2018/05/04     13:03           1231 UnityEngine.AccessibilityModule.xml
-a----       2018/05/04     13:03          34304 UnityEngine.AIModule.dll
-a----       2018/05/04     13:03           8382 UnityEngine.AIModule.dll.mdb
-a----       2018/05/04     13:03          59638 UnityEngine.AIModule.xml
-a----       2018/05/04     13:03          80896 UnityEngine.AnimationModule.dll
-a----       2018/05/04     13:03          27607 UnityEngine.AnimationModule.dll.mdb
-a----       2018/05/04     13:03         113694 UnityEngine.AnimationModule.xml
-a----       2018/05/04     13:03          23040 UnityEngine.ARModule.dll
-a----       2018/05/04     13:03           3938 UnityEngine.ARModule.dll.mdb
-a----       2018/05/04     13:03           3009 UnityEngine.ARModule.xml
-a----       2018/05/04     13:03          50176 UnityEngine.AudioModule.dll
-a----       2018/05/04     13:03          11814 UnityEngine.AudioModule.dll.mdb
-a----       2018/05/04     13:03          75706 UnityEngine.AudioModule.xml
-a----       2018/05/04     13:03          11264 UnityEngine.ClothModule.dll
-a----       2018/05/04     13:03            836 UnityEngine.ClothModule.dll.mdb
-a----       2018/05/04     13:03           6995 UnityEngine.ClothModule.xml
-a----       2018/05/04     13:03           7680 UnityEngine.ClusterInputModule.dll
-a----       2018/05/04     13:03            440 UnityEngine.ClusterInputModule.dll.mdb
-a----       2018/05/04     13:03           5274 UnityEngine.ClusterInputModule.xml
-a----       2018/05/04     13:03           6656 UnityEngine.ClusterRendererModule.dll
-a----       2018/05/04     13:03            112 UnityEngine.ClusterRendererModule.dll.mdb
-a----       2018/05/04     13:03           1003 UnityEngine.ClusterRendererModule.xml
-a----       2018/05/04     13:02         684544 UnityEngine.CoreModule.dll
-a----       2018/05/04     13:03         239327 UnityEngine.CoreModule.dll.mdb
-a----       2018/05/04     13:02        1368546 UnityEngine.CoreModule.xml
-a----       2018/05/04     13:03           6656 UnityEngine.CrashReportingModule.dll
-a----       2018/05/04     13:03            112 UnityEngine.CrashReportingModule.dll.mdb
-a----       2018/05/04     13:03            655 UnityEngine.CrashReportingModule.xml
-a----       2018/05/04     13:03           8704 UnityEngine.DirectorModule.dll
-a----       2018/05/04     13:03            651 UnityEngine.DirectorModule.dll.mdb
-a----       2018/05/04     13:03           9485 UnityEngine.DirectorModule.xml
-a----       2018/05/04     13:03          49664 UnityEngine.dll
-a----       2018/05/04     13:03            258 UnityEngine.dll.mdb
-a----       2018/05/04     13:03          24576 UnityEngine.GameCenterModule.dll
-a----       2018/05/04     13:03           6570 UnityEngine.GameCenterModule.dll.mdb
-a----       2018/05/04     13:03          19303 UnityEngine.GameCenterModule.xml
-a----       2018/05/04     13:03           9728 UnityEngine.GridModule.dll
-a----       2018/05/04     13:03           1304 UnityEngine.GridModule.dll.mdb
-a----       2018/05/04     13:03           8627 UnityEngine.GridModule.xml
-a----       2018/05/04     13:03           7168 UnityEngine.ImageConversionModule.dll
-a----       2018/05/04     13:03            416 UnityEngine.ImageConversionModule.dll.mdb
-a----       2018/05/04     13:03           2328 UnityEngine.ImageConversionModule.xml
-a----       2018/05/04     13:03         140288 UnityEngine.IMGUIModule.dll
-a----       2018/05/04     13:03          58673 UnityEngine.IMGUIModule.dll.mdb
-a----       2018/05/04     13:02         287281 UnityEngine.IMGUIModule.xml
-a----       2018/05/04     13:03          12800 UnityEngine.InputModule.dll
-a----       2018/05/04     13:03           1464 UnityEngine.InputModule.dll.mdb
-a----       2018/05/04     13:03            168 UnityEngine.InputModule.xml
-a----       2018/05/04     13:03           6656 UnityEngine.JSONSerializeModule.dll
-a----       2018/05/04     13:03            342 UnityEngine.JSONSerializeModule.dll.mdb
-a----       2018/05/04     13:03           2515 UnityEngine.JSONSerializeModule.xml
-a----       2018/05/04     13:03         254464 UnityEngine.Networking.dll
-a----       2018/05/04     13:03          15360 UnityEngine.ParticlesLegacyModule.dll
-a----       2018/05/04     13:03           2180 UnityEngine.ParticlesLegacyModule.dll.mdb
-a----       2018/05/04     13:03          12318 UnityEngine.ParticlesLegacyModule.xml
-a----       2018/05/04     13:03         109568 UnityEngine.ParticleSystemModule.dll
-a----       2018/05/04     13:03          36260 UnityEngine.ParticleSystemModule.dll.mdb
-a----       2018/05/04     13:03         162130 UnityEngine.ParticleSystemModule.xml
-a----       2018/05/04     13:03           6656 UnityEngine.PerformanceReportingModule.dll
-a----       2018/05/04     13:03            112 UnityEngine.PerformanceReportingModule.dll.mdb
-a----       2018/05/04     13:03            592 UnityEngine.PerformanceReportingModule.xml
-a----       2018/05/04     13:03          77312 UnityEngine.Physics2DModule.dll
-a----       2018/05/04     13:03          21976 UnityEngine.Physics2DModule.dll.mdb
-a----       2018/05/04     13:03         150171 UnityEngine.Physics2DModule.xml
-a----       2018/05/04     13:03          68608 UnityEngine.PhysicsModule.dll
-a----       2018/05/04     13:03          21370 UnityEngine.PhysicsModule.dll.mdb
-a----       2018/05/04     13:03         108959 UnityEngine.PhysicsModule.xml
-a----       2018/05/04     13:03           6656 UnityEngine.ScreenCaptureModule.dll
-a----       2018/05/04     13:03            320 UnityEngine.ScreenCaptureModule.dll.mdb
-a----       2018/05/04     13:03            699 UnityEngine.ScreenCaptureModule.xml
-a----       2018/05/04     13:03           9216 UnityEngine.SpatialTracking.dll
-a----       2018/05/04     13:03           7680 UnityEngine.SpriteMaskModule.dll
-a----       2018/05/04     13:03            311 UnityEngine.SpriteMaskModule.dll.mdb
-a----       2018/05/04     13:03           1722 UnityEngine.SpriteMaskModule.xml
-a----       2018/05/04     13:03          12288 UnityEngine.StyleSheetsModule.dll
-a----       2018/05/04     13:03           2907 UnityEngine.StyleSheetsModule.dll.mdb
-a----       2018/05/04     13:03            174 UnityEngine.StyleSheetsModule.xml
-a----       2018/05/04     13:03          28672 UnityEngine.TerrainModule.dll
-a----       2018/05/04     13:03           4393 UnityEngine.TerrainModule.dll.mdb
-a----       2018/05/04     13:03          31207 UnityEngine.TerrainModule.xml
-a----       2018/05/04     13:03           6656 UnityEngine.TerrainPhysicsModule.dll
-a----       2018/05/04     13:03            112 UnityEngine.TerrainPhysicsModule.dll.mdb
-a----       2018/05/04     13:03            492 UnityEngine.TerrainPhysicsModule.xml
-a----       2018/05/04     13:03          25088 UnityEngine.TextRenderingModule.dll
-a----       2018/05/04     13:03           4154 UnityEngine.TextRenderingModule.dll.mdb
-a----       2018/05/04     13:03          31175 UnityEngine.TextRenderingModule.xml
-a----       2018/05/04     13:03          21504 UnityEngine.TilemapModule.dll
-a----       2018/05/04     13:03           5990 UnityEngine.TilemapModule.dll.mdb
-a----       2018/05/04     13:03          39458 UnityEngine.TilemapModule.xml
-a----       2018/05/04     13:03          86528 UnityEngine.Timeline.dll
-a----       2018/05/04     13:03         248832 UnityEngine.UI.dll
-a----       2018/05/04     13:03         166400 UnityEngine.UIElementsModule.dll
-a----       2018/05/04     13:03          64385 UnityEngine.UIElementsModule.dll.mdb
-a----       2018/05/04     13:03          47368 UnityEngine.UIElementsModule.xml
-a----       2018/05/04     13:03          19968 UnityEngine.UIModule.dll
-a----       2018/05/04     13:03           3068 UnityEngine.UIModule.dll.mdb
-a----       2018/05/04     13:03          24389 UnityEngine.UIModule.xml
-a----       2018/05/04     13:03          75264 UnityEngine.UNETModule.dll
-a----       2018/05/04     13:03          19971 UnityEngine.UNETModule.dll.mdb
-a----       2018/05/04     13:03         105092 UnityEngine.UNETModule.xml
-a----       2018/05/04     13:03          13312 UnityEngine.UnityAnalyticsModule.dll
-a----       2018/05/04     13:03           2940 UnityEngine.UnityAnalyticsModule.dll.mdb
-a----       2018/05/04     13:03           8964 UnityEngine.UnityAnalyticsModule.xml
-a----       2018/05/04     13:03          10752 UnityEngine.UnityConnectModule.dll
-a----       2018/05/04     13:03            734 UnityEngine.UnityConnectModule.dll.mdb
-a----       2018/05/04     13:03           6725 UnityEngine.UnityConnectModule.xml
-a----       2018/05/04     13:03           8192 UnityEngine.UnityWebRequestAudioModule.dll
-a----       2018/05/04     13:03            798 UnityEngine.UnityWebRequestAudioModule.dll.mdb
-a----       2018/05/04     13:03           4539 UnityEngine.UnityWebRequestAudioModule.xml
-a----       2018/05/04     13:03          35328 UnityEngine.UnityWebRequestModule.dll
-a----       2018/05/04     13:03          10486 UnityEngine.UnityWebRequestModule.dll.mdb
-a----       2018/05/04     13:03          50260 UnityEngine.UnityWebRequestModule.xml
-a----       2018/05/04     13:03           7680 UnityEngine.UnityWebRequestTextureModule.dll
-a----       2018/05/04     13:03            783 UnityEngine.UnityWebRequestTextureModule.dll.mdb
-a----       2018/05/04     13:03           3322 UnityEngine.UnityWebRequestTextureModule.xml
-a----       2018/05/04     13:03          18432 UnityEngine.UnityWebRequestWWWModule.dll
-a----       2018/05/04     13:03           3423 UnityEngine.UnityWebRequestWWWModule.dll.mdb
-a----       2018/05/04     13:03          21202 UnityEngine.UnityWebRequestWWWModule.xml
-a----       2018/05/04     13:03          10240 UnityEngine.VehiclesModule.dll
-a----       2018/05/04     13:03           1174 UnityEngine.VehiclesModule.dll.mdb
-a----       2018/05/04     13:03           6165 UnityEngine.VehiclesModule.xml
-a----       2018/05/04     13:03          17408 UnityEngine.VideoModule.dll
-a----       2018/05/04     13:03           1278 UnityEngine.VideoModule.dll.mdb
-a----       2018/05/04     13:03          25078 UnityEngine.VideoModule.xml
-a----       2018/05/04     13:03          24576 UnityEngine.VRModule.dll
-a----       2018/05/04     13:03           5395 UnityEngine.VRModule.dll.mdb
-a----       2018/05/04     13:03          21952 UnityEngine.VRModule.xml
-a----       2018/05/04     13:03          29696 UnityEngine.WebModule.dll
-a----       2018/05/04     13:03           8736 UnityEngine.WebModule.dll.mdb
-a----       2018/05/04     13:03            166 UnityEngine.WebModule.xml
-a----       2018/05/04     13:03           7168 UnityEngine.WindModule.dll
-a----       2018/05/04     13:03            112 UnityEngine.WindModule.dll.mdb
-a----       2018/05/04     13:03           2147 UnityEngine.WindModule.xml

However, there are only 2 files that are of interest, the rest are irrelivant for now.

  1. Assembly-CSharp.dll
  2. Assembly-CSharp-firstpass.dll

Both contain compiled code from the scripts that are used to build a game.

Assembly-CSharp

Dropping that library into dnspy has dissapointing results. It's empty, apart from a few core classes and methods for unity engine.

Clearly no point in wasting time here.

Assembly-CSharp-firstpass

Dropping this library into dnSpy results in a jackpot. ALl the game logic we want is in this library.

Cheat/Debug methods/classes

Cheats in video games were used as debug tools historically, allowing developers to test levels/whatever without dying for instance, but were often left over for players to mess around with for fun.

So... It is worthwhile checking if there are any such gems within this game.

Searching for Cheat doesn't yeild much, other than a few calls to the Steamworks library. Steamworks is essentially the SteamAPI used to communicate between the game and steam.

A search for Debug, however, presents a veeery interesting class.

Navigating to that class within dnSpy reveals the exact code we are looking for.

using System;
using UnityEngine;
using UnityEngine.SceneManagement;

// Token: 0x02000296 RID: 662
public class DebugMenu : MonoBehaviour
{
    // Token: 0x06001BE6 RID: 7142 RVA: 0x00049A22 File Offset: 0x00047E22
    private void Start()
    {
        this.ctrl = GameController.Get();
        this.m_pcBuilder = base.gameObject.AddComponent<PCBuilder>();
    }

    // Token: 0x06001BE7 RID: 7143 RVA: 0x00049A40 File Offset: 0x00047E40
    private void OnGUI()
    {
        using (new HorizontalLayout())
        {
            using (new VerticalLayout())
            {
                for (int i = 0; i < 5; i++)
                {
                    DebugMenu.Mode mode = (DebugMenu.Mode)i;
                    if (GUILayout.Button(mode.ToString(), new GUILayoutOption[0]))
                    {
                        this.m_mode = (DebugMenu.Mode)i;
                    }
                }
            }
            GUILayout.BeginVertical(GUI.skin.box, new GUILayoutOption[0]);
            this.scrollPos = GUILayout.BeginScrollView(this.scrollPos, GUI.skin.box);
            GUI.color = Color.white;
            switch (this.m_mode)
            {
            case DebugMenu.Mode.General:
                this.DoGeneral();
                break;
            case DebugMenu.Mode.Career:
                this.m_career.DoCareer();
                break;
            case DebugMenu.Mode.Parts:
                this.m_parts.DoParts();
                break;
            case DebugMenu.Mode.RandomText:
                this.m_career.DoRandomText();
                break;
            case DebugMenu.Mode.PCBuilder:
                this.m_pcBuilder.DoPCBuilder();
                break;
            }
            GUILayout.EndScrollView();
            GUILayout.EndVertical();
        }
    }

    // Token: 0x06001BE8 RID: 7144 RVA: 0x00049BA0 File Offset: 0x00047FA0
    private void DoGeneral()
    {
        if (GUILayout.Button("load photoMode", new GUILayoutOption[0]))
        {
            SceneManager.LoadScene("PhotoMode");
        }
        if (GUILayout.Button("toggle UI", new GUILayoutOption[0]))
        {
            this.ctrl.SetUIShowing(!this.ctrl.isUIShowing);
        }
        if (GUILayout.Button("toggle Freecamera", new GUILayoutOption[0]))
        {
            GameController.Get().ToggleFreeCam(this.freeCamera.GetComponent<Camera>());
        }
        DebugVars.DoGUI();
    }

    // Token: 0x04000F76 RID: 3958
    public FreeMovement freeCamera;

    // Token: 0x04000F77 RID: 3959
    private Vector2 scrollPos = Vector2.zero;

    // Token: 0x04000F78 RID: 3960
    private DebugMenu.Mode m_mode;

    // Token: 0x04000F79 RID: 3961
    private GameController ctrl;

    // Token: 0x04000F7A RID: 3962
    private CareerDebug m_career = new CareerDebug();

    // Token: 0x04000F7B RID: 3963
    private PartsDebug m_parts = new PartsDebug();

    // Token: 0x04000F7C RID: 3964
    private PCBuilder m_pcBuilder;

    // Token: 0x02000297 RID: 663
    private enum Mode
    {
        // Token: 0x04000F7E RID: 3966
        General,
        // Token: 0x04000F7F RID: 3967
        Career,
        // Token: 0x04000F80 RID: 3968
        Parts,
        // Token: 0x04000F81 RID: 3969
        RandomText,
        // Token: 0x04000F82 RID: 3970
        PCBuilder,
        // Token: 0x04000F83 RID: 3971
        MAX
    }
}

The question is now, how the heck do we use it. Because it clearly isn't just available when you start a new game.

Enabling the debug menu

A quick analysis of the DebugMenu class in dnSpy points to a few interesting classes which use the DebugMenu class.

The GameController.ShowDebugMenu() method looks promising, and expanding it's Used By tree shows it is only used by a single class.

However, there is a bit of a problem now. GameController.ShowDebugMenu() is used by PCBuilder.DoPCBuilder(), however PCBuilder.DoPCBuilder() is only used by DebugMenu.OnGUI(). That doesn't help at all.

Doubling back to the inital Used By tree for the DebugMenu class points to something else that could be helpful: CommonUI.Awake().

Decompiling that function reveals the code that is needed.

private void Awake()
{
    CommonUI.s_instance = this;
    GameController.Get().AddUI(base.gameObject);
    CommonUI.optionsMenu = this.FindUI<OptionsMenu>();
    CommonUI.inGameMenu = this.FindUI<InGameMenu>();
    CommonUI.saveMenu = this.FindUI<SaveLoadMenu>();
    CommonUI.tutorialUI = this.FindUI<TutorialUI>();
    CommonUI.messageBox = this.FindUI<MessageBox>();
    CommonUI.keyBindings = this.FindUI<KeyBindingMenu>();
    CommonUI.debugMenu = UnityEngine.Object.FindObjectOfType<DebugMenu>();
    if (CommonUI.debugMenu)
    {
        CommonUI.debugMenu.gameObject.SetActive(false);
    }
    CommonUI.RotationIndicator = this._RotationIndicator;
    CommonUI.backButton = this._backButton;
    CommonUI.actions = base.GetComponentsInChildren<WorldInteractionInfo>();
}

Specifically this part: CommonUI.debugMenu.gameObject.SetActive(false);
Logically, false must mean disabled, so changing SetActive() to true should enable the debug menu!

Make the modification and save the module (don't forget to take a backup)

Then, when running PCBS, and starting the career; this lovely menu pops up!

Review

This probably isn't the best method to enable the Debug Menu, but it works and that is what I was after!