NQC
Dave Baum's Not Quite C, a small C-like language that compiles to the bytecode of LEGO's own RCX firmware, which made it the first popular way to program LEGO MINDSTORMS robots in text rather than graphical blocks
Created by Dave Baum
NQC, short for Not Quite C, is a small programming language with C-like syntax for LEGO’s programmable bricks: above all the yellow RCX from the 1998 MINDSTORMS Robotics Invention System, and later the CyberMaster, Scout and Spybotics. Dave Baum wrote it in 1998, within weeks of the RCX reaching shops. Instead of replacing LEGO’s firmware, NQC compiles programs into the bytecode that LEGO’s own firmware already interprets. This made it the easiest route from drag-and-drop RCX Code to typed programs, and for several years it was, by most accounts, the most popular way to program the RCX in text. NQC is a good example of a language shaped by the machine underneath it. Nearly every unusual restriction it has, from functions that cannot return values to a limit of eight subroutines, comes straight from what the RCX bytecode interpreter could do.
History & Origins
A toy that adults took apart
LEGO announced MINDSTORMS in January 1998 and shipped the Robotics Invention System (RIS) in the first week of September 1998. The kit’s programmable brick, the RCX, had a Hitachi H8 microcontroller, three motor outputs, three sensor inputs and an infrared link to a tower on the PC’s serial port. LEGO supplied RCX Code, a graphical language for Windows. Many of the earliest buyers were adults, and they soon wanted something more powerful.
The community opened up the brick quickly. Kekoa Proudfoot, a Stanford graduate student, documented the RCX’s internals, firmware and bytecodes. According to IEEE Spectrum, David Baum, who was then a software engineer at Motorola, worked out the communications protocol for the IR link. Baum then wrote a compiler for a C dialect he called Not Quite C. It turned source text into LEGO bytecodes and downloaded them through the IR tower, without touching the firmware.
The first months
The earliest traces of NQC are on LUGNET, the LEGO fan discussion server, whose lugnet.robotics group opened on 28 September 1998. On 30 September a member wrote that his projects were “using Dave Baum’s NQCC, rather than TLG’s graphical language” (TLG is The LEGO Group). On 6 October he posted a robot-tag program “written in NQC version 0.5b1”, which he downloaded from Baum’s page at enteract.com/~dbaum/lego/nqc/. By mid-October, Mac users were happy to have Baum’s NQC MPW tool, because LEGO’s software did not run on the Mac at all.
Baum later told IEEE Spectrum that for the first few months after he released NQC, he half-expected a letter from LEGO’s lawyers. It never came; instead, he says, he ended up meeting and befriending LEGO designers. The same article reports that, according to a LEGO official quoted at the 2001 Mindfest conference, the company might once have considered legal action against the hackers instead of welcoming them. NQC stayed a free, independent project under the Mozilla Public License. It was never sponsored or endorsed by LEGO.
Debian began packaging NQC 1.0b4 in December 1998. On 19 February 1999 LUGNET created a dedicated discussion group, lugnet.robotics.rcx.nqc, described in its charter as being for “an unofficial language and compiler for programming the LEGO MINDSTORMS RIS”.
Design Philosophy
The NQC Programmer’s Guide is open about what the language is and is not:
Although the preprocessor and control structures of NQC are very similar to C, NQC is not a general purpose language - there are many restrictions that stem from limitations of the LEGO bytecode interpreter.
Three ideas run through the design:
- Keep LEGO’s firmware. NQC programs run on the standard firmware. As Baum’s FAQ points out, RCX Code, ROBOLAB and NQC programs can then sit on the brick side by side, and the user keeps the firmware’s stability and its on-brick interface, such as the View button. The cost is that NQC “must live within the constraints of the standard firmware”. There is no floating point, for example, because the firmware has none. Alternatives such as legOS and pbForth replaced the firmware to remove those limits.
- Look like C, so C programmers feel at home. The project’s welcome page puts it simply: for a C programmer who prefers “typing a few lines to drag and drop icon programming”, NQC “may be perfect”.
- Separate the language from the API. The guide defines NQC as two pieces: the language (syntax, statements, preprocessor) and the API (functions and constants such as
OnFwd,SENSOR_1andOUT_A). The API is a header file built into the compiler, andnqc -apiprints it. Supporting a new brick mostly meant writing new API definitions, not changing the language.
Key Features
Program structure
An NQC program is made of global variables and three kinds of code block:
| Block | Keyword | Notes |
|---|---|---|
| Task | task | Maps directly onto a firmware task. main starts when the program runs. The RCX allows 10 tasks, CyberMaster 4, Scout 6 and Spybotics 8 |
| Inline function | void | Expanded inline at every call site. Takes arguments, but cannot return a value |
| Subroutine | sub | One shared copy of the code, but no arguments, no calls to other subroutines, and at most 8 on the RCX |
The guide explains the void keyword as “an artifact of NQC’s heritage”: since functions cannot return data, every function is declared void. Function arguments come in six flavours, int, const int, int &, const int &, int* and const int*, because some firmware operations accept only constants and others only variables.
A taste of NQC
This program drives a two-motor robot forward until its bumper (a touch sensor on input 1) is pressed, then backs up:
| |
until, repeat (n) and start/stop for tasks are NQC additions to C’s familiar if, while, do, for and switch.
Types and storage
Every NQC variable is a 16-bit signed integer. Pointers to integers were added in NQC 3.0. Variables are assigned to the brick’s limited global and local storage locations by the compiler. #pragma reserve keeps the compiler away from particular locations, such as the ones the RCX 2.0 firmware uses for its counters.
Events and resource control
From NQC 2.2 the language added two statements for targets whose firmware supports them (the Scout, RCX 2.0 firmware, Spybotics and Dick Swan’s firmware):
| |
acquire asks for ownership of outputs or sound, and jumps to catch if a higher-priority task takes them away. monitor runs a block while watching up to 16 configurable events, with separate catch handlers for different events. These statements gave NQC a structured, almost exception-like way to write the reactive, interrupt-driven code that robots need.
The compiler as a toolkit
The nqc command does more than compile. It downloads programs and firmware over the IR tower (including a -firmfast firmware-download mode that, according to the 2.1 release notes, loads firmware about four times as fast as the standard method but needs the IR tower in “near” mode), prints disassembly listings, can merge source with assembly, and selects targets with options such as -TRCX2, -TScout and -Tspy. Its asm statement lets programmers emit raw bytecodes when the API lacks something.
Evolution
NQC’s release notes show a language that grew with LEGO’s product line:
| Version | Approximate date | Highlights |
|---|---|---|
| 0.5b1 | in use by October 1998 | Early public build, already in hobbyist use |
| 1.0b4 | by December 1998 | First Debian package |
| 2.0 | 1999 | First 2.x release; 2.0.2 packaged for Debian by November 1999 |
| 2.1 | — | Scout support, switch, faster firmware download, -T target option |
| 2.2 | — | Preliminary RCX 2.0 API, local variables, monitor/acquire, for, arrays on RCX 2 |
| 2.3 | by October 2001 | Conditions and expressions merged with C precedence, multiple catch clauses |
| 2.4 | — | Ternary ?:, shift and xor operators, USB IR tower support; old 1.x syntax removed |
| 2.5 | by 2003 | Spybotics support, limited goto, Linux USB tower driver |
| 3.0 a1/a2 | January–February 2004 | Pointers, built-in Spybotics API, asm syntax change |
| 3.1 r1–r6 | March 2005 – June 2007 | Swan firmware, LASM-compatible listings, bug fixes, 64-bit builds |
| 4.0.0–4.1.0 | April–September 2025 | BrickBot community releases: TCP support (for the BrickEmu emulator), Cygwin and WebAssembly builds, bundled libraries and docs |
Version dates before 2004 come from Debian package uploads and LUGNET posts, so they show when a release was in use, not the day it came out. The 2.1, 2.2 and 2.4 releases cannot be dated from the sources consulted; 2.3 r1 is dated only by its Debian upload in October 2001.
Baum’s own copyright notices run through 2005, and the 3.x Programmer’s Guide is credited to “Dave Baum & John Hansen”. The 3.x releases, starting with the 3.0 betas of January 2004, are published on the SourceForge site of the Bricx Command Center project, and source files carry portions copyrighted by John Hansen in 2005. When LEGO released the NXT brick in 2006, NQC did not follow. Its home page sends NXT users to NXC (Not eXactly C), which it describes as “very similar to NQC so that you don’t have to learn a completely new programming language.”
Current Relevance
The original NQC line stopped at 3.1 r6 in June 2007, and LEGO reportedly discontinued the last RCX-based set, the Robotics Invention System 2.0, around 2006, when the NXT replaced it. That is why NQC is listed here as historical. It is not dead, though. The RCX still has an active retro community, and NQC remains its standard language:
- Distribution packages. Debian still ships NQC. Its unstable branch moved to 4.1.0 after many years on 3.1 r6.
- BrickBot/nqc. Since April 2025 this GitHub repository has published new releases. It merges patches that were posted to SourceForge but never applied, fixes for OS X and BSD from John Verne’s 2014 fork, and a WebAssembly target. Version 4.1.0 also brought the old tutorial, FAQ and Baum’s book examples into a documentation site.
- In the browser. WebPBrick compiles NQC in a web page and talks to a real RCX through the Web Serial and WebUSB APIs. Someone with a 1998 brick and an IR tower can now program it without installing anything.
Why It Matters
NQC was one of the first and most widely used results of the “right to hack” culture that grew up around MINDSTORMS. It showed that a hobbyist could put a real textual language on a commercial toy without permission and without replacing its firmware, simply by targeting the bytecode the vendor had already shipped. LEGO’s decision to tolerate, and later welcome, the hackers rather than pursue legal action left room for that kind of work.
As a language, NQC is a clear case study in designing for a fixed virtual machine. Its quirks are not arbitrary. Each one shows a limitation of the RCX bytecode interpreter, so reading the NQC manual is also a guided tour of what LEGO’s firmware could and could not do. For many students in university robotics courses, and for thousands of hobbyists, it was also a first introduction to concurrent, event-driven embedded programming: several tasks sharing motors, sensors firing events, and code that has to react to the physical world in real time.
Timeline
Notable Uses & Legacy
Hobbyist RCX robotics
NQC was the main text language of the early MINDSTORMS community, which shared programs on LUGNET from the autumn of 1998. A 1999 LUGNET feature called it "a highly popular third-party tool", and in 2001 IEEE Spectrum reported that tens of thousands of users had downloaded the compiler
University robotics courses
Courses used NQC to teach embedded and robot programming on the RCX. Brown University's 2001 robotics course (CS148), for example, did its programming work in NQC, and its lecture notes compared NQC with the replacement-firmware legOS
RCX Command Center and BricxCC
Mark Overmars' RCX Command Center (RcxCC), and its successor Bricx Command Center (BricxCC), are Windows IDEs that call the NQC compiler to edit programs, download them to the brick and control it
MINDSTORMS books and tutorials
NQC was the language of Dave Baum's own books for Apress and of Mark Overmars' widely copied tutorial. Knudsen's O'Reilly guide also gave it a chapter
WebPBrick
A browser IDE started in 2024 that compiles NQC with a WebAssembly build of the compiler, offers the Blockly-based BlockNQC editor, and downloads programs to a real RCX through LEGO's serial or USB IR tower over the Web Serial and WebUSB APIs