Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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. #include "quakedef.h"
  22.  
  23.  
  24. /*
  25.  
  26. */
  27.  
  28. typedef struct
  29. {
  30.         int                             s;
  31.         dfunction_t             *f;
  32. } prstack_t;
  33.  
  34. #define MAX_STACK_DEPTH         32
  35. prstack_t       pr_stack[MAX_STACK_DEPTH];
  36. int                     pr_depth;
  37.  
  38. #define LOCALSTACK_SIZE         2048
  39. int                     localstack[LOCALSTACK_SIZE];
  40. int                     localstack_used;
  41.  
  42.  
  43. qboolean        pr_trace;
  44. dfunction_t     *pr_xfunction;
  45. int                     pr_xstatement;
  46.  
  47.  
  48. int             pr_argc;
  49.  
  50. char *pr_opnames[] =
  51. {
  52. "DONE",
  53.  
  54. "MUL_F",
  55. "MUL_V",
  56. "MUL_FV",
  57. "MUL_VF",
  58.  
  59. "DIV",
  60.  
  61. "ADD_F",
  62. "ADD_V",
  63.  
  64. "SUB_F",
  65. "SUB_V",
  66.  
  67. "EQ_F",
  68. "EQ_V",
  69. "EQ_S",
  70. "EQ_E",
  71. "EQ_FNC",
  72.  
  73. "NE_F",
  74. "NE_V",
  75. "NE_S",
  76. "NE_E",
  77. "NE_FNC",
  78.  
  79. "LE",
  80. "GE",
  81. "LT",
  82. "GT",
  83.  
  84. "INDIRECT",
  85. "INDIRECT",
  86. "INDIRECT",
  87. "INDIRECT",
  88. "INDIRECT",
  89. "INDIRECT",
  90.  
  91. "ADDRESS",
  92.  
  93. "STORE_F",
  94. "STORE_V",
  95. "STORE_S",
  96. "STORE_ENT",
  97. "STORE_FLD",
  98. "STORE_FNC",
  99.  
  100. "STOREP_F",
  101. "STOREP_V",
  102. "STOREP_S",
  103. "STOREP_ENT",
  104. "STOREP_FLD",
  105. "STOREP_FNC",
  106.  
  107. "RETURN",
  108.  
  109. "NOT_F",
  110. "NOT_V",
  111. "NOT_S",
  112. "NOT_ENT",
  113. "NOT_FNC",
  114.  
  115. "IF",
  116. "IFNOT",
  117.  
  118. "CALL0",
  119. "CALL1",
  120. "CALL2",
  121. "CALL3",
  122. "CALL4",
  123. "CALL5",
  124. "CALL6",
  125. "CALL7",
  126. "CALL8",
  127.  
  128. "STATE",
  129.  
  130. "GOTO",
  131.  
  132. "AND",
  133. "OR",
  134.  
  135. "BITAND",
  136. "BITOR"
  137. };
  138.  
  139. char *PR_GlobalString (int ofs);
  140. char *PR_GlobalStringNoContents (int ofs);
  141.  
  142.  
  143. //=============================================================================
  144.  
  145. /*
  146. =================
  147. PR_PrintStatement
  148. =================
  149. */
  150. void PR_PrintStatement (dstatement_t *s)
  151. {
  152.         int             i;
  153.        
  154.         if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
  155.         {
  156.                 Con_Printf ("%s ",  pr_opnames[s->op]);
  157.                 i = strlen(pr_opnames[s->op]);
  158.                 for ( ; i<10 ; i++)
  159.                         Con_Printf (" ");
  160.         }
  161.                
  162.         if (s->op == OP_IF || s->op == OP_IFNOT)
  163.                 Con_Printf ("%sbranch %i",PR_GlobalString(s->a),s->b);
  164.         else if (s->op == OP_GOTO)
  165.         {
  166.                 Con_Printf ("branch %i",s->a);
  167.         }
  168.         else if ( (unsigned)(s->op - OP_STORE_F) < 6)
  169.         {
  170.                 Con_Printf ("%s",PR_GlobalString(s->a));
  171.                 Con_Printf ("%s", PR_GlobalStringNoContents(s->b));
  172.         }
  173.         else
  174.         {
  175.                 if (s->a)
  176.                         Con_Printf ("%s",PR_GlobalString(s->a));
  177.                 if (s->b)
  178.                         Con_Printf ("%s",PR_GlobalString(s->b));
  179.                 if (s->c)
  180.                         Con_Printf ("%s", PR_GlobalStringNoContents(s->c));
  181.         }
  182.         Con_Printf ("\n");
  183. }
  184.  
  185. /*
  186. ============
  187. PR_StackTrace
  188. ============
  189. */
  190. void PR_StackTrace (void)
  191. {
  192.         dfunction_t     *f;
  193.         int                     i;
  194.        
  195.         if (pr_depth == 0)
  196.         {
  197.                 Con_Printf ("<NO STACK>\n");
  198.                 return;
  199.         }
  200.        
  201.         pr_stack[pr_depth].f = pr_xfunction;
  202.         for (i=pr_depth ; i>=0 ; i--)
  203.         {
  204.                 f = pr_stack[i].f;
  205.                
  206.                 if (!f)
  207.                 {
  208.                         Con_Printf ("<NO FUNCTION>\n");
  209.                 }
  210.                 else
  211.                         Con_Printf ("%12s : %s\n", pr_strings + f->s_file, pr_strings + f->s_name);            
  212.         }
  213. }
  214.  
  215.  
  216. /*
  217. ============
  218. PR_Profile_f
  219.  
  220. ============
  221. */
  222. void PR_Profile_f (void)
  223. {
  224.         dfunction_t     *f, *best;
  225.         int                     max;
  226.         int                     num;
  227.         int                     i;
  228.        
  229.         num = 0;       
  230.         do
  231.         {
  232.                 max = 0;
  233.                 best = NULL;
  234.                 for (i=0 ; i<progs->numfunctions ; i++)
  235.                 {
  236.                         f = &pr_functions[i];
  237.                         if (f->profile > max)
  238.                         {
  239.                                 max = f->profile;
  240.                                 best = f;
  241.                         }
  242.                 }
  243.                 if (best)
  244.                 {
  245.                         if (num < 10)
  246.                                 Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name);
  247.                         num++;
  248.                         best->profile = 0;
  249.                 }
  250.         } while (best);
  251. }
  252.  
  253.  
  254. /*
  255. ============
  256. PR_RunError
  257.  
  258. Aborts the currently executing function
  259. ============
  260. */
  261. void PR_RunError (char *error, ...)
  262. {
  263.         va_list         argptr;
  264.         char            string[1024];
  265.  
  266.         va_start (argptr,error);
  267.         vsprintf (string,error,argptr);
  268.         va_end (argptr);
  269.  
  270.         PR_PrintStatement (pr_statements + pr_xstatement);
  271.         PR_StackTrace ();
  272.         Con_Printf ("%s\n", string);
  273.        
  274.         pr_depth = 0;           // dump the stack so host_error can shutdown functions
  275.  
  276.         Host_Error ("Program error");
  277. }
  278.  
  279. /*
  280. ============================================================================
  281. PR_ExecuteProgram
  282.  
  283. The interpretation main loop
  284. ============================================================================
  285. */
  286.  
  287. /*
  288. ====================
  289. PR_EnterFunction
  290.  
  291. Returns the new program statement counter
  292. ====================
  293. */
  294. int PR_EnterFunction (dfunction_t *f)
  295. {
  296.         int             i, j, c, o;
  297.  
  298.         pr_stack[pr_depth].s = pr_xstatement;
  299.         pr_stack[pr_depth].f = pr_xfunction;   
  300.         pr_depth++;
  301.         if (pr_depth >= MAX_STACK_DEPTH)
  302.                 PR_RunError ("stack overflow");
  303.  
  304. // save off any locals that the new function steps on
  305.         c = f->locals;
  306.         if (localstack_used + c > LOCALSTACK_SIZE)
  307.                 PR_RunError ("PR_ExecuteProgram: locals stack overflow\n");
  308.  
  309.         for (i=0 ; i < c ; i++)
  310.                 localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
  311.         localstack_used += c;
  312.  
  313. // copy parameters
  314.         o = f->parm_start;
  315.         for (i=0 ; i<f->numparms ; i++)
  316.         {
  317.                 for (j=0 ; j<f->parm_size[i] ; j++)
  318.                 {
  319.                         ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
  320.                         o++;
  321.                 }
  322.         }
  323.  
  324.         pr_xfunction = f;
  325.         return f->first_statement - 1;  // offset the s++
  326. }
  327.  
  328. /*
  329. ====================
  330. PR_LeaveFunction
  331. ====================
  332. */
  333. int PR_LeaveFunction (void)
  334. {
  335.         int             i, c;
  336.  
  337.         if (pr_depth <= 0)
  338.                 Sys_Error ("prog stack underflow");
  339.  
  340. // restore locals from the stack
  341.         c = pr_xfunction->locals;
  342.         localstack_used -= c;
  343.         if (localstack_used < 0)
  344.                 PR_RunError ("PR_ExecuteProgram: locals stack underflow\n");
  345.  
  346.         for (i=0 ; i < c ; i++)
  347.                 ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
  348.  
  349. // up stack
  350.         pr_depth--;
  351.         pr_xfunction = pr_stack[pr_depth].f;
  352.         return pr_stack[pr_depth].s;
  353. }
  354.  
  355.  
  356. /*
  357. ====================
  358. PR_ExecuteProgram
  359. ====================
  360. */
  361. void PR_ExecuteProgram (func_t fnum)
  362. {
  363.         eval_t  *a, *b, *c;
  364.         int                     s;
  365.         dstatement_t    *st;
  366.         dfunction_t     *f, *newf;
  367.         int             runaway;
  368.         int             i;
  369.         edict_t *ed;
  370.         int             exitdepth;
  371.         eval_t  *ptr;
  372.  
  373.         if (!fnum || fnum >= progs->numfunctions)
  374.         {
  375.                 if (pr_global_struct->self)
  376.                         ED_Print (PROG_TO_EDICT(pr_global_struct->self));
  377.                 Host_Error ("PR_ExecuteProgram: NULL function");
  378.         }
  379.        
  380.         f = &pr_functions[fnum];
  381.  
  382.         runaway = 100000;
  383.         pr_trace = false;
  384.  
  385. // make a stack frame
  386.         exitdepth = pr_depth;
  387.  
  388.         s = PR_EnterFunction (f);
  389.        
  390. while (1)
  391. {
  392.         s++;    // next statement
  393.  
  394.         st = &pr_statements[s];
  395.         a = (eval_t *)&pr_globals[st->a];
  396.         b = (eval_t *)&pr_globals[st->b];
  397.         c = (eval_t *)&pr_globals[st->c];
  398.        
  399.         if (!--runaway)
  400.                 PR_RunError ("runaway loop error");
  401.                
  402.         pr_xfunction->profile++;
  403.         pr_xstatement = s;
  404.        
  405.         if (pr_trace)
  406.                 PR_PrintStatement (st);
  407.                
  408.         switch (st->op)
  409.         {
  410.         case OP_ADD_F:
  411.                 c->_float = a->_float + b->_float;
  412.                 break;
  413.         case OP_ADD_V:
  414.                 c->vector[0] = a->vector[0] + b->vector[0];
  415.                 c->vector[1] = a->vector[1] + b->vector[1];
  416.                 c->vector[2] = a->vector[2] + b->vector[2];
  417.                 break;
  418.                
  419.         case OP_SUB_F:
  420.                 c->_float = a->_float - b->_float;
  421.                 break;
  422.         case OP_SUB_V:
  423.                 c->vector[0] = a->vector[0] - b->vector[0];
  424.                 c->vector[1] = a->vector[1] - b->vector[1];
  425.                 c->vector[2] = a->vector[2] - b->vector[2];
  426.                 break;
  427.  
  428.         case OP_MUL_F:
  429.                 c->_float = a->_float * b->_float;
  430.                 break;
  431.         case OP_MUL_V:
  432.                 c->_float = a->vector[0]*b->vector[0]
  433.                                 + a->vector[1]*b->vector[1]
  434.                                 + a->vector[2]*b->vector[2];
  435.                 break;
  436.         case OP_MUL_FV:
  437.                 c->vector[0] = a->_float * b->vector[0];
  438.                 c->vector[1] = a->_float * b->vector[1];
  439.                 c->vector[2] = a->_float * b->vector[2];
  440.                 break;
  441.         case OP_MUL_VF:
  442.                 c->vector[0] = b->_float * a->vector[0];
  443.                 c->vector[1] = b->_float * a->vector[1];
  444.                 c->vector[2] = b->_float * a->vector[2];
  445.                 break;
  446.  
  447.         case OP_DIV_F:
  448.                 c->_float = a->_float / b->_float;
  449.                 break;
  450.        
  451.         case OP_BITAND:
  452.                 c->_float = (int)a->_float & (int)b->_float;
  453.                 break;
  454.        
  455.         case OP_BITOR:
  456.                 c->_float = (int)a->_float | (int)b->_float;
  457.                 break;
  458.        
  459.                
  460.         case OP_GE:
  461.                 c->_float = a->_float >= b->_float;
  462.                 break;
  463.         case OP_LE:
  464.                 c->_float = a->_float <= b->_float;
  465.                 break;
  466.         case OP_GT:
  467.                 c->_float = a->_float > b->_float;
  468.                 break;
  469.         case OP_LT:
  470.                 c->_float = a->_float < b->_float;
  471.                 break;
  472.         case OP_AND:
  473.                 c->_float = a->_float && b->_float;
  474.                 break;
  475.         case OP_OR:
  476.                 c->_float = a->_float || b->_float;
  477.                 break;
  478.                
  479.         case OP_NOT_F:
  480.                 c->_float = !a->_float;
  481.                 break;
  482.         case OP_NOT_V:
  483.                 c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2];
  484.                 break;
  485.         case OP_NOT_S:
  486.                 c->_float = !a->string || !pr_strings[a->string];
  487.                 break;
  488.         case OP_NOT_FNC:
  489.                 c->_float = !a->function;
  490.                 break;
  491.         case OP_NOT_ENT:
  492.                 c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts);
  493.                 break;
  494.  
  495.         case OP_EQ_F:
  496.                 c->_float = a->_float == b->_float;
  497.                 break;
  498.         case OP_EQ_V:
  499.                 c->_float = (a->vector[0] == b->vector[0]) &&
  500.                                         (a->vector[1] == b->vector[1]) &&
  501.                                         (a->vector[2] == b->vector[2]);
  502.                 break;
  503.         case OP_EQ_S:
  504.                 c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string);
  505.                 break;
  506.         case OP_EQ_E:
  507.                 c->_float = a->_int == b->_int;
  508.                 break;
  509.         case OP_EQ_FNC:
  510.                 c->_float = a->function == b->function;
  511.                 break;
  512.  
  513.  
  514.         case OP_NE_F:
  515.                 c->_float = a->_float != b->_float;
  516.                 break;
  517.         case OP_NE_V:
  518.                 c->_float = (a->vector[0] != b->vector[0]) ||
  519.                                         (a->vector[1] != b->vector[1]) ||
  520.                                         (a->vector[2] != b->vector[2]);
  521.                 break;
  522.         case OP_NE_S:
  523.                 c->_float = strcmp(pr_strings+a->string,pr_strings+b->string);
  524.                 break;
  525.         case OP_NE_E:
  526.                 c->_float = a->_int != b->_int;
  527.                 break;
  528.         case OP_NE_FNC:
  529.                 c->_float = a->function != b->function;
  530.                 break;
  531.  
  532. //==================
  533.         case OP_STORE_F:
  534.         case OP_STORE_ENT:
  535.         case OP_STORE_FLD:              // integers
  536.         case OP_STORE_S:
  537.         case OP_STORE_FNC:              // pointers
  538.                 b->_int = a->_int;
  539.                 break;
  540.         case OP_STORE_V:
  541.                 b->vector[0] = a->vector[0];
  542.                 b->vector[1] = a->vector[1];
  543.                 b->vector[2] = a->vector[2];
  544.                 break;
  545.                
  546.         case OP_STOREP_F:
  547.         case OP_STOREP_ENT:
  548.         case OP_STOREP_FLD:             // integers
  549.         case OP_STOREP_S:
  550.         case OP_STOREP_FNC:             // pointers
  551.                 ptr = (eval_t *)((byte *)sv.edicts + b->_int);
  552.                 ptr->_int = a->_int;
  553.                 break;
  554.         case OP_STOREP_V:
  555.                 ptr = (eval_t *)((byte *)sv.edicts + b->_int);
  556.                 ptr->vector[0] = a->vector[0];
  557.                 ptr->vector[1] = a->vector[1];
  558.                 ptr->vector[2] = a->vector[2];
  559.                 break;
  560.                
  561.         case OP_ADDRESS:
  562.                 ed = PROG_TO_EDICT(a->edict);
  563. #ifdef PARANOID
  564.                 NUM_FOR_EDICT(ed);              // make sure it's in range
  565. #endif
  566.                 if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
  567.                         PR_RunError ("assignment to world entity");
  568.                 c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts;
  569.                 break;
  570.                
  571.         case OP_LOAD_F:
  572.         case OP_LOAD_FLD:
  573.         case OP_LOAD_ENT:
  574.         case OP_LOAD_S:
  575.         case OP_LOAD_FNC:
  576.                 ed = PROG_TO_EDICT(a->edict);
  577. #ifdef PARANOID
  578.                 NUM_FOR_EDICT(ed);              // make sure it's in range
  579. #endif
  580.                 a = (eval_t *)((int *)&ed->v + b->_int);
  581.                 c->_int = a->_int;
  582.                 break;
  583.  
  584.         case OP_LOAD_V:
  585.                 ed = PROG_TO_EDICT(a->edict);
  586. #ifdef PARANOID
  587.                 NUM_FOR_EDICT(ed);              // make sure it's in range
  588. #endif
  589.                 a = (eval_t *)((int *)&ed->v + b->_int);
  590.                 c->vector[0] = a->vector[0];
  591.                 c->vector[1] = a->vector[1];
  592.                 c->vector[2] = a->vector[2];
  593.                 break;
  594.                
  595. //==================
  596.  
  597.         case OP_IFNOT:
  598.                 if (!a->_int)
  599.                         s += st->b - 1; // offset the s++
  600.                 break;
  601.                
  602.         case OP_IF:
  603.                 if (a->_int)
  604.                         s += st->b - 1; // offset the s++
  605.                 break;
  606.                
  607.         case OP_GOTO:
  608.                 s += st->a - 1; // offset the s++
  609.                 break;
  610.                
  611.         case OP_CALL0:
  612.         case OP_CALL1:
  613.         case OP_CALL2:
  614.         case OP_CALL3:
  615.         case OP_CALL4:
  616.         case OP_CALL5:
  617.         case OP_CALL6:
  618.         case OP_CALL7:
  619.         case OP_CALL8:
  620.                 pr_argc = st->op - OP_CALL0;
  621.                 if (!a->function)
  622.                         PR_RunError ("NULL function");
  623.  
  624.                 newf = &pr_functions[a->function];
  625.  
  626.                 if (newf->first_statement < 0)
  627.                 {       // negative statements are built in functions
  628.                         i = -newf->first_statement;
  629.                         if (i >= pr_numbuiltins)
  630.                                 PR_RunError ("Bad builtin call number");
  631.                         pr_builtins[i] ();
  632.                         break;
  633.                 }
  634.  
  635.                 s = PR_EnterFunction (newf);
  636.                 break;
  637.  
  638.         case OP_DONE:
  639.         case OP_RETURN:
  640.                 pr_globals[OFS_RETURN] = pr_globals[st->a];
  641.                 pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
  642.                 pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
  643.        
  644.                 s = PR_LeaveFunction ();
  645.                 if (pr_depth == exitdepth)
  646.                         return;         // all done
  647.                 break;
  648.                
  649.         case OP_STATE:
  650.                 ed = PROG_TO_EDICT(pr_global_struct->self);
  651. #ifdef FPS_20
  652.                 ed->v.nextthink = pr_global_struct->time + 0.05;
  653. #else
  654.                 ed->v.nextthink = pr_global_struct->time + 0.1;
  655. #endif
  656.                 if (a->_float != ed->v.frame)
  657.                 {
  658.                         ed->v.frame = a->_float;
  659.                 }
  660.                 ed->v.think = b->function;
  661.                 break;
  662.                
  663.         default:
  664.                 PR_RunError ("Bad opcode %i", st->op);
  665.         }
  666. }
  667.  
  668. }
  669.