The brothers, who had enjoyed cooperative play of the DOS version of “Wing Commander” as children, spent 11 years reverse-engineering the game and finally realized their dream of “cooperative play with a wingman.” The project began with their childhood desire to fly their own aircraft and play cooperatively rather than share a single cockpit, and evolved into a complex technical undertaking spanning several years, exploring the depths of the game’s memory, code, and network protocols.

Wing Commander Together
https://fireflyk64.github.io/wcmulti/

The project’s initial inspiration dates back to October 4, 2015, when brothers Daniel Horn and Patrick Horn realized that the entire memory footprint of “Wing Commander” might fit within the 640 KB of RAM available under DOS. The central idea was to extract the coordinates of the player’s ship and wingman from the game’s memory and use network packets to control the wingman. If they could dump the memory and identify where the XYZ coordinates of the player’s ship and wingman were stored, they should be able to control the wingman with network packets.


The brothers adopted a systematic approach using the DOSBox debugger. They took snapshots of memory before and after moving through an empty region of the player’s space and compared them, enabling them to identify the changed memory region containing the spatial coordinate data.


This technique was refined through cross-referencing with the chase camera view, ultimately identifying the ship’s position at 13D3:A9C2 and its speed at CAE2.


Further investigation revealed the direction vectors and their memory locations—for example, right at AEB6, up at B1B6, and forward at B4B6—as well as the fact that the game uses 64 slots for entity properties, with the camera located at 0x3D and temporary variables at 0x3F.


Because the memory regions were close together, it became possible to identify single-byte changes associated with rotation. Below is a view of a yaw from level flight in which forward[0] changed by 9 bytes and up[0] changed from 00 01 to 7E 00.


As the project progressed, it became clear that simple memory writes alone were insufficient for actions such as firing weapons, making it necessary to “hijack” the game’s own functions. This led to the development of a “trampoline system” for calling functions with the correct arguments, particularly when considering the game’s use of dynamically loaded overlays. The breakthrough was achieved by using the “dead string” “Loading WING COMMANDER” as a trampoline placeholder at 13D3:0187.By overwriting the dead string with instructions, it became possible to make the game call specific functions such as fireAllGuns().

00 terminates any string pointing here. pushf; pusha the game is mid-frame; leave registers as we found them xor si,si; push si argument: ship 0. Later thunks use mov si,imm16 for each argument call far 12D7:0156 through the stub, so it works wherever the overlay is loaded pop si; popa; popf cdecl: caller cleans the arguments retf back to the CS:IP DOSBox pushed

This method made it possible to activate laser cannons, ultimately leading to the implementation of more complex actions.


In August 2017, a network protocol was created using a simple TCP client/server architecture and protobuf messages. On each frame, the server sent the clients the positions of all ships, firing events, destruction, and damage information. Conversely, the clients sent back their own positions whenever a laser was fired or an important status update occurred, such as takeoff, landing, or death.


The biggest problem was ensuring consistent entity slots between the server and clients, especially for temporary objects such as meteors and laser projectiles. The team implemented a mapping system to convert server ship IDs into local IDs, solving the problem that previously prevented meteors from working correctly in multiplayer.


In June 2019, it became apparent that the mission victory calculation was unstable and difficult to handle, so we decided to perform a binary search to find where the actual victory points were being accumulated. We copied the entire 64K-byte data segment over the network and progressively split it in half. After repeatedly performing binary searches, we identified the 80-byte region containing the mission tree at 13D3:D248. Then, in October, we found the overall victory point counter at 13D3:C280 and the mission numbers at 13D3:C255 and C256, respectively, making it possible to select a mission to play from the drop-down list.


After identifying a function that played back communications text in early 2020, we were able to send chat over the network, directly incorporate the entered chat into the system, and play it back on the wingman's VDU (display). This provided a highly immersive chat method that evoked the intense combat scenes in the game.


Final adjustments were made in 2020, leaving the game in a playable state, but ideas for how to actually enjoy it with friends ran dry, and the game was apparently left abandoned on GitHub for some time.


However, in 2026, the game was revived through the adoption of WebRTC technology and the development of a new system called “lobbylink.” Lobbylink is a simple Go-based lobby system that depends only on a WebSocket library and orchestrates peer-to-peer WebRTC connections.


Lobbylink runs on any small server and allows players to connect easily with one another using WebRTC and shared room codes. The server maintains a static allowlist of permitted origins, allowing browser or client software written in nearly any language to connect using a room code.


An LLM was also enlisted to add further functionality, and the integration of voice chat via a second WebRTC peer connection enabled real-time voice communication during gameplay. According to the report, this final implementation finally allowed players to “fly together and laugh together.”

A demonstration of two-player online co-op in “Wing Commander” can be seen in the following video, beginning at approximately 23 minutes 55 seconds.

Wing Commander Co-Op: Reverse Engineering x86 Assembly and Memory to Add Multiplayer. - YouTube