Quake C Disassembler Documentation _______________________________________________________________________________________________________________ 1. Disclaimer I CAN ACCEPT NO RESPONSIBILITY FOR ANY DAMAGE CAUSED EITHER DIRECTLY OR INDIRECTLY, THROUGH TORT, NEGLIGENCE OR OTHERWISE BY THE USE OR MISUSE OF THE SOFTWARE SUPPLIED HEREIN. THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, AND INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY OR FITNESS FOR PURPOSE. IN NO EVENT SHALL I BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS, ARISING OUT OF ABILITY OR INABILITY TO USE THE SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES/COUNTRIES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, IN WHICH CASE I DO NOT PROVIDE SPECIFIC LICENSE TO DISTRIBUTE THE SOFTWARE IN THOSE STATES/COUNTRIES, AND IT IS IMPORTED ENTIRELY AT THE USER'S OWN RISK. (I.E. YOU TAKE ON RESPONSIBILITY FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR IMPORTATION OF THE SOFTWARE). If that disclaimer isn't long or complicated enough, then you're not reading it properly. 2. Using the Program Firstly, you need to be a raving mad assembly language/Quake C hacker to like this program. Here endeth the sanity. The command line is as follows qcc_dasm [switches...] You *MUST* include the filename. If you don't specify any switches, you just get a disassembly of each and every function. The switches are optional, and are, in order: -allglobals Dump a list of all the global symbols in the PROGS.DAT file. This includes the function and field symbols, along with all immediate values used in the Quake C. -allfields Dump a list of all the field symbols in the PROGS.DAT file. -allfunctions Dump a list of all the function symbols in the PROGS.DAT file. -all Dump all of the above -global Print information about the specified global -field Print information about the specified field -function Print information about the specified function -function_disassembly Disassemble the specified function -disassemble_all Disassemble all the statements (doesn't produce very useful output, but you might want to do this for some reason) -disassemble_functions Disassemble all the functions -info Print file information All output is to the screen, so if you want it in a file (a *GOOD* idea - qcc_dasm produces about 1.5Mb of code when you do this on a full progs.dat), you'll have to redirect it. An example: qcc_dasm c:\quake\id1\progs.dat -info -disassemble_functions > out.txt Note that qcc_dasm will perform the requested operations in the order you tell it to on the command line; this will first output information to the file, followed by disassembling all the functions. 3. Notes on the assembly language If you see , what this means is that the disassembler was unable to determine the name of the symbol with index xxxxx. You'll see this a great deal, because the Quake C compiler (qcc) generates global variables for each and every stage of every single expression. The assembly language is a three-operand format: mnemonic.type source1, source2, destination Some instructions are only two operands, in which case it is: mnemonic.type source1, destination The operands are in RISC-like/Motorola-like ordering, so the instruction mov.e self, Means copy the entity self into the entity in the global block with index 17483. Opcodes are: done This subroutine is finished mul.[f|v|fv|vf] Multiply [float|vector|float by vector|vector by float] div.f Divide float add.[f|v] Add [float|vector] sub.[f|v] Subtract [float|vector] teq.[f|v|s|e|p] Test equality [float|vector|string|entity|function] tne.[f|v|s|e|p] Test inequality [float|vector|string|entity|function] tle.f Test less than or equal tge.f Test greater than or equal tlt.f Test less than tgt.f Test greater than ldm.[f|v|s|e|m|p] Load member (or field) [float|vector|string|entity|field|function] lea Load effective address of field mov.[f|v|s|e|m|p] Move [float|vector|string|entity|field|function] sto.[f|v|s|e|m|p] Store [float|vector|string|entity|field|function] in field pointed to by destination return Return a value from a function not.[f|v|s|e|p] !([float|vector|string|entity|function]) if if (source) then goto (destination) ifnot if !(source) then goto (destination) call.x Call function with x parameters state Sets the next frame to source1 and the think function to source2 goto goto (destination) and.l Logical AND (i.e. &&) or.l Logical OR (i.e. ||) and.f Bitwise AND (i.e. &) or.f Bitwise OR (i.e. |) P.S. Don't ask my opinion of the Quake C compiler. It's hopeless. Really really bad. All you have to do is look at the code it produces - it's terrible. And as for the 30,000 global variables, each taking up four bytes, and all the instructions that take 8 bytes each; well, I'll just go off and cry. However, it's what we've got, so we may as well make the most of it (or write another... but that's another story). _______________________________________________________________________________________________________________ Alastair Houghton ajh8@doc.ic.ac.uk [NO JUNK E-MAIL]