Turok 4 Multiplayer – Part 1
To start this off I suppose I should explain what Turok 4 Multiplayer is, Put simply it’s actually a modification for the original Turok 4: Evolution game which was released on PC with no multiplayer support. It introduces Multiplayer Online via means of reverse engineering, programming, and injecting custom code into the game engine.
The idea of this series of posts will be to go over the various hurdles and challenges I went through and am still going through while creating this modification with the hope in mind that it will help others learn this stuff or even create a similar project of their own for their own game, the caveat here is that Turok 4: Evolution on PC did have some local multiplayer code available within the binary this was a huge step towards already having existing Multiplayer content usable and reduced the amount of work needed drastically.
If we look at other games such as Grand Theft Auto 3 or Grand Theft Auto: San Andres while there was no multiplayer support initially there was a wide open world and tons of NPCs to control or replace, that task (replacing NPCs with players, or dynamically spawning them) should have been relatively straight forward once some initial reversing was done… I’ll get into that later in the article/series though.
The idea when I obtained Turok 4 was the same; I had no idea I was walking into a game where Multiplayer modes would exist but there would be no way to control other players, disable the split-screen modes, among other things including various bugs and crashes to overcome.
So the question I had to ask myself before even having the game was where to start; I’ll get into that next but first I want to note that this series will assume the reader has some prior reverse engineering and game hacking knowledge as well as some understanding of the tools such as Cheat Engine/MHS, IDA Pro + Hex Rays Decompiler/OllyDBG, and ReClass.
The first part of this article won’t be super technical as it’s an introduction to the project and initial steps taken; if you’re looking for more technical information in terms of how classes were able to be discovered, player spawning functionality, or the networking put in place please tune-in at a later period this part of the series probably isn’t for you.
If you’re just into the source-code and not interested in the reading of how this came to be this is for you:
A video of the current progress of this project can be seen here:
As promised though, here’s a series part by part on how the Turok 4: Multiplayer modification took place what the code contains how it works and etc.
I had decided the first steps to entering this would be to research the game engine used, file formats in place to determine if any files could provide clues about how the game worked, and if there was any source code available for the engine out there.
In researching the Game Engine I had discovered it was used by a few other games Vexx, 100 Bullets ( Unreleased ) and at least one other the idea here was that if I was stuck maybe I would be able to open the files or binaries of one of these games and find additional debug strings, or information there and carry it back to the engine I was working with. Having multiple copies of an engine even if it’s used for entirely different games is never a bad idea.
Though in my case here it honestly did not help much.
Game Engine – File Formats
There was no information readily available online about the file formats used by the game engine even today I personally haven’t really documented my own research much, there is a map editor project out there now but everything is still very limited and I expect this is something anyone should expect and also experience with any game which doesn’t have major popularity at the moment or some pre-existing project or modification such as this.
Though looking at the game engine’s files is honestly what intrigued me the most about the game, there are a set of “Actors” and each actor has two sets of files an actor instance file and an actor data file if you will, while this didn’t help me a lot with the idea of how things worked browsing through them I was able to discover that there was still Multiplayer.atr (Actor Data File) and Multiplayer.ati (Actor Instance File) within the game’s content.
To me this immediately implied there was some Multiplayer mode available, after further research I had discovered that the game was ported to the PC from the Original Xbox console and when the game existed on the console it had 4 player split-screen modes… So this was kind of a cool concept, if I could get the game to go into this mode I now had most of the Multiplayer problem solved (Maps, Weapons, Score Board – or so I thought, players etc).
Trial and Error, and the Guessing/Testing Game
From here my focus shifted a bit from File Formats and more towards playing the guessing/testing game honestly a lot of my personal reverse engineering has been just this rather than fully reversing the engine out of the starting gate I had nothing to lose but trying to do some random stuff that may or may not work and would save me some time if it did…
So the first steps I took here was simply replacing existing Atr/Ati files with the Multiplayer ones the ones I chose were Cheats.Atr and Cheats.ati due to the fact that there was a “Cheats” option already available on the main menu of the game.
Getting Lucky – Multiplayer Split-Screen:
Starting the game and clicking my “Cheats” button I was in luck!, The game opened a Multiplayer menu of some sort where it appeared to be the same as the Original Xbox, I prompted with 4 separate boxes and each one requesting the player to press a button to choose their avatar.
Now, the idea was I could easily create a ‘ghetto’ Mutliplayer online here if I simply synced the position of the other players (2,3,4) as the first player of the other systems but the problem I was facing was the game on PC was never designed to accept more than just the local player’s input so there was no way to actually select a character or even “sign-in” the other players what I had noticed initially was that the players were signing in but backing them selves as well as the first player out for some reason.
So searching back around the files I ended up running into MultiplayerJoin.atr/MultiplayerJoin.ati; with this I was at a point where I needed to shift my focus slightly back on the file formats and attempting to understand them… the reason being my understanding was that these files were responsible for actually allowing players to join and displaying the appropriate menus in order to allow them to select the player they wish to have and such.
My assumptions were correct here and these were the menus used for choosing the individual players. Browsing through the file I was able to determine there was various references to each player (The files were not encoded in any way, and had text strings in them making things much easier).
After finding that players were being referenced and searching between the individual players I was able to get an idea of which “Block” of data contained each player’s data, from there I simply browsed through strings until one caught my eye for some reason,
I had discovered that this was forcing the players to go “out” of the sign-in and after a bit of experimenting managed to get just the first and second player logged into the screen and had the second player automatically select the default character, my goal of creating a ghetto multiplayer was one step further as I was finally in the game and had 2 players spawned that I could (potentially) control.
A video of what progress had been achieved at this point can be seen here:
While these bugs don’t necessarily coincide with the actual timeline of events they are bugs I had faced after gaining access to the multiplayer screens and wanted to cover them before going into further detail about the next steps as they were pretty important to making any of this worthwhile, the only bug I’ll really be covering in-depth is the Invisible Players.
Beyond that I faced some other bugs such as specific Multiplayer only weapons causing crashes; Rather than reverse engineering the subroutine that was crashing I simply nopped ( Replaced code/instruction with the assembly for “No Operation” aka nop) the reference to invalid memory and prayed it would work. I got lucky and encountered no additional issues related to this nop. A lot of this has been major trial and error and major persistence.
The way the rendering loop worked with the game when porting it to PC they decided to clear the depth buffer before rendering the player’s weapon, the side-effect to this was that the first player would be rendered behind everything due to having no depth buffer data (Z Buffer), an example of this can be seen in the video below.
The main reason I’m covering this is to go over how this was actually fixed as I’m sure other people may run into graphics issues at some point maybe the game is rendering something they don’t want it to or is failing to render something similar to what I was experiencing; Your best friend here is PIX the DirectX debugging/tracing tool. Using this I was able to determine exactly what was causing the issue to occur and was how I had discovered that at the point of the player’s weapon being rendered the depth buffer was being cleared.
So using PIX you can see in the following image the player exists in the upper black/white box containing depth data by having the “Depth” channel selected:
And in the next image you’ll see that the player disappears just after that IDirect3DDevice9::Clear() is called.
In order to fix this problem I made use of an D3D9 proxy dll which exports all of the functions of the original replaces it and calls the original allowing you to intercept and change any functions involving DirectX 9 which the game was making use of, I have to thank Azorbix for this as the d3d9 kit was I using was originally created by him. Since game-deception is gone the only reference I can find to it is here: https://www.mpgh.net/forum/showthread.php?t=90063
With this I simply looked at the clear function and the arguments being used and stopped one of the calls from happening so that the depth buffer was only cleared the one time.
Skipping forward a bit and getting back to the file formats I discovered history files which I was later able to reverse engineer the loading of and actually tell the engine after the level had started loading that only the first player had joined preventing the second player’s screen from rendering entirely, when I get more in-depth I’ll cover that but for now here’s the video of the fixes applied:
So at this point I was in the game with two players, I had a major bug fixed now I had to figure out how I was going to control the second player which I’ll cover in part 2. I’ll be making use of IDA Pro in order to identify player data and dive into how to control the second player.