Where I left off
For the last week or so the job has been reading. Take the compiled game code out of the client (the “decompile” step from the earlier posts), turn it back into something human-readable, and write down how it all fits together. Login flow, character loading, the 197 data files, the split between the code that runs on your machine and the code that used to run on Auran’s servers.
That’s finished. Phase 2 is closed. I also finally posted the Phase 1 findings to r/ReverseEngineering for a sanity check, which was the last thing hanging over from that phase. No replies yet. That’s fine, it’s out there.
So now the reading turns into building. Phase 3: a minimal arena server. One match, one map, running on my own machine, that an unmodified copy of Fury can connect to. If I can log in and move my character around a level that a second program is running, Phase 3 is done. Everything fancier than that comes later.
Quick recap: client and server
If you’re new here. A game like Fury is two programs. The client is the one you run: it draws the world, reads your mouse, plays the sounds. The server is the one the company runs: it’s the referee. It holds the real state of the match, decides what actually happened when two people swing at each other, and tells every client what to draw. Take the server away and the client is a very pretty puppet with nobody’s hand in it.
Fury’s servers went dark in 2008. Nobody has the server program, the source code, or any documentation for it. What I do have, thanks to Phase 2, is the client, and it turns out the client knows a surprising amount about what the server was supposed to do.
Why this isn’t just “turn the server code back on”
Here’s the thing I keep having to explain to myself. Phase 2 found that the server logic is right there in the client. Auran shipped one big pile of code that contained both halves, the client half and the server half, and just switched the server half off at build time. So the obvious thought is: flip it back on. Done.
It’s not that easy, for three separate reasons.
One: the client refuses to be a server. I spent most of Phase 1 testing this. Every normal way of telling an Unreal Engine game “you be the server this time” has been quietly disabled in Fury’s build. The doors are welded shut. So even with perfect server code sitting in the client, there’s no way to start it in server mode.
Two: the server code is switched off in a way that’s baked in. The on/off
switch isn’t a setting I can change. It was a value the compiler read once, years
ago, and then hard-coded into the finished program as literally “false, skip this
bit”. Un-baking that is possible in theory (the write-up in research/phase3/
has the gory detail) but it’s a hex-editing job with an open question mark over
whether it breaks a checksum, and even if it works I still hit reason one.
Three: the interesting bits aren’t in the readable code at all. The server code I can read is full of calls out to functions like “talk to the database” and “send this over the network”. Those functions are written in C++ and compiled into the client as raw machine code. Not readable, not reusable. Any server I build has to supply its own versions of all of them.
So what does “build the server” mean
The honest answer is I have to write a new program, from scratch, that does what the switched-off code describes. The decompiled script is the blueprint. It tells me exactly what the server is supposed to say and when. I just have to be the one saying it.
The good news is that the part I need first, the actual match, uses bog-standard Unreal Engine 3 networking. That’s well-charted territory. People have built servers that speak it before, for other UE3 games. The scary hand-rolled Auran networking is all in the login system, and I’m deliberately not going near that in Phase 3. Phase 3 gets to cheat: no real login, no database, no account, just enough of a fib to get one character into one match on loopback.
I’ve written up four ways to approach it and settled on this one: write it fresh, and first go looking for an open-source UE3 server project I can build on top of, because I’d be daft not to reuse someone else’s netcode if it exists. The one small experiment I wanted to do first is done (see the checksum bit below), and it came back clean enough to not worry about.
The option I wish we had
There’s a fifth way to do this and it’s the one I can’t have, so it’s worth explaining why.
Fury runs on Unreal Engine 3, which Auran licensed from Epic Games. Studios that licensed UE3 didn’t just get the finished engine, they got the whole thing: the full C++ source, and the tools to compile their own version of the game, including a proper dedicated server build. If I had that toolchain, this phase mostly evaporates. I could flip the switched-off server code back on in the source, hit compile, and run the result. No reverse-engineering the network protocol, no reimplementing anything. Weeks of work, gone.
I can’t have it for a few reasons stacked on top of each other. That toolchain was never public. It went to paying studios under a non-disclosure agreement and nowhere else. The blessing I got from Auran’s co-founder covers Fury’s client material, the stuff Auran actually made. It doesn’t cover Epic’s engine source, because that was never Auran’s to hand out. And Auran itself is long gone, so there’s no one to even ask for the official version.
The one thread here, and it’s a thin one: when I emailed Tony Hilliam (Auran co-founder, post 2), he floated that if this ever got interesting he could ask ex-staff to dig through their archives for old DVDs sitting in a cupboard somewhere. That could be nothing. It could also be a server build, or source, or bits of the backend. I’m not chasing it now. It stays parked until I’ve got a working decompile and something worth showing him. But it’s the one thing that could change the entire shape of what comes next.
The checksum bit
Quick tangent, because I actually did this bit already. When my decompiler was learning to read Fury’s files back in Phase 2, it found two mystery numbers Auran had bolted onto the file format that a normal Unreal Engine 3 file doesn’t have. One per file, one per chunk-of-data inside the file. They looked like checksums, little fingerprints that go stale the moment you change a single byte. That matters here because one of the four approaches involves changing bytes in those files by hand, and a checksum you forgot to update means the game just refuses to load the file.
So I checked. The per-chunk one turned out to be nothing at all: it’s zero on every single chunk, all 49,660 of them in the main game file. Not a checksum, just an empty slot. The per-file one is more interesting. It’s a real, different-looking number for every file, but it doesn’t match any of the standard checksum recipes I threw at it, so I still don’t know what it is or whether the game even checks it. The way to find out is dumb and effective: change one byte in a copy of a file, launch the game, see if it complains. That’s a job for later, if I ever go down the byte-editing road. For now it’s enough to know the scary-looking version of the problem, a fingerprint on every chunk, isn’t real.
Next up
Pick the approach. Then the first real task is to point an unmodified client at a dead port and watch exactly what it says when it tries to join a match. Whatever bytes come out of it, that’s the conversation my server has to learn to hold up its end of.