Quake(tm) Assembler Manual 1.0 ------------------------------ Copyright (C) 1996 by Ferrara Francesco QUAKE (C) 1996 id software, Inc., All right reserved Table of contents ----------------- 1. Introduction 2. The executable file PROGS.DAT 2. Crc calculus 4. Statements 4.1 Descriptions of instructions 5. Globaldefs 6. Fielddefs 7. Functions 8. Strings 9. Globals 10. Comments 11. Tables 11.1 Types 11.2 Standard offset for builtin functions 11.3 Builtin function number ________________________________________________________________________________ 1. Introduction This is a manual of Quake Assembler that are the instructions that Quake run for the entities in the QuakeWorld. It is a not so complex set of instructions. It's different from the sets known to computer world. I have written this manual from the analyzing of qcc compiler. The QuakeC compiler (qcc) can compile a subset of the ANSI C language into Quake Assembler so the game can run these instructions. If you want an introduction of the Quake Entities please read the one of the QuakeC specs. This manual is written to help the writing of other compilers maybe C++ or Assemblers for the game Quake. QuakeC is a lot far from the best compiler. All sources between bars are taken from the source code of QCC the QuakeC compiler. Please excuse my poor english, think to read this in Italian. If you want to help me with english write to the address below. This text is E-mail ware if you found this text useful you must write to me an e-mail letter!!! ;) E-Mail: frank@aerre.it HPage: http:\\www.aerre.it\~frank\qasm10.txt ________________________________________________________________________________ 2. The executable file PROGS.DAT Quake run the file progs.dat that is in your game data directory. That is \QUAKE\ID1 or the dir that you have specified with the '-game' option. It contains the instructions, the data, and the names of all your variables. The first thing in the file is the header. A struct that contains the number and the offset of the other struct of the datas. Now you can read below the first structure of progs.dat: ------------------------- typedef struct { int version; // The version nr. is 6 in Q1.01 int crc; // check of header file read CRC int ofs_statements; // This is the offset from the beginning of the file int numstatements; // This is the number of asm istructions 4 short wide (4*2 bytes) int ofs_globaldefs; int numglobaldefs; // That contains the definition of the names of variables int ofs_fielddefs; int numfielddefs; // That contains the definition of the names of fields of entity int ofs_functions; int numfunctions; // This is the nr. of info struct for functions int ofs_strings; int numstrings; // This is the nr. of byte that this list contains int ofs_globals; int numglobals; // That is a long list of float values int entityfields; // How many field that are in the entity data struct } dprograms_t; ------------------------- ________________________________________________________________________________ 3. CRC Calculus This is a 16 bit, non-reflected CRC using the polynomial 0x1021 and the initial and final xor values shown below... in other words, the CCITT standard CRC used by XMODEM. ------------------------- #define CRC_INIT_VALUE 0xffff #define CRC_XOR_VALUE 0x0000 static unsigned short crctable[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; void CRC_Init(unsigned short *crcvalue) { *crcvalue = CRC_INIT_VALUE; } void CRC_ProcessByte(unsigned short *crcvalue, byte data) { *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data]; } unsigned short CRC_Value(unsigned short crcvalue) { return crcvalue ^ CRC_XOR_VALUE; } ------------------------- You must construct a file progdefs.h like this: ------------------------- /* file generated by qcc, do not modify */ typedef struct { int pad[28]; int self; int other; int world; float time; float frametime; float force_retouch; string_t mapname; float deathmatch; float coop; float teamplay; float serverflags; float total_secrets; float total_monsters; float found_secrets; float killed_monsters; float parm1; float parm2; float parm3; float parm4; float parm5; float parm6; float parm7; float parm8; float parm9; float parm10; float parm11; float parm12; float parm13; float parm14; float parm15; float parm16; vec3_t v_forward; vec3_t v_up; vec3_t v_right; float trace_allsolid; float trace_startsolid; float trace_fraction; vec3_t trace_endpos; vec3_t trace_plane_normal; float trace_plane_dist; int trace_ent; float trace_inopen; float trace_inwater; int msg_entity; func_t main; func_t StartFrame; func_t PlayerPreThink; func_t PlayerPostThink; func_t ClientKill; func_t ClientConnect; func_t PutClientInServer; func_t ClientDisconnect; func_t SetNewParms; func_t SetChangeParms; } globalvars_t; typedef struct { float modelindex; vec3_t absmin; vec3_t absmax; float ltime; float movetype; float solid; vec3_t origin; vec3_t oldorigin; vec3_t velocity; vec3_t angles; vec3_t avelocity; vec3_t punchangle; string_t classname; string_t model; float frame; float skin; float effects; vec3_t mins; vec3_t maxs; vec3_t size; func_t touch; func_t use; func_t think; func_t blocked; float nextthink; int groundentity; float health; float frags; float weapon; string_t weaponmodel; float weaponframe; float currentammo; float ammo_shells; float ammo_nails; float ammo_rockets; float ammo_cells; float items; float takedamage; int chain; float deadflag; vec3_t view_ofs; float button0; float button1; float button2; float impulse; float fixangle; vec3_t v_angle; float idealpitch; string_t netname; int enemy; float flags; float colormap; float team; float max_health; float teleport_time; float armortype; float armorvalue; float waterlevel; float watertype; float ideal_yaw; float yaw_speed; int aiment; int goalentity; float spawnflags; string_t target; string_t targetname; float dmg_take; float dmg_save; int dmg_inflictor; int owner; vec3_t movedir; string_t message; float sounds; string_t noise; string_t noise1; string_t noise2; string_t noise3; } entvars_t; #define PROGHEADER_CRC 5927 ------------------------- With the two struct of global vars and entities vars pass this file byte by byte to crc and then write the last line the the decimal code. Like this functions, the filename is "progdefs.h": ------------------------- int PR_WriteProgdefs (char *filename) { def_t *d; FILE *f; unsigned short crc; int c; printf ("writing %s\n", filename); f = fopen (filename, "w"); // print global vars until the first field is defined fprintf (f,"\n/* file generated by qcc, do not modify */\n\ntypedef struct\n{\tint\tpad[%i];\n", RESERVED_OFS); for (d=pr.def_head.next ; d ; d=d->next) { if (!strcmp (d->name, "end_sys_globals")) break; switch (d->type->type) { case ev_float: fprintf (f, "\tfloat\t%s;\n",d->name); break; case ev_vector: fprintf (f, "\tvec3_t\t%s;\n",d->name); d=d->next->next->next; // skip the elements break; case ev_string: fprintf (f,"\tstring_t\t%s;\n",d->name); break; case ev_function: fprintf (f,"\tfunc_t\t%s;\n",d->name); break; case ev_entity: fprintf (f,"\tint\t%s;\n",d->name); break; default: fprintf (f,"\tint\t%s;\n",d->name); break; } } fprintf (f,"} globalvars_t;\n\n"); // print all fields fprintf (f,"typedef struct\n{\n"); for (d=pr.def_head.next ; d ; d=d->next) { if (!strcmp (d->name, "end_sys_fields")) break; if (d->type->type != ev_field) continue; switch (d->type->aux_type->type) { case ev_float: fprintf (f,"\tfloat\t%s;\n",d->name); break; case ev_vector: fprintf (f,"\tvec3_t\t%s;\n",d->name); d=d->next->next->next; // skip the elements break; case ev_string: fprintf (f,"\tstring_t\t%s;\n",d->name); break; case ev_function: fprintf (f,"\tfunc_t\t%s;\n",d->name); break; case ev_entity: fprintf (f,"\tint\t%s;\n",d->name); break; default: fprintf (f,"\tint\t%s;\n",d->name); break; } } fprintf (f,"} entvars_t;\n\n"); fclose (f); // do a crc of the file CRC_Init (&crc); f = fopen (filename, "r+"); while ((c = fgetc(f)) != EOF) CRC_ProcessByte (&crc, c); fprintf (f,"#define PROGHEADER_CRC %i\n", crc); fclose (f); return crc; } ------------------------- ________________________________________________________________________________ 4. Statements The structure of one asm istruction is: ------------------------- typedef struct statement_s { unsigned short op; short a,b,c; } dstatement_t; ------------------------- The op is the opcode that are: Nummber,Name, Priotity, RightAssociative, 1stpar, 2ndpar, respar. 0x00 DONE, -1, false, &def_entity, &def_field, &def_void 0x01 MUL_F, 2, false, &def_float, &def_float, &def_float 0x02 MUL_V, 2, false, &def_vector, &def_vector, &def_float 0x03 MUL_FV, 2, false, &def_float, &def_vector, &def_vector 0x04 MUL_VF, 2, false, &def_vector, &def_float, &def_vector 0x05 DIV, 2, false, &def_float, &def_float, &def_float 0x06 ADD_F, 3, false, &def_float, &def_float, &def_float 0x07 ADD_V, 3, false, &def_vector, &def_vector, &def_vector 0x08 SUB_F, 3, false, &def_float, &def_float, &def_float 0x09 SUB_V, 3, false, &def_vector, &def_vector, &def_vector 0x0a EQ_F, 4, false, &def_float, &def_float, &def_float 0x0b EQ_V, 4, false, &def_vector, &def_vector, &def_float 0x0c EQ_S, 4, false, &def_string, &def_string, &def_float 0x0d EQ_E, 4, false, &def_entity, &def_entity, &def_float 0x0e EQ_FNC, 4, false, &def_function, &def_function, &def_float 0x0f NE_F, 4, false, &def_float, &def_float, &def_float 0x10 NE_V, 4, false, &def_vector, &def_vector, &def_float 0x11 NE_S, 4, false, &def_string, &def_string, &def_float 0x12 NE_E, 4, false, &def_entity, &def_entity, &def_float 0x13 NE_FNC, 4, false, &def_function, &def_function, &def_float 0x14 LE, 4, false, &def_float, &def_float, &def_float 0x15 GE, 4, false, &def_float, &def_float, &def_float 0x16 LT, 4, false, &def_float, &def_float, &def_float 0x17 GT, 4, false, &def_float, &def_float, &def_float 0x18 INDIRECT, 1, false, &def_entity, &def_field, &def_float 0x19 INDIRECT, 1, false, &def_entity, &def_field, &def_vector 0x1a INDIRECT, 1, false, &def_entity, &def_field, &def_string 0x1b INDIRECT, 1, false, &def_entity, &def_field, &def_entity 0x1c INDIRECT, 1, false, &def_entity, &def_field, &def_field 0x1d INDIRECT, 1, false, &def_entity, &def_field, &def_function 0x1e ADDRESS, 1, false, &def_entity, &def_field, &def_pointer 0x1f STORE_F, 5, true, &def_float, &def_float, &def_float 0x20 STORE_V, 5, true, &def_vector, &def_vector, &def_vector 0x21 STORE_S, 5, true, &def_string, &def_string, &def_string 0x22 STORE_ENT, 5, true, &def_entity, &def_entity, &def_entity 0x23 STORE_FLD, 5, true, &def_field, &def_field, &def_field 0x24 STORE_FNC, 5, true, &def_function, &def_function&def_function}, 0x25 STOREP_F, 5, true, &def_pointer, &def_float, &def_float 0x26 STOREP_V, 5, true, &def_pointer, &def_vector, &def_vector 0x27 STOREP_S, 5, true, &def_pointer, &def_string, &def_string 0x28 STOREP_ENT, 5, true, &def_pointer, &def_entity, &def_entity 0x29 STOREP_FLD, 5, true, &def_pointer, &def_field, &def_field 0x2a STOREP_FNC, 5, true, &def_pointer, &def_function&def_function}, 0x2b RETURN, -1, false, &def_void, &def_void, &def_void 0x2c NOT_F, -1, false, &def_float, &def_void, &def_float 0x2d NOT_V, -1, false, &def_vector, &def_void, &def_float 0x2e NOT_S, -1, false, &def_vector, &def_void, &def_float 0x2f NOT_ENT, -1, false, &def_entity, &def_void, &def_float 0x30 NOT_FNC, -1, false, &def_function, &def_void, &def_float 0x31 IF, -1, false, &def_float, &def_float, &def_void 0x32 IFNOT, -1, false, &def_float, &def_float, &def_void 0x33 CALL0, -1, false, &def_function, &def_void, &def_void 0x34 CALL1, -1, false, &def_function, &def_void, &def_void 0x35 CALL2, -1, false, &def_function, &def_void, &def_void} 0x36 CALL3, -1, false, &def_function, &def_void, &def_void} 0x37 CALL4, -1, false, &def_function, &def_void, &def_void 0x38 CALL5, -1, false, &def_function, &def_void, &def_void 0x39 CALL6, -1, false, &def_function, &def_void, &def_void 0x3a CALL7, -1, false, &def_function, &def_void, &def_void 0x3b CALL8, -1, false, &def_function, &def_void, &def_void 0x3c STATE, -1, false, &def_float, &def_float, &def_void 0x3d GOTO, -1, false, &def_float, &def_void, &def_void 0x3e AND, 6, false, &def_float, &def_float, &def_float 0x3f OR, 6, false, &def_float, &def_float, &def_float 0x40 BITAND, 2, false, &def_float, &def_float, &def_float 0x41 BITOR, 2, false, &def_float, &def_float, &def_float 4.1 Descriptions of instructions 0x00 DONE It is the last istr. of procedure. That end the proc. 0x01 MUL_F, 2, false, &def_float, &def_float, &def_float 0x02 MUL_V, 2, false, &def_vector, &def_vector, &def_float 0x03 MUL_FV, 2, false, &def_float, &def_vector, &def_vector 0x04 MUL_VF, 2, false, &def_vector, &def_float, &def_vector These instruction multiply their args 0x05 DIV, 2, false, &def_float, &def_float, &def_float Only two float can be divided 0x06 ADD_F, 3, false, &def_float, &def_float, &def_float 0x07 ADD_V, 3, false, &def_vector, &def_vector, &def_vector Adding. You can't add a float to a vector 0x08 SUB_F, 3, false, &def_float, &def_float, &def_float 0x09 SUB_V, 3, false, &def_vector, &def_vector, &def_vector Subtract. 0x0a EQ_F, 4, false, &def_float, &def_float, &def_float 0x0b EQ_V, 4, false, &def_vector, &def_vector, &def_float 0x0c EQ_S, 4, false, &def_string, &def_string, &def_float 0x0d EQ_E, 4, false, &def_entity, &def_entity, &def_float These instr. test the the 1st and the 2nd args and then emit in the result 0(false) or 1(true) the answer. 0x0e EQ_FNC, 4, false, &def_function, &def_function, &def_float This instruction test if a function is defined. 0x0f NE_F, 4, false, &def_float, &def_float, &def_float 0x10 NE_V, 4, false, &def_vector, &def_vector, &def_float 0x11 NE_S, 4, false, &def_string, &def_string, &def_float 0x12 NE_E, 4, false, &def_entity, &def_entity, &def_float Not equal. 0x13 NE_FNC, 4, false, &def_function, &def_function, &def_float This istruction test if a function is not defined 0x14 LE, 4, false, &def_float, &def_float, &def_float 1st <= 2nd args 0(false) 1(true) in result 0x15 GE, 4, false, &def_float, &def_float, &def_float 1st >= 2nd args 0(false) 1(true) in result 0x16 LT, 4, false, &def_float, &def_float, &def_float 1st < 2nd args 0(false) 1(true) in result 0x17 GT, 4, false, &def_float, &def_float, &def_float 1st > 2nd args 0(false) 1(true) in result 0x18 INDIRECT, 1, false, &def_entity, &def_field, &def_float Access a float field in an entity vars. 0x19 INDIRECT, 1, false, &def_entity, &def_field, &def_vector Access a vector field in an entity vars. 0x1a INDIRECT, 1, false, &def_entity, &def_field, &def_string Access a string field in an entity vars. 0x1b INDIRECT, 1, false, &def_entity, &def_field, &def_entity Access a entity field in an entity vars. 0x1c INDIRECT, 1, false, &def_entity, &def_field, &def_field Access a field field in an entity vars. 0x1d INDIRECT, 1, false, &def_entity, &def_field, &def_function Access a function field in an entity vars. 0x1e ADDRESS, 1, false, &def_entity, &def_field, &def_pointer write a globals position of a entity.field type 0x1f STORE_F, 5, true, &def_float, &def_float, &def_float Movs a 1st vars in the 2nd, 3rd is ignored. 0x20 STORE_V, 5, true, &def_vector, &def_vector, &def_vector 0x21 STORE_S, 5, true, &def_string, &def_string, &def_string 0x22 STORE_ENT, 5, true, &def_entity, &def_entity, &def_entity 0x23 STORE_FLD, 5, true, &def_field, &def_field, &def_field 0x24 STORE_FNC, 5, true, &def_function, &def_function, &def_function 0x25 STOREP_F, 5, true, &def_pointer, &def_float, &def_float These instruction read the pointer grab the float in and write this to the 2nd pars 0x26 STOREP_V, 5, true, &def_pointer, &def_vector, &def_vector 0x27 STOREP_S, 5, true, &def_pointer, &def_string, &def_string 0x28 STOREP_ENT, 5, true, &def_pointer, &def_entity, &def_entity 0x29 STOREP_FLD, 5, true, &def_pointer, &def_field, &def_field 0x2a STOREP_FNC, 5, true, &def_pointer, &def_function, &def_function 0x2b RETURN, -1, false, &def_void, &def_void, &def_void This function return from a function. Contrary to DONE it is not the end of the function. 0x2c NOT_F, -1, false, &def_float, &def_void, &def_float 0x2d NOT_V, -1, false, &def_vector, &def_void, &def_float 0x2e NOT_S, -1, false, &def_vector, &def_void, &def_float 0x2f NOT_ENT, -1, false, &def_entity, &def_void, &def_float 0x30 NOT_FNC, -1, false, &def_function, &def_void, &def_float These istr. are logical not bitwise. 0x31 IF, -1, false, &def_float, &def_float, &def_void If 1st pars is true next istr is 2nd pars istr. after 0x32 IFNOT, -1, false, &def_float, &def_float, &def_void If 1st pars is false next istr is 2nd pars istr. after 0x33 CALL0, -1, false, &def_function, &def_void, &def_void A call with 0 parameter. 0x34 CALL1, -1, false, &def_function, &def_void, &def_void A call with 1 parameter. 0x35 CALL2, -1, false, &def_function, &def_void, &def_void A call with 2 parameter. 0x36 CALL3, -1, false, &def_function, &def_void, &def_void A call with 3 parameter. 0x37 CALL4, -1, false, &def_function, &def_void, &def_void A call with 4 parameter. 0x38 CALL5, -1, false, &def_function, &def_void, &def_void A call with 5 parameter. 0x39 CALL6, -1, false, &def_function, &def_void, &def_void A call with 6 parameter. 0x3a CALL7, -1, false, &def_function, &def_void, &def_void A call with 7 parameter. 0x3b CALL8, -1, false, &def_function, &def_void, &def_void A call with 8 parameter. 0x3c STATE, -1, false, &def_float, &def_float, &def_void the 1st arg is written to self.frame the 2nd is written to self.think, self.nextthink is automatically time+0.1 0x3d GOTO, -1, false, &def_float, &def_void, &def_void Goto to 1st pars istr. after is neg is before. 0x3e AND, 6, false, &def_float, &def_float, &def_float Logical and 0x3f OR, 6, false, &def_float, &def_float, &def_float Logical or 0x40 BITAND, 2, false, &def_float, &def_float, &def_float Bitwise and 0x41 BITOR, 2, false, &def_float, &def_float, &def_float Bitwise or ________________________________________________________________________________ 5. Globaldefs Are simply a long list of struct that can contain all variables in the game. The type are in the range 0-7 and the ofs is the position in the globals list. s_name is the position in the stings list. if DEF_SAVEGLOBGAL is 1 than that variable must be save in save game. ------------------------- typedef struct { unsigned short type; unsigned short ofs; int s_name; } ddef_t; #define DEF_SAVEGLOBGAL (1<<15) ------------------------- ________________________________________________________________________________ 6. Fielddefs It's the same of Globaldefs but are the name of the fields of the entity structure. ________________________________________________________________________________ 7. Functions In this list of structures you can find all info that you want for the functions: ------------------------- #define MAX_PARMS 8 // The max number of parameters typedef struct { int first_statement; // negative numbers are builtins // This is the number of the first istructions in statements structs. int parm_start; // This is the number of the 1st parm in the global heap int locals; // total ints of parms + locals // ex: 7 for 1 entities 1 vector 1 float 1 func 1 local float int profile; // runtime info set to 0 int s_name; // string number of the name int s_file; // source file defined in int numparms; byte parm_size[MAX_PARMS]; } dfunction_t; ------------------------- Note: Entity = 1 float float = 1 float vector = 3 float func = 1 float ________________________________________________________________________________ 8. Strings The strings data are zero-terminated c-style strings. That can contain the name of the functions or the name of the variables or simply strings to be printed in your code. All strings are associated with a number that is the positions in the list of strings. The First string is the number 0. Warning: the s_name field in all other struct is the positions in the list of strings NOT the offset. ex: "pippo0pluto0paperino0" s_name: 0 pippo 1 pluto 2 paperino ________________________________________________________________________________ 9. Globals A long list of floats. All float are 32-bit wide. ________________________________________________________________________________ 10. Comments All parameter are not dinamically allocated but are fixed in the globals list. The function use only 28 fixed positions in the global list to pass parameters. Read tables below. Quake engine read the 28 fixed position and write to the parameters of the function explaned Globals for functions are 0.0 fixed. Quake can reading functions list fill the value with the correct position in the list. Builtin function have negative first_statement number. Warning all number are position in another structure not offset in the structure. All structure have fixed dim only strings is size-variable, but you can reconstruct a list of pointers to the strings. So reading a s_name field you can regenerate the name of that var. ________________________________________________________________________________ 11. Tables 11.1 Types (number of globals allocated) 0 void (0) 1 string (0) 2 float (1) 3 vector (3) 4 entity (1) 5 field (0) 6 function(1) 7 pointer (1) 11.2 Standard offset to passing func functions All parameters have 3 float of space to have the possibility to pass vectors. 0 Null 1 Return value 4 1st parameter 7 2nd parameter 10 3rd parameter 13 4th parameter 16 5th parameter 19 6th parameter 22 7th parameter 25 8th parameter 28 First free globals position 11.3 Builtin function number makevectors: -1 setorigin: -2 setmodel: -3 setsize: -4 break: -6 random: -7 sound: -8 normalize: -9 error: -10 objerror: -11 vlen: -12 vectoyaw: -13 spawn: -14 remove: -15 traceline: -16 checkclient: -17 find: -18 precache_sound: -19 precache_model: -20 stuffcmd: -21 findradius: -22 bprint: -23 sprint: -24 dprint: -25 ftos: -26 vtos: -27 coredump: -28 traceon: -29 traceoff: -30 eprint: -31 walkmove: -32 droptofloor: -34 lightstyle: -35 rint: -36 floor: -37 ceil: -38 checkbottom: -40 pointcontents: -41 fabs: -43 aim: -44 cvar: -45 localcmd: -46 nextent: -47 particle: -48 ChangeYaw: -49 vectoangles: -51 WriteByte: -52 WriteChar: -53 WriteShort: -54 WriteLong: -55 WriteCoord: -56 WriteAngle: -57 WriteString: -58 WriteEntity: -59 movetogoal: -67 precache_file: -68 makestatic: -69 changelevel: -70 cvar_set: -72 centerprint: -73 ambientsound: -74 precache_model2: -75 precache_sound2: -76 precache_file2: -77 setspawnparms: -78 ________________________________________________________________________________ Copyright(C) 1996 by Ferrara Francesco (frank@aerre.it), id Software Inc.