A maintainer's, archivist's, and developer's reference for the chrislgarry/Apollo-11 repository — the digitised source code of the Apollo Guidance Computer (AGC) flight programs that flew aboard Columbia and Eagle in July 1969.
This guide is for repository maintainers, deep-dive readers, embedded-systems researchers, and engineers who want to understand the AGC architecture, the transcription workflow, the verb/noun command surface, the operating-system layer (executive, waitlist, interpreter), and the fault-tolerant design patterns that allowed the lunar landing to proceed through the now-famous 1201/1202 program alarms.
1. Architecture Overview
1.1 What this repository is
chrislgarry/Apollo-11 is a historical archive, not a live software product. It preserves two flight programs that were physically loaded into the core-rope memory of Apollo Guidance Computer hardware in 1969:
- Comanche055 — Build 055 of the Colossus 2A flight program (Command Module Computer, CMC), aboard Columbia.
- Luminary099 — Build 099 of the Luminary 1A flight program (Lunar Module Guidance Computer, LGC), aboard Eagle.
Both programs were digitised from MIT Museum hardcopies by Paul Fjeld, are in the public domain, and are mirrored across multiple archives including Software Heritage for long-term preservation.
The repository is not a fork of Virtual AGC; it ships the source listings only. Assembly and simulation are out of scope.
1.2 The AGC at a glance
Understanding the hardware is essential to understanding the source code. Every quirk in the listing maps to a property of the AGC.
| Property | Specification |
|---|---|
| Word size | 15 bits + 1 parity bit |
| Address space | 12-bit, banked |
| Erasable memory | 2 KW (2,048 words) of 16-bit core (RAM equivalent) |
| Fixed memory | 36 KW (36,864 words) of core rope (read-only, mask-programmed at manufacture) |
| Clock | 1.024 MHz master, ~2.048 µs per memory cycle (~12 µs per typical instruction) |
| Instruction set | ~36 native opcodes plus interpretive virtual-machine opcodes |
| Multitasking | Cooperative + interrupt-driven via a hand-coded executive and waitlist |
| I/O | DSKY (display/keyboard), IMU, optical telescope/sextant, radars, engines, RCS jets, downlink telemetry |
| Mass / power | ~32 kg, ~55 W; two units flew on every CSM/LM pair |
The Block II AGC is a fixed-architecture computer — there is no microcode, no abstraction layer, no operating system in the modern sense. The "operating system" is the executive and waitlist hand-written into the rope.
Note
The repository's source files map one-to-one to the AGC's internal subroutine log sections. Reading a file is reading a printout — the bank directives, page-number anchors, and
R0000line markers are all load-bearing artefacts of the original 1969 printout layout, not modern conveniences.
1.3 Memory model
AGC memory is split into erasable (writeable) and fixed (rope, read-only):
Erasable: Fixed:
+--------------------+ +--------------------+
| 0000-002F Unswitched/ | 02000-03777 Fixed-fixed (always mapped)
| "Lower" | (banks 02 and 03)
| 0030-04FF E-banks 0-7 | 04000-07777 Switched fixed (banks 4-7)
| (switched, 256w each) |
+--------------------+ | 10000-77777 Switched fixed (banks 10-43)
| (rope-stored, read-only)
+--------------------+
Bank registers (FBANK, EBANK) select which fixed/erasable bank is mapped into the windowed regions. Source code uses BANK n and EBANK= label directives to declare which banks the assembler should pack code/data into.
In the source you will see this pattern constantly:
BANK 32 # pack the following into fixed bank 32
SETLOC F2DPS*32 # address inside bank 32 (label-relative)
BANK
EBANK= E2DPS # assume erasable bank E2DPS in scope
Bank-management bugs were a major source of original-development complexity. The BANKCALL macro (used heavily) handles cross-bank function calls correctly.
1.4 Component inventory
| Component | Path | Role |
|---|---|---|
| Command Module flight program | Comanche055/ |
80 .agc files; CSM control software |
| Lunar Module flight program | Luminary099/ |
86 .agc files; LM control software |
| Localised documentation | Translations/ |
70 README.<lang>.md / CONTRIBUTING.<lang>.md |
| Project documentation | README.md, CONTRIBUTING.md, LICENSE.md |
English originals |
| Lint configuration | .markdownlint.yml, package.json, .editorconfig |
Markdown lint pipeline |
| Repository hygiene | .gitignore, bun.lockb |
Standard ignores; Bun lockfile |
1.5 Technology stack
| Layer | Technology |
|---|---|
| Source language | AGC assembly (yaYUL dialect) |
| Original assembler | YUL → GAP (1968, no longer available) |
| Modern assembler | yaYUL (Virtual AGC project) |
| Modern simulator | yaAGC + yaDSKY2 (Virtual AGC project) |
| Documentation | GitHub-Flavored Markdown |
| Lint | markdownlint-cli2 ^0.16.0 |
| Package manager | Bun (lockfile shipped); npm-compatible |
| Hosting | GitHub + Software Heritage mirror |
2. System Requirements
2.1 For reading and proof-reading
| Requirement | Minimum |
|---|---|
| Disk | ~30 MB (text only) |
| RAM | None beyond OS baseline |
| Tooling | git, any text editor, optionally grep/less |
| Network | Required only for cloning / fetching scans |
Proof-reading does not require a build toolchain. The reviewer's job is to compare the diff against scanned printout images, which can be done with two browser windows.
2.2 For markdown linting
| Requirement | Minimum |
|---|---|
| Node.js (npm path) | 18+ recommended for markdownlint-cli2 0.16 |
| Bun (lockfile path) | Any recent version |
| Disk | A few MB for node_modules/ |
| Network | Required only on first install |
2.3 For assembly and simulation
The Virtual AGC toolchain has its own requirements; the canonical reference is the virtualagc/virtualagc README. In practice on Linux:
| Requirement | Minimum |
|---|---|
| Compiler | GCC or Clang with C11 support |
| Build system | GNU Make |
| GUI libraries | wxWidgets (for yaDSKY2), Tcl/Tk (legacy DSKY) |
| Disk | ~1 GB for full Virtual AGC build |
Important
Virtual AGC is the only supported assembler/simulator. The original 1969 YUL and GAP assemblers are no longer available. Any toolchain claim in legacy documentation that does not refer to
yaYUL/yaAGCis historical and not actionable today.
2.4 Supported platforms
| Platform | Read | Lint | Assemble (Virtual AGC) |
|---|---|---|---|
| Linux | Yes | Yes | Yes (canonical) |
| macOS | Yes | Yes | Yes |
| Windows (WSL2) | Yes | Yes | Yes |
| Windows (native MinGW) | Yes | Yes | Possible, manual setup |
| FreeBSD / other UNIX | Yes | Yes | Probably (community) |
3. Configuration Reference
There is no runtime configuration. The only configuration files in the tree govern editor behaviour, markdown linting, and repository hygiene.
3.1 .editorconfig
root = true
[*]
indent_style = tab
indent_size = 8
trim_trailing_whitespace = true
Tab indentation with width 8 matches the original 1969 printout convention. Trimming trailing whitespace prevents accidental whitespace-only diffs. Editors that respect .editorconfig (most modern ones) will pick this up automatically.
| Key | Value | Why |
|---|---|---|
indent_style |
tab |
Original printout used hard tabs |
indent_size |
8 |
Original printout column width |
trim_trailing_whitespace |
true |
Avoids whitespace-only diffs |
3.2 .markdownlint.yml
default: true
MD007: false
MD010: false
MD013: false
MD026: false
MD033: false
MD034: false
MD036: false
MD041: false
MD050: false
MD053: false
The configuration disables 10 default rules that conflict with the multilingual / historical-attribution / table-heavy nature of the documentation. Enabling any of these would generate hundreds of false-positive lint failures across the translations folder.
| Rule | Default | Disabled — Why |
|---|---|---|
MD007 (ul-indent) |
error | Translation lists use varied indentation |
MD010 (no-hard-tabs) |
error | Tabs are intentional (matches .editorconfig) |
MD013 (line-length) |
error | Translation lines and attribution tables are intentionally long |
MD026 (no-trailing-punct in headings) |
error | Translation headings use punctuation in some scripts |
MD033 (no-inline-html) |
error | RTL languages (Arabic, Hebrew, Persian) use HTML for direction |
MD034 (no-bare-urls) |
error | Translation links in the README header are bare by design |
MD036 (emphasis-as-heading) |
error | Contract block uses bold-italic for role labels |
MD041 (first-line-h1) |
error | Some translations open with a TOC table |
MD050 (strong-style) |
error | Translations use varying bold conventions |
MD053 (link-image-reference-defs) |
error | Reference-link blocks span sections |
3.3 package.json
{
"scripts": {
"lint": "markdownlint-cli2 *.md translations/*.md Comanche055/*.md Luminary099/*.md --config .markdownlint.yml",
"lint:fix": "markdownlint-cli2 *.md translations/*.md Comanche055/*.md Luminary099/*.md --config .markdownlint.yml --fix"
},
"dependencies": {},
"devDependencies": {
"markdownlint-cli2": "^0.16.0"
}
}
| Script | Purpose |
|---|---|
npm run lint |
Lint all markdown files under root, translations/, Comanche055/, Luminary099/ against .markdownlint.yml. Used in CI / pre-merge. |
npm run lint:fix |
Same scope, but auto-fixes what is auto-fixable. |
Important
The script glob
translations/*.mdis lower-case while the directory in the repository isTranslations/(capitalised). On case-sensitive filesystems (Linux, CI runners), this glob may not match unless filesystem case-folding is on. Verify against your runner's filesystem semantics; if you need full coverage, runnpx markdownlint-cli2 'Translations/*.md'separately.
3.4 .gitignore
Standard Node.js / IDE patterns: node_modules/, .DS_Store, *.log, IDE config dirs. No build outputs (the repository produces no build artefacts).
3.5 Lockfile choice
The repository ships bun.lockb, indicating the maintainer uses Bun as the package manager rather than npm. npm install works (resolving from package.json), but contributors who modify devDependencies should use bun install to keep the lockfile coherent.
There is no package-lock.json checked in; when contributors run npm install it generates a transient lockfile that should not be committed.
3.6 Environment variables and runtime config
There are none. The repository has no runtime — only static text files plus an opt-in markdown lint pipeline.
4. Deployment & Scaling
There is no traditional deployment. The repository is a static collection of text files plus a markdown lint dev-dependency. "Deployment" here means publication and mirroring for long-term preservation.
4.1 Publication channels
| Channel | URL | Cadence |
|---|---|---|
| Primary GitHub repository | https://github.com/chrislgarry/Apollo-11 | Continuous |
| Software Heritage archive | https://archive.softwareheritage.org/browse/origin/https://github.com/chrislgarry/Apollo-11/ | Snapshot of master automatic |
| Virtual AGC mirror (independent transcription) | https://github.com/virtualagc/virtualagc | Independent |
4.2 Release process
There are no releases. The repository has no build outputs, no tags driven by content, no semantic version. Software Heritage snapshots master automatically; that is the canonical "release" surface.
Note
The absence of versions is by design: each merged PR is a small proof-reading delta, and tagging cuts would be arbitrary. If a published artefact is required (e.g. for citation), reference a specific commit hash.
4.3 Scaling considerations
| Dimension | Approach |
|---|---|
| Storage | Negligible (~30 MB total). Git repo is fine for archival. |
| Read traffic | GitHub handles all read load; no operational concern. |
| Contributor scale | Limited by reviewer bandwidth (proof-reading PRs need careful eye-against-scan review). |
| Translation scale | 39+ README translations and 28 CONTRIBUTING translations exist; new languages welcome but no automation. |
4.4 Rebuild from scratch
To produce a clean local copy for archival:
git clone --mirror https://github.com/chrislgarry/Apollo-11.git
cd Apollo-11.git
git bundle create apollo-11.bundle --all
sha256sum apollo-11.bundle > apollo-11.bundle.sha256
The mirror clone preserves all branches, tags, and refs. The bundle is a single-file artefact suitable for offline storage.
Tip
Pair the bundle with a copy of the linked scans at http://www.ibiblio.org/apollo/ScansForConversion/ for a fully self-contained archive that does not depend on third-party uptime.
5. Operations
5.1 Repository maintenance
There is no on-call rotation, no SLO, no production runbook. Day-to-day "operations" are PR review and issue triage.
Merging proof-reading PRs
- Squash by default — proof-reading commits are often noisy ("fix typo", "fix typo again"), and the per-page work is the meaningful unit.
- Preserve the page-number reference in the squashed commit message.
- If the PR touches multiple files, prefer keeping commits per-file and merging unsquashed.
Translations updates
When merging a translation PR:
- Verify the file is named
Translations/README.<lang>.mdorTranslations/CONTRIBUTING.<lang>.md. - Confirm the language link is added to root
README.mdandCONTRIBUTING.mdheaders. - Run
npm run lintto verify the new file passes the relaxed config.
New scans / new programs
The repository deliberately limits scope to Apollo 11 only (Comanche055 and Luminary099). Other AGC programs (Comanche072, Luminary116/131/210, Sundance, etc.) live at Virtual AGC. PRs that add new program directories should be redirected there.
5.2 Issue triage
Issues fall into recognisable categories:
| Category | Example | Action |
|---|---|---|
| Per-file proof campaign | "Proof XYZ.agc" | Leave open until the file is reconciled with scans |
| Typo report | "Line 42 has wrong word" | Convert to PR or close after fix |
| Off-topic | YouTube channel (#973) | Close politely |
| Validation tooling request | #960 "automated scan validation" | Track as long-running enhancement |
Tip
When closing an off-topic issue, point the submitter to the Virtual AGC project for assembly/simulation questions and to the Apollo Guidance Computer Software History on Wikipedia for general context. Most off-topic submissions are honest curiosity, not spam.
5.3 Active proof-reading campaigns
The following per-file campaigns are open as of commit 247dd7d:
| Issue | File | Status |
|---|---|---|
| #960 | (project-level) Add line-by-line validation tests against scans | OPEN |
| #608 | MEASUREMENT_INCORPORATION.agc |
OPEN |
| #217 | INTERPRETER.agc |
OPEN |
| #566 | AOTMARK.agc |
OPEN |
| #234 | P34-35_P74-75.agc |
OPEN |
| #204 | ERASABLE_ASSIGNMENTS.agc |
OPEN |
| #639 | SPS_BACK-UP_RCS_CONTROL.agc |
OPEN |
| #648 | TJET_LAW.agc |
OPEN |
| #647 | TIME_OF_FREE_FALL.agc |
OPEN |
5.4 Reviewer protocol
When reviewing a proof-reading PR:
- [ ] Open the cited scan page in a separate window or tab
- [ ] Walk every changed line in the diff against the scan
- [ ] Verify whitespace was changed only where scan-justified
- [ ] Check that no
R0000marker was removed or moved - [ ] Verify no perceived "code improvement" was bundled into the PR (out of scope)
- [ ] Run
npm run lintif the PR touched any.mdfile - [ ] Confirm the page number is in the commit message; ask for it if missing
Note
The reviewer's most common pushback is "please cite the scan page". This is non-negotiable: without it the reviewer cannot perform the comparison and cannot merge.
5.5 Edge cases
- Missing pages: If a scan page is illegible, the contact for higher-resolution images is
[email removed](Ron Burkey, Virtual AGC). - Disagreement between scans and Virtual AGC's mirror: This repository's transcription is independent of Virtual AGC's. Where they differ, the chrislgarry repo follows its own scans-first rule.
- GAP-generated tables: The original printouts include cross-reference tables generated by the GAP assembler at the end of each section. These are not transcribed — they are GAP-tool artefacts, not source. They are noted as "GAP-generated tables" in the program READMEs.
5.6 The transcription pipeline
1969 hardcopy printouts
|
v
MIT Museum custody
|
v
Paul Fjeld scans pages → high-resolution PNG/JPEG images
|
v
Hosted at ibiblio.org/apollo/ScansForConversion/
|
v
Community transcribes to .agc (line-by-line)
|
v
Pull request against chrislgarry/Apollo-11
|
v
Reviewer compares scan vs diff
|
v
Merge into master
|
v
Software Heritage mirror snapshots master
The community's tooling at https://28gpc.csb.app/ presents scan and transcription side-by-side for reviewers.
6. Performance
The repository itself has no runtime performance — it is a collection of text files. This section concerns:
- Lint pipeline performance (the only "build" step in the repo).
- AGC runtime performance characteristics, captured here because they are essential context for reading the source.
6.1 Lint pipeline
markdownlint-cli2 walks the four globs (*.md, Translations/*.md, Comanche055/*.md, Luminary099/*.md), parses each file, and reports rule violations.
| Phase | Wall time (modern laptop) |
|---|---|
npm install (cold, no cache) |
5–15 s |
bun install (cold) |
<2 s |
npm run lint |
~1 s |
npm run lint:fix |
~1 s |
There is no parallelism beyond what markdownlint-cli2 provides internally. The lint completes well within any reasonable CI budget.
6.2 AGC runtime characteristics (for source-reading context)
The original AGC ran at 1.024 MHz with ~12 µs per typical instruction — extraordinary slow by modern standards. This drove every architectural decision in the source:
| Constraint | Source-code consequence |
|---|---|
| ~80,000 instructions/second | Tight loops written in interpreter VM rather than native to save program memory; native code for time-critical paths only |
| 36 KW fixed memory | Aggressive code reuse; the interpreter "fan" is itself a compression mechanism |
| 2 KW erasable memory | VAC areas (vector accumulator scratch) are pooled and recycled |
| Bank-switched memory | Bank-aware boilerplate (BANK n, EBANK= label) at the top of every section |
| No floating point | Fixed-point arithmetic everywhere; scaling is encoded into the noun definitions in PINBALL_NOUN_TABLES.agc |
Tip
If a routine seems impossibly compact for the math it performs, check whether it is interpretive. The interpreter's higher-level opcodes pack a lot of capability per source line —
VLOAD,VSL4,MXV,STCALLand so on each do work that would take many native instructions.
6.3 The interpreter as a runtime
INTERPRETER.agc is the longest single source file in either program (Comanche055 pages 1107–1199, Luminary099 pages 1002–1094). It implements approximately 100 interpretive opcodes used pervasively by guidance, navigation, and integration code. Structurally, it is a small VM complete with:
- An opcode dispatch table (the interpretive "fan").
- A push-down stack.
- VAC and MPAC scratch areas (vector and primary accumulators).
- Type-aware opcodes (single-precision, double-precision, vector, mixed).
- Subroutine call / return (
CALL,EXIT).
Code that does any meaningful guidance math (Kalman filter updates, conic propagation, IMU compensation, lunar guidance equations) is mostly interpretive. Reading INTERPRETER.agc is essentially reading the runtime that those routines target.
When you see code like:
STCALL TPIP # interpretive: store, then call
VSL4 MXV
REFSMMAT
…that is interpretive code, executed by the interpreter, not native AGC instructions. Native instructions are short opcodes like TC, CA, TS, XCH, INDEX, EXTEND. The transition between the two modes is mediated by TC INTPRET (enter interpreter) and EXIT (return to native).
6.4 Real-time scheduling
The most timing-critical code in either program is the Digital Auto-Pilot (DAP): P-AXIS_RCS_AUTOPILOT.agc, Q_R-AXIS_RCS_AUTOPILOT.agc, DAPIDLER_PROGRAM.agc, DAP_INTERFACE_SUBROUTINES.agc in Luminary099; RCS-CSM_DIGITAL_AUTOPILOT.agc and the TVCDAPS.agc family in Comanche055.
DAP runs at high priority off T5RUPT for fast-loop autopilot updates. Spurious interrupts (rendezvous-radar in Apollo 11) can starve the executive of VAC areas — this is exactly what triggered the 1201/1202 alarms during the descent. The restart logic was specifically designed to handle this scheduling failure and recover the active mission program.
7. Security
There is no traditional attack surface: the repository ships text files, no executables, no installable code, no service. Standard "supply chain" considerations:
| Concern | Status |
|---|---|
| Executable code in the repo | None. .agc files are plain text. |
| Network exposure | None. Static files. |
| Secrets / credentials | None. Public domain code with public attribution. |
| Dependency CVEs | Surface limited to markdownlint-cli2. Watch via npm audit. |
Warning
The
markdownlint-cli2lint dependency itself has occasionally had transitive vulnerabilities. Runnpm audit fixperiodically and bump the pinned^0.16.0upper bound when a security release lands. This is the only realistic security maintenance burden the repository carries.
7.1 Public-domain status
NASA software written under government contract before 1978 has no copyright protection in the United States. The original Apollo Guidance Computer source code was developed by the MIT Instrumentation Laboratory under contract NAS 9-4065 with the NASA Manned Spacecraft Center (now Johnson Space Center). The contract block in Comanche055/CONTRACT_AND_APPROVALS.agc records the names and signing date of the original engineering team, including Margaret H. Hamilton (Colossus Programming Leader), Daniel J. Lickly, Fred H. Martin, Norman E. Sears, Richard H. Battin, David G. Hoag, and Ralph R. Ragan, dated 28 March 1969.
The LICENSE.md and per-file # Copyright: Public domain. headers reaffirm the public-domain status. Anyone may copy, modify, and redistribute the source without restriction.
Important
The transcription work performed by community contributors is also released under the same public-domain understanding. The repository accepts proof-reading PRs only; "improvements" or new code would not be in the public domain by default and are out of scope.
7.2 Mirroring for preservation
To protect against single-platform availability risk, the repository is mirrored at:
- Software Heritage — guaranteed preservation infrastructure.
- Virtual AGC — independent transcription with its own scan source.
- Multiple personal forks and mirrors across GitHub, GitLab, and other Git hosts.
Any maintainer who is concerned about long-term availability should clone with git clone --mirror to preserve the full history independent of GitHub.
7.3 No CI / no automation today
There is no GitHub Actions workflow checked in. Linting is performed locally by contributors. Adding a workflow that runs npm run lint on PRs is an obvious enhancement (see Section 8.6). Until that lands, the repository does not run any automated code on push, which means the CI attack surface is also nil.
8. Developer Internals
8.1 The operating-system layer
The AGC has no traditional OS — its scheduler, multitasker, and interrupt dispatch are all hand-coded into the rope. The relevant source files form a tightly-coupled core:
+------------------+
| INTERRUPT_LEAD_ | <- vector table at fixed addr 4000
| INS.agc |
+---------+--------+
|
+-----------------------+--------------------+
v v
+---------------+ +---------------------+
| T4RUPT_PROGRAM|---------+ | KEYRUPT_UPRUPT.agc |
| T6-RUPT_PROG..| | | (DSKY + uplink ISR) |
+---------------+ | +---------------------+
| v
v +-----------+
+---------------+ | WAITLIST | <-- timed-task scheduler
| EXECUTIVE.agc |<-+ .agc | (TASKOVER, NEWJOB, etc.)
| (cooperative | +-----------+
| priority | |
| scheduler) | v
+-------+-------+ +----------------+
| | RESTARTS_ | <-- fault-tolerant restart
+--------> | ROUTINE.agc | (1201, 1202, etc.)
+----------------+
Interrupt vector
INTERRUPT_LEAD_INS.agc is the AGC's vector table at fixed address 4000. Each interrupt type lands at a specific offset:
| Vector | Source | Trigger |
|---|---|---|
4000 |
GO (fresh start) |
Power-on reset |
4004 |
T6RUPT |
TIME6 counter overflow (digital autopilot) |
4010 |
T5RUPT |
TIME5 counter overflow (autopilot) |
4014 |
T3RUPT |
TIME3 counter overflow (waitlist) |
4020 |
T4RUPT |
TIME4 counter overflow (DSKY refresh, ~10 ms) |
4024 |
KEYRUPT1 |
DSKY keypress |
4030 |
KEYRUPT2 |
(LM only) AOT mark button |
4034 |
UPRUPT |
Uplink telemetry character received |
4040 |
DOWNRUPT |
Downlink telemetry character buffer empty |
4044 |
RADAR RUPT |
Radar data ready |
4050 |
RUPT10 |
Hand-controller / CDU drift |
Each lead-in saves accumulator state (DXCH ARUPT) and dispatches to the actual handler in another bank.
The executive
EXECUTIVE.agc is the cooperative priority scheduler. Jobs are submitted via two entry points:
NOVAC— priority job that needs no Vector Accumulator (VAC) area.FINDVAC— priority job that needs a VAC area (for interpretive math).
Each job carries a priority byte. The executive maintains a fixed-size table of core sets (job control blocks) and VAC areas (interpretive scratch). Overflow of either table is the cause of the now-famous 1202 (no VAC) and 1201 (no core set) restart alarms.
Job dispatch is cooperative: a running job yields by calling TC ENDOFJOB (no more work), TC JOBSLEEP (block on event), or TC CHANG1 (suspend for higher priority).
The waitlist
WAITLIST.agc implements the timed task scheduler — a min-heap-like structure where each entry has a delta-time relative to the entry above it. The T3RUPT interrupt fires on TIME3 overflow, decrements the head entry, and runs any task whose delta has reached zero.
This is how the AGC schedules deferred work: TC WAITLIST with a delta-time and a 2CADR (bank+address) installs a future task without blocking the current job.
Restart logic
The restart architecture is one of the AGC's most celebrated achievements. RESTARTS_ROUTINE.agc and FRESH_START_AND_RESTART.agc together implement:
- Phase tables (
PHASE_TABLE_MAINTENANCE.agc): each major mission program registers its current phase as a redundant pair of phase numbers. - Restart on alarm: when the executive overflows or the program detects an inconsistency, it invokes a software restart that re-validates phase tables, kills broken jobs, and resumes from the last known-good phase.
- Hardware restart (
V69): the operator can force a restart manually.
Important
During the Apollo 11 powered descent, spurious rendezvous-radar interrupts overloaded the executive's VAC pool, triggering 1201/1202 alarms. The restart logic in these files re-issued the in-progress mission program (P63 then P64) without losing position/velocity state. Buzz Aldrin and Neil Armstrong continued the descent because the restart system worked exactly as designed by the MIT team.
8.2 The verb/noun operating language
The astronaut interacts with the AGC through the DSKY — a 19-key keypad and a 7-digit display. Operations are encoded as a verb (action) plus a noun (data subject).
| File | Role |
|---|---|
PINBALL_GAME_BUTTONS_AND_LIGHTS.agc |
Keypad scanner, display driver, lamp logic, verb/noun decoder |
PINBALL_NOUN_TABLES.agc |
Noun definitions, scaling, units, decimal/octal display rules |
EXTENDED_VERBS.agc |
Verbs ≥40 (the operator-action verbs) |
DISPLAY_INTERFACE_ROUTINES.agc |
Display-mode arbitration (priority displays vs. monitor displays) |
Verb taxonomy
Verbs <40 are decoded inside PINBALL_GAME_BUTTONS_AND_LIGHTS.agc and are mostly display verbs (V01-V05 = display octal, V06-V07 = display decimal, V11-V25 = monitor variants, V37 = change major mode).
Verbs ≥40 are dispatched from a fan-out table at the top of EXTENDED_VERBS.agc (the LST2FAN table). A representative excerpt from Luminary099:
| Verb | Routine | Action |
|---|---|---|
V37 |
(in pinball) | Change major mode (selects P-program) |
V40 |
VBZERO |
Zero (used with Noun 20 or 72 only) |
V42 |
IMUFINEK |
Fine-align IMU |
V47 |
V47TXACT |
AGS (Abort Guidance System) initialisation |
V49 |
CREWMANU |
Start automatic attitude maneuver |
V57 |
LRON |
Permit landing-radar updates |
V58 |
LROFF |
Inhibit landing-radar updates |
V63 |
R04 |
Sample radar once per second |
V69 |
VERB69 |
Force a hardware restart |
V70-V73 |
V7?UPDAT |
Telemetry update (liftoff time, universal block, single, AGC time) |
V75 |
OUTSNUFF |
Enable U,V jets during DPS burns |
V76 |
MINIMP |
Minimum-impulse mode |
V77 |
NOMINIMP |
Rate-command mode |
V82 |
V82PERF |
Request orbit-parameter display (R30) |
V83 |
V83PERF |
Request rendezvous-parameter display (R31) |
V92 |
SYSTEST |
Operate IMU performance test |
V96 |
VERB96 |
Interrupt integration and go to P00 |
The exact verb roster differs between Comanche055 and Luminary099 — the LM has lunar-radar verbs, the CSM has reentry verbs.
Noun taxonomy
PINBALL_NOUN_TABLES.agc defines each noun's:
- Component count (1, 2, or 3 registers).
- Scale factor (units interpretation).
- Display format (octal vs. decimal, sign rules).
- Type (normal noun vs. mixed-noun).
Nouns 0–17 are reserved for DSKY internal use; nouns 18+ encode mission data (e.g. N17 = ICDU angle, N20 = present spacecraft attitude, N62 = present velocity).
8.3 Mission programs (P-program catalogue)
Mission programs are the high-level state machines. Each P-program drives one phase of the mission.
Comanche055 (CSM) major P-programs
| Program | File(s) | Phase |
|---|---|---|
P11 |
P11.agc |
Earth orbit insertion monitor |
P20-P25 |
P20-P25.agc |
Rendezvous navigation, sextant marking |
P30-P37 |
P30-P37.agc |
External Δv, return-to-Earth, deorbit targeting |
P32-P33 |
P32-P33_P72-P73.agc |
Coelliptic sequence initiate (CSI) |
P34-P35 |
P34-35_P74-75.agc |
Transfer phase initiate (TPI) targeting |
P40-P47 |
P40-P47.agc |
Major SPS / RCS burns |
P51-P53 |
P51-P53.agc |
IMU realignment via star sightings |
P61-P67 |
P61-P67.agc |
Atmospheric entry guidance |
P76 |
P76.agc |
Target Δv update from MSFN |
P37/P70 |
P37_P70.agc |
Return-to-Earth + entry maneuver |
Luminary099 (LM) major P-programs
| Program | File(s) | Phase |
|---|---|---|
P12 |
P12.agc |
LM ascent — aborted-stage |
P20-P25 |
P20-P25.agc |
Rendezvous navigation (LM perspective) |
P30/P37 |
P30_P37.agc |
External Δv targeting |
P32-P35/P72-P75 |
P32-P35_P72-P75.agc |
CSI, TPI, and active-vehicle counterparts |
P40-P47 |
P40-P47.agc |
DPS / APS burn programs |
P63-P67 |
THE_LUNAR_LANDING.agc + LUNAR_LANDING_GUIDANCE_EQUATIONS.agc |
Powered descent (P63 braking, P64 visibility, P66 ROD, P67 landed) |
P70-P71 |
P70-P71.agc |
DPS / APS abort |
P76 |
P76.agc |
Target Δv update |
R-routine catalogue (selected)
R-routines are reusable subroutines callable from any P-program:
| Routine | File | Purpose |
|---|---|---|
R02 |
various | IMU status check |
R04 |
(called via V63) | Sample radar |
R30 |
R30.agc |
Orbit parameter display |
R31 |
R31.agc |
Rendezvous parameter display |
R60/R61/R62 |
R60_62.agc |
Crew-defined attitude maneuver display |
R63 |
R63.agc (LM only) |
LM body-vector pointing |
R77 |
(called via V78/V79) | LR spurious-return test |
The full catalogue is enumerated in each program's README.md.
8.4 The "executive overflow" pattern (1201/1202)
The cause of the famous Apollo 11 alarms is structurally simple:
- The executive maintains fixed-size tables of core sets (job control blocks) and VAC areas (interpretive scratch).
- When a new job is requested via
NOVACorFINDVACand either table is full, the executive cannot allocate. - Rather than hang, the executive posts a program alarm (1201 or 1202) and triggers a software restart.
NOVAC entry
|
+-----------+-----------+
v v
free core set? alarm 1201
| + restart
v
install in pool
The restart path:
- Saves the current major mode and any registered restart-protected variables.
- Walks the phase table; each P-program records its current phase as a redundant pair (
PHASE_TABLE_MAINTENANCE.agc). - Re-issues the active P-program from its last good phase.
- Continues at the recovered point, having dropped the broken jobs.
Caution
The restart only works because every mission program is written to be restart-safe: it must register its phase before doing irreversible work, and it must be re-entrant from the registered phase. New code added to a P-program without honouring this contract would break restart recovery — but no new code is being added (this is a historical archive), so the contract is automatically preserved.
8.5 Idiomatic patterns
Reading any .agc file, you will see consistent conventions established by MIT in 1969:
- Tab-indented two-column layout: label column + opcode/operand column, both at fixed character positions.
- All-caps labels and opcodes: no mixed case anywhere in source.
- Pound-sign comments:
#introduces a line or trailing comment. - Bank-aware boilerplate: every section starts with
BANK n/SETLOC .../EBANK= ...to assert assembler context. - Page-number anchors:
# Page NNNcomments mark printout page boundaries. - Header copyright/provenance block: every file has the standard header described in Section 4.4 of the User Guide.
COUNT*directives:COUNT* $$/<TAG>records the section name for the GAP-generated cross-reference (yaYUL emits these into the.lst.html).
Common macros:
BANKCALL+CADR <label>— call a routine in another fixed bank with automatic bank save/restore.TC INTPRET— enter the interpreter; the next bytes are interpretive opcodes untilEXIT.INHINT/RELINT— disable / enable interrupts (used to bracket critical sections).EXTEND— flag the next instruction as an "extend" instruction (extra opcode space).CCS— count, compare, skip (the AGC's primary branch instruction; tests sign + zero of operand and skips by 0/1/2 instructions).
These conventions are historical artefacts. Do not modernise them.
8.6 Potential improvements
These are out-of-scope for the proof-reading focus of the repository, but worth tracking as long-term enhancements:
Automated scan-vs-source validation (issue #960)
A pipeline that runs OCR on each scanned page, normalises whitespace, and diffs against the transcription would catch many proof-reading discrepancies automatically. Likely tools: Tesseract OCR with a custom AGC training set, or a hand-tuned matcher that exploits the highly regular two-column layout.
GitHub Actions CI for markdown lint
A workflow file at .github/workflows/lint.yml would run npm run lint on every PR. This catches translation-formatting regressions before merge.
name: Lint
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- run: npm ci
- run: npm run lint
Per-program assembly check
A second CI step could git submodule add or pin a Virtual AGC commit and run yaYUL Luminary099/MAIN.agc, asserting that the binary image matches a known-good SHA-256. This would catch semantic corruption (label shifts, missing instructions) that markdownlint cannot.
Translations/ glob case sensitivity
package.json's lint script targets translations/*.md (lower-case) but the repository folder is Translations/. Aligning the glob to Translations/*.md would make linting consistent on case-sensitive filesystems.
Translation status table
A maintained table mapping language → last-updated commit → up-to-date-vs-master status would help translators identify which localisations need refreshing. Could be auto-generated from git log on each Translations/README.<lang>.md.
Page-number index
A machine-readable manifest (e.g. pages.json) mapping (program, file, page-range) would enable scan-viewer tools to deep-link from a page number to the exact file and line, accelerating proof-reading.
8.7 Code quality signals
Both Comanche055 and Luminary099 are remarkably well-commented for assembly code of their era. Substantial blocks of in-line prose explain mission intent, rationale for constants, and edge-case handling. Many comments preserve the original engineers' voices — BURN_BABY_BURN--MASTER_IGNITION_ROUTINE.agc is the most-quoted example, but any file's comment density is striking compared to typical 1960s assembly listings.
The interpreter's existence is itself a quality signal: a 1965-1969 team built a compact virtual machine for vector and double-precision arithmetic to compress program memory and improve readability, and they carried it forward across multiple program builds. The INTERPRETER.agc file is a genuinely impressive piece of language design for a memory-constrained machine.
9. Integration Points
9.1 Upstream dependencies
| Dependency | Role | Direction |
|---|---|---|
| MIT Museum (hardcopy custody) | Source of scanned printouts | Inbound (scans flow in) |
| Paul Fjeld (digitisation) | Page-image scans | Inbound |
markdownlint-cli2 (npm) |
Markdown lint of all .md files |
Build-time only |
| Bun runtime (optional) | Faster install via lockfile | Optional |
9.2 Downstream consumers
| Consumer | Role | URL |
|---|---|---|
| Virtual AGC | Independent transcription + simulator + assembler | https://github.com/virtualagc/virtualagc |
| Software Heritage | Archival mirror | Snapshots master automatically |
| Educational sites and books | Cite individual files / lines | e.g. Digital Apollo, Sunburst and Luminary |
| Side-by-side scan viewer | Web tool that renders source next to scans | https://28gpc.csb.app/ |
9.3 No webhooks, no APIs
There are no webhooks fired from this repository, no REST API exposed, no push-notification integration. Downstream consumers poll GitHub or rely on the Software Heritage snapshot cadence.
9.4 Maintainer contact channels
| Channel | URL / Contact |
|---|---|
| Repository issues | https://github.com/chrislgarry/Apollo-11/issues |
| Repository PRs | https://github.com/chrislgarry/Apollo-11/pulls |
| Virtual AGC project (assembler/simulator) | https://github.com/virtualagc/virtualagc |
| High-resolution scan custodian | Ron Burkey, [email removed] |
| Original digitisation | Paul Fjeld (via Virtual AGC project) |
| Hardcopy custodian | MIT Museum, https://web.mit.edu/museum/ |
9.5 File-tree statistics
| Metric | Value |
|---|---|
Total tracked files (commit 247dd7d) |
254 |
.agc source files |
165 (80 Comanche, 85 Luminary) |
| Markdown files (root + program + translations) | 76 |
| Configuration files | 5 (.editorconfig, .gitignore, .markdownlint.yml, package.json, bun.lockb) |
| Languages with README translations | 39+ |
| Languages with CONTRIBUTING translations | 28 |
9.6 Key historical dates encoded in source
| Date | Event |
|---|---|
| 28 March 1969 | Margaret Hamilton signs off Comanche055 contract block |
| 1 April 1969 | Comanche055 assembled (10:28 APR. 1, 1969) |
| 14 July 1969 | Luminary099 hardcopy printed (16:27 JUL. 14, 1969) |
| 16 July 1969 | Apollo 11 launch |
| 20 July 1969 | Eagle lands at Tranquility Base, running Luminary099 |
| 24 July 1969 | Splashdown, Columbia running Comanche055 through reentry |
9.7 Quick command reference
# Clone
git clone https://github.com/chrislgarry/Apollo-11.git
cd Apollo-11
# Install lint deps (npm)
npm install
# Or with Bun (matches checked-in lockfile)
bun install
# Lint markdown
npm run lint
npm run lint:fix
# Find a label across the whole tree
grep -rn "^P63LM" .
# Show file headers (page ranges, transcriber, mod history)
head -20 Luminary099/THE_LUNAR_LANDING.agc
# Count source files in each program
ls Comanche055/*.agc | wc -l
ls Luminary099/*.agc | wc -l
9.8 Glossary
AGC — Apollo Guidance Computer. The 15-bit, ~64 KW core-rope flight computer.
Bank, BANK directive — Memory-bank selector. AGC has banked fixed and erasable memory; BANK n directives in source declare which bank the assembler should fill.
BANKCALL — Macro for cross-bank function calls (saves and restores FBANK).
Block II — The AGC hardware revision used on Apollo 11 (and all manned Block lunar missions). Block I was the unmanned/early-test variant.
CADR — A 2-word combined-address-register. Encodes (bank, address) for cross-bank dispatch.
CDU — Coupling Data Unit. Hardware that translates IMU resolver angles into AGC-readable counters.
CMC / LGC — Command Module Computer / Lunar [Module] Guidance Computer. Two AGC instances on each mission.
Colossus — Family name of CSM flight programs across multiple Apollo missions. Build 055 = "Comanche" (Apollo 11).
Core rope — The mask-programmed read-only memory used for fixed program storage. Wires literally hand-woven through ferrite cores.
DAP — Digital Auto-Pilot. RCS-jet attitude control law.
DSKY — Display/Keyboard. The astronaut's interface to the AGC.
EBANK — Erasable bank register; EBANK= label declares the assumed bank for subsequent code.
Executive — The AGC's cooperative priority scheduler in EXECUTIVE.agc.
Fixed-fixed — The always-mapped portion of fixed memory (banks 02 and 03), addressable without bank switching.
GAP — The original 1968-era assembler that replaced YUL. No longer available.
IMU — Inertial Measurement Unit. Stable-platform gyro/accelerometer assembly.
Interpreter — The software-implemented virtual machine in INTERPRETER.agc that executes interpretive opcodes (vector/double-precision math).
Interpretive opcode — An opcode of the interpreter VM (e.g. VLOAD, VSL4, MXV, STCALL). Executed by the interpreter, not natively.
Luminary — Family name of LM flight programs. Build 099 = "Luminary 1A" (Apollo 11).
MPAC / VAC — Primary Accumulator / Vector Accumulator. Interpreter scratch areas.
P-program — Mission Program. State machine driving a mission phase (e.g. P63 = lunar-landing braking phase).
R-routine — Reusable subroutine called by P-programs (e.g. R30 = orbit-parameter display).
RCS — Reaction Control System. Attitude-control thrusters.
RUPT — Interrupt. Lead-ins live in INTERRUPT_LEAD_INS.agc at fixed address 4000.
Software restart — The fault-tolerant recovery path triggered by executive overflow. RESTARTS_ROUTINE.agc re-issues the active mission program from its last good phase.
SPS — Service Propulsion System. The CSM main engine. Fired in P40-P47 burns.
TVC — Thrust Vector Control. SPS-engine gimbal control (CSM only).
VAC area — Vector Accumulator scratch block allocated by the executive to interpretive jobs.
Verb / Noun — DSKY operating language. Verb = action, Noun = data subject.
Waitlist — Timed-task scheduler in WAITLIST.agc, driven by T3RUPT.
yaYUL / yaAGC / yaDSKY2 — yet-another re-implementations of the historical assembler / simulator / DSKY-UI under the Virtual AGC project (virtualagc/virtualagc).
YUL — The original AGC assembler. No longer available.