Note: this is NOT the official q3lcc source! I repeat, this is NOT the stuff from Id Software!

UPDATE: as of November 2002, the official q3lcc souce from Id Software is available in their Q3 1.32 SDK from their FTP site, I am not mirroring that stuff here.


Translate C source text into Q3VM assembly compatible with q3asm and Q3VM.


The Linux Quake 3 SDK (linuxq3a-sdk) comes with binary-only q3lcc, that is, without source available. The source text for the modified lcc has been long in coming, and is still yet to be released of this writing (9 Jun 2002). As far as I can tell, lcc is the last in the Q3 toolchain without source available.

Prompted by this lack of source text and my (admittedly puny) experience with Q3VM-style assembly, I set about to discover the changes to lcc to make it Q3VM-friendly. Apparently, I'm not the first to attempt such a feat. I was ushered down the final coding leg by zinx(at on Incidentally, zinx also made the final breakthrough in solving the CNSTF4 bug (where lcc would output "ADDRGP4 floataddress; IDIRF4" instead of just "CNSTF4 value").


Edit for installation path, at line 7 (prefix=). Typical values are "/usr/local" or "/opt". You might want to back up any previous installations of q3lcc and friends.

Run without parameters. This will build lcc and install them in the path specified in the script. Files in bin/ are q3lcc, q3rcc, and q3cpp.

This is mostly a drop-in replacement for Id's q3lcc.


Although C source lines are printed as assembly comments, there might be minor problems regarding certain sequences of whitespaces.

Tested only on Debian GNU/Linux unstable (2002.06.06). This includes building lcc, installing lcc, compiling qvm, and testing qvm (by running Quake 3).


Programming Notes

Makefile-ish files are modified to prefix "q3" to names of lcc binaries.

lcc-4.1/lburg/gram.c is automagically derived by running a grammar generator (bison) on lcc-4.1/lburg/gram.y. If compiling gram.c fails, you may need to delete the file and run yacc or bison on gram.y to recreate a newer gram.c.

All functions return a value, regardless of type. This means any call to a void-type function must deal with a(n undefined type) return value. This is dealt with by a Q3VM-specific "pop" opcode. Any other types of function calls (I=signed integer, U=unsigned integer, F=floating-point, P=pointer value) for which the return value is not immediately used (arithmetic, comparision, or assignment) must be discarded with the "pop" opcode. I originally had a pretty evil hack in bytecode.c to produce the "pop" opcode as needed, but zinx found a cleaner solution, which is currently used instead.

All floating-point values are mashed into "float" (32-bit floating-point). Literal float constants (e.g. "float foo = 3.141516;") have to be forced into "float" type. These modifications are scattered among bytecode.c, lex.c, simp.c, types.c.

Q3 SDK 1.32, containing the official qlcc, from Id's ftp:

Diff against lcc-4.1 (entire tree): q3lcc-PH-00003.diff.gz (3375 B)

The canonical homepage for LCC is
Direct link to lcc 4.1 tarball (660 KB)

-- PhaethonH (