In the past few months, I've been getting in touch with my inner self (a fancy way of saying "I just wanted to keep myself busy outside of work"). Originally, when I first encountered a PC, I wanted to be a gamer. But I was terrible at games, being headshot, zerg-rushed and all that (Yes, Couter-Strike and StarCraft: Broodwar). Then I wondered that if I knew how the game worked, I could be better. That led me to the world of software development, and here I am now. Now, I venture back into games...
...and hit a brick wall. Sure, games are just like any other software, except they're totally not. They're entirely different beasts. It's like the demon love-child between Computer Science and Fine Arts. I started to search on where to get started and the results... well... not very helpful. It's a wild goose-chase of selecting an engine vs learning the internals vs creating the resources vs doing it all in code vs using a game development tool.
So frustrated with all the running around, I decided to just pick up an old game I once played and took it apart. And oh boy I learned a lot more than going through a video course or reading through an e-book.
We're all probably familiar with the executable. It's the thing we run to start the game. It's the thing behind that shorcut. It's the thing that we apply OS compatibility settings on. It's the thing that we replace when cracking software. But then, its's just the tip of the iceberg. It's just the entrypoint and probably the thing that calls out the other things in the game.
However, I learned how to decompile binaries with several tools, and run through the binary itself. It was a lot of assembly code and bit flipping. I even saw hard-coded references to resource files. Not really exciting, but it was just the start.
Like any other software, games use libraries. What made them interesting isn't just the things the library is capable of, but their existence as well. For instance,
dx3dx9_XX.dll tells me that the game is for Windows because of the extension
.dll, it's relatively old or falls back to weaker graphics because it's DX9, and it's a 3D game because it has a Direct3D component.
All of the above is true. The game is relatively old, but DX9 was new that time. The game is 3D and DX9 pretty much described the level of 3D the game was capable of. I'd say around the likes of the original Halo: CE or Quake 3.
Games come with configurations, normally in the form of
.ini or XML files. This ranges from simple keybindings, to environment settings. Now what could I possibly get from configuration files? Well, to start, I know how the game was played and what the default controls were.
The key learning here was that regular key codes from the web are different from virtual key codes. This happened when I tried to match keyboard config with regular keycode in the effort to learn what the default keybindings are. I was expecting a left-hand to keyboard, right-hand to mouse game. They bindings got weird when they bound to scattered keys on the right side of the keyboard.
When I discovered that the executable wasn't the place to be, I ventured to look for the resource files to see what they have to offer. Resource files are normally just archives. The problem comes when they come with the wrong extension, no extension at all or even worse, a proprietary format. In this case, the resources had the right extension, but the file layout was a custom implementation of the standard spec.
Extensionless or wrong extensions can be solved by reading the first few bytes of the file, known as the "header". Given that information, you can search the interwebs. A proprietary format, however, is impossible without a spec sheet of the file layout. Luckily, the game used a known format albeit in a different implementation. Through meticulous inspection, I figured out the layout and built a script to unpack the files. The output just gave me a whole lot of possibilities afterwards.
When I said earlier that the game executable is just half the story, the other half lies in game scripts. Scripts make the entire game logic. They could contain storylines, AI behavior, the environment. The reason why the game logic is scripted rather than embedded is to have the game be able to update content without actually replacing the binary. Scripts are also easier to build because they're executed during runtime, making them easier to test. They're also in a higher programming language, making them easier to write.
Unfortunately in my adventure, I'm stuck as the game uses a weirdly configured compiled Lua which pre-made decompilers can't decompile. My next step is to probably learn Lua bytecode. Well, I was interested writing Lua before. I never thought of creating a decompiler though.
The most interesting and visible part of the game is probably the UI and the game models. In the case of this game, since it's DX9, it was inevitable to encounter DX-made models. Not the most interesting of formats, but meh. The part that made me a bit curious was that the mesh, animation, and textures were separate files. A bit of searching revealed that this method allowed for swappable models, shareable animations, and changeable textures. This is pretty much in line with Skyrim mods I install where the animation, bones, meshes and textures must all be compatible with each other.
Well, I learned more about game construction rather than how to build a game. It's probably comparable to being the engineer rather than the architect. However, it gave me a lot of insight as to what games do internally which was my original intent. Game development would now be easier thanks to these insights.