ProductSphere and the Apollo 11 Code: A Modernisation Case Study
ProductSphere mapped and documented Apollo 11’s flight software. Our engineers then rewrote one routine and tested it against the 1969 original.
What if your most critical legacy system were as difficult to understand as the software that took humans to the Moon?
Before an enterprise can safely modernise decades-old software, it must understand what the system does, why its components interact, and which behaviours cannot change.
Most large enterprises have learned this the hard way: 79% of IT leaders report a failed modernisation project, at an average cost of about $1.5 million and 16 months. The expensive part is rarely the rewrite. It is changing a system nobody fully understood, and finding out in production which behaviours mattered.
We used Apollo 11’s preserved flight-software repository to explore how ProductSphere approaches that challenge: understand the code, document its behaviour, modernise it incrementally, and test the result against the original.
Apollo 11: the extreme version of the problem
Apollo 11 flew two computers, one in each spacecraft, each running its own program: Comanche055 in the Command Module and Luminary099 in the Lunar Module. Each computer had 2,048 words of erasable memory and 36,864 words of program woven by hand into core rope.
The software has every classic legacy problem, at the extreme. Its authors are long gone, its knowledge lives in scanned printouts, and one comment in the landing guidance, on a call that flew, still reads “TEMPORARY, I HOPE HOPE HOPE”.
What we did, and how you can check it
The code is public: the MIT Museum scanned the original printouts, volunteers at the Virtual AGC project transcribed and proofread them, and the result sits on GitHub. That means every claim below can be checked, so we have sorted them by where they come from.
- Read all 175 source files, no unrecognised instructions
- Catalogued 14,531 routines, data and files
- Mapped 12,235 connections and 265 entry points
- Answered questions in chat, citing file and line
- Added a small language module so ProductSphere could read Apollo’s assembly
- Assembled the full Lunar Module program, Luminary099, after fixing two file names
- Ran the original SPSIN and SPCOS on an emulator of the Apollo Guidance Computer, 65,536 calls
- Rewrote both routines in TypeScript
- Tested the rewrite against every original result
- ProductSphere’s counts against a raw count of the files
- Every KILLTASK caller and both NOVACs, against the source
- Our assembled program against the proofread core-rope listing: identical where SPSIN and SPCOS live, 4 words different elsewhere
- The test itself, against three deliberately planted bugs
- The chat screen: a recreation of our session, answers summarised
- The cover art
Each step below has the same four parts: what makes it hard, what was done, the evidence you can inspect, and what a person checked before moving on.
Step 1: Understand the system
Two languages in the same files, calls routed through a scheduler instead of by name, and two programs that share routine names.
Read all 175 files, once our engineers had added a small language module for Apollo’s assembly, and built a map of the system.
A map of every routine, connection and entry point in both programs, counted in the figure below, with no routine attributed to the wrong program.
An engineer compared the counts with an independent count of the raw files: one program matched exactly, the other within 0.1%.
For a CIO, this map is the inventory a modernisation business case is built on: what exists, what depends on what, and where work begins. Without it, every estimate is a guess.
Step 2: Document what it does
Names that mean different things in different programs, and behaviour spread across files nobody has opened in decades.
Explained routines in plain English and answered questions in chat, asking which NOVAC we meant before answering, because both programs define one.
Every answer cites file and line. In the source, KILLTASK is called from 11 places in the Lunar Module program, each cancelling a named task.
We cross-checked the answers by hand against the public source: both NOVAC definitions are where the answer says. All 11 KILLTASK call sites in the source are listed below.
Documentation is where knowledge stops depending on who is still in the building. Because every answer carries its source line, an engineer can verify it in seconds rather than take it on trust.
COMFAIL2BURN_BABY_BURN…:630ZOOMNULLCLOKBURN_BABY_BURN…:797ULLGTASKR21LEM12P20-P25:952BEGDESR21LEM9P20-P25:997STDESIGR24ENDP20-P25:1187CALLDGCHR24LEM3P20-P25:1215CALLDGCHNOTP20P20-P25:2706DESLOOP +2CSMINTP20-P25:3207DESLOOP +2CONTDESGP20-P25:4301DESLOOP +2STORE1SP20-P25:4379DESLOOP +2LIMALARMP20-P25:4386CALLDGCHStep 3: Modernise one routine
For the rewrite we chose SPSIN and SPCOS, the Lunar Module’s single-precision sine and cosine: 32 lines of assembly, small enough to show in full below, and full of the traps that make real legacy code hard to move.
Ones’-complement arithmetic with a negative zero, multiplies that truncate, and a constant table that only works because of where it sits in memory.
Rewrote SPSIN and SPCOS, the Lunar Module’s sine and cosine, in TypeScript from their intent: same polynomial, same flight constants, same rounding rules.
The full original and the full rewrite, side by side below, and the map of everything in the program that depends on them.
Every AGC rule the rewrite depends on is written down as a comment, so a reviewer can check each one against the original listing.
First, the blast radius. The source says who depends on these two routines, and it is not a short list: the autopilot’s timer interrupt, the navigation and guidance cycle, the landing displays and the rendezvous radar. One of the callers, QUICTRIG, exists because it is, in its own comment, 10 times as fast as the general routine. Speed is why sine was a cheap polynomial in the first place.
Pick any part of the program. Everything that would feel a change to it lights up. Start with SPSIN / SPCOS at the bottom.
Then the traps. The AGC used ones’-complement arithmetic, which has a negative zero. Its multiplies keep the high word of an exact product, so they truncate. And the routine folds angles past 90° using a three-entry table it reaches by stepping one word either side of a constant called LIMITS. The table only works because of where the constants sit in memory; the source warns that one of them “must be two locations in front of BIT14”. It is exactly the kind of dependency a rewrite breaks without anyone noticing.
SPCOS AD HALF+90°SPSIN TS TEMK TCF SPT CS TEMKpast 180°: wrapSPT DOUBLEscale to π/2 TS TEMKoverflow = past 90° TCF POLLEY XCH TEMK INDEX TEMKstep ±1 word… AD LIMITS…either side of LIMITS COM AD TEMKmirror at 32768 TS TEMK TCF POLLEY TCF ARG90exactly 90°POLLEY EXTEND MP TEMKt² TS SQ EXTEND MP C5/2 AD C3/2 EXTEND MP SQ AD C1/2 EXTEND MP TEMK× t, exact DDOUBLdouble, then keep high word TS TEMKoverflow → ARG90 TC QARG90 INDEX A CS LIMITS±full scale TC Q
function fold(x) { const t = 2 * x if (Math.abs(t) <= MAX) return t const r = t > 0 ? 32768 - t : -32768 - t if (Math.abs(r) > MAX) return 'full' return r}function polynomial(t) { const t2 = mul(t, t) const a = mul(t2, C5) + C3 const inner = mul(a, t2) + C1 const y = Math.trunc((2 * inner * t) / ONE) return Math.max(-MAX, Math.min(MAX, y))}function spsin(x) { const t = fold(x) if (t === 'full') return x > 0 ? MAX : -MAX return polynomial(t)}function spcos(x) { const shifted = x + ONE / 2 return spsin(shifted <= MAX ? shifted : ONE / 2 - x)}
Step 4: Test it against the original
Legacy systems rarely have tests, so there is nothing to tell you whether the new code behaves like the old.
Ran the original routines from the flight binary on Virtual AGC, an emulator of the Apollo Guidance Computer, for all 32,768 possible inputs, and compared the rewrite against every result.
0 mismatches in 65,536 calls. The obvious rewrite, using Math.sin, changed 66% of the outputs, each by up to 4/16,384.
The pass rule was set before the run: the same value as the original on every input. Three deliberately planted bugs showed the test can fail.
Legacy systems rarely come with tests, so we used the original as the test. We assembled the full Luminary099 program (after fixing two file names in the repository) and compared it with Virtual AGC’s proofread core-rope listing: the memory bank holding SPSIN and SPCOS is identical, and 4 words differ elsewhere. We then ran the original routines from the proofread listing on Virtual AGC’s emulator of the Apollo Guidance Computer for every possible input, and compared each rewrite against all 65,536 results.
The obvious rewrite is the instructive failure. Math.sin is more accurate than the 1969 polynomial, and in a code review it looks like an improvement. It also changes two out of every three answers, because the original is approximate on purpose, in a smooth, repeatable way:
| Angle | True value × 16,384 | 1969 original | Math.sin rewrite |
|---|---|---|---|
10° 01616 | 2844.36 | 2844 | 2844 |
30° 05253 | 8192.91 | 8194 | 8193 differs by 1 |
45° 10000 | 11585.24 | 11587 | 11585 differs by 2 |
60° 12525 | 14188.44 | 14191 | 14188 differs by 3 |
Whether a difference of 3/16,384 matters depends on everything downstream of it. That is exactly why the test compares against the original rather than against the textbook.
What this proves, and what it does not
Apollo is a demonstration of specific capabilities, not proof that every enterprise migration is now easy. It shows that ProductSphere can understand and document a system written in a language mainstream code tools don’t support, and that one routine can be modernised and shown to give the same values as the original.
It does not show a whole program migrated. Each routine was tested on its own, with interrupts off, on an emulator rather than flight hardware. Understanding the source code is an important starting point; real modernisation also needs environment-specific validation, integration testing and operational acceptance by the people who run the system.
Start with a Legacy-Code Assessment
If you have a system nobody wants to touch, the first step is the one we took with Apollo: understand it before you change it. We agree the scope with you before anything starts.
Sources
- Apollo 11 flight software, chrislgarry/Apollo-11 on GitHub: Comanche055 and Luminary099, public domain
- Virtual AGC project, ibiblio.org/apollo and virtualagc on GitHub: the yaYUL assembler, the yaAGC emulator and the proofread Luminary099 core-rope listing
- MIT News, Margaret Hamilton, computing pioneer who led software development for the Apollo program, dies at 90, 7 October 2026
- NASA Apollo Lunar Surface Journal, Apollo 11 program alarms
- Wikipedia, Apollo Guidance Computer: memory sizes and weight
- Vanson Bourne for Micro Focus, The size of COBOL, February 2022
- US GAO, GAO-16-468: Federal Agencies Need to Address Aging Legacy Systems, 25 May 2016
- vFunction, Common pitfalls of app modernization projects: vFunction and Wakefield Research survey, 2022
- ProductSphere figures: tiramai internal test on the full Apollo 11 repository, 10 October 2026. Modernisation and equivalence test: tiramai, 22 October 2026. The method, code and results are linked from the test results figure above
Working through this for your organisation? Our team can walk you through it on your own use case.
How tiramai runs governed AI in the cloud, your private cloud or fully on-premises.
Explore ProductSphere
