diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c new file mode 100644 index 000000000..b99e12c7d --- /dev/null +++ b/engine/client/pr_csqc.c @@ -0,0 +1,409 @@ +#include "quakedef.h" + +#ifdef CSQC_DAT + +typedef struct menuedict_s +{ + qboolean isfree; + float freetime; // sv.time when the object was freed + int entnum; + qboolean readonly; //world +} csqcedict_t; + +#define RETURN_SSTRING(s) (*(char **)&((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //static - exe will not change it. +char *PF_TempStr(void); + +int csqcentsize; + +//pr_cmds.c builtins that need to be moved to a common. +void VARGS PR_BIError(progfuncs_t *progfuncs, char *format, ...); +void PF_cvar_string (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_cvar_set (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_dprint (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_error (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_rint (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_floor (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_ceil (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_Tokenize (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_FindString (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_FindFloat (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_nextent (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_randomvec (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_Sin (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_Cos (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_Sqrt (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_bound (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_strlen(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_strcat (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_ftos (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_fabs (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_vtos (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_etos (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_stof (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_mod (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_substring (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_stov (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_dupstring(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_forgetstring(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_Spawn (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_min (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_max (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_registercvar (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_pow (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_chr2str (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_localcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_random (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_fopen (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_fclose (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_normalize (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_vlen (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_vectoyaw (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_vectoangles (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_findchain (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_findchainfloat (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_coredump (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_traceon (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_traceoff (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_eprint (progfuncs_t *prinst, struct globalvars_s *pr_globals); + +void PF_fclose_progs (progfuncs_t *prinst); +char *PF_VarString (progfuncs_t *prinst, int first, struct globalvars_s *pr_globals); + +static void PF_cvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + cvar_t *var; + char *str; + + str = PR_GetStringOfs(prinst, OFS_PARM0); + { + var = Cvar_Get(str, "", 0, "csqc cvars"); + if (var) + G_FLOAT(OFS_RETURN) = var->value; + else + G_FLOAT(OFS_RETURN) = 0; + } +} + +//too specific to the prinst's builtins. +static void PF_Fixme (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + Con_Printf("\n"); + + prinst->PR_RunError(prinst, "\nBuiltin %i not implemented.\nMenu is not compatable.", prinst->lastcalledbuiltinnumber); + PR_BIError (prinst, "bulitin not implemented"); +} + + + +static void PF_makevectors (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +// AngleVectors (G_VECTOR(OFS_PARM0), CSQC_VEC(v_forward), CSQC_VEC(v_right), CSQC_VEC(v_up)); +} + + + +//warning: functions that depend on globals are bad, mkay? +builtin_t csqc_builtins[] = { +//0 + PF_Fixme, + PF_makevectors, + PF_Fixme, //PF_setorigin + PF_Fixme, //PF_setmodel + PF_Fixme, //PF_setsize + PF_Fixme, + PF_Fixme, //PF_break, + PF_random, + PF_Fixme, //PF_sound, + PF_normalize, +//10 + PF_error, + PF_Fixme, //PF_objerror, + PF_vlen, + PF_vectoyaw, + PF_Spawn, + PF_Fixme, //PF_Remove, + PF_Fixme, //PF_traceline, + PF_Fixme, //PF_checkclient, + PF_FindString, + PF_Fixme, //PF_precache_sound, +//20 + PF_Fixme, //PF_precache_model, + PF_Fixme, //PF_stuffcmd, + PF_Fixme, //PF_findradius, + PF_Fixme, //PF_bprint, + PF_Fixme, //PF_sprint, + PF_dprint, + PF_ftos, + PF_vtos, + PF_coredump, + PF_traceon, +//30 + PF_traceoff, + PF_eprint, + PF_Fixme, //PF_walkmove, + PF_Fixme, +PF_Fixme, //PF_droptofloor, +PF_Fixme, //PF_lightstyle, +PF_rint, +PF_floor, +PF_ceil, +PF_Fixme, +//40 +PF_Fixme, //PF_checkbottom, +PF_Fixme, //PF_pointcontents, +PF_Fixme, +PF_fabs, +PF_Fixme, //PF_aim, hehehe... +PF_cvar, +PF_localcmd, +PF_nextent, +PF_Fixme, //PF_particle, +PF_Fixme, //PF_changeyaw, +//50 +PF_Fixme, +PF_vectoangles, + +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +//60 +PF_Fixme, + +PF_Sin, +PF_Cos, +PF_Sqrt, + +PF_Fixme, + +PF_Fixme, +PF_Fixme, +SV_MoveToGoal, +PF_Fixme, //PF_precache_file, +PF_Fixme, //PF_makestatic, +//70 +PF_Fixme, //PF_changelevel, +PF_Fixme, +PF_cvar_set, +PF_Fixme, //PF_centerprint, +PF_Fixme, //PF_ambientsound, + +PF_Fixme, //PF_precache_model, +PF_Fixme, //PF_precache_sound, +PF_Fixme, //PF_precache_file, +PF_Fixme, //PF_setspawnparms, +PF_Fixme, //PF_logfrag, +//80 +PF_Fixme, //PF_infokey, +PF_stof, +PF_Fixme, //PF_multicast, +PF_Fixme, +PF_Fixme, + +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +//90 +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, + +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +//100 +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, + +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +//110 +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, + +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, + + + +PF_Fixme}; +int csqc_numbuiltins = sizeof(csqc_builtins)/sizeof(csqc_builtins[0]); + + + + + +jmp_buf csqc_abort; +int incsqcprogs; +progfuncs_t *csqcprogs; +progparms_t csqcprogparms; +csqcedict_t *csqc_edicts; +int num_csqc_edicts; + +func_t csqc_init_function; +func_t csqc_shutdown_function; +func_t csqc_draw_function; +func_t csqc_keydown_function; +func_t csqc_keyup_function; +func_t csqc_toggle_function; + +float *csqc_time; + + + + +int COM_FileSize(char *path); +pbool QC_WriteFile(char *name, void *data, int len); +void *VARGS PR_Malloc(int size); //these functions should be tracked by the library reliably, so there should be no need to track them ourselves. +void VARGS PR_Free(void *mem); + +//Any menu builtin error or anything like that will come here. +void VARGS CSQC_Abort (char *format, ...) +{ + va_list argptr; + char string[1024]; + + va_start (argptr, format); + _vsnprintf (string,sizeof(string)-1, format,argptr); + va_end (argptr); + + Con_Printf("CSQC_Abort: %s\nShutting down csqc\n", string); + + +{ + static char buffer[1024*1024*8]; + int size = sizeof buffer; + csqcprogs->save_ents(csqcprogs, buffer, &size, 3); + COM_WriteFile("csqccore.txt", buffer, size); +} + + Host_EndGame("csqc error"); +} + +double csqctime; +void CSQC_Init (void) +{ + if (!qrenderer) + { + return; + } + + + csqcprogparms.progsversion = PROGSTRUCT_VERSION; + csqcprogparms.ReadFile = COM_LoadStackFile;//char *(*ReadFile) (char *fname, void *buffer, int *len); + csqcprogparms.FileSize = COM_FileSize;//int (*FileSize) (char *fname); //-1 if file does not exist + csqcprogparms.WriteFile = QC_WriteFile;//bool (*WriteFile) (char *name, void *data, int len); + csqcprogparms.printf = (void *)Con_Printf;//Con_Printf;//void (*printf) (char *, ...); + csqcprogparms.Sys_Error = Sys_Error; + csqcprogparms.Abort = CSQC_Abort; + csqcprogparms.edictsize = sizeof(csqcedict_t); + + csqcprogparms.entspawn = NULL;//void (*entspawn) (struct edict_s *ent); //ent has been spawned, but may not have all the extra variables (that may need to be set) set + csqcprogparms.entcanfree = NULL;//bool (*entcanfree) (struct edict_s *ent); //return true to stop ent from being freed + csqcprogparms.stateop = NULL;//StateOp;//void (*stateop) (float var, func_t func); + csqcprogparms.cstateop = NULL;//CStateOp; + csqcprogparms.cwstateop = NULL;//CWStateOp; + csqcprogparms.thinktimeop = NULL;//ThinkTimeOp; + + //used when loading a game + csqcprogparms.builtinsfor = NULL;//builtin_t *(*builtinsfor) (int num); //must return a pointer to the builtins that were used before the state was saved. + csqcprogparms.loadcompleate = NULL;//void (*loadcompleate) (int edictsize); //notification to reset any pointers. + + csqcprogparms.memalloc = PR_Malloc;//void *(*memalloc) (int size); //small string allocation malloced and freed randomly + csqcprogparms.memfree = PR_Free;//void (*memfree) (void * mem); + + + csqcprogparms.globalbuiltins = csqc_builtins;//builtin_t *globalbuiltins; //these are available to all progs + csqcprogparms.numglobalbuiltins = csqc_numbuiltins; + + csqcprogparms.autocompile = PR_NOCOMPILE;//enum {PR_NOCOMPILE, PR_COMPILENEXIST, PR_COMPILECHANGED, PR_COMPILEALWAYS} autocompile; + + csqcprogparms.gametime = &csqctime; + + csqcprogparms.sv_edicts = (edict_t **)&csqc_edicts; + csqcprogparms.sv_num_edicts = &num_csqc_edicts; + + csqcprogparms.useeditor = NULL;//sorry... QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms); + + csqctime = Sys_DoubleTime(); + if (!csqcprogs) + { + csqcprogs = InitProgs(&csqcprogparms); + PR_Configure(csqcprogs, NULL, -1, 1); + if (PR_LoadProgs(csqcprogs, "qwprogs.dat", 54730, NULL, 0) < 0) //no per-progs builtins. + { + //failed to load or something + M_Init_Internal(); + return; + } + if (setjmp(csqc_abort)) + { + M_Init_Internal(); + return; + } + incsqcprogs++; + + csqc_time = (float*)PR_FindGlobal(csqcprogs, "time", 0); + if (csqc_time) + *csqc_time = Sys_DoubleTime(); + + csqcentsize = PR_InitEnts(csqcprogs, 3072); + + + //'world' edict + EDICT_NUM(csqcprogs, 0)->readonly = true; + EDICT_NUM(csqcprogs, 0)->isfree = false; + + + csqc_init_function = PR_FindFunction(csqcprogs, "csqc_init", PR_ANY); + csqc_shutdown_function = PR_FindFunction(csqcprogs, "csqc_shutdown", PR_ANY); + csqc_draw_function = PR_FindFunction(csqcprogs, "csqc_draw", PR_ANY); + csqc_keydown_function = PR_FindFunction(csqcprogs, "csqc_keydown", PR_ANY); + csqc_keyup_function = PR_FindFunction(csqcprogs, "csqc_keyup", PR_ANY); + csqc_toggle_function = PR_FindFunction(csqcprogs, "csqc_toggle", PR_ANY); + + if (csqc_init_function) + PR_ExecuteProgram(csqcprogs, csqc_init_function); + incsqcprogs--; + } +} + +qboolean CSQC_DrawView(void) +{ + if (!csqcprogs || !csqc_draw_function) + return false; + + incsqcprogs++; + + PR_ExecuteProgram(csqcprogs, csqc_draw_function); + + incsqcprogs--; + return true; +} + +#endif