X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=progsvm.h;h=6bcb808a1dd75fa1db884a068eb2f32745e74c48;hp=b87822a41482f9f7f11172ff40524cc0dece064c;hb=HEAD;hpb=d2036753773b0c3c0a5347bc48c82cb7eca296af diff --git a/progsvm.h b/progsvm.h index b87822a4..32632f30 100644 --- a/progsvm.h +++ b/progsvm.h @@ -29,10 +29,20 @@ The code uses void pointers instead. #ifndef PROGSVM_H #define PROGSVM_H +#include +#include "qtypes.h" +#include "qdefs.h" +#include "common.h" +#include "zone.h" #include "pr_comp.h" // defs shared with qcc #include "progdefs.h" // generated by program cdefs #include "clprogdefs.h" // generated by program cdefs +struct framegroupblend_s; +struct frameblend_s; +struct cmd_state_s; +struct qfile_s; + #ifndef DP_SMALLMEMORY #define PROFILING #endif @@ -49,13 +59,13 @@ typedef struct prvm_stack_s typedef union prvm_eval_s { - string_t string; - float _float; - float vector[3]; - func_t function; - int ivector[3]; - int _int; - int edict; + prvm_int_t string; + prvm_vec_t _float; + prvm_vec_t vector[3]; + prvm_int_t function; + prvm_int_t ivector[3]; + prvm_int_t _int; + prvm_int_t edict; } prvm_eval_t; typedef struct prvm_required_field_s @@ -64,30 +74,35 @@ typedef struct prvm_required_field_s const char *name; } prvm_required_field_t; - +#define PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN -1 +#define PRVM_EDICT_MARK_SETORIGIN_CAUGHT -2 // AK: I dont call it engine private cause it doesnt really belongs to the engine // it belongs to prvm. typedef struct prvm_edict_private_s { - qboolean free; - float freetime; - int mark; // used during leaktest (0 = unref, >0 = referenced); special values during server physics: -#define PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN -1 -#define PRVM_EDICT_MARK_SETORIGIN_CAUGHT -2 + // mark for the leak detector + int mark; + // place in the code where it was allocated (for the leak detector) const char *allocation_origin; } prvm_edict_private_t; typedef struct prvm_edict_s { + // true if this edict is unused + qbool free; + // sv.time when the object was freed (to prevent early reuse which could + // mess up client interpolation or obscure severe QuakeC bugs) + double freetime; + // engine-private fields (stored in dynamically resized array) - //edict_engineprivate_t *e; union { prvm_edict_private_t *required; - vec_t *vp; + prvm_vec_t *fp; + prvm_int_t *ip; // FIXME: this server pointer really means world, not server // (it is used by both server qc and client qc, but not menu qc) - edict_engineprivate_t *server; + struct edict_engineprivate_s *server; // add other private structs as you desire // new structs have to start with the elements of prvm_edit_private_t // e.g. a new struct has to either look like this: @@ -98,7 +113,7 @@ typedef struct prvm_edict_s // ... } server_edict_private_t; // or: // typedef struct server_edict_private_s { - // qboolean free; + // qbool free; // float freetime; // vec3_t moved_from; // vec3_t moved_fromangles; @@ -108,49 +123,13 @@ typedef struct prvm_edict_s // QuakeC fields (stored in dynamically resized array) union { - vec_t *vp; + prvm_vec_t *fp; + prvm_int_t *ip; // entvars_t *server; // cl_entvars_t *client; } fields; } prvm_edict_t; -#define VMPOLYGONS_MAXPOINTS 64 - -typedef struct vmpolygons_triangle_s -{ - rtexture_t *texture; - int drawflag; - qboolean hasalpha; - unsigned short elements[3]; -} vmpolygons_triangle_t; - -typedef struct vmpolygons_s -{ - mempool_t *pool; - qboolean initialized; - - int max_vertices; - int num_vertices; - float *data_vertex3f; - float *data_color4f; - float *data_texcoord2f; - - int max_triangles; - int num_triangles; - vmpolygons_triangle_t *data_triangles; - unsigned short *data_sortedelement3s; - - qboolean begin_active; - int begin_draw2d; - rtexture_t *begin_texture; - int begin_drawflag; - int begin_vertices; - float begin_vertex[VMPOLYGONS_MAXPOINTS][3]; - float begin_color[VMPOLYGONS_MAXPOINTS][4]; - float begin_texcoord[VMPOLYGONS_MAXPOINTS][2]; - qboolean begin_texture_hasalpha; -} vmpolygons_t; - extern prvm_eval_t prvm_badvalue; #define PRVM_alledictfloat(ed, fieldname) (PRVM_EDICTFIELDFLOAT(ed, prog->fieldoffsets.fieldname)) @@ -226,35 +205,37 @@ extern prvm_eval_t prvm_badvalue; #define PRVM_menufunction(funcname) (prog->funcoffsets.funcname) #if 1 -#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)) +#define PRVM_EDICTFIELDVALUE(ed, fieldoffset) ((fieldoffset) < 0 ? Con_Printf("Invalid fieldoffset at %s:%i\n", __FILE__, __LINE__), &prvm_badvalue : (prvm_eval_t *)((ed)->fields.fp + (fieldoffset))) #define PRVM_EDICTFIELDFLOAT(ed, fieldoffset) (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->_float) #define PRVM_EDICTFIELDVECTOR(ed, fieldoffset) (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->vector) #define PRVM_EDICTFIELDSTRING(ed, fieldoffset) (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->string) #define PRVM_EDICTFIELDEDICT(ed, fieldoffset) (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->edict) #define PRVM_EDICTFIELDFUNCTION(ed, fieldoffset) (PRVM_EDICTFIELDVALUE(ed, fieldoffset)->function) -#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)) +#define PRVM_GLOBALFIELDVALUE(fieldoffset) ((fieldoffset) < 0 ? Con_Printf("Invalid fieldoffset at %s:%i\n", __FILE__, __LINE__), &prvm_badvalue : (prvm_eval_t *)(prog->globals.fp + (fieldoffset))) #define PRVM_GLOBALFIELDFLOAT(fieldoffset) (PRVM_GLOBALFIELDVALUE(fieldoffset)->_float) #define PRVM_GLOBALFIELDVECTOR(fieldoffset) (PRVM_GLOBALFIELDVALUE(fieldoffset)->vector) #define PRVM_GLOBALFIELDSTRING(fieldoffset) (PRVM_GLOBALFIELDVALUE(fieldoffset)->string) #define PRVM_GLOBALFIELDEDICT(fieldoffset) (PRVM_GLOBALFIELDVALUE(fieldoffset)->edict) #define PRVM_GLOBALFIELDFUNCTION(fieldoffset) (PRVM_GLOBALFIELDVALUE(fieldoffset)->function) #else -#define PRVM_EDICTFIELDVALUE(ed, fieldoffset) ((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset)) -#define PRVM_EDICTFIELDFLOAT(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->_float) -#define PRVM_EDICTFIELDVECTOR(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->vector) -#define PRVM_EDICTFIELDSTRING(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->string) -#define PRVM_EDICTFIELDEDICT(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->edict) -#define PRVM_EDICTFIELDFUNCTION(ed, fieldoffset) (((prvm_eval_t *)((int *)ed->fields.vp + fieldoffset))->function) -#define PRVM_GLOBALFIELDVALUE(fieldoffset) ((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset)) -#define PRVM_GLOBALFIELDFLOAT(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->_float) -#define PRVM_GLOBALFIELDVECTOR(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->vector) -#define PRVM_GLOBALFIELDSTRING(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->string) -#define PRVM_GLOBALFIELDEDICT(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->edict) -#define PRVM_GLOBALFIELDFUNCTION(fieldoffset) (((prvm_eval_t *)((int *)prog->globals.generic + fieldoffset))->function) +#define PRVM_EDICTFIELDVALUE(ed, fieldoffset) ((prvm_eval_t *)(ed->fields.fp + fieldoffset)) +#define PRVM_EDICTFIELDFLOAT(ed, fieldoffset) (((prvm_eval_t *)(ed->fields.fp + fieldoffset))->_float) +#define PRVM_EDICTFIELDVECTOR(ed, fieldoffset) (((prvm_eval_t *)(ed->fields.fp + fieldoffset))->vector) +#define PRVM_EDICTFIELDSTRING(ed, fieldoffset) (((prvm_eval_t *)(ed->fields.fp + fieldoffset))->string) +#define PRVM_EDICTFIELDEDICT(ed, fieldoffset) (((prvm_eval_t *)(ed->fields.fp + fieldoffset))->edict) +#define PRVM_EDICTFIELDFUNCTION(ed, fieldoffset) (((prvm_eval_t *)(ed->fields.fp + fieldoffset))->function) +#define PRVM_GLOBALFIELDVALUE(fieldoffset) ((prvm_eval_t *)(prog->globals.fp + fieldoffset)) +#define PRVM_GLOBALFIELDFLOAT(fieldoffset) (((prvm_eval_t *)(prog->globals.fp + fieldoffset))->_float) +#define PRVM_GLOBALFIELDVECTOR(fieldoffset) (((prvm_eval_t *)(prog->globals.fp + fieldoffset))->vector) +#define PRVM_GLOBALFIELDSTRING(fieldoffset) (((prvm_eval_t *)(prog->globals.fp + fieldoffset))->string) +#define PRVM_GLOBALFIELDEDICT(fieldoffset) (((prvm_eval_t *)(prog->globals.fp + fieldoffset))->edict) +#define PRVM_GLOBALFIELDFUNCTION(fieldoffset) (((prvm_eval_t *)(prog->globals.fp + fieldoffset))->function) #endif //============================================================================ -#define PRVM_OP_STATE 1 +// prog->flag +#define PRVM_OP_STATE 1 +#define PRVM_CSQC_SIMPLE 2 #ifdef DP_SMALLMEMORY #define PRVM_MAX_STACK_DEPTH 128 @@ -511,8 +492,9 @@ typedef struct prvm_prog_funcoffsets_s prvm_prog_funcoffsets_t; // stringbuffer flags -#define STRINGBUFFER_SAVED 1 // saved in savegames - +#define STRINGBUFFER_SAVED 1 // saved in savegames +#define STRINGBUFFER_QCFLAGS 1 // allowed to be set by QC +#define STRINGBUFFER_TEMP 128 // internal use ONLY typedef struct prvm_stringbuffer_s { int max_strings; @@ -523,21 +505,47 @@ typedef struct prvm_stringbuffer_s } prvm_stringbuffer_t; +// flags for knownstrings +#define KNOWNSTRINGFLAG_ENGINE 1 +#define KNOWNSTRINGFLAG_GCMARK 2 +#define KNOWNSTRINGFLAG_GCPRUNE 4 // cleared by GCMARK code, string is freed if prune remains after two sweeps + +typedef enum prvm_prog_garbagecollection_state_stage_e +{ + PRVM_GC_START = 0, + PRVM_GC_GLOBALS_MARK, + PRVM_GC_FIELDS_MARK, + PRVM_GC_KNOWNSTRINGS_SWEEP, + PRVM_GC_RESET, +} +prvm_prog_garbagecollection_state_stage_t; + +typedef struct prvm_prog_garbagecollection_state_s +{ + int stage; + int globals_mark_progress; + int fields_mark_progress; + int fields_mark_progress_entity; + int knownstrings_sweep_progress; +} +prvm_prog_garbagecollection_state_t; + // [INIT] variables flagged with this token can be initialized by 'you' // NOTE: external code has to create and free the mempools but everything else is done by prvm ! typedef struct prvm_prog_s { double starttime; // system time when PRVM_Prog_Load was called + double inittime; // system time when QC initialization code finished (any entity created before is not a leak) double profiletime; // system time when last PRVM_CallProfile was called (or PRVM_Prog_Load initially) - unsigned int id; // increasing unique id of progs instance mfunction_t *functions; + int functions_covered; char *strings; int stringssize; - ddef_t *fielddefs; - ddef_t *globaldefs; + mdef_t *fielddefs; + mdef_t *globaldefs; mstatement_t *statements; int entityfields; // number of vec_t fields in progs (some variables are 3) - int entityfieldsarea; // LordHavoc: equal to max_edicts * entityfields (for bounds checking) + int entityfieldsarea; // LadyHavoc: equal to max_edicts * entityfields (for bounds checking) // loaded values from the disk format int progs_version; @@ -559,11 +567,17 @@ typedef struct prvm_prog_s int numglobals; int *statement_linenums; // NULL if not available + int *statement_columnnums; // NULL if not available double *statement_profile; // only incremented if prvm_statementprofiling is on + int statements_covered; + double *explicit_profile; // only incremented if prvm_statementprofiling is on + int explicit_covered; + int numexplicitcoveragestatements; union { - vec_t *generic; + prvm_vec_t *fp; + prvm_int_t *ip; // globalvars_t *server; // cl_globalvars_t *client; } globals; @@ -574,12 +588,15 @@ typedef struct prvm_prog_s // (simple optimization of the free string search) int firstfreeknownstring; const char **knownstrings; - unsigned char *knownstrings_freeable; + unsigned char *knownstrings_flags; const char **knownstrings_origin; const char ***stringshash; memexpandablearray_t stringbuffersarray; + // garbage collection status + prvm_prog_garbagecollection_state_t gc; + // all memory allocations related to this vm_prog (code, edicts, strings) mempool_t *progs_mempool; // [INIT] @@ -589,6 +606,16 @@ typedef struct prvm_prog_s int argc; int trace; + int break_statement; + int break_stack_index; + int watch_global; + etype_t watch_global_type; + prvm_eval_t watch_global_value; + int watch_edict; + int watch_field; + etype_t watch_field_type; + prvm_eval_t watch_edictfield_value; + mfunction_t *xfunction; int xstatement; @@ -597,7 +624,7 @@ typedef struct prvm_prog_s prvm_stack_t stack[PRVM_MAX_STACK_DEPTH+1]; int depth; - int localstack[PRVM_LOCALSTACK_SIZE]; + prvm_int_t localstack[PRVM_LOCALSTACK_SIZE]; int localstack_used; unsigned short filecrc; @@ -605,18 +632,39 @@ typedef struct prvm_prog_s //============================================================================ // until this point everything also exists (with the pr_ prefix) in the old vm - qfile_t *openfiles[PRVM_MAX_OPENFILES]; + struct qfile_s *openfiles[PRVM_MAX_OPENFILES]; const char * openfiles_origin[PRVM_MAX_OPENFILES]; - fssearch_t *opensearches[PRVM_MAX_OPENSEARCHES]; + struct fssearch_s *opensearches[PRVM_MAX_OPENSEARCHES]; const char * opensearches_origin[PRVM_MAX_OPENSEARCHES]; - skeleton_t *skeletons[MAX_EDICTS]; + struct skeleton_s *skeletons[MAX_EDICTS]; + struct cmd_state_s *console_cmd; // points to the relevant console command interpreter for this vm (cmd_local or &cmd_server), also used to access cvars // buffer for storing all tempstrings created during one invocation of ExecuteProgram sizebuf_t tempstringsbuf; - // LordHavoc: moved this here to clean up things that relied on prvm_prog_list too much - // FIXME: make VM_CL_R_Polygon functions use Debug_Polygon functions? - vmpolygons_t vmpolygons; + // polygonbegin, polygonvertex, polygonend state + // the polygon is buffered here until polygonend commits it to the relevant + // CL_Mesh entity, because important decisions depend on the vertex data + // provided (e.g. whether the polygon is transparent), we can't really do much + // with it until we have all of the data... + + // this tracks the last polygonbegin's choice of + // CL_Mesh_CSQC or CL_Mesh_UI for this polygon + struct model_s *polygonbegin_model; + // indicates if polygonbegin should be interpreted as 2d + // (clearscene sets this to false, renderscene sets this to true, drawpic + // also sets this to true) + // note that in FTEQW polygonbegin with 2 args is handled very differently, + // where the behavior is always 3D unless DRAWFLAG_2D is passed, but + // DRAWFLAG_2D conflicts with our DRAWFLAG_SCREEN. + qbool polygonbegin_guess2d; + // the texture name and drawflags provided to polygonbegin + char polygonbegin_texname[MAX_QPATH]; + int polygonbegin_drawflags; + // the vertex data + int polygonbegin_numvertices; + int polygonbegin_maxvertices; + float *polygonbegin_vertexdata; // copies of some vars that were former read from sv int num_edicts; @@ -629,8 +677,12 @@ typedef struct prvm_prog_s int reserved_edicts; // [INIT] prvm_edict_t *edicts; - vec_t *edictsfields; - void *edictprivate; + union + { + prvm_vec_t *fp; + prvm_int_t *ip; + } edictsfields; + void *edictprivate; // size of the engine private struct int edictprivate_size; // [INIT] @@ -641,21 +693,21 @@ typedef struct prvm_prog_s // allow writing to world entity fields, this is set by server init and // cleared before first server frame - qboolean allowworldwrites; + qbool allowworldwrites; // name of the prog, e.g. "Server", "Client" or "Menu" (used for text output) const char *name; // [INIT] // flag - used to store general flags like PRVM_GE_SELF, etc. - int flag; + unsigned flag; - const char *extensionstring; // [INIT] + const char **extensionstring; // [INIT] - qboolean loadintoworld; // [INIT] + qbool loadintoworld; // [INIT] // used to indicate whether a prog is loaded - qboolean loaded; - qboolean leaktest_active; + qbool loaded; + qbool leaktest_active; // translation buffer (only needs to be freed on unloading progs, type is private to prvm_edict.c) void *po; @@ -663,15 +715,17 @@ typedef struct prvm_prog_s // printed together with backtraces const char *statestring; + struct animatemodel_cache *animatemodel_cache; + // prvm_builtin_mem_t *mem_list; -// now passed as parameter of PRVM_LoadProgs +// now passed as parameter of PRVM_Prog_Load // char **required_func; // int numrequiredfunc; //============================================================================ - ddef_t *self; // if self != 0 then there is a global self + mdef_t *self; // if self != 0 then there is a global self //============================================================================ // function pointers @@ -684,7 +738,7 @@ typedef struct prvm_prog_s void (*count_edicts)(struct prvm_prog_s *prog); // [INIT] used by PRVM_ED_Count_f - qboolean (*load_edict)(struct prvm_prog_s *prog, prvm_edict_t *ent); // [INIT] used by PRVM_ED_LoadFromFile + qbool (*load_edict)(struct prvm_prog_s *prog, prvm_edict_t *ent); // [INIT] used by PRVM_ED_LoadFromFile void (*init_cmd)(struct prvm_prog_s *prog); // [INIT] used by PRVM_InitProg void (*reset_cmd)(struct prvm_prog_s *prog); // [INIT] used by PRVM_ResetProg @@ -710,7 +764,9 @@ prvm_prog_t *PRVM_FriendlyProgFromString(const char *str); // for console comman #define PRVM_ProgLoaded(n) (PRVM_GetProg(n)->loaded) #define SVVM_prog (&prvm_prog_list[PRVM_PROG_SERVER]) #define CLVM_prog (&prvm_prog_list[PRVM_PROG_CLIENT]) +#ifdef CONFIG_MENU #define MVM_prog (&prvm_prog_list[PRVM_PROG_MENU]) +#endif //============================================================================ // prvm_cmds part @@ -723,8 +779,8 @@ extern const int vm_sv_numbuiltins; extern const int vm_cl_numbuiltins; extern const int vm_m_numbuiltins; -extern const char * vm_sv_extensions; // client also uses this -extern const char * vm_m_extensions; +extern const char *vm_sv_extensions[]; // client also uses this +extern const char *vm_m_extensions[]; void SVVM_init_cmd(prvm_prog_t *prog); void SVVM_reset_cmd(prvm_prog_t *prog); @@ -732,8 +788,10 @@ void SVVM_reset_cmd(prvm_prog_t *prog); void CLVM_init_cmd(prvm_prog_t *prog); void CLVM_reset_cmd(prvm_prog_t *prog); +#ifdef CONFIG_MENU void MVM_init_cmd(prvm_prog_t *prog); void MVM_reset_cmd(prvm_prog_t *prog); +#endif void VM_Cmd_Init(prvm_prog_t *prog); void VM_Cmd_Reset(prvm_prog_t *prog); @@ -744,11 +802,15 @@ void PRVM_Init (void); #ifdef PROFILING void SVVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage); void CLVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage); +#ifdef CONFIG_MENU void MVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage); +#endif #else #define SVVM_ExecuteProgram PRVM_ExecuteProgram #define CLVM_ExecuteProgram PRVM_ExecuteProgram +#ifdef CONFIG_MENU #define MVM_ExecuteProgram PRVM_ExecuteProgram +#endif void PRVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage); #endif @@ -756,18 +818,20 @@ void PRVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa #define PRVM_Free(buffer) Mem_Free(buffer) void PRVM_Profile (prvm_prog_t *prog, int maxfunctions, double mintime, int sortby); -void PRVM_Profile_f (void); -void PRVM_ChildProfile_f (void); -void PRVM_CallProfile_f (void); -void PRVM_PrintFunction_f (void); +void PRVM_Profile_f(struct cmd_state_s *cmd); +void PRVM_ChildProfile_f(struct cmd_state_s *cmd); +void PRVM_CallProfile_f(struct cmd_state_s *cmd); +void PRVM_PrintFunction_f(struct cmd_state_s *cmd); -void PRVM_PrintState(prvm_prog_t *prog); -void PRVM_Crash(prvm_prog_t *prog); +void PRVM_PrintState(prvm_prog_t *prog, int stack_index); +void PRVM_Crash(void); void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize); const char *PRVM_AllocationOrigin(prvm_prog_t *prog); +void PRVM_GarbageCollection(prvm_prog_t *prog); -ddef_t *PRVM_ED_FindField(prvm_prog_t *prog, const char *name); -ddef_t *PRVM_ED_FindGlobal(prvm_prog_t *prog, const char *name); +mdef_t *PRVM_ED_FindField(prvm_prog_t *prog, const char *name); +mdef_t *PRVM_ED_FindGlobal(prvm_prog_t *prog, const char *name); +prvm_eval_t *PRVM_ED_FindGlobalEval(prvm_prog_t *prog, const char *name); mfunction_t *PRVM_ED_FindFunction(prvm_prog_t *prog, const char *name); int PRVM_ED_FindFieldOffset(prvm_prog_t *prog, const char *name); @@ -778,30 +842,34 @@ func_t PRVM_ED_FindFunctionOffset(prvm_prog_t *prog, const char *name); void PRVM_MEM_IncreaseEdicts(prvm_prog_t *prog); -qboolean PRVM_ED_CanAlloc(prvm_prog_t *prog, prvm_edict_t *e); +qbool PRVM_ED_CanAlloc(prvm_prog_t *prog, prvm_edict_t *e); prvm_edict_t *PRVM_ED_Alloc(prvm_prog_t *prog); void PRVM_ED_Free(prvm_prog_t *prog, prvm_edict_t *ed); void PRVM_ED_ClearEdict(prvm_prog_t *prog, prvm_edict_t *e); void PRVM_PrintFunctionStatements(prvm_prog_t *prog, const char *name); void PRVM_ED_Print(prvm_prog_t *prog, prvm_edict_t *ed, const char *wildcard_fieldname); -void PRVM_ED_Write(prvm_prog_t *prog, qfile_t *f, prvm_edict_t *ed); +void PRVM_ED_Write(prvm_prog_t *prog, struct qfile_s *f, prvm_edict_t *ed); const char *PRVM_ED_ParseEdict(prvm_prog_t *prog, const char *data, prvm_edict_t *ent); -void PRVM_ED_WriteGlobals(prvm_prog_t *prog, qfile_t *f); +void PRVM_ED_WriteGlobals(prvm_prog_t *prog, struct qfile_s *f); void PRVM_ED_ParseGlobals(prvm_prog_t *prog, const char *data); +void PRVM_ED_CallPrespawnFunction(prvm_prog_t *prog, prvm_edict_t *ent); +qbool PRVM_ED_CallSpawnFunction(prvm_prog_t *prog, prvm_edict_t *ent, const char *data, const char *start); +void PRVM_ED_CallPostspawnFunction (prvm_prog_t *prog, prvm_edict_t *ent); + void PRVM_ED_LoadFromFile(prvm_prog_t *prog, const char *data); unsigned int PRVM_EDICT_NUM_ERROR(prvm_prog_t *prog, unsigned int n, const char *filename, int fileline); -#define PRVM_EDICT(n) (((unsigned)(n) < (unsigned int)prog->max_edicts) ? (unsigned int)(n) : PRVM_EDICT_NUM_ERROR(prog, (unsigned int)(n), __FILE__, __LINE__)) -#define PRVM_EDICT_NUM(n) (prog->edicts + PRVM_EDICT(n)) +#define PRVM_EDICT(n) (((unsigned)(n) < (unsigned int)prog->max_edicts) ? (unsigned int)(n) : PRVM_EDICT_NUM_ERROR(prog, (unsigned int)(n), __FILE__, __LINE__)) +#define PRVM_EDICT_NUM(n) (prog->edicts + PRVM_EDICT(n)) //int NUM_FOR_EDICT_ERROR(prvm_edict_t *e); #define PRVM_NUM_FOR_EDICT(e) ((int)((prvm_edict_t *)(e) - prog->edicts)) //int PRVM_NUM_FOR_EDICT(prvm_edict_t *e); -#define PRVM_NEXT_EDICT(e) ((e) + 1) +#define PRVM_NEXT_EDICT(e) ((e) + 1) #define PRVM_EDICT_TO_PROG(e) (PRVM_NUM_FOR_EDICT(e)) //int PRVM_EDICT_TO_PROG(prvm_edict_t *e); @@ -810,37 +878,38 @@ unsigned int PRVM_EDICT_NUM_ERROR(prvm_prog_t *prog, unsigned int n, const char //============================================================================ -#define PRVM_G_FLOAT(o) (prog->globals.generic[o]) -#define PRVM_G_INT(o) (*(int *)&prog->globals.generic[o]) -#define PRVM_G_EDICT(o) (PRVM_PROG_TO_EDICT(*(int *)&prog->globals.generic[o])) +#define PRVM_G_FLOAT(o) (prog->globals.fp[o]) +#define PRVM_G_INT(o) (prog->globals.ip[o]) +#define PRVM_G_EDICT(o) (PRVM_PROG_TO_EDICT(prog->globals.ip[o])) #define PRVM_G_EDICTNUM(o) PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(o)) -#define PRVM_G_VECTOR(o) (&prog->globals.generic[o]) -#define PRVM_G_STRING(o) (PRVM_GetString(prog, *(string_t *)&prog->globals.generic[o])) -//#define PRVM_G_FUNCTION(prog, o) (*(func_t *)&prog->globals.generic[o]) +#define PRVM_G_VECTOR(o) (&prog->globals.fp[o]) +#define PRVM_G_STRING(o) (PRVM_GetString(prog, prog->globals.ip[o])) +//#define PRVM_G_FUNCTION(prog, o) (prog->globals.ip[o]) // FIXME: make these go away? -#define PRVM_E_FLOAT(e,o) (((float*)e->fields.vp)[o]) -#define PRVM_E_INT(e,o) (((int*)e->fields.vp)[o]) -//#define PRVM_E_VECTOR(e,o) (&((float*)e->fields.vp)[o]) -#define PRVM_E_STRING(e,o) (PRVM_GetString(prog, *(string_t *)&((float*)e->fields.vp)[o])) +#define PRVM_E_FLOAT(e,o) (e->fields.fp[o]) +#define PRVM_E_INT(e,o) (e->fields.ip[o]) +//#define PRVM_E_VECTOR(e,o) (&(e->fields.fp[o])) +#define PRVM_E_STRING(e,o) (PRVM_GetString(prog, e->fields.ip[o])) -extern int prvm_type_size[8]; // for consistency : I think a goal of this sub-project is to +extern int prvm_type_size[8]; // for consistency : I think a goal of this sub-project is to // make the new vm mostly independent from the old one, thus if it's necessary, I copy everything void PRVM_Init_Exec(prvm_prog_t *prog); -void PRVM_ED_PrintEdicts_f (void); +void PRVM_ED_PrintEdicts_f(struct cmd_state_s *cmd); void PRVM_ED_PrintNum (prvm_prog_t *prog, int ent, const char *wildcard_fieldname); const char *PRVM_GetString(prvm_prog_t *prog, int num); int PRVM_SetEngineString(prvm_prog_t *prog, const char *s); const char *PRVM_ChangeEngineString(prvm_prog_t *prog, int i, const char *s); -int PRVM_SetTempString(prvm_prog_t *prog, const char *s); +/// Takes an strlen (not a buffer size). +int PRVM_SetTempString(prvm_prog_t *prog, const char *s, size_t slen); int PRVM_AllocString(prvm_prog_t *prog, size_t bufferlength, char **pointer); void PRVM_FreeString(prvm_prog_t *prog, int num); -ddef_t *PRVM_ED_FieldAtOfs(prvm_prog_t *prog, int ofs); -qboolean PRVM_ED_ParseEpair(prvm_prog_t *prog, prvm_edict_t *ent, ddef_t *key, const char *s, qboolean parsebackslash); +mdef_t *PRVM_ED_FieldAtOfs(prvm_prog_t *prog, unsigned int ofs); +qbool PRVM_ED_ParseEpair(prvm_prog_t *prog, prvm_edict_t *ent, mdef_t *key, const char *s, qbool parsebackslash); char *PRVM_UglyValueString(prvm_prog_t *prog, etype_t type, prvm_eval_t *val, char *line, size_t linelength); char *PRVM_GlobalString(prvm_prog_t *prog, int ofs, char *line, size_t linelength); char *PRVM_GlobalStringNoContents(prvm_prog_t *prog, int ofs, char *line, size_t linelength); @@ -853,18 +922,22 @@ Call InitProg with the num Set up the fields marked with [INIT] in the prog struct Load a program with LoadProgs */ -// Load expects to be called right after Init -void PRVM_Prog_Init(prvm_prog_t *prog); -void PRVM_Prog_Load(prvm_prog_t *prog, 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); +// Load expects to be called right after Reset +void PRVM_Prog_Init(prvm_prog_t *prog, struct cmd_state_s *cmd); +void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data, fs_offset_t size, void CheckRequiredFuncs(prvm_prog_t *prog, const char *filename), int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global); void PRVM_Prog_Reset(prvm_prog_t *prog); void PRVM_StackTrace(prvm_prog_t *prog); +void PRVM_Breakpoint(prvm_prog_t *prog, int stack_index, const char *text); +void PRVM_Watchpoint(prvm_prog_t *prog, int stack_index, const char *text, etype_t type, prvm_eval_t *o, prvm_eval_t *n); void VM_Warning(prvm_prog_t *prog, const char *fmt, ...) DP_FUNC_PRINTF(2); -void VM_GenerateFrameGroupBlend(prvm_prog_t *prog, framegroupblend_t *framegroupblend, const prvm_edict_t *ed); -void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroupblend_t *framegroupblend, const dp_model_t *model, double curtime); -void VM_UpdateEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed, const dp_model_t *edmodel, const frameblend_t *frameblend); +void VM_GenerateFrameGroupBlend(prvm_prog_t *prog, struct framegroupblend_s *framegroupblend, const prvm_edict_t *ed); +void VM_FrameBlendFromFrameGroupBlend(struct frameblend_s *frameblend, const struct framegroupblend_s *framegroupblend, const struct model_s *model, double curtime); +void VM_UpdateEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed, const struct model_s *edmodel, const struct frameblend_s *frameblend); void VM_RemoveEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed); +void PRVM_ExplicitCoverageEvent(prvm_prog_t *prog, mfunction_t *func, int statement); + #endif