Dominic Kennedy

Spacewar! From DOS to Web

Game DevelopmentRetro ComputingJavaScript

Reverse-engineering a 1985 DOS binary to get the physics right in a web recreation. A story about obsession with authenticity.

The amber glow

Some games imprint on you. Spacewar! hit me through an amber CGA monitor in the late eighties — two ships, a star, and Newtonian physics rendered in monochrome. Bill Seiler's 1985 DOS adaptation of the . I never forgot the weight of those ships.

In 2015 I tried to recreate it in Haskell. The project stalled — . A decade later, in October 2025, I came back with a simpler idea: one HTML file, one JavaScript file, no build system. Just Canvas 2D and the Web Audio API.

The original 1985 DOS title screen

Single-file architecture

The entire game lives in game.js — around 3,000 lines. . This was deliberate. The original ran as a single binary. The recreation should feel just as self-contained.

Key decisions from the first week:

  • CGA amber monochrome#FFAA00 on black, matching the original DOS palette
  • Toroidal space — screen wrapping with
  • Web Audio API — all sound effects synthesized in real-time, no audio files
  • RequestAnimationFrame loop with

By the end of the first week, the DOS-style interface with cycling demo screens was working, and core mechanics — torpedoes, phasers, thrust, cloak, hyperspace — matched the original game parameters.

Chasing authenticity

Getting the look right was one thing. Getting the feel right took months.

Phase by phase, the game grew more faithful. Realistic torpedo ballistics replaced placeholder physics. The title screen earned a . Press Start 2P font was swapped for actual . The HUD got blinking shield bars at critical levels.

Spacewar web gameplay

The audio deserves its own mention. Every sound is generated through the . The Pretzel ship hums differently from the Triangle ship. Phasers sweep. Torpedoes pop. It sounds like a DOS game running through a PC speaker, which is exactly the point.

The physics deep-dive

After months of polish, the ships still felt wrong. Too twitchy. Too fast. You could spin on a dime and rocket to full speed in half a second. Time to go back to the source.

I reverse-engineered the original SPACEWAR.EXE v1.72 binary to extract the exact physics parameters. The findings surprised me.

— rotation was nearly perfect already, but thrust acceleration was 3x too fast and max speed was 50% too high.

The fix was a single commit. The result: ships now feel weighty and deliberate. Full rotation takes ~2.6 seconds instead of 1.7. Reaching top speed takes ~1.7 seconds instead of 0.6. Combat becomes strategic — you plan your turns and commits instead of twitching your way out of danger.

This was the moment the game stopped being a recreation and started being a faithful recreation.

Code review by committee

Before calling it done, I ran the codebase through a . Security hardening, performance improvements, dead code removal. The agents found issues a single pair of eyes would miss — strict mode violations, render optimizations, places where the game loop was doing unnecessary work.

Current state

The game is live at spacewar.dmnc.tech with . You can play against a friend on the same keyboard or watch two AI ships duke it out in demo mode.

The web recreation title screen

What started as a nostalgia project became an exercise in reverse engineering and authenticity. The , the synthesized audio, the physics constants pulled from a 40-year-old binary — each detail matters because each detail is what makes Spacewar! feel like Spacewar! and not just another space shooter.

Next up: gamepad support, mobile/touch controls, and eventually online multiplayer. But first — the Apple TV port. That story is its own post.