Script_Interpreter.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "../Game_local.h"
  23. /*
  24. ================
  25. idInterpreter::idInterpreter()
  26. ================
  27. */
  28. idInterpreter::idInterpreter() {
  29. localstackUsed = 0;
  30. terminateOnExit = true;
  31. debug = 0;
  32. memset( localstack, 0, sizeof( localstack ) );
  33. memset( callStack, 0, sizeof( callStack ) );
  34. Reset();
  35. }
  36. /*
  37. ================
  38. idInterpreter::Save
  39. ================
  40. */
  41. void idInterpreter::Save( idSaveGame *savefile ) const {
  42. int i;
  43. savefile->WriteInt( callStackDepth );
  44. for( i = 0; i < callStackDepth; i++ ) {
  45. savefile->WriteInt( callStack[i].s );
  46. if ( callStack[i].f ) {
  47. savefile->WriteInt( gameLocal.program.GetFunctionIndex( callStack[i].f ) );
  48. } else {
  49. savefile->WriteInt( -1 );
  50. }
  51. savefile->WriteInt( callStack[i].stackbase );
  52. }
  53. savefile->WriteInt( maxStackDepth );
  54. savefile->WriteInt( localstackUsed );
  55. savefile->Write( &localstack, localstackUsed );
  56. savefile->WriteInt( localstackBase );
  57. savefile->WriteInt( maxLocalstackUsed );
  58. if ( currentFunction ) {
  59. savefile->WriteInt( gameLocal.program.GetFunctionIndex( currentFunction ) );
  60. } else {
  61. savefile->WriteInt( -1 );
  62. }
  63. savefile->WriteInt( instructionPointer );
  64. savefile->WriteInt( popParms );
  65. if ( multiFrameEvent ) {
  66. savefile->WriteString( multiFrameEvent->GetName() );
  67. } else {
  68. savefile->WriteString( "" );
  69. }
  70. savefile->WriteObject( eventEntity );
  71. savefile->WriteObject( thread );
  72. savefile->WriteBool( doneProcessing );
  73. savefile->WriteBool( threadDying );
  74. savefile->WriteBool( terminateOnExit );
  75. savefile->WriteBool( debug );
  76. }
  77. /*
  78. ================
  79. idInterpreter::Restore
  80. ================
  81. */
  82. void idInterpreter::Restore( idRestoreGame *savefile ) {
  83. int i;
  84. idStr funcname;
  85. int func_index;
  86. savefile->ReadInt( callStackDepth );
  87. for( i = 0; i < callStackDepth; i++ ) {
  88. savefile->ReadInt( callStack[i].s );
  89. savefile->ReadInt( func_index );
  90. if ( func_index >= 0 ) {
  91. callStack[i].f = gameLocal.program.GetFunction( func_index );
  92. } else {
  93. callStack[i].f = NULL;
  94. }
  95. savefile->ReadInt( callStack[i].stackbase );
  96. }
  97. savefile->ReadInt( maxStackDepth );
  98. savefile->ReadInt( localstackUsed );
  99. savefile->Read( &localstack, localstackUsed );
  100. savefile->ReadInt( localstackBase );
  101. savefile->ReadInt( maxLocalstackUsed );
  102. savefile->ReadInt( func_index );
  103. if ( func_index >= 0 ) {
  104. currentFunction = gameLocal.program.GetFunction( func_index );
  105. } else {
  106. currentFunction = NULL;
  107. }
  108. savefile->ReadInt( instructionPointer );
  109. savefile->ReadInt( popParms );
  110. savefile->ReadString( funcname );
  111. if ( funcname.Length() ) {
  112. multiFrameEvent = idEventDef::FindEvent( funcname );
  113. }
  114. savefile->ReadObject( reinterpret_cast<idClass *&>( eventEntity ) );
  115. savefile->ReadObject( reinterpret_cast<idClass *&>( thread ) );
  116. savefile->ReadBool( doneProcessing );
  117. savefile->ReadBool( threadDying );
  118. savefile->ReadBool( terminateOnExit );
  119. savefile->ReadBool( debug );
  120. }
  121. /*
  122. ================
  123. idInterpreter::Reset
  124. ================
  125. */
  126. void idInterpreter::Reset( void ) {
  127. callStackDepth = 0;
  128. localstackUsed = 0;
  129. localstackBase = 0;
  130. maxLocalstackUsed = 0;
  131. maxStackDepth = 0;
  132. popParms = 0;
  133. multiFrameEvent = NULL;
  134. eventEntity = NULL;
  135. currentFunction = 0;
  136. NextInstruction( 0 );
  137. threadDying = false;
  138. doneProcessing = true;
  139. }
  140. /*
  141. ================
  142. idInterpreter::GetRegisterValue
  143. Returns a string representation of the value of the register. This is
  144. used primarily for the debugger and debugging
  145. //FIXME: This is pretty much wrong. won't access data in most situations.
  146. ================
  147. */
  148. bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDepth ) {
  149. varEval_t reg;
  150. idVarDef *d;
  151. char funcObject[ 1024 ];
  152. char *funcName;
  153. const idVarDef *scope;
  154. const idTypeDef *field;
  155. const idScriptObject *obj;
  156. const function_t *func;
  157. out.Empty();
  158. if ( scopeDepth == -1 ) {
  159. scopeDepth = callStackDepth;
  160. }
  161. if ( scopeDepth == callStackDepth ) {
  162. func = currentFunction;
  163. } else {
  164. func = callStack[ scopeDepth ].f;
  165. }
  166. if ( !func ) {
  167. return false;
  168. }
  169. idStr::Copynz( funcObject, func->Name(), sizeof( funcObject ) );
  170. funcName = strstr( funcObject, "::" );
  171. if ( funcName ) {
  172. *funcName = '\0';
  173. scope = gameLocal.program.GetDef( NULL, funcObject, &def_namespace );
  174. funcName += 2;
  175. } else {
  176. funcName = funcObject;
  177. scope = &def_namespace;
  178. }
  179. // Get the function from the object
  180. d = gameLocal.program.GetDef( NULL, funcName, scope );
  181. if ( !d ) {
  182. return false;
  183. }
  184. // Get the variable itself and check various namespaces
  185. d = gameLocal.program.GetDef( NULL, name, d );
  186. if ( !d ) {
  187. if ( scope == &def_namespace ) {
  188. return false;
  189. }
  190. d = gameLocal.program.GetDef( NULL, name, scope );
  191. if ( !d ) {
  192. d = gameLocal.program.GetDef( NULL, name, &def_namespace );
  193. if ( !d ) {
  194. return false;
  195. }
  196. }
  197. }
  198. reg = GetVariable( d );
  199. switch( d->Type() ) {
  200. case ev_float:
  201. if ( reg.floatPtr ) {
  202. out = va("%g", *reg.floatPtr );
  203. } else {
  204. out = "0";
  205. }
  206. return true;
  207. break;
  208. case ev_vector:
  209. if ( reg.vectorPtr ) {
  210. out = va( "%g,%g,%g", reg.vectorPtr->x, reg.vectorPtr->y, reg.vectorPtr->z );
  211. } else {
  212. out = "0,0,0";
  213. }
  214. return true;
  215. break;
  216. case ev_boolean:
  217. if ( reg.intPtr ) {
  218. out = va( "%d", *reg.intPtr );
  219. } else {
  220. out = "0";
  221. }
  222. return true;
  223. break;
  224. case ev_field:
  225. if ( scope == &def_namespace ) {
  226. // should never happen, but handle it safely anyway
  227. return false;
  228. }
  229. field = scope->TypeDef()->GetParmType( reg.ptrOffset )->FieldType();
  230. obj = *reinterpret_cast<const idScriptObject **>( &localstack[ callStack[ callStackDepth ].stackbase ] );
  231. if ( !field || !obj ) {
  232. return false;
  233. }
  234. switch ( field->Type() ) {
  235. case ev_boolean:
  236. out = va( "%d", *( reinterpret_cast<int *>( &obj->data[ reg.ptrOffset ] ) ) );
  237. return true;
  238. case ev_float:
  239. out = va( "%g", *( reinterpret_cast<float *>( &obj->data[ reg.ptrOffset ] ) ) );
  240. return true;
  241. default:
  242. return false;
  243. }
  244. break;
  245. case ev_string:
  246. if ( reg.stringPtr ) {
  247. out = "\"";
  248. out += reg.stringPtr;
  249. out += "\"";
  250. } else {
  251. out = "\"\"";
  252. }
  253. return true;
  254. default:
  255. return false;
  256. }
  257. }
  258. /*
  259. ================
  260. idInterpreter::GetCallstackDepth
  261. ================
  262. */
  263. int idInterpreter::GetCallstackDepth( void ) const {
  264. return callStackDepth;
  265. }
  266. /*
  267. ================
  268. idInterpreter::GetCallstack
  269. ================
  270. */
  271. const prstack_t *idInterpreter::GetCallstack( void ) const {
  272. return &callStack[ 0 ];
  273. }
  274. /*
  275. ================
  276. idInterpreter::GetCurrentFunction
  277. ================
  278. */
  279. const function_t *idInterpreter::GetCurrentFunction( void ) const {
  280. return currentFunction;
  281. }
  282. /*
  283. ================
  284. idInterpreter::GetThread
  285. ================
  286. */
  287. idThread *idInterpreter::GetThread( void ) const {
  288. return thread;
  289. }
  290. /*
  291. ================
  292. idInterpreter::SetThread
  293. ================
  294. */
  295. void idInterpreter::SetThread( idThread *pThread ) {
  296. thread = pThread;
  297. }
  298. /*
  299. ================
  300. idInterpreter::CurrentLine
  301. ================
  302. */
  303. int idInterpreter::CurrentLine( void ) const {
  304. if ( instructionPointer < 0 ) {
  305. return 0;
  306. }
  307. return gameLocal.program.GetLineNumberForStatement( instructionPointer );
  308. }
  309. /*
  310. ================
  311. idInterpreter::CurrentFile
  312. ================
  313. */
  314. const char *idInterpreter::CurrentFile( void ) const {
  315. if ( instructionPointer < 0 ) {
  316. return "";
  317. }
  318. return gameLocal.program.GetFilenameForStatement( instructionPointer );
  319. }
  320. /*
  321. ============
  322. idInterpreter::StackTrace
  323. ============
  324. */
  325. void idInterpreter::StackTrace( void ) const {
  326. const function_t *f;
  327. int i;
  328. int top;
  329. if ( callStackDepth == 0 ) {
  330. gameLocal.Printf( "<NO STACK>\n" );
  331. return;
  332. }
  333. top = callStackDepth;
  334. if ( top >= MAX_STACK_DEPTH ) {
  335. top = MAX_STACK_DEPTH - 1;
  336. }
  337. if ( !currentFunction ) {
  338. gameLocal.Printf( "<NO FUNCTION>\n" );
  339. } else {
  340. gameLocal.Printf( "%12s : %s\n", gameLocal.program.GetFilename( currentFunction->filenum ), currentFunction->Name() );
  341. }
  342. for( i = top; i >= 0; i-- ) {
  343. f = callStack[ i ].f;
  344. if ( !f ) {
  345. gameLocal.Printf( "<NO FUNCTION>\n" );
  346. } else {
  347. gameLocal.Printf( "%12s : %s\n", gameLocal.program.GetFilename( f->filenum ), f->Name() );
  348. }
  349. }
  350. }
  351. /*
  352. ============
  353. idInterpreter::Error
  354. Aborts the currently executing function
  355. ============
  356. */
  357. void idInterpreter::Error( char *fmt, ... ) const {
  358. va_list argptr;
  359. char text[ 1024 ];
  360. va_start( argptr, fmt );
  361. vsprintf( text, fmt, argptr );
  362. va_end( argptr );
  363. StackTrace();
  364. if ( ( instructionPointer >= 0 ) && ( instructionPointer < gameLocal.program.NumStatements() ) ) {
  365. statement_t &line = gameLocal.program.GetStatement( instructionPointer );
  366. common->Error( "%s(%d): Thread '%s': %s\n", gameLocal.program.GetFilename( line.file ), line.linenumber, thread->GetThreadName(), text );
  367. } else {
  368. common->Error( "Thread '%s': %s\n", thread->GetThreadName(), text );
  369. }
  370. }
  371. /*
  372. ============
  373. idInterpreter::Warning
  374. Prints file and line number information with warning.
  375. ============
  376. */
  377. void idInterpreter::Warning( char *fmt, ... ) const {
  378. va_list argptr;
  379. char text[ 1024 ];
  380. va_start( argptr, fmt );
  381. vsprintf( text, fmt, argptr );
  382. va_end( argptr );
  383. if ( ( instructionPointer >= 0 ) && ( instructionPointer < gameLocal.program.NumStatements() ) ) {
  384. statement_t &line = gameLocal.program.GetStatement( instructionPointer );
  385. common->Warning( "%s(%d): Thread '%s': %s", gameLocal.program.GetFilename( line.file ), line.linenumber, thread->GetThreadName(), text );
  386. } else {
  387. common->Warning( "Thread '%s' : %s", thread->GetThreadName(), text );
  388. }
  389. }
  390. /*
  391. ================
  392. idInterpreter::DisplayInfo
  393. ================
  394. */
  395. void idInterpreter::DisplayInfo( void ) const {
  396. const function_t *f;
  397. int i;
  398. gameLocal.Printf( " Stack depth: %d bytes, %d max\n", localstackUsed, maxLocalstackUsed );
  399. gameLocal.Printf( " Call depth: %d, %d max\n", callStackDepth, maxStackDepth );
  400. gameLocal.Printf( " Call Stack: " );
  401. if ( callStackDepth == 0 ) {
  402. gameLocal.Printf( "<NO STACK>\n" );
  403. } else {
  404. if ( !currentFunction ) {
  405. gameLocal.Printf( "<NO FUNCTION>\n" );
  406. } else {
  407. gameLocal.Printf( "%12s : %s\n", gameLocal.program.GetFilename( currentFunction->filenum ), currentFunction->Name() );
  408. }
  409. for( i = callStackDepth; i > 0; i-- ) {
  410. gameLocal.Printf( " " );
  411. f = callStack[ i ].f;
  412. if ( !f ) {
  413. gameLocal.Printf( "<NO FUNCTION>\n" );
  414. } else {
  415. gameLocal.Printf( "%12s : %s\n", gameLocal.program.GetFilename( f->filenum ), f->Name() );
  416. }
  417. }
  418. }
  419. }
  420. /*
  421. ====================
  422. idInterpreter::ThreadCall
  423. Copys the args from the calling thread's stack
  424. ====================
  425. */
  426. void idInterpreter::ThreadCall( idInterpreter *source, const function_t *func, int args ) {
  427. Reset();
  428. memcpy( localstack, &source->localstack[ source->localstackUsed - args ], args );
  429. localstackUsed = args;
  430. localstackBase = 0;
  431. maxLocalstackUsed = localstackUsed;
  432. EnterFunction( func, false );
  433. thread->SetThreadName( currentFunction->Name() );
  434. }
  435. /*
  436. ================
  437. idInterpreter::EnterObjectFunction
  438. Calls a function on a script object.
  439. NOTE: If this is called from within a event called by this interpreter, the function arguments will be invalid after calling this function.
  440. ================
  441. */
  442. void idInterpreter::EnterObjectFunction( idEntity *self, const function_t *func, bool clearStack ) {
  443. if ( clearStack ) {
  444. Reset();
  445. }
  446. if ( popParms ) {
  447. PopParms( popParms );
  448. popParms = 0;
  449. }
  450. Push( self->entityNumber + 1 );
  451. EnterFunction( func, false );
  452. }
  453. /*
  454. ====================
  455. idInterpreter::EnterFunction
  456. Returns the new program statement counter
  457. NOTE: If this is called from within a event called by this interpreter, the function arguments will be invalid after calling this function.
  458. ====================
  459. */
  460. void idInterpreter::EnterFunction( const function_t *func, bool clearStack ) {
  461. int c;
  462. prstack_t *stack;
  463. if ( clearStack ) {
  464. Reset();
  465. }
  466. if ( popParms ) {
  467. PopParms( popParms );
  468. popParms = 0;
  469. }
  470. if ( callStackDepth >= MAX_STACK_DEPTH ) {
  471. Error( "call stack overflow" );
  472. }
  473. stack = &callStack[ callStackDepth ];
  474. stack->s = instructionPointer + 1; // point to the next instruction to execute
  475. stack->f = currentFunction;
  476. stack->stackbase = localstackBase;
  477. callStackDepth++;
  478. if ( callStackDepth > maxStackDepth ) {
  479. maxStackDepth = callStackDepth;
  480. }
  481. if ( !func ) {
  482. Error( "NULL function" );
  483. }
  484. if ( debug ) {
  485. if ( currentFunction ) {
  486. gameLocal.Printf( "%d: call '%s' from '%s'(line %d)%s\n", gameLocal.time, func->Name(), currentFunction->Name(),
  487. gameLocal.program.GetStatement( instructionPointer ).linenumber, clearStack ? " clear stack" : "" );
  488. } else {
  489. gameLocal.Printf( "%d: call '%s'%s\n", gameLocal.time, func->Name(), clearStack ? " clear stack" : "" );
  490. }
  491. }
  492. currentFunction = func;
  493. assert( !func->eventdef );
  494. NextInstruction( func->firstStatement );
  495. // allocate space on the stack for locals
  496. // parms are already on stack
  497. c = func->locals - func->parmTotal;
  498. assert( c >= 0 );
  499. if ( localstackUsed + c > LOCALSTACK_SIZE ) {
  500. Error( "EnterFuncton: locals stack overflow\n" );
  501. }
  502. // initialize local stack variables to zero
  503. memset( &localstack[ localstackUsed ], 0, c );
  504. localstackUsed += c;
  505. localstackBase = localstackUsed - func->locals;
  506. if ( localstackUsed > maxLocalstackUsed ) {
  507. maxLocalstackUsed = localstackUsed ;
  508. }
  509. }
  510. /*
  511. ====================
  512. idInterpreter::LeaveFunction
  513. ====================
  514. */
  515. void idInterpreter::LeaveFunction( idVarDef *returnDef ) {
  516. prstack_t *stack;
  517. varEval_t ret;
  518. if ( callStackDepth <= 0 ) {
  519. Error( "prog stack underflow" );
  520. }
  521. // return value
  522. if ( returnDef ) {
  523. switch( returnDef->Type() ) {
  524. case ev_string :
  525. gameLocal.program.ReturnString( GetString( returnDef ) );
  526. break;
  527. case ev_vector :
  528. ret = GetVariable( returnDef );
  529. gameLocal.program.ReturnVector( *ret.vectorPtr );
  530. break;
  531. default :
  532. ret = GetVariable( returnDef );
  533. gameLocal.program.ReturnInteger( *ret.intPtr );
  534. }
  535. }
  536. // remove locals from the stack
  537. PopParms( currentFunction->locals );
  538. assert( localstackUsed == localstackBase );
  539. if ( debug ) {
  540. statement_t &line = gameLocal.program.GetStatement( instructionPointer );
  541. gameLocal.Printf( "%d: %s(%d): exit %s", gameLocal.time, gameLocal.program.GetFilename( line.file ), line.linenumber, currentFunction->Name() );
  542. if ( callStackDepth > 1 ) {
  543. gameLocal.Printf( " return to %s(line %d)\n", callStack[ callStackDepth - 1 ].f->Name(), gameLocal.program.GetStatement( callStack[ callStackDepth - 1 ].s ).linenumber );
  544. } else {
  545. gameLocal.Printf( " done\n" );
  546. }
  547. }
  548. // up stack
  549. callStackDepth--;
  550. stack = &callStack[ callStackDepth ];
  551. currentFunction = stack->f;
  552. localstackBase = stack->stackbase;
  553. NextInstruction( stack->s );
  554. if ( !callStackDepth ) {
  555. // all done
  556. doneProcessing = true;
  557. threadDying = true;
  558. currentFunction = 0;
  559. }
  560. }
  561. /*
  562. ================
  563. idInterpreter::CallEvent
  564. ================
  565. */
  566. void idInterpreter::CallEvent( const function_t *func, int argsize ) {
  567. int i;
  568. int j;
  569. varEval_t var;
  570. int pos;
  571. int start;
  572. int data[ D_EVENT_MAXARGS ];
  573. const idEventDef *evdef;
  574. const char *format;
  575. if ( !func ) {
  576. Error( "NULL function" );
  577. }
  578. assert( func->eventdef );
  579. evdef = func->eventdef;
  580. start = localstackUsed - argsize;
  581. var.intPtr = ( int * )&localstack[ start ];
  582. eventEntity = GetEntity( *var.entityNumberPtr );
  583. if ( !eventEntity || !eventEntity->RespondsTo( *evdef ) ) {
  584. if ( eventEntity && developer.GetBool() ) {
  585. // give a warning in developer mode
  586. Warning( "Function '%s' not supported on entity '%s'", evdef->GetName(), eventEntity->name.c_str() );
  587. }
  588. // always return a safe value when an object doesn't exist
  589. switch( evdef->GetReturnType() ) {
  590. case D_EVENT_INTEGER :
  591. gameLocal.program.ReturnInteger( 0 );
  592. break;
  593. case D_EVENT_FLOAT :
  594. gameLocal.program.ReturnFloat( 0 );
  595. break;
  596. case D_EVENT_VECTOR :
  597. gameLocal.program.ReturnVector( vec3_zero );
  598. break;
  599. case D_EVENT_STRING :
  600. gameLocal.program.ReturnString( "" );
  601. break;
  602. case D_EVENT_ENTITY :
  603. case D_EVENT_ENTITY_NULL :
  604. gameLocal.program.ReturnEntity( ( idEntity * )NULL );
  605. break;
  606. case D_EVENT_TRACE :
  607. default:
  608. // unsupported data type
  609. break;
  610. }
  611. PopParms( argsize );
  612. eventEntity = NULL;
  613. return;
  614. }
  615. format = evdef->GetArgFormat();
  616. for( j = 0, i = 0, pos = type_object.Size(); ( pos < argsize ) || ( format[ i ] != 0 ); i++ ) {
  617. switch( format[ i ] ) {
  618. case D_EVENT_INTEGER :
  619. var.intPtr = ( int * )&localstack[ start + pos ];
  620. data[ i ] = int( *var.floatPtr );
  621. break;
  622. case D_EVENT_FLOAT :
  623. var.intPtr = ( int * )&localstack[ start + pos ];
  624. ( *( float * )&data[ i ] ) = *var.floatPtr;
  625. break;
  626. case D_EVENT_VECTOR :
  627. var.intPtr = ( int * )&localstack[ start + pos ];
  628. ( *( idVec3 ** )&data[ i ] ) = var.vectorPtr;
  629. break;
  630. case D_EVENT_STRING :
  631. ( *( const char ** )&data[ i ] ) = ( char * )&localstack[ start + pos ];
  632. break;
  633. case D_EVENT_ENTITY :
  634. var.intPtr = ( int * )&localstack[ start + pos ];
  635. ( *( idEntity ** )&data[ i ] ) = GetEntity( *var.entityNumberPtr );
  636. if ( !( *( idEntity ** )&data[ i ] ) ) {
  637. Warning( "Entity not found for event '%s'. Terminating thread.", evdef->GetName() );
  638. threadDying = true;
  639. PopParms( argsize );
  640. return;
  641. }
  642. break;
  643. case D_EVENT_ENTITY_NULL :
  644. var.intPtr = ( int * )&localstack[ start + pos ];
  645. ( *( idEntity ** )&data[ i ] ) = GetEntity( *var.entityNumberPtr );
  646. break;
  647. case D_EVENT_TRACE :
  648. Error( "trace type not supported from script for '%s' event.", evdef->GetName() );
  649. break;
  650. default :
  651. Error( "Invalid arg format string for '%s' event.", evdef->GetName() );
  652. break;
  653. }
  654. pos += func->parmSize[ j++ ];
  655. }
  656. popParms = argsize;
  657. eventEntity->ProcessEventArgPtr( evdef, data );
  658. if ( !multiFrameEvent ) {
  659. if ( popParms ) {
  660. PopParms( popParms );
  661. }
  662. eventEntity = NULL;
  663. } else {
  664. doneProcessing = true;
  665. }
  666. popParms = 0;
  667. }
  668. /*
  669. ================
  670. idInterpreter::BeginMultiFrameEvent
  671. ================
  672. */
  673. bool idInterpreter::BeginMultiFrameEvent( idEntity *ent, const idEventDef *event ) {
  674. if ( eventEntity != ent ) {
  675. Error( "idInterpreter::BeginMultiFrameEvent called with wrong entity" );
  676. }
  677. if ( multiFrameEvent ) {
  678. if ( multiFrameEvent != event ) {
  679. Error( "idInterpreter::BeginMultiFrameEvent called with wrong event" );
  680. }
  681. return false;
  682. }
  683. multiFrameEvent = event;
  684. return true;
  685. }
  686. /*
  687. ================
  688. idInterpreter::EndMultiFrameEvent
  689. ================
  690. */
  691. void idInterpreter::EndMultiFrameEvent( idEntity *ent, const idEventDef *event ) {
  692. if ( multiFrameEvent != event ) {
  693. Error( "idInterpreter::EndMultiFrameEvent called with wrong event" );
  694. }
  695. multiFrameEvent = NULL;
  696. }
  697. /*
  698. ================
  699. idInterpreter::MultiFrameEventInProgress
  700. ================
  701. */
  702. bool idInterpreter::MultiFrameEventInProgress( void ) const {
  703. return multiFrameEvent != NULL;
  704. }
  705. /*
  706. ================
  707. idInterpreter::CallSysEvent
  708. ================
  709. */
  710. void idInterpreter::CallSysEvent( const function_t *func, int argsize ) {
  711. int i;
  712. int j;
  713. varEval_t source;
  714. int pos;
  715. int start;
  716. int data[ D_EVENT_MAXARGS ];
  717. const idEventDef *evdef;
  718. const char *format;
  719. if ( !func ) {
  720. Error( "NULL function" );
  721. }
  722. assert( func->eventdef );
  723. evdef = func->eventdef;
  724. start = localstackUsed - argsize;
  725. format = evdef->GetArgFormat();
  726. for( j = 0, i = 0, pos = 0; ( pos < argsize ) || ( format[ i ] != 0 ); i++ ) {
  727. switch( format[ i ] ) {
  728. case D_EVENT_INTEGER :
  729. source.intPtr = ( int * )&localstack[ start + pos ];
  730. *( int * )&data[ i ] = int( *source.floatPtr );
  731. break;
  732. case D_EVENT_FLOAT :
  733. source.intPtr = ( int * )&localstack[ start + pos ];
  734. *( float * )&data[ i ] = *source.floatPtr;
  735. break;
  736. case D_EVENT_VECTOR :
  737. source.intPtr = ( int * )&localstack[ start + pos ];
  738. *( idVec3 ** )&data[ i ] = source.vectorPtr;
  739. break;
  740. case D_EVENT_STRING :
  741. *( const char ** )&data[ i ] = ( char * )&localstack[ start + pos ];
  742. break;
  743. case D_EVENT_ENTITY :
  744. source.intPtr = ( int * )&localstack[ start + pos ];
  745. *( idEntity ** )&data[ i ] = GetEntity( *source.entityNumberPtr );
  746. if ( !*( idEntity ** )&data[ i ] ) {
  747. Warning( "Entity not found for event '%s'. Terminating thread.", evdef->GetName() );
  748. threadDying = true;
  749. PopParms( argsize );
  750. return;
  751. }
  752. break;
  753. case D_EVENT_ENTITY_NULL :
  754. source.intPtr = ( int * )&localstack[ start + pos ];
  755. *( idEntity ** )&data[ i ] = GetEntity( *source.entityNumberPtr );
  756. break;
  757. case D_EVENT_TRACE :
  758. Error( "trace type not supported from script for '%s' event.", evdef->GetName() );
  759. break;
  760. default :
  761. Error( "Invalid arg format string for '%s' event.", evdef->GetName() );
  762. break;
  763. }
  764. pos += func->parmSize[ j++ ];
  765. }
  766. popParms = argsize;
  767. thread->ProcessEventArgPtr( evdef, data );
  768. if ( popParms ) {
  769. PopParms( popParms );
  770. }
  771. popParms = 0;
  772. }
  773. /*
  774. ====================
  775. idInterpreter::Execute
  776. ====================
  777. */
  778. bool idInterpreter::Execute( void ) {
  779. varEval_t var_a;
  780. varEval_t var_b;
  781. varEval_t var_c;
  782. varEval_t var;
  783. statement_t *st;
  784. int runaway;
  785. idThread *newThread;
  786. float floatVal;
  787. idScriptObject *obj;
  788. const function_t *func;
  789. if ( threadDying || !currentFunction ) {
  790. return true;
  791. }
  792. if ( multiFrameEvent ) {
  793. // move to previous instruction and call it again
  794. instructionPointer--;
  795. }
  796. runaway = 5000000;
  797. doneProcessing = false;
  798. while( !doneProcessing && !threadDying ) {
  799. instructionPointer++;
  800. if ( !--runaway ) {
  801. Error( "runaway loop error" );
  802. }
  803. // next statement
  804. st = &gameLocal.program.GetStatement( instructionPointer );
  805. switch( st->op ) {
  806. case OP_RETURN:
  807. LeaveFunction( st->a );
  808. break;
  809. case OP_THREAD:
  810. newThread = new idThread( this, st->a->value.functionPtr, st->b->value.argSize );
  811. newThread->Start();
  812. // return the thread number to the script
  813. gameLocal.program.ReturnFloat( newThread->GetThreadNum() );
  814. PopParms( st->b->value.argSize );
  815. break;
  816. case OP_OBJTHREAD:
  817. var_a = GetVariable( st->a );
  818. obj = GetScriptObject( *var_a.entityNumberPtr );
  819. if ( obj ) {
  820. func = obj->GetTypeDef()->GetFunction( st->b->value.virtualFunction );
  821. assert( st->c->value.argSize == func->parmTotal );
  822. newThread = new idThread( this, GetEntity( *var_a.entityNumberPtr ), func, func->parmTotal );
  823. newThread->Start();
  824. // return the thread number to the script
  825. gameLocal.program.ReturnFloat( newThread->GetThreadNum() );
  826. } else {
  827. // return a null thread to the script
  828. gameLocal.program.ReturnFloat( 0.0f );
  829. }
  830. PopParms( st->c->value.argSize );
  831. break;
  832. case OP_CALL:
  833. EnterFunction( st->a->value.functionPtr, false );
  834. break;
  835. case OP_EVENTCALL:
  836. CallEvent( st->a->value.functionPtr, st->b->value.argSize );
  837. break;
  838. case OP_OBJECTCALL:
  839. var_a = GetVariable( st->a );
  840. obj = GetScriptObject( *var_a.entityNumberPtr );
  841. if ( obj ) {
  842. func = obj->GetTypeDef()->GetFunction( st->b->value.virtualFunction );
  843. EnterFunction( func, false );
  844. } else {
  845. // return a 'safe' value
  846. gameLocal.program.ReturnVector( vec3_zero );
  847. gameLocal.program.ReturnString( "" );
  848. PopParms( st->c->value.argSize );
  849. }
  850. break;
  851. case OP_SYSCALL:
  852. CallSysEvent( st->a->value.functionPtr, st->b->value.argSize );
  853. break;
  854. case OP_IFNOT:
  855. var_a = GetVariable( st->a );
  856. if ( *var_a.intPtr == 0 ) {
  857. NextInstruction( instructionPointer + st->b->value.jumpOffset );
  858. }
  859. break;
  860. case OP_IF:
  861. var_a = GetVariable( st->a );
  862. if ( *var_a.intPtr != 0 ) {
  863. NextInstruction( instructionPointer + st->b->value.jumpOffset );
  864. }
  865. break;
  866. case OP_GOTO:
  867. NextInstruction( instructionPointer + st->a->value.jumpOffset );
  868. break;
  869. case OP_ADD_F:
  870. var_a = GetVariable( st->a );
  871. var_b = GetVariable( st->b );
  872. var_c = GetVariable( st->c );
  873. *var_c.floatPtr = *var_a.floatPtr + *var_b.floatPtr;
  874. break;
  875. case OP_ADD_V:
  876. var_a = GetVariable( st->a );
  877. var_b = GetVariable( st->b );
  878. var_c = GetVariable( st->c );
  879. *var_c.vectorPtr = *var_a.vectorPtr + *var_b.vectorPtr;
  880. break;
  881. case OP_ADD_S:
  882. SetString( st->c, GetString( st->a ) );
  883. AppendString( st->c, GetString( st->b ) );
  884. break;
  885. case OP_ADD_FS:
  886. var_a = GetVariable( st->a );
  887. SetString( st->c, FloatToString( *var_a.floatPtr ) );
  888. AppendString( st->c, GetString( st->b ) );
  889. break;
  890. case OP_ADD_SF:
  891. var_b = GetVariable( st->b );
  892. SetString( st->c, GetString( st->a ) );
  893. AppendString( st->c, FloatToString( *var_b.floatPtr ) );
  894. break;
  895. case OP_ADD_VS:
  896. var_a = GetVariable( st->a );
  897. SetString( st->c, var_a.vectorPtr->ToString() );
  898. AppendString( st->c, GetString( st->b ) );
  899. break;
  900. case OP_ADD_SV:
  901. var_b = GetVariable( st->b );
  902. SetString( st->c, GetString( st->a ) );
  903. AppendString( st->c, var_b.vectorPtr->ToString() );
  904. break;
  905. case OP_SUB_F:
  906. var_a = GetVariable( st->a );
  907. var_b = GetVariable( st->b );
  908. var_c = GetVariable( st->c );
  909. *var_c.floatPtr = *var_a.floatPtr - *var_b.floatPtr;
  910. break;
  911. case OP_SUB_V:
  912. var_a = GetVariable( st->a );
  913. var_b = GetVariable( st->b );
  914. var_c = GetVariable( st->c );
  915. *var_c.vectorPtr = *var_a.vectorPtr - *var_b.vectorPtr;
  916. break;
  917. case OP_MUL_F:
  918. var_a = GetVariable( st->a );
  919. var_b = GetVariable( st->b );
  920. var_c = GetVariable( st->c );
  921. *var_c.floatPtr = *var_a.floatPtr * *var_b.floatPtr;
  922. break;
  923. case OP_MUL_V:
  924. var_a = GetVariable( st->a );
  925. var_b = GetVariable( st->b );
  926. var_c = GetVariable( st->c );
  927. *var_c.floatPtr = *var_a.vectorPtr * *var_b.vectorPtr;
  928. break;
  929. case OP_MUL_FV:
  930. var_a = GetVariable( st->a );
  931. var_b = GetVariable( st->b );
  932. var_c = GetVariable( st->c );
  933. *var_c.vectorPtr = *var_a.floatPtr * *var_b.vectorPtr;
  934. break;
  935. case OP_MUL_VF:
  936. var_a = GetVariable( st->a );
  937. var_b = GetVariable( st->b );
  938. var_c = GetVariable( st->c );
  939. *var_c.vectorPtr = *var_a.vectorPtr * *var_b.floatPtr;
  940. break;
  941. case OP_DIV_F:
  942. var_a = GetVariable( st->a );
  943. var_b = GetVariable( st->b );
  944. var_c = GetVariable( st->c );
  945. if ( *var_b.floatPtr == 0.0f ) {
  946. Warning( "Divide by zero" );
  947. *var_c.floatPtr = idMath::INFINITY;
  948. } else {
  949. *var_c.floatPtr = *var_a.floatPtr / *var_b.floatPtr;
  950. }
  951. break;
  952. case OP_MOD_F:
  953. var_a = GetVariable( st->a );
  954. var_b = GetVariable( st->b );
  955. var_c = GetVariable ( st->c );
  956. if ( *var_b.floatPtr == 0.0f ) {
  957. Warning( "Divide by zero" );
  958. *var_c.floatPtr = *var_a.floatPtr;
  959. } else {
  960. *var_c.floatPtr = static_cast<int>( *var_a.floatPtr ) % static_cast<int>( *var_b.floatPtr );
  961. }
  962. break;
  963. case OP_BITAND:
  964. var_a = GetVariable( st->a );
  965. var_b = GetVariable( st->b );
  966. var_c = GetVariable( st->c );
  967. *var_c.floatPtr = static_cast<int>( *var_a.floatPtr ) & static_cast<int>( *var_b.floatPtr );
  968. break;
  969. case OP_BITOR:
  970. var_a = GetVariable( st->a );
  971. var_b = GetVariable( st->b );
  972. var_c = GetVariable( st->c );
  973. *var_c.floatPtr = static_cast<int>( *var_a.floatPtr ) | static_cast<int>( *var_b.floatPtr );
  974. break;
  975. case OP_GE:
  976. var_a = GetVariable( st->a );
  977. var_b = GetVariable( st->b );
  978. var_c = GetVariable( st->c );
  979. *var_c.floatPtr = ( *var_a.floatPtr >= *var_b.floatPtr );
  980. break;
  981. case OP_LE:
  982. var_a = GetVariable( st->a );
  983. var_b = GetVariable( st->b );
  984. var_c = GetVariable( st->c );
  985. *var_c.floatPtr = ( *var_a.floatPtr <= *var_b.floatPtr );
  986. break;
  987. case OP_GT:
  988. var_a = GetVariable( st->a );
  989. var_b = GetVariable( st->b );
  990. var_c = GetVariable( st->c );
  991. *var_c.floatPtr = ( *var_a.floatPtr > *var_b.floatPtr );
  992. break;
  993. case OP_LT:
  994. var_a = GetVariable( st->a );
  995. var_b = GetVariable( st->b );
  996. var_c = GetVariable( st->c );
  997. *var_c.floatPtr = ( *var_a.floatPtr < *var_b.floatPtr );
  998. break;
  999. case OP_AND:
  1000. var_a = GetVariable( st->a );
  1001. var_b = GetVariable( st->b );
  1002. var_c = GetVariable( st->c );
  1003. *var_c.floatPtr = ( *var_a.floatPtr != 0.0f ) && ( *var_b.floatPtr != 0.0f );
  1004. break;
  1005. case OP_AND_BOOLF:
  1006. var_a = GetVariable( st->a );
  1007. var_b = GetVariable( st->b );
  1008. var_c = GetVariable( st->c );
  1009. *var_c.floatPtr = ( *var_a.intPtr != 0 ) && ( *var_b.floatPtr != 0.0f );
  1010. break;
  1011. case OP_AND_FBOOL:
  1012. var_a = GetVariable( st->a );
  1013. var_b = GetVariable( st->b );
  1014. var_c = GetVariable( st->c );
  1015. *var_c.floatPtr = ( *var_a.floatPtr != 0.0f ) && ( *var_b.intPtr != 0 );
  1016. break;
  1017. case OP_AND_BOOLBOOL:
  1018. var_a = GetVariable( st->a );
  1019. var_b = GetVariable( st->b );
  1020. var_c = GetVariable( st->c );
  1021. *var_c.floatPtr = ( *var_a.intPtr != 0 ) && ( *var_b.intPtr != 0 );
  1022. break;
  1023. case OP_OR:
  1024. var_a = GetVariable( st->a );
  1025. var_b = GetVariable( st->b );
  1026. var_c = GetVariable( st->c );
  1027. *var_c.floatPtr = ( *var_a.floatPtr != 0.0f ) || ( *var_b.floatPtr != 0.0f );
  1028. break;
  1029. case OP_OR_BOOLF:
  1030. var_a = GetVariable( st->a );
  1031. var_b = GetVariable( st->b );
  1032. var_c = GetVariable( st->c );
  1033. *var_c.floatPtr = ( *var_a.intPtr != 0 ) || ( *var_b.floatPtr != 0.0f );
  1034. break;
  1035. case OP_OR_FBOOL:
  1036. var_a = GetVariable( st->a );
  1037. var_b = GetVariable( st->b );
  1038. var_c = GetVariable( st->c );
  1039. *var_c.floatPtr = ( *var_a.floatPtr != 0.0f ) || ( *var_b.intPtr != 0 );
  1040. break;
  1041. case OP_OR_BOOLBOOL:
  1042. var_a = GetVariable( st->a );
  1043. var_b = GetVariable( st->b );
  1044. var_c = GetVariable( st->c );
  1045. *var_c.floatPtr = ( *var_a.intPtr != 0 ) || ( *var_b.intPtr != 0 );
  1046. break;
  1047. case OP_NOT_BOOL:
  1048. var_a = GetVariable( st->a );
  1049. var_c = GetVariable( st->c );
  1050. *var_c.floatPtr = ( *var_a.intPtr == 0 );
  1051. break;
  1052. case OP_NOT_F:
  1053. var_a = GetVariable( st->a );
  1054. var_c = GetVariable( st->c );
  1055. *var_c.floatPtr = ( *var_a.floatPtr == 0.0f );
  1056. break;
  1057. case OP_NOT_V:
  1058. var_a = GetVariable( st->a );
  1059. var_c = GetVariable( st->c );
  1060. *var_c.floatPtr = ( *var_a.vectorPtr == vec3_zero );
  1061. break;
  1062. case OP_NOT_S:
  1063. var_c = GetVariable( st->c );
  1064. *var_c.floatPtr = ( strlen( GetString( st->a ) ) == 0 );
  1065. break;
  1066. case OP_NOT_ENT:
  1067. var_a = GetVariable( st->a );
  1068. var_c = GetVariable( st->c );
  1069. *var_c.floatPtr = ( GetEntity( *var_a.entityNumberPtr ) == NULL );
  1070. break;
  1071. case OP_NEG_F:
  1072. var_a = GetVariable( st->a );
  1073. var_c = GetVariable( st->c );
  1074. *var_c.floatPtr = -*var_a.floatPtr;
  1075. break;
  1076. case OP_NEG_V:
  1077. var_a = GetVariable( st->a );
  1078. var_c = GetVariable( st->c );
  1079. *var_c.vectorPtr = -*var_a.vectorPtr;
  1080. break;
  1081. case OP_INT_F:
  1082. var_a = GetVariable( st->a );
  1083. var_c = GetVariable( st->c );
  1084. *var_c.floatPtr = static_cast<int>( *var_a.floatPtr );
  1085. break;
  1086. case OP_EQ_F:
  1087. var_a = GetVariable( st->a );
  1088. var_b = GetVariable( st->b );
  1089. var_c = GetVariable( st->c );
  1090. *var_c.floatPtr = ( *var_a.floatPtr == *var_b.floatPtr );
  1091. break;
  1092. case OP_EQ_V:
  1093. var_a = GetVariable( st->a );
  1094. var_b = GetVariable( st->b );
  1095. var_c = GetVariable( st->c );
  1096. *var_c.floatPtr = ( *var_a.vectorPtr == *var_b.vectorPtr );
  1097. break;
  1098. case OP_EQ_S:
  1099. var_a = GetVariable( st->a );
  1100. var_b = GetVariable( st->b );
  1101. var_c = GetVariable( st->c );
  1102. *var_c.floatPtr = ( idStr::Cmp( GetString( st->a ), GetString( st->b ) ) == 0 );
  1103. break;
  1104. case OP_EQ_E:
  1105. case OP_EQ_EO:
  1106. case OP_EQ_OE:
  1107. case OP_EQ_OO:
  1108. var_a = GetVariable( st->a );
  1109. var_b = GetVariable( st->b );
  1110. var_c = GetVariable( st->c );
  1111. *var_c.floatPtr = ( *var_a.entityNumberPtr == *var_b.entityNumberPtr );
  1112. break;
  1113. case OP_NE_F:
  1114. var_a = GetVariable( st->a );
  1115. var_b = GetVariable( st->b );
  1116. var_c = GetVariable( st->c );
  1117. *var_c.floatPtr = ( *var_a.floatPtr != *var_b.floatPtr );
  1118. break;
  1119. case OP_NE_V:
  1120. var_a = GetVariable( st->a );
  1121. var_b = GetVariable( st->b );
  1122. var_c = GetVariable( st->c );
  1123. *var_c.floatPtr = ( *var_a.vectorPtr != *var_b.vectorPtr );
  1124. break;
  1125. case OP_NE_S:
  1126. var_c = GetVariable( st->c );
  1127. *var_c.floatPtr = ( idStr::Cmp( GetString( st->a ), GetString( st->b ) ) != 0 );
  1128. break;
  1129. case OP_NE_E:
  1130. case OP_NE_EO:
  1131. case OP_NE_OE:
  1132. case OP_NE_OO:
  1133. var_a = GetVariable( st->a );
  1134. var_b = GetVariable( st->b );
  1135. var_c = GetVariable( st->c );
  1136. *var_c.floatPtr = ( *var_a.entityNumberPtr != *var_b.entityNumberPtr );
  1137. break;
  1138. case OP_UADD_F:
  1139. var_a = GetVariable( st->a );
  1140. var_b = GetVariable( st->b );
  1141. *var_b.floatPtr += *var_a.floatPtr;
  1142. break;
  1143. case OP_UADD_V:
  1144. var_a = GetVariable( st->a );
  1145. var_b = GetVariable( st->b );
  1146. *var_b.vectorPtr += *var_a.vectorPtr;
  1147. break;
  1148. case OP_USUB_F:
  1149. var_a = GetVariable( st->a );
  1150. var_b = GetVariable( st->b );
  1151. *var_b.floatPtr -= *var_a.floatPtr;
  1152. break;
  1153. case OP_USUB_V:
  1154. var_a = GetVariable( st->a );
  1155. var_b = GetVariable( st->b );
  1156. *var_b.vectorPtr -= *var_a.vectorPtr;
  1157. break;
  1158. case OP_UMUL_F:
  1159. var_a = GetVariable( st->a );
  1160. var_b = GetVariable( st->b );
  1161. *var_b.floatPtr *= *var_a.floatPtr;
  1162. break;
  1163. case OP_UMUL_V:
  1164. var_a = GetVariable( st->a );
  1165. var_b = GetVariable( st->b );
  1166. *var_b.vectorPtr *= *var_a.floatPtr;
  1167. break;
  1168. case OP_UDIV_F:
  1169. var_a = GetVariable( st->a );
  1170. var_b = GetVariable( st->b );
  1171. if ( *var_a.floatPtr == 0.0f ) {
  1172. Warning( "Divide by zero" );
  1173. *var_b.floatPtr = idMath::INFINITY;
  1174. } else {
  1175. *var_b.floatPtr = *var_b.floatPtr / *var_a.floatPtr;
  1176. }
  1177. break;
  1178. case OP_UDIV_V:
  1179. var_a = GetVariable( st->a );
  1180. var_b = GetVariable( st->b );
  1181. if ( *var_a.floatPtr == 0.0f ) {
  1182. Warning( "Divide by zero" );
  1183. var_b.vectorPtr->Set( idMath::INFINITY, idMath::INFINITY, idMath::INFINITY );
  1184. } else {
  1185. *var_b.vectorPtr = *var_b.vectorPtr / *var_a.floatPtr;
  1186. }
  1187. break;
  1188. case OP_UMOD_F:
  1189. var_a = GetVariable( st->a );
  1190. var_b = GetVariable( st->b );
  1191. if ( *var_a.floatPtr == 0.0f ) {
  1192. Warning( "Divide by zero" );
  1193. *var_b.floatPtr = *var_a.floatPtr;
  1194. } else {
  1195. *var_b.floatPtr = static_cast<int>( *var_b.floatPtr ) % static_cast<int>( *var_a.floatPtr );
  1196. }
  1197. break;
  1198. case OP_UOR_F:
  1199. var_a = GetVariable( st->a );
  1200. var_b = GetVariable( st->b );
  1201. *var_b.floatPtr = static_cast<int>( *var_b.floatPtr ) | static_cast<int>( *var_a.floatPtr );
  1202. break;
  1203. case OP_UAND_F:
  1204. var_a = GetVariable( st->a );
  1205. var_b = GetVariable( st->b );
  1206. *var_b.floatPtr = static_cast<int>( *var_b.floatPtr ) & static_cast<int>( *var_a.floatPtr );
  1207. break;
  1208. case OP_UINC_F:
  1209. var_a = GetVariable( st->a );
  1210. ( *var_a.floatPtr )++;
  1211. break;
  1212. case OP_UINCP_F:
  1213. var_a = GetVariable( st->a );
  1214. obj = GetScriptObject( *var_a.entityNumberPtr );
  1215. if ( obj ) {
  1216. var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
  1217. ( *var.floatPtr )++;
  1218. }
  1219. break;
  1220. case OP_UDEC_F:
  1221. var_a = GetVariable( st->a );
  1222. ( *var_a.floatPtr )--;
  1223. break;
  1224. case OP_UDECP_F:
  1225. var_a = GetVariable( st->a );
  1226. obj = GetScriptObject( *var_a.entityNumberPtr );
  1227. if ( obj ) {
  1228. var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
  1229. ( *var.floatPtr )--;
  1230. }
  1231. break;
  1232. case OP_COMP_F:
  1233. var_a = GetVariable( st->a );
  1234. var_c = GetVariable( st->c );
  1235. *var_c.floatPtr = ~static_cast<int>( *var_a.floatPtr );
  1236. break;
  1237. case OP_STORE_F:
  1238. var_a = GetVariable( st->a );
  1239. var_b = GetVariable( st->b );
  1240. *var_b.floatPtr = *var_a.floatPtr;
  1241. break;
  1242. case OP_STORE_ENT:
  1243. var_a = GetVariable( st->a );
  1244. var_b = GetVariable( st->b );
  1245. *var_b.entityNumberPtr = *var_a.entityNumberPtr;
  1246. break;
  1247. case OP_STORE_BOOL:
  1248. var_a = GetVariable( st->a );
  1249. var_b = GetVariable( st->b );
  1250. *var_b.intPtr = *var_a.intPtr;
  1251. break;
  1252. case OP_STORE_OBJENT:
  1253. var_a = GetVariable( st->a );
  1254. var_b = GetVariable( st->b );
  1255. obj = GetScriptObject( *var_a.entityNumberPtr );
  1256. if ( !obj ) {
  1257. *var_b.entityNumberPtr = 0;
  1258. } else if ( !obj->GetTypeDef()->Inherits( st->b->TypeDef() ) ) {
  1259. //Warning( "object '%s' cannot be converted to '%s'", obj->GetTypeName(), st->b->TypeDef()->Name() );
  1260. *var_b.entityNumberPtr = 0;
  1261. } else {
  1262. *var_b.entityNumberPtr = *var_a.entityNumberPtr;
  1263. }
  1264. break;
  1265. case OP_STORE_OBJ:
  1266. case OP_STORE_ENTOBJ:
  1267. var_a = GetVariable( st->a );
  1268. var_b = GetVariable( st->b );
  1269. *var_b.entityNumberPtr = *var_a.entityNumberPtr;
  1270. break;
  1271. case OP_STORE_S:
  1272. SetString( st->b, GetString( st->a ) );
  1273. break;
  1274. case OP_STORE_V:
  1275. var_a = GetVariable( st->a );
  1276. var_b = GetVariable( st->b );
  1277. *var_b.vectorPtr = *var_a.vectorPtr;
  1278. break;
  1279. case OP_STORE_FTOS:
  1280. var_a = GetVariable( st->a );
  1281. SetString( st->b, FloatToString( *var_a.floatPtr ) );
  1282. break;
  1283. case OP_STORE_BTOS:
  1284. var_a = GetVariable( st->a );
  1285. SetString( st->b, *var_a.intPtr ? "true" : "false" );
  1286. break;
  1287. case OP_STORE_VTOS:
  1288. var_a = GetVariable( st->a );
  1289. SetString( st->b, var_a.vectorPtr->ToString() );
  1290. break;
  1291. case OP_STORE_FTOBOOL:
  1292. var_a = GetVariable( st->a );
  1293. var_b = GetVariable( st->b );
  1294. if ( *var_a.floatPtr != 0.0f ) {
  1295. *var_b.intPtr = 1;
  1296. } else {
  1297. *var_b.intPtr = 0;
  1298. }
  1299. break;
  1300. case OP_STORE_BOOLTOF:
  1301. var_a = GetVariable( st->a );
  1302. var_b = GetVariable( st->b );
  1303. *var_b.floatPtr = static_cast<float>( *var_a.intPtr );
  1304. break;
  1305. case OP_STOREP_F:
  1306. var_b = GetVariable( st->b );
  1307. if ( var_b.evalPtr && var_b.evalPtr->floatPtr ) {
  1308. var_a = GetVariable( st->a );
  1309. *var_b.evalPtr->floatPtr = *var_a.floatPtr;
  1310. }
  1311. break;
  1312. case OP_STOREP_ENT:
  1313. var_b = GetVariable( st->b );
  1314. if ( var_b.evalPtr && var_b.evalPtr->entityNumberPtr ) {
  1315. var_a = GetVariable( st->a );
  1316. *var_b.evalPtr->entityNumberPtr = *var_a.entityNumberPtr;
  1317. }
  1318. break;
  1319. case OP_STOREP_FLD:
  1320. var_b = GetVariable( st->b );
  1321. if ( var_b.evalPtr && var_b.evalPtr->intPtr ) {
  1322. var_a = GetVariable( st->a );
  1323. *var_b.evalPtr->intPtr = *var_a.intPtr;
  1324. }
  1325. break;
  1326. case OP_STOREP_BOOL:
  1327. var_b = GetVariable( st->b );
  1328. if ( var_b.evalPtr && var_b.evalPtr->intPtr ) {
  1329. var_a = GetVariable( st->a );
  1330. *var_b.evalPtr->intPtr = *var_a.intPtr;
  1331. }
  1332. break;
  1333. case OP_STOREP_S:
  1334. var_b = GetVariable( st->b );
  1335. if ( var_b.evalPtr && var_b.evalPtr->stringPtr ) {
  1336. idStr::Copynz( var_b.evalPtr->stringPtr, GetString( st->a ), MAX_STRING_LEN );
  1337. }
  1338. break;
  1339. case OP_STOREP_V:
  1340. var_b = GetVariable( st->b );
  1341. if ( var_b.evalPtr && var_b.evalPtr->vectorPtr ) {
  1342. var_a = GetVariable( st->a );
  1343. *var_b.evalPtr->vectorPtr = *var_a.vectorPtr;
  1344. }
  1345. break;
  1346. case OP_STOREP_FTOS:
  1347. var_b = GetVariable( st->b );
  1348. if ( var_b.evalPtr && var_b.evalPtr->stringPtr ) {
  1349. var_a = GetVariable( st->a );
  1350. idStr::Copynz( var_b.evalPtr->stringPtr, FloatToString( *var_a.floatPtr ), MAX_STRING_LEN );
  1351. }
  1352. break;
  1353. case OP_STOREP_BTOS:
  1354. var_b = GetVariable( st->b );
  1355. if ( var_b.evalPtr && var_b.evalPtr->stringPtr ) {
  1356. var_a = GetVariable( st->a );
  1357. if ( *var_a.floatPtr != 0.0f ) {
  1358. idStr::Copynz( var_b.evalPtr->stringPtr, "true", MAX_STRING_LEN );
  1359. } else {
  1360. idStr::Copynz( var_b.evalPtr->stringPtr, "false", MAX_STRING_LEN );
  1361. }
  1362. }
  1363. break;
  1364. case OP_STOREP_VTOS:
  1365. var_b = GetVariable( st->b );
  1366. if ( var_b.evalPtr && var_b.evalPtr->stringPtr ) {
  1367. var_a = GetVariable( st->a );
  1368. idStr::Copynz( var_b.evalPtr->stringPtr, var_a.vectorPtr->ToString(), MAX_STRING_LEN );
  1369. }
  1370. break;
  1371. case OP_STOREP_FTOBOOL:
  1372. var_b = GetVariable( st->b );
  1373. if ( var_b.evalPtr && var_b.evalPtr->intPtr ) {
  1374. var_a = GetVariable( st->a );
  1375. if ( *var_a.floatPtr != 0.0f ) {
  1376. *var_b.evalPtr->intPtr = 1;
  1377. } else {
  1378. *var_b.evalPtr->intPtr = 0;
  1379. }
  1380. }
  1381. break;
  1382. case OP_STOREP_BOOLTOF:
  1383. var_b = GetVariable( st->b );
  1384. if ( var_b.evalPtr && var_b.evalPtr->floatPtr ) {
  1385. var_a = GetVariable( st->a );
  1386. *var_b.evalPtr->floatPtr = static_cast<float>( *var_a.intPtr );
  1387. }
  1388. break;
  1389. case OP_STOREP_OBJ:
  1390. var_b = GetVariable( st->b );
  1391. if ( var_b.evalPtr && var_b.evalPtr->entityNumberPtr ) {
  1392. var_a = GetVariable( st->a );
  1393. *var_b.evalPtr->entityNumberPtr = *var_a.entityNumberPtr;
  1394. }
  1395. break;
  1396. case OP_STOREP_OBJENT:
  1397. var_b = GetVariable( st->b );
  1398. if ( var_b.evalPtr && var_b.evalPtr->entityNumberPtr ) {
  1399. var_a = GetVariable( st->a );
  1400. obj = GetScriptObject( *var_a.entityNumberPtr );
  1401. if ( !obj ) {
  1402. *var_b.evalPtr->entityNumberPtr = 0;
  1403. // st->b points to type_pointer, which is just a temporary that gets its type reassigned, so we store the real type in st->c
  1404. // so that we can do a type check during run time since we don't know what type the script object is at compile time because it
  1405. // comes from an entity
  1406. } else if ( !obj->GetTypeDef()->Inherits( st->c->TypeDef() ) ) {
  1407. //Warning( "object '%s' cannot be converted to '%s'", obj->GetTypeName(), st->c->TypeDef()->Name() );
  1408. *var_b.evalPtr->entityNumberPtr = 0;
  1409. } else {
  1410. *var_b.evalPtr->entityNumberPtr = *var_a.entityNumberPtr;
  1411. }
  1412. }
  1413. break;
  1414. case OP_ADDRESS:
  1415. var_a = GetVariable( st->a );
  1416. var_c = GetVariable( st->c );
  1417. obj = GetScriptObject( *var_a.entityNumberPtr );
  1418. if ( obj ) {
  1419. var_c.evalPtr->bytePtr = &obj->data[ st->b->value.ptrOffset ];
  1420. } else {
  1421. var_c.evalPtr->bytePtr = NULL;
  1422. }
  1423. break;
  1424. case OP_INDIRECT_F:
  1425. var_a = GetVariable( st->a );
  1426. var_c = GetVariable( st->c );
  1427. obj = GetScriptObject( *var_a.entityNumberPtr );
  1428. if ( obj ) {
  1429. var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
  1430. *var_c.floatPtr = *var.floatPtr;
  1431. } else {
  1432. *var_c.floatPtr = 0.0f;
  1433. }
  1434. break;
  1435. case OP_INDIRECT_ENT:
  1436. var_a = GetVariable( st->a );
  1437. var_c = GetVariable( st->c );
  1438. obj = GetScriptObject( *var_a.entityNumberPtr );
  1439. if ( obj ) {
  1440. var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
  1441. *var_c.entityNumberPtr = *var.entityNumberPtr;
  1442. } else {
  1443. *var_c.entityNumberPtr = 0;
  1444. }
  1445. break;
  1446. case OP_INDIRECT_BOOL:
  1447. var_a = GetVariable( st->a );
  1448. var_c = GetVariable( st->c );
  1449. obj = GetScriptObject( *var_a.entityNumberPtr );
  1450. if ( obj ) {
  1451. var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
  1452. *var_c.intPtr = *var.intPtr;
  1453. } else {
  1454. *var_c.intPtr = 0;
  1455. }
  1456. break;
  1457. case OP_INDIRECT_S:
  1458. var_a = GetVariable( st->a );
  1459. obj = GetScriptObject( *var_a.entityNumberPtr );
  1460. if ( obj ) {
  1461. var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
  1462. SetString( st->c, var.stringPtr );
  1463. } else {
  1464. SetString( st->c, "" );
  1465. }
  1466. break;
  1467. case OP_INDIRECT_V:
  1468. var_a = GetVariable( st->a );
  1469. var_c = GetVariable( st->c );
  1470. obj = GetScriptObject( *var_a.entityNumberPtr );
  1471. if ( obj ) {
  1472. var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
  1473. *var_c.vectorPtr = *var.vectorPtr;
  1474. } else {
  1475. var_c.vectorPtr->Zero();
  1476. }
  1477. break;
  1478. case OP_INDIRECT_OBJ:
  1479. var_a = GetVariable( st->a );
  1480. var_c = GetVariable( st->c );
  1481. obj = GetScriptObject( *var_a.entityNumberPtr );
  1482. if ( !obj ) {
  1483. *var_c.entityNumberPtr = 0;
  1484. } else {
  1485. var.bytePtr = &obj->data[ st->b->value.ptrOffset ];
  1486. *var_c.entityNumberPtr = *var.entityNumberPtr;
  1487. }
  1488. break;
  1489. case OP_PUSH_F:
  1490. var_a = GetVariable( st->a );
  1491. Push( *var_a.intPtr );
  1492. break;
  1493. case OP_PUSH_FTOS:
  1494. var_a = GetVariable( st->a );
  1495. PushString( FloatToString( *var_a.floatPtr ) );
  1496. break;
  1497. case OP_PUSH_BTOF:
  1498. var_a = GetVariable( st->a );
  1499. floatVal = *var_a.intPtr;
  1500. Push( *reinterpret_cast<int *>( &floatVal ) );
  1501. break;
  1502. case OP_PUSH_FTOB:
  1503. var_a = GetVariable( st->a );
  1504. if ( *var_a.floatPtr != 0.0f ) {
  1505. Push( 1 );
  1506. } else {
  1507. Push( 0 );
  1508. }
  1509. break;
  1510. case OP_PUSH_VTOS:
  1511. var_a = GetVariable( st->a );
  1512. PushString( var_a.vectorPtr->ToString() );
  1513. break;
  1514. case OP_PUSH_BTOS:
  1515. var_a = GetVariable( st->a );
  1516. PushString( *var_a.intPtr ? "true" : "false" );
  1517. break;
  1518. case OP_PUSH_ENT:
  1519. var_a = GetVariable( st->a );
  1520. Push( *var_a.entityNumberPtr );
  1521. break;
  1522. case OP_PUSH_S:
  1523. PushString( GetString( st->a ) );
  1524. break;
  1525. case OP_PUSH_V:
  1526. var_a = GetVariable( st->a );
  1527. Push( *reinterpret_cast<int *>( &var_a.vectorPtr->x ) );
  1528. Push( *reinterpret_cast<int *>( &var_a.vectorPtr->y ) );
  1529. Push( *reinterpret_cast<int *>( &var_a.vectorPtr->z ) );
  1530. break;
  1531. case OP_PUSH_OBJ:
  1532. var_a = GetVariable( st->a );
  1533. Push( *var_a.entityNumberPtr );
  1534. break;
  1535. case OP_PUSH_OBJENT:
  1536. var_a = GetVariable( st->a );
  1537. Push( *var_a.entityNumberPtr );
  1538. break;
  1539. case OP_BREAK:
  1540. case OP_CONTINUE:
  1541. default:
  1542. Error( "Bad opcode %i", st->op );
  1543. break;
  1544. }
  1545. }
  1546. return threadDying;
  1547. }