]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - progsvm.h
reworked PRVM_EDICTFIELD* and PRVM_GLOBALFIELD* usage to have more
[xonotic/darkplaces.git] / progsvm.h
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 /*
21 This is a try to make the vm more generic, it is mainly based on the progs.h file.
22 For the license refer to progs.h.
23
24 Generic means, less as possible hard-coded links with the other parts of the engine.
25 This means no edict_engineprivate struct usage, etc.
26 The code uses void pointers instead.
27 */
28
29 #ifndef PROGSVM_H
30 #define PROGSVM_H
31
32 #include "pr_comp.h"                    // defs shared with qcc
33 #include "progdefs.h"                   // generated by program cdefs
34 #include "clprogdefs.h"                 // generated by program cdefs
35
36 #ifndef DP_SMALLMEMORY
37 #define PROFILING
38 #endif
39
40 // forward declaration of clgecko_t
41 struct clgecko_s;
42
43 typedef struct prvm_stack_s
44 {
45         int                             s;
46         mfunction_t             *f;
47         double                  tprofile_acc;
48         double                  profile_acc;
49         double                  builtinsprofile_acc;
50 } prvm_stack_t;
51
52
53 typedef union prvm_eval_s
54 {
55         string_t                string;
56         float                   _float;
57         float                   vector[3];
58         func_t                  function;
59         int                             ivector[3];
60         int                             _int;
61         int                             edict;
62 } prvm_eval_t;
63
64 typedef struct prvm_required_field_s
65 {
66         int type;
67         const char *name;
68 } prvm_required_field_t;
69
70
71 // AK: I dont call it engine private cause it doesnt really belongs to the engine
72 //     it belongs to prvm.
73 typedef struct prvm_edict_private_s
74 {
75         qboolean free;
76         float freetime;
77         int mark;
78         const char *allocation_origin;
79 } prvm_edict_private_t;
80
81 typedef struct prvm_edict_s
82 {
83         // engine-private fields (stored in dynamically resized array)
84         //edict_engineprivate_t *e;
85         union
86         {
87                 prvm_edict_private_t *required;
88                 vec_t *vp;
89                 // FIXME: this server pointer really means world, not server
90                 // (it is used by both server qc and client qc, but not menu qc)
91                 edict_engineprivate_t *server;
92                 // add other private structs as you desire
93                 // new structs have to start with the elements of prvm_edit_private_t
94                 // e.g. a new struct has to either look like this:
95                 //      typedef struct server_edict_private_s {
96                 //              prvm_edict_private_t base;
97                 //              vec3_t moved_from;
98                 //      vec3_t moved_fromangles;
99                 //              ... } server_edict_private_t;
100                 // or:
101                 //      typedef struct server_edict_private_s {
102                 //              qboolean free;
103                 //              float freetime;
104                 //              vec3_t moved_from;
105                 //      vec3_t moved_fromangles;
106                 //              ... } server_edict_private_t;
107                 // However, the first one should be preferred.
108         } priv;
109         // QuakeC fields (stored in dynamically resized array)
110         union
111         {
112                 vec_t *vp;
113                 entvars_t               *server;
114                 cl_entvars_t    *client;
115         } fields;
116 } prvm_edict_t;
117
118 extern prvm_eval_t prvm_badvalue;
119
120 #define PRVM_alledictfloat(ed, fieldname)    (PRVM_EDICTFIELDFLOAT(ed, prog->fieldoffsets.fieldname))
121 #define PRVM_alledictvector(ed, fieldname)   (PRVM_EDICTFIELDVECTOR(ed, prog->fieldoffsets.fieldname))
122 #define PRVM_alledictstring(ed, fieldname)   (PRVM_EDICTFIELDSTRING(ed, prog->fieldoffsets.fieldname))
123 #define PRVM_alledictedict(ed, fieldname)    (PRVM_EDICTFIELDEDICT(ed, prog->fieldoffsets.fieldname))
124 #define PRVM_alledictfunction(ed, fieldname) (PRVM_EDICTFIELDFUNCTION(ed, prog->fieldoffsets.fieldname))
125 #define PRVM_allglobalfloat(fieldname)       (PRVM_GLOBALFIELDFLOAT(prog->globaloffsets.fieldname))
126 #define PRVM_allglobalvector(fieldname)      (PRVM_GLOBALFIELDVECTOR(prog->globaloffsets.fieldname))
127 #define PRVM_allglobalstring(fieldname)      (PRVM_GLOBALFIELDSTRING(prog->globaloffsets.fieldname))
128 #define PRVM_allglobaledict(fieldname)       (PRVM_GLOBALFIELDEDICT(prog->globaloffsets.fieldname))
129 #define PRVM_allglobalfunction(fieldname)    (PRVM_GLOBALFIELDFUNCTION(prog->globaloffsets.fieldname))
130
131 #define PRVM_drawedictfloat(ed, fieldname)    (PRVM_EDICTFIELDFLOAT(ed, prog->fieldoffsets.fieldname))
132 #define PRVM_drawedictvector(ed, fieldname)   (PRVM_EDICTFIELDVECTOR(ed, prog->fieldoffsets.fieldname))
133 #define PRVM_drawedictstring(ed, fieldname)   (PRVM_EDICTFIELDSTRING(ed, prog->fieldoffsets.fieldname))
134 #define PRVM_drawedictedict(ed, fieldname)    (PRVM_EDICTFIELDEDICT(ed, prog->fieldoffsets.fieldname))
135 #define PRVM_drawedictfunction(ed, fieldname) (PRVM_EDICTFIELDFUNCTION(ed, prog->fieldoffsets.fieldname))
136 #define PRVM_drawglobalfloat(fieldname)       (PRVM_GLOBALFIELDFLOAT(prog->globaloffsets.fieldname))
137 #define PRVM_drawglobalvector(fieldname)      (PRVM_GLOBALFIELDVECTOR(prog->globaloffsets.fieldname))
138 #define PRVM_drawglobalstring(fieldname)      (PRVM_GLOBALFIELDSTRING(prog->globaloffsets.fieldname))
139 #define PRVM_drawglobaledict(fieldname)       (PRVM_GLOBALFIELDEDICT(prog->globaloffsets.fieldname))
140 #define PRVM_drawglobalfunction(fieldname)    (PRVM_GLOBALFIELDFUNCTION(prog->globaloffsets.fieldname))
141
142 #define PRVM_gameedictfloat(ed, fieldname)    (PRVM_EDICTFIELDFLOAT(ed, prog->fieldoffsets.fieldname))
143 #define PRVM_gameedictvector(ed, fieldname)   (PRVM_EDICTFIELDVECTOR(ed, prog->fieldoffsets.fieldname))
144 #define PRVM_gameedictstring(ed, fieldname)   (PRVM_EDICTFIELDSTRING(ed, prog->fieldoffsets.fieldname))
145 #define PRVM_gameedictedict(ed, fieldname)    (PRVM_EDICTFIELDEDICT(ed, prog->fieldoffsets.fieldname))
146 #define PRVM_gameedictfunction(ed, fieldname) (PRVM_EDICTFIELDFUNCTION(ed, prog->fieldoffsets.fieldname))
147 #define PRVM_gameglobalfloat(fieldname)       (PRVM_GLOBALFIELDFLOAT(prog->globaloffsets.fieldname))
148 #define PRVM_gameglobalvector(fieldname)      (PRVM_GLOBALFIELDVECTOR(prog->globaloffsets.fieldname))
149 #define PRVM_gameglobalstring(fieldname)      (PRVM_GLOBALFIELDSTRING(prog->globaloffsets.fieldname))
150 #define PRVM_gameglobaledict(fieldname)       (PRVM_GLOBALFIELDEDICT(prog->globaloffsets.fieldname))
151 #define PRVM_gameglobalfunction(fieldname)    (PRVM_GLOBALFIELDFUNCTION(prog->globaloffsets.fieldname))
152
153 #define PRVM_serveredictfloat(ed, fieldname)    (PRVM_EDICTFIELDFLOAT(ed, prog->fieldoffsets.fieldname))
154 #define PRVM_serveredictvector(ed, fieldname)   (PRVM_EDICTFIELDVECTOR(ed, prog->fieldoffsets.fieldname))
155 #define PRVM_serveredictstring(ed, fieldname)   (PRVM_EDICTFIELDSTRING(ed, prog->fieldoffsets.fieldname))
156 #define PRVM_serveredictedict(ed, fieldname)    (PRVM_EDICTFIELDEDICT(ed, prog->fieldoffsets.fieldname))
157 #define PRVM_serveredictfunction(ed, fieldname) (PRVM_EDICTFIELDFUNCTION(ed, prog->fieldoffsets.fieldname))
158 #define PRVM_serverglobalfloat(fieldname)       (PRVM_GLOBALFIELDFLOAT(prog->globaloffsets.fieldname))
159 #define PRVM_serverglobalvector(fieldname)      (PRVM_GLOBALFIELDVECTOR(prog->globaloffsets.fieldname))
160 #define PRVM_serverglobalstring(fieldname)      (PRVM_GLOBALFIELDSTRING(prog->globaloffsets.fieldname))
161 #define PRVM_serverglobaledict(fieldname)       (PRVM_GLOBALFIELDEDICT(prog->globaloffsets.fieldname))
162 #define PRVM_serverglobalfunction(fieldname)    (PRVM_GLOBALFIELDFUNCTION(prog->globaloffsets.fieldname))
163
164 #define PRVM_clientedictfloat(ed, fieldname)    (PRVM_EDICTFIELDFLOAT(ed, prog->fieldoffsets.fieldname))
165 #define PRVM_clientedictvector(ed, fieldname)   (PRVM_EDICTFIELDVECTOR(ed, prog->fieldoffsets.fieldname))
166 #define PRVM_clientedictstring(ed, fieldname)   (PRVM_EDICTFIELDSTRING(ed, prog->fieldoffsets.fieldname))
167 #define PRVM_clientedictedict(ed, fieldname)    (PRVM_EDICTFIELDEDICT(ed, prog->fieldoffsets.fieldname))
168 #define PRVM_clientedictfunction(ed, fieldname) (PRVM_EDICTFIELDFUNCTION(ed, prog->fieldoffsets.fieldname))
169 #define PRVM_clientglobalfloat(fieldname)       (PRVM_GLOBALFIELDFLOAT(prog->globaloffsets.fieldname))
170 #define PRVM_clientglobalvector(fieldname)      (PRVM_GLOBALFIELDVECTOR(prog->globaloffsets.fieldname))
171 #define PRVM_clientglobalstring(fieldname)      (PRVM_GLOBALFIELDSTRING(prog->globaloffsets.fieldname))
172 #define PRVM_clientglobaledict(fieldname)       (PRVM_GLOBALFIELDEDICT(prog->globaloffsets.fieldname))
173 #define PRVM_clientglobalfunction(fieldname)    (PRVM_GLOBALFIELDFUNCTION(prog->globaloffsets.fieldname))
174
175
176 #if 1
177 #define PRVM_EDICTFIELDVALUE(ed, fieldoffset)    (fieldoffset < 0 ? Con_Printf("Invalid fieldoffset at %s:%i\n", __FILE__, __LINE__), &prvm_badvalue : (prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))
178 #define PRVM_EDICTFIELDFLOAT(ed, fieldoffset)    (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->_float)
179 #define PRVM_EDICTFIELDVECTOR(ed, fieldoffset)   (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->vector)
180 #define PRVM_EDICTFIELDSTRING(ed, fieldoffset)   (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->string)
181 #define PRVM_EDICTFIELDEDICT(ed, fieldoffset)    (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->edict)
182 #define PRVM_EDICTFIELDFUNCTION(ed, fieldoffset) (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->function)
183 #define PRVM_GLOBALFIELDVALUE(fieldoffset)       (fieldoffset < 0 ? Con_Printf("Invalid fieldoffset at %s:%i\n", __FILE__, __LINE__), &prvm_badvalue : (prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))
184 #define PRVM_GLOBALFIELDFLOAT(fieldoffset)       (PRVM_GLOBALFIELDVALUE(fieldoffset)->_float)
185 #define PRVM_GLOBALFIELDVECTOR(fieldoffset)      (PRVM_GLOBALFIELDVALUE(fieldoffset)->vector)
186 #define PRVM_GLOBALFIELDSTRING(fieldoffset)      (PRVM_GLOBALFIELDVALUE(fieldoffset)->string)
187 #define PRVM_GLOBALFIELDEDICT(fieldoffset)       (PRVM_GLOBALFIELDVALUE(fieldoffset)->edict)
188 #define PRVM_GLOBALFIELDFUNCTION(fieldoffset)    (PRVM_GLOBALFIELDVALUE(fieldoffset)->function)
189 #else
190 #define PRVM_EDICTFIELDVALUE(ed, fieldoffset) ((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))
191 #define PRVM_EDICTFIELDFLOAT(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->_float)
192 #define PRVM_EDICTFIELDVECTOR(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->vector)
193 #define PRVM_EDICTFIELDSTRING(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->string)
194 #define PRVM_EDICTFIELDEDICT(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->edict)
195 #define PRVM_EDICTFIELDFUNCTION(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->function)
196 #define PRVM_GLOBALFIELDVALUE(fieldoffset) ((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))
197 #define PRVM_GLOBALFIELDFLOAT(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->_float)
198 #define PRVM_GLOBALFIELDVECTOR(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->vector)
199 #define PRVM_GLOBALFIELDSTRING(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->string)
200 #define PRVM_GLOBALFIELDEDICT(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->edict)
201 #define PRVM_GLOBALFIELDFUNCTION(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->function)
202 #endif
203
204 //============================================================================
205 #define PRVM_OP_STATE           1
206
207 #ifdef DP_SMALLMEMORY
208 #define PRVM_MAX_STACK_DEPTH            128
209 #define PRVM_LOCALSTACK_SIZE            2048
210
211 #define PRVM_MAX_OPENFILES 16
212 #define PRVM_MAX_OPENSEARCHES 8
213 #define PRVM_MAX_GECKOINSTANCES 1
214 #else
215 #define PRVM_MAX_STACK_DEPTH            1024
216 #define PRVM_LOCALSTACK_SIZE            16384
217
218 #define PRVM_MAX_OPENFILES 256
219 #define PRVM_MAX_OPENSEARCHES 128
220 #define PRVM_MAX_GECKOINSTANCES 32
221 #endif
222
223 typedef void (*prvm_builtin_t) (void);
224
225 // NOTE: field offsets use -1 for NULL
226 typedef struct prvm_prog_fieldoffsets_s
227 {
228         // server and client use a lot of similar fields, so this is combined
229         int SendEntity; // ssqc
230         int SendFlags; // ssqc
231         int Version; // ssqc (legacy)
232         int alpha; // ssqc / csqc
233         int ammo_cells1; // ssqc - Dissolution of Eternity mission pack
234         int ammo_lava_nails; // ssqc - Dissolution of Eternity mission pack
235         int ammo_multi_rockets; // ssqc - Dissolution of Eternity mission pack
236         int ammo_nails1; // ssqc - Dissolution of Eternity mission pack
237         int ammo_plasma; // ssqc - Dissolution of Eternity mission pack
238         int ammo_rockets1; // ssqc - Dissolution of Eternity mission pack
239         int ammo_shells1; // ssqc - Dissolution of Eternity mission pack
240         int angles; // common - used by changeyaw/changepitch
241         int button3; // ssqc
242         int button4; // ssqc
243         int button5; // ssqc
244         int button6; // ssqc
245         int button7; // ssqc
246         int button8; // ssqc
247         int button9; // ssqc
248         int button10; // ssqc
249         int button11; // ssqc
250         int button12; // ssqc
251         int button13; // ssqc
252         int button14; // ssqc
253         int button15; // ssqc
254         int button16; // ssqc
255         int buttonchat; // ssqc
256         int buttonuse; // ssqc
257         int chain; // common - used by find builtins
258         int classname; // common
259         int clientcamera; // ssqc
260         int clientcolors; // ssqc
261         int clientstatus; // ssqc
262         int color; // ssqc
263         int colormod; // ssqc / csqc
264         int contentstransition; // ssqc
265         int cursor_active; // ssqc
266         int cursor_screen; // ssqc
267         int cursor_trace_endpos; // ssqc
268         int cursor_trace_ent; // ssqc
269         int cursor_trace_start; // ssqc
270         int customizeentityforclient; // ssqc
271         int dimension_hit; // ssqc / csqc
272         int dimension_solid; // ssqc / csqc
273         int disableclientprediction; // ssqc
274         int discardabledemo; // ssqc
275         int dphitcontentsmask; // ssqc / csqc
276         int drawonlytoclient; // ssqc
277         int exteriormodeltoclient; // ssqc
278         int fatness; // ssqc / csqc
279         int forceshader; // csqc
280         int frame1time; // csqc
281         int frame2; // csqc
282         int frame2time; // csqc
283         int frame3; // csqc
284         int frame3time; // csqc
285         int frame4; // csqc
286         int frame4time; // csqc
287         int frame; // common - used by OP_STATE
288         int fullbright; // ssqc - Nehahra support
289         int glow_color; // ssqc
290         int glow_size; // ssqc
291         int glow_trail; // ssqc
292         int glowmod; // ssqc / csqc
293         int gravity; // ssqc
294         int groundentity; // ssqc / csqc
295         int hull; // ssqc / csqc
296         int ideal_yaw; // ssqc / csqc
297         int idealpitch; // ssqc / csqc
298         int items2; // ssqc
299         int lerpfrac3; // csqc
300         int lerpfrac4; // csqc
301         int lerpfrac; // csqc
302         int light_lev; // ssqc
303         int message; // csqc
304         int modelflags; // ssqc
305         int movement; // ssqc
306         int movetypesteplandevent; // ssqc
307         int netaddress; // ssqc
308         int nextthink; // common - used by OP_STATE
309         int nodrawtoclient; // ssqc
310         int pflags; // ssqc
311         int ping; // ssqc
312         int ping_packetloss; // ssqc
313         int ping_movementloss; // ssqc
314         int pitch_speed; // ssqc / csqc
315         int playermodel; // ssqc
316         int playerskin; // ssqc
317         int pmodel; // ssqc
318         int punchvector; // ssqc
319         int renderamt; // ssqc - HalfLife support
320         int renderflags; // csqc
321         int rendermode; // ssqc - HalfLife support
322         int scale; // ssqc / csqc
323         int shadertime; // csqc
324         int skeletonindex; // csqc / ssqc FTE_CSQC_SKELETONOBJECTS / DP_SKELETONOBJECTS
325         int style; // ssqc
326         int tag_entity; // ssqc / csqc
327         int tag_index; // ssqc / csqc
328         int think; // common - used by OP_STATE
329         int viewmodelforclient; // ssqc
330         int viewzoom; // ssqc
331         int yaw_speed; // ssqc / csqc
332         int bouncefactor; // ssqc
333         int bouncestop; // ssqc
334         int sendcomplexanimation; // ssqc
335
336         int solid; // ssqc / csqc (physics)
337         int movetype; // ssqc / csqc (physics)
338         int modelindex; // ssqc / csqc (physics)
339         int mins; // ssqc / csqc (physics)
340         int maxs; // ssqc / csqc (physics)
341         int mass; // ssqc / csqc (physics)
342         int origin; // ssqc / csqc (physics)
343         int velocity; // ssqc / csqc (physics)
344         //int axis_forward; // ssqc / csqc (physics)
345         //int axis_left; // ssqc / csqc (physics)
346         //int axis_up; // ssqc / csqc (physics)
347         //int spinvelocity; // ssqc / csqc (physics)
348         //int angles; // ssqc / csqc (physics)
349         int avelocity; // ssqc / csqc (physics)
350         int jointtype; // ssqc / csqc (physics)
351         int enemy; // ssqc / csqc (physics)
352         int aiment; // ssqc / csqc (physics)
353         int movedir; // ssqc / csqc (physics)
354
355         int camera_transform; // csqc (warpzones)
356
357         int userwavefunc_param0; // csqc (userwavefunc)
358         int userwavefunc_param1; // csqc (userwavefunc)
359         int userwavefunc_param2; // csqc (userwavefunc)
360         int userwavefunc_param3; // csqc (userwavefunc)
361
362         int crypto_keyfp; // ssqc (DP_CRYPTO)
363         int crypto_mykeyfp; // ssqc (DP_CRYPTO)
364         int crypto_idfp; // ssqc (DP_CRYPTO)
365         int crypto_encryptmethod; // ssqc (DP_CRYPTO)
366         int crypto_signmethod; // ssqc (DP_CRYPTO)
367 }
368 prvm_prog_fieldoffsets_t;
369
370 // NOTE: global offsets use -1 for NULL
371 typedef struct prvm_prog_globaloffsets_s
372 {
373         // server and client use a lot of similar globals, so this is combined
374         int SV_InitCmd; // ssqc
375         int self; // common
376         int time; // ssqc / csqc
377         int v_forward; // ssqc / csqc
378         int v_right; // ssqc / csqc
379         int v_up; // ssqc / csqc
380         int view_angles; // csqc
381         int view_punchangle; // csqc
382         int view_punchvector; // csqc
383         int trace_allsolid; // ssqc / csqc
384         int trace_startsolid; // ssqc / csqc
385         int trace_fraction; // ssqc / csqc
386         int trace_inwater; // ssqc / csqc
387         int trace_inopen; // ssqc / csqc
388         int trace_endpos; // ssqc / csqc
389         int trace_plane_normal; // ssqc / csqc
390         int trace_plane_dist; // ssqc / csqc
391         int trace_ent; // ssqc / csqc
392         int trace_networkentity; // csqc
393         int trace_dphitcontents; // ssqc / csqc
394         int trace_dphitq3surfaceflags; // ssqc / csqc
395         int trace_dphittexturename; // ssqc / csqc
396         int trace_dpstartcontents; // ssqc / csqc
397         int intermission; // csqc
398         int coop; // csqc
399         int deathmatch; // csqc
400         int dmg_take; // csqc
401         int dmg_save; // csqc
402         int dmg_origin; // csqc
403         int sb_showscores; // csqc
404         int drawfont; // csqc / menu
405         int drawfontscale; // csqc / menu
406         int pmove_onground; // csqc
407         int pmove_inwater; // csqc
408         int require_spawnfunc_prefix; // ssqc
409         int worldstatus; // ssqc
410         int servertime; // csqc
411         int serverprevtime; // csqc
412         int serverdeltatime; // csqc
413         int gettaginfo_name; // ssqc / csqc
414         int gettaginfo_parent; // ssqc / csqc
415         int gettaginfo_offset; // ssqc / csqc
416         int gettaginfo_forward; // ssqc / csqc
417         int gettaginfo_right; // ssqc / csqc
418         int gettaginfo_up; // ssqc / csqc
419         int transparent_offset; // csqc
420
421         int particles_alphamin; // csqc
422         int particles_alphamax; // csqc
423         int particles_colormin; // csqc
424         int particles_colormax; // csqc
425
426         int particle_type; // csqc
427         int particle_blendmode; // csqc
428         int particle_orientation; // csqc
429         int particle_color1; // csqc
430         int particle_color2; // csqc
431         int particle_tex; // csqc
432         int particle_size; // csqc
433         int particle_sizeincrease; // csqc
434         int particle_alpha; // csqc
435         int particle_alphafade; // csqc
436         int particle_time; // csqc
437         int particle_gravity; // csqc
438         int particle_bounce; // csqc
439         int particle_airfriction; // csqc
440         int particle_liquidfriction; // csqc
441         int particle_originjitter; // csqc
442         int particle_velocityjitter; // csqc
443         int particle_qualityreduction; // csqc
444         int particle_stretch; // csqc
445         int particle_staincolor1; // csqc
446         int particle_staincolor2; // csqc
447         int particle_stainalpha; // csqc
448         int particle_stainsize; // csqc
449         int particle_staintex; // csqc
450         int particle_delayspawn; // csqc
451         int particle_delaycollision; // csqc
452         int particle_angle; // csqc
453         int particle_spin; // csqc
454 }
455 prvm_prog_globaloffsets_t;
456
457 // these are initialized using PRVM_ED_FindFunction
458 // NOTE: function offsets use 0 for NULL
459 typedef struct prvm_prog_funcoffsets_s
460 {
461         func_t CSQC_ConsoleCommand; // csqc
462         func_t CSQC_Ent_Remove; // csqc
463         func_t CSQC_Ent_Spawn; // csqc DP_CSQC_ENT_SPAWN extension (BlackHC - TODO: needs to be added to dpextensions.qc)
464         func_t CSQC_Ent_Update; // csqc
465         func_t CSQC_Event; // csqc [515]: engine call this for its own needs so csqc can do some things according to what engine it's running on.  example: to say about edicts increase, whatever...
466         func_t CSQC_Event_Sound; // csqc : called by engine when an incoming sound packet arrives so CSQC can act on it
467         func_t CSQC_Init; // csqc
468         func_t CSQC_InputEvent; // csqc
469         func_t CSQC_Parse_CenterPrint; // csqc
470         func_t CSQC_Parse_Print; // csqc
471         func_t CSQC_Parse_StuffCmd; // csqc
472         func_t CSQC_Parse_TempEntity; // csqc [515]: very helpfull when you want to create your own particles/decals/etc for effects that already exist
473         func_t CSQC_Shutdown; // csqc
474         func_t CSQC_UpdateView; // csqc
475         func_t Gecko_Query; // csqc, mqc
476         func_t EndFrame; // ssqc
477         func_t RestoreGame; // ssqc
478         func_t SV_ChangeTeam; // ssqc
479         func_t SV_ParseClientCommand; // ssqc
480         func_t SV_PlayerPhysics; // ssqc
481         func_t SV_OnEntityPreSpawnFunction; // ssqc
482         func_t SV_OnEntityNoSpawnFunction; // ssqc
483         func_t SV_OnEntityPostSpawnFunction; // ssqc
484         func_t GameCommand; // any
485         func_t SV_Shutdown; // ssqc
486         func_t URI_Get_Callback; // any
487         func_t SV_PausedTic; //ssqc
488
489         // menu qc only uses some functions, nothing else
490         func_t m_draw; // mqc
491         func_t m_init; // mqc
492         func_t m_keydown; // mqc
493         func_t m_keyup; // mqc
494         func_t m_shutdown; // mqc
495         func_t m_toggle; // mqc
496         func_t m_newmap; // mqc
497 }
498 prvm_prog_funcoffsets_t;
499
500 // stringbuffer flags
501 #define STRINGBUFFER_SAVED      1 // saved in savegames
502
503 typedef struct prvm_stringbuffer_s
504 {
505         int max_strings;
506         int num_strings;
507         char **strings;
508         const char *origin;
509         unsigned char flags;
510 }
511 prvm_stringbuffer_t;
512
513 // [INIT] variables flagged with this token can be initialized by 'you'
514 // NOTE: external code has to create and free the mempools but everything else is done by prvm !
515 typedef struct prvm_prog_s
516 {
517         double              starttime;
518         unsigned int            id; // increasing unique id of progs instance
519         mfunction_t                     *functions;
520         char                            *strings;
521         int                                     stringssize;
522         ddef_t                          *fielddefs;
523         ddef_t                          *globaldefs;
524         mstatement_t            *statements;
525         int                                     entityfields;                   // number of vec_t fields in progs (some variables are 3)
526         int                                     entityfieldsarea;               // LordHavoc: equal to max_edicts * entityfields (for bounds checking)
527
528         // loaded values from the disk format
529         int                                     progs_version;
530         int                                     progs_crc;
531         int                                     progs_numstatements;
532         int                                     progs_numglobaldefs;
533         int                                     progs_numfielddefs;
534         int                                     progs_numfunctions;
535         int                                     progs_numstrings;
536         int                                     progs_numglobals;
537         int                                     progs_entityfields;
538
539         // real values in memory (some modified by loader)
540         int                                     numstatements;
541         int                                     numglobaldefs;
542         int                                     numfielddefs;
543         int                                     numfunctions;
544         int                                     numstrings;
545         int                                     numglobals;
546
547         int                                     *statement_linenums; // NULL if not available
548
549         double                          *statement_profile; // only incremented if prvm_statementprofiling is on
550
551         union {
552                 vec_t *generic;
553                 globalvars_t *server;
554                 cl_globalvars_t *client;
555         } globals;
556
557         int                                     maxknownstrings;
558         int                                     numknownstrings;
559         // this is updated whenever a string is removed or added
560         // (simple optimization of the free string search)
561         int                                     firstfreeknownstring;
562         const char                      **knownstrings;
563         unsigned char           *knownstrings_freeable;
564         const char          **knownstrings_origin;
565         const char                      ***stringshash;
566
567         memexpandablearray_t    stringbuffersarray;
568
569         // all memory allocations related to this vm_prog (code, edicts, strings)
570         mempool_t                       *progs_mempool; // [INIT]
571
572         prvm_builtin_t          *builtins; // [INIT]
573         int                                     numbuiltins; // [INIT]
574
575         int                                     argc;
576
577         int                                     trace;
578         mfunction_t                     *xfunction;
579         int                                     xstatement;
580
581         // stacktrace writes into stack[MAX_STACK_DEPTH]
582         // thus increase the array, so depth wont be overwritten
583         prvm_stack_t            stack[PRVM_MAX_STACK_DEPTH+1];
584         int                                     depth;
585
586         int                                     localstack[PRVM_LOCALSTACK_SIZE];
587         int                                     localstack_used;
588
589         unsigned short          headercrc; // [INIT]
590         unsigned short          headercrc2; // [INIT] alternate CRC for tenebrae progs.dat
591
592         unsigned short          filecrc;
593
594         //============================================================================
595         // until this point everything also exists (with the pr_ prefix) in the old vm
596
597         qfile_t                         *openfiles[PRVM_MAX_OPENFILES];
598         const char *         openfiles_origin[PRVM_MAX_OPENFILES];
599         fssearch_t                      *opensearches[PRVM_MAX_OPENSEARCHES];
600         const char *         opensearches_origin[PRVM_MAX_OPENSEARCHES];
601         struct clgecko_s                *opengeckoinstances[PRVM_MAX_GECKOINSTANCES];
602         skeleton_t                      *skeletons[MAX_EDICTS];
603
604         // copies of some vars that were former read from sv
605         int                                     num_edicts;
606         // number of edicts for which space has been (should be) allocated
607         int                                     max_edicts; // [INIT]
608         // used instead of the constant MAX_EDICTS
609         int                                     limit_edicts; // [INIT]
610
611         // number of reserved edicts (allocated from 1)
612         int                                     reserved_edicts; // [INIT]
613
614         prvm_edict_t            *edicts;
615         vec_t                           *edictsfields;
616         void                                    *edictprivate;
617
618         // size of the engine private struct
619         int                                     edictprivate_size; // [INIT]
620
621         prvm_prog_fieldoffsets_t        fieldoffsets;
622         prvm_prog_globaloffsets_t       globaloffsets;
623         prvm_prog_funcoffsets_t         funcoffsets;
624
625         // allow writing to world entity fields, this is set by server init and
626         // cleared before first server frame
627         qboolean                        allowworldwrites;
628
629         // name of the prog, e.g. "Server", "Client" or "Menu" (used for text output)
630         const char                      *name; // [INIT]
631
632         // flag - used to store general flags like PRVM_GE_SELF, etc.
633         int                             flag;
634
635         const char                      *extensionstring; // [INIT]
636
637         qboolean                        loadintoworld; // [INIT]
638
639         // used to indicate whether a prog is loaded
640         qboolean                        loaded;
641         qboolean                        leaktest_active;
642
643         // translation buffer (only needs to be freed on unloading progs, type is private to prvm_edict.c)
644         void *po;
645
646         // printed together with backtraces
647         const char *statestring;
648
649 //      prvm_builtin_mem_t  *mem_list;
650
651 // now passed as parameter of PRVM_LoadProgs
652 //      char                            **required_func;
653 //      int                                     numrequiredfunc;
654
655         //============================================================================
656
657         ddef_t                          *self; // if self != 0 then there is a global self
658
659         //============================================================================
660         // function pointers
661
662         void                            (*begin_increase_edicts)(void); // [INIT] used by PRVM_MEM_Increase_Edicts
663         void                            (*end_increase_edicts)(void); // [INIT]
664
665         void                            (*init_edict)(prvm_edict_t *edict); // [INIT] used by PRVM_ED_ClearEdict
666         void                            (*free_edict)(prvm_edict_t *ed); // [INIT] used by PRVM_ED_Free
667
668         void                            (*count_edicts)(void); // [INIT] used by PRVM_ED_Count_f
669
670         qboolean                        (*load_edict)(prvm_edict_t *ent); // [INIT] used by PRVM_ED_LoadFromFile
671
672         void                            (*init_cmd)(void); // [INIT] used by PRVM_InitProg
673         void                            (*reset_cmd)(void); // [INIT] used by PRVM_ResetProg
674
675         void                            (*error_cmd)(const char *format, ...) DP_FUNC_PRINTF(1); // [INIT]
676
677         void                            (*ExecuteProgram)(func_t fnum, const char *errormessage); // pointer to one of the *VM_ExecuteProgram functions
678 } prvm_prog_t;
679
680 extern prvm_prog_t * prog;
681
682 #define PRVM_MAXPROGS 3
683 #define PRVM_SERVERPROG 0 // actually not used at the moment
684 #define PRVM_CLIENTPROG 1
685 #define PRVM_MENUPROG   2
686
687 extern prvm_prog_t prvm_prog_list[PRVM_MAXPROGS];
688
689 //============================================================================
690 // prvm_cmds part
691
692 extern prvm_builtin_t vm_sv_builtins[];
693 extern prvm_builtin_t vm_cl_builtins[];
694 extern prvm_builtin_t vm_m_builtins[];
695
696 extern const int vm_sv_numbuiltins;
697 extern const int vm_cl_numbuiltins;
698 extern const int vm_m_numbuiltins;
699
700 extern const char * vm_sv_extensions; // client also uses this
701 extern const char * vm_m_extensions;
702
703 void VM_SV_Cmd_Init(void);
704 void VM_SV_Cmd_Reset(void);
705
706 void VM_CL_Cmd_Init(void);
707 void VM_CL_Cmd_Reset(void);
708
709 void VM_M_Cmd_Init(void);
710 void VM_M_Cmd_Reset(void);
711
712 void VM_Cmd_Init(void);
713 void VM_Cmd_Reset(void);
714 //============================================================================
715
716 void PRVM_Init (void);
717
718 #ifdef PROFILING
719 void MVM_ExecuteProgram (func_t fnum, const char *errormessage);
720 void CLVM_ExecuteProgram (func_t fnum, const char *errormessage);
721 void SVVM_ExecuteProgram (func_t fnum, const char *errormessage);
722 #else
723 #define MVM_ExecuteProgram SVVM_ExecuteProgram
724 #define CLVM_ExecuteProgram SVVM_ExecuteProgram
725 void SVVM_ExecuteProgram (func_t fnum, const char *errormessage);
726 #endif
727 #define PRVM_ExecuteProgram prog->ExecuteProgram
728
729 #define PRVM_Alloc(buffersize) _PRVM_Alloc(buffersize, __FILE__, __LINE__)
730 #define PRVM_Free(buffer) _PRVM_Free(buffer, __FILE__, __LINE__)
731 #define PRVM_FreeAll() _PRVM_FreeAll(__FILE__, __LINE__)
732 void *_PRVM_Alloc (size_t buffersize, const char *filename, int fileline);
733 void _PRVM_Free (void *buffer, const char *filename, int fileline);
734 void _PRVM_FreeAll (const char *filename, int fileline);
735
736 void PRVM_Profile (int maxfunctions, double mintime, int sortby);
737 void PRVM_Profile_f (void);
738 void PRVM_ChildProfile_f (void);
739 void PRVM_CallProfile_f (void);
740 void PRVM_PrintFunction_f (void);
741
742 void PRVM_PrintState(void);
743 void PRVM_CrashAll (void);
744 void PRVM_Crash (void);
745 void PRVM_ShortStackTrace(char *buf, size_t bufsize);
746 const char *PRVM_AllocationOrigin(void);
747
748 ddef_t *PRVM_ED_FindField(const char *name);
749 ddef_t *PRVM_ED_FindGlobal(const char *name);
750 mfunction_t *PRVM_ED_FindFunction(const char *name);
751
752 int PRVM_ED_FindFieldOffset(const char *name);
753 int PRVM_ED_FindGlobalOffset(const char *name);
754 func_t PRVM_ED_FindFunctionOffset(const char *name);
755 #define PRVM_ED_FindFieldOffset_FromStruct(st, field) prog->fieldoffsets . field = ((int *)(&((st *)NULL)-> field ) - ((int *)NULL))
756 #define PRVM_ED_FindGlobalOffset_FromStruct(st, field) prog->globaloffsets . field = ((int *)(&((st *)NULL)-> field ) - ((int *)NULL))
757
758 void PRVM_MEM_IncreaseEdicts(void);
759
760 qboolean PRVM_ED_CanAlloc(prvm_edict_t *e);
761 prvm_edict_t *PRVM_ED_Alloc (void);
762 void PRVM_ED_Free (prvm_edict_t *ed);
763 void PRVM_ED_ClearEdict (prvm_edict_t *e);
764
765 void PRVM_PrintFunctionStatements (const char *name);
766 void PRVM_ED_Print(prvm_edict_t *ed, const char *wildcard_fieldname);
767 void PRVM_ED_Write (qfile_t *f, prvm_edict_t *ed);
768 const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent);
769
770 void PRVM_ED_WriteGlobals (qfile_t *f);
771 void PRVM_ED_ParseGlobals (const char *data);
772
773 void PRVM_ED_LoadFromFile (const char *data);
774
775 unsigned int PRVM_EDICT_NUM_ERROR(unsigned int n, const char *filename, int fileline);
776 #define PRVM_EDICT(n) (((unsigned)(n) < (unsigned int)prog->max_edicts) ? (unsigned int)(n) : PRVM_EDICT_NUM_ERROR((unsigned int)(n), __FILE__, __LINE__))
777 #define PRVM_EDICT_NUM(n) (prog->edicts + PRVM_EDICT(n))
778
779 //int NUM_FOR_EDICT_ERROR(prvm_edict_t *e);
780 #define PRVM_NUM_FOR_EDICT(e) ((int)((prvm_edict_t *)(e) - prog->edicts))
781 //int PRVM_NUM_FOR_EDICT(prvm_edict_t *e);
782
783 #define PRVM_NEXT_EDICT(e) ((e) + 1)
784
785 #define PRVM_EDICT_TO_PROG(e) (PRVM_NUM_FOR_EDICT(e))
786 //int PRVM_EDICT_TO_PROG(prvm_edict_t *e);
787 #define PRVM_PROG_TO_EDICT(n) (PRVM_EDICT_NUM(n))
788 //prvm_edict_t *PRVM_PROG_TO_EDICT(int n);
789
790 //============================================================================
791
792 #define PRVM_G_FLOAT(o) (prog->globals.generic[o])
793 #define PRVM_G_INT(o) (*(int *)&prog->globals.generic[o])
794 #define PRVM_G_EDICT(o) (PRVM_PROG_TO_EDICT(*(int *)&prog->globals.generic[o]))
795 #define PRVM_G_EDICTNUM(o) PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(o))
796 #define PRVM_G_VECTOR(o) (&prog->globals.generic[o])
797 #define PRVM_G_STRING(o) (PRVM_GetString(*(string_t *)&prog->globals.generic[o]))
798 //#define       PRVM_G_FUNCTION(o) (*(func_t *)&prog->globals.generic[o])
799
800 // FIXME: make these go away?
801 #define PRVM_E_FLOAT(e,o) (((float*)e->fields.vp)[o])
802 #define PRVM_E_INT(e,o) (((int*)e->fields.vp)[o])
803 //#define       PRVM_E_VECTOR(e,o) (&((float*)e->fields.vp)[o])
804 #define PRVM_E_STRING(e,o) (PRVM_GetString(*(string_t *)&((float*)e->fields.vp)[o]))
805
806 extern  int             prvm_type_size[8]; // for consistency : I think a goal of this sub-project is to
807 // make the new vm mostly independent from the old one, thus if it's necessary, I copy everything
808
809 void PRVM_Init_Exec(void);
810
811 void PRVM_ED_PrintEdicts_f (void);
812 void PRVM_ED_PrintNum (int ent, const char *wildcard_fieldname);
813
814 const char *PRVM_GetString(int num);
815 int PRVM_SetEngineString(const char *s);
816 const char *PRVM_ChangeEngineString(int i, const char *s);
817 int PRVM_SetTempString(const char *s);
818 int PRVM_AllocString(size_t bufferlength, char **pointer);
819 void PRVM_FreeString(int num);
820
821 //============================================================================
822
823 // used as replacement for a prog stack
824 //#define PRVM_DEBUGPRSTACK
825
826 #ifdef PRVM_DEBUGPRSTACK
827 #define PRVM_Begin  if(prog != 0) Con_Printf("prog not 0(prog = %i) in file: %s line: %i!\n", PRVM_GetProgNr(), __FILE__, __LINE__)
828 #define PRVM_End        prog = 0
829 #else
830 #define PRVM_Begin
831 #define PRVM_End        prog = 0
832 #endif
833
834 //#define PRVM_SAFENAME
835 #ifndef PRVM_SAFENAME
836 #       define PRVM_NAME        (prog->name)
837 #else
838 #       define PRVM_NAME        (prog->name ? prog->name : "Unknown prog name")
839 #endif
840
841 // helper macro to make function pointer calls easier
842 #define PRVM_GCALL(func)        if(prog->func) prog->func
843
844 #define PRVM_ERROR              prog->error_cmd
845
846 // other prog handling functions
847 qboolean PRVM_SetProgFromString(const char *str);
848 void PRVM_SetProg(int prognr);
849
850 /*
851 Initializing a vm:
852 Call InitProg with the num
853 Set up the fields marked with [INIT] in the prog struct
854 Load a program with LoadProgs
855 */
856 void PRVM_InitProg(int prognr);
857 // LoadProgs expects to be called right after InitProg
858 void PRVM_LoadProgs (const char *filename, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global);
859 void PRVM_ResetProg(void);
860
861 qboolean PRVM_ProgLoaded(int prognr);
862
863 int     PRVM_GetProgNr(void);
864
865 void VM_Warning(const char *fmt, ...) DP_FUNC_PRINTF(1);
866
867 // TODO: fill in the params
868 //void PRVM_Create();
869
870 void VM_GenerateFrameGroupBlend(framegroupblend_t *framegroupblend, const prvm_edict_t *ed);
871 void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroupblend_t *framegroupblend, const dp_model_t *model);
872 void VM_UpdateEdictSkeleton(prvm_edict_t *ed, const dp_model_t *edmodel, const frameblend_t *frameblend);
873 void VM_RemoveEdictSkeleton(prvm_edict_t *ed);
874
875 #endif