I had a wave of nostalgia recently and found an old Hell Fighter binary that I haven’t played in easily 20 years. Hell Fighter is an old freeware space battle simulator from the late 90s / early 00s era of PC gaming. I remember playing it on my mom’s old Windows 98 PC I had set up in my bedroom. I might have gotten it from one of those old 100-in-1 shareware discs that were popular at the time. Where I first learned of it is lost to time, but the game was awesome. It featured a fancy battle editor with dozens of ship types, so it was super fun to blow everything up in the game’s sandbox.

I distinctly remember it had this weird growling sound on the splash screen whenever you booted the game. It’s incredibly odd to think about now, but that sound is ingrained into my memory and just hearing it brings back all sorts of memories.

Hell Fighter v21.01 (multiplayer) Splash Screen
The Hell Fighter v21.01 splash screen. It growls at you.
Hell Fighter v21.01 In-Game
Two opposing forces duking. Teams of Starfighter, Wyvern, and Hellfighter class ships escorting freighters.


The game was built by David Peterson. In his own words, he describes Hell Fighter:

Hell Fighter is a fast action combination of space craft simulation, arcade scroller, and tactical gameplay... all brought onto a single battlefield.

As an internet multiplayer game, you control one of the ships in combat on a network server. Fighters, capital ships, bases, merchants, freighters, and other units appear in the game... they may be controlled by players or AI. They may be on your side... or they may be the enemy.

Hell Fighter is freeware. I write this game because I wanted a game like this to exist, and there is just nothing else like it out there.

Hell Fighter Versions

Everything I’ll talk about in this section comes with the giant caveat that it’s as far as I know – I’ll be piecing together information from archives of the Hell Fighter website www.dracova.com that went offline sometime within the last 5 years (from what I can tell).

There were several iterations of Hell Fighter, including Hell Fighter 16 for DOS, Hell Fighter 32 for Windows. There was even talk of a 3D Hell Fighter at one point, although development on it ceased long ago. There’s a ton of screenshots of all the assets used to create this game in all its iterations, and they’re simply fascinating. Every ship comes from hand-drawn concept art!

Hell Fighter Image Gallery

Hell Fighter v21.01

The version I’ll dig into today is Hell Fighter 32 v21.01 which introduced alpha multiplayer functionality on top of the base Hell Fighter game. This version released on July 5, 2003 according to David’s news post on July 6 of that year, and the download is archived here.

Hell Fighter server browser populated by OpenHFDS

Of course, when I booted the game the first time the server browser was not populated at all, unlike the screenshot above. Not surprising, since it’s a 23 year old freeware game that required me to spend a few hours figuring out I needed a cnc-ddraw shim to properly handle the old DirectDraw graphics API. Getting the game running is probably a bloggable topic in and of itself, so it’s almost guaranteed no one is trying to play this game multiplayer anymore.

Emulating the Directory Server

I was curious if I could host and join a game via the server browser, so I started experimenting. I hosted a new game with the “List my Server in the Directory” option checked, but using the “Get Directory Listing” button didn’t populate the server. I got lucky here – the error logs pointed me in the right direction:

ERROR RECOVERABLE: 7.028 - HFDS:  Directory server didn't respond to info command. - Code 0x0

This is exactly the breadcrumb I needed to figure out what I’m looking at. Now I’m committed to reverse engineering this thing, so let’s break out some tools.

Throw Wireshark and Ghidra at it

Figuring out the network traffic was pretty easy:

  1. Run strings on the HellFighter.exe game binary, find any references to HFDS
  2. Locate the hardcoded hostname that probably didn’t respond (hfds.dracova.com)
  3. Update C:/Windows/system32/drivers/etc/hosts to point hfds.dracova.com to 127.0.0.1
  4. Run Wireshark and capture traffic, figure out the game is sending UDP datagrams on port 10666
  5. Stand up a simple Python script that listens on UDP port 10666 and logs received bytes while the game is running

Deciphering the protocol was a little harder, but still straightforward. My Python script logged out a received info message when clicking “Get Directory Listing”. Fortunately, there were new error messages around timeouts since the client was obviously expecting my mock directory server to return some useful info.

I loaded the HellFighter.exe binary into Ghidra and poked around at references to that HFDS string as well as any error messages I found. Luckily this binary isn’t really obfuscated so I was able to reverse engineer fairly well given my meager skillset. I was able to figure out some useful functions like UDP sendto() / recvfrom() calls, some strlen() bounds checking, and a useful sscanf() call that cracked the protocol open.

The Client info Datagram

For the info datagram, the client is expecting a response with a matching command followed by data fields space-delimited. The client calls sendto() with info to the hfds.dracova.com server (or a mock server in my case). The server needs to respond with info <session_count> 0 0 0 0. The client will read recvfrom() data into a buffer and then call sscanf("info %d %d %d %d %d") to extract the data. If all 5 integers aren’t present, it calls an error handler. Why 5 integers? Who knows, I wasn’t able to trace this down, and they don’t seem to be used anywhere.

So, I hard-coded the mock server to send info 5 0 0 0 0 to any info request. The client then dutifully started pinging get 0 4. A bit more digging shows that the client is requesting detailed session information for sessions at indices 0 through 4 inclusive, for a total of 5. Exactly what the directry server sent to it. And of course, I was able to track down another sscanf() call with a format string which gave me the fields it wants as a response.

I figured there had to be other messages to add a server and disconnect it. There are! The set and humorously-named delete me commands also exist. set does exactly what you think, it adds a session to the directory. It also functions as an update command as well as a heartbeat – anything that hasn’t sent its heartbeat in over 3 minutes should be removed from the directory. delete me is a little weird because it doesn’t provide a session ID. I think the expectation is the sessions are keyed by IP or hostname and you can reference the socket address to get that data.

The HFDS Protocol

With all that mapped out, here are the client / server commands:

Client Request Server Response
info info <count> 0 0 0 0
get <first> <last> get <ID> <hostname> <name> <location> <connection> <cur> <max> <flags> <version>
set <name> <location> <connection> <cur> <max> <flags> <version> None
delete me None

Humorously, you’re allowed to set the location and connection to whatever you want. This probably mattered when network speeds were slower. The flags field sets whether the session is password-protected or not. I wasn’t able to find other flags that may be set.

The server should convert any spaces in the server name to underscores, which the client will then convert back. That’s important because this is a space-delimited protocol.

Once a session is listed in the directory, the connection between players is typically peer-to-peer which works as long as the host port is reachable on the other end. Therefore, the HFDS protocol doesn’t concern itself with gameplay directly.

Session Lifecycle

The lifecycle of a session is the following:

# Client adds/updates/ticks a session, server sends no response

set Hell_Fighter_Server USA FAST 1 24 0 v21.01

# Client requests sessions

info

# Server sends the number of sessions (3 here)

info 3 0 0 0 0

# Client requests 3 sessions

get 0 2

# Server sends detailed info for sessions 0, 1, 2
# The client might re-ping with new indices if it's already parsed some

get 0 Hell_Fighter_Server USA FAST 1 24 0 v21.01
get 1 HF-1C_Super_Hell_Fighters_Only USA MED 14 24 1 v21.01
get 2 PvP_Big_Battles USA Fast 27 48 0 v21.01

# Client kills a server

delete me

OpenHFDS Implementation

Armed with all this knowledge, I built out OpenHFDS, an open-source implementation of the HFDS protocol. You can find it here: https://github.com/ty-porter/OpenHFDS.

OpenHFDS also includes some more detailed notes on the protocol, including some limitations. The most obvious concern is that packets are plaintext and unauthenticated, so malicious actors can simply fire off spoofed delete me datagrams and remove all the sessions from the directory.


This will always be a niche game and probably no one cares about this information anymore, but it’s a game that I remember fondly. I enjoyed preserving this little piece of video game history.

One last note on David Peterson. He wrote one final Hell Fighter news blurb on www.dracova.com on September 30, 2004 notifying players that Hell Fighter development had sadly ended. He signed off for the last time with the following:

All I can say for sure is that you have not seen the last from me.

David, though it’s been 22 years, I certainly hope that to be true.

`dracova.com` FLEET4S splash

That’s all for now. Thanks for reading!