2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition 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 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
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 .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# pragma hdrstop
# include "../idlib/precompiled.h"
2012-11-28 15:47:07 +00:00
idCVar swf_debug ( " swf_debug " , " 0 " , CVAR_INTEGER | CVAR_ARCHIVE , " debug swf scripts. 1 shows traces/errors. 2 also shows warnings. 3 also shows disassembly. 4 shows parameters in the disassembly. " ) ;
2012-11-26 18:58:24 +00:00
idCVar swf_debugInvoke ( " swf_debugInvoke " , " 0 " , CVAR_INTEGER , " debug swf functions being called from game. " ) ;
2012-11-28 15:47:07 +00:00
idSWFConstantPool : : idSWFConstantPool ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSWFConstantPool : : Clear
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSWFConstantPool : : Clear ( )
{
for ( int i = 0 ; i < pool . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
pool [ i ] - > Release ( ) ;
}
pool . Clear ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSWFConstantPool : : Copy
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSWFConstantPool : : Copy ( const idSWFConstantPool & other )
{
2012-11-26 18:58:24 +00:00
Clear ( ) ;
pool . SetNum ( other . pool . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < pool . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
pool [ i ] = other . pool [ i ] ;
pool [ i ] - > AddRef ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSWFScriptFunction_Script : : ~ idSWFScriptFunction_Script
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSWFScriptFunction_Script : : ~ idSWFScriptFunction_Script ( )
{
for ( int i = 0 ; i < scope . Num ( ) ; i + + )
{
if ( verify ( scope [ i ] ) )
{
2012-11-26 18:58:24 +00:00
scope [ i ] - > Release ( ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( prototype )
{
2012-11-26 18:58:24 +00:00
prototype - > Release ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSWFScriptFunction_Script : : Call
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSWFScriptFunction_Script : : SetScope ( idList < idSWFScriptObject * > & newScope )
{
2012-11-26 18:58:24 +00:00
assert ( scope . Num ( ) = = 0 ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < scope . Num ( ) ; i + + )
{
if ( verify ( scope [ i ] ) )
{
2012-11-26 18:58:24 +00:00
scope [ i ] - > Release ( ) ;
}
}
scope . Clear ( ) ;
scope . Append ( newScope ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < newScope . Num ( ) ; i + + )
{
if ( verify ( scope [ i ] ) )
{
2012-11-26 18:58:24 +00:00
scope [ i ] - > AddRef ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSWFScriptFunction_Script : : Call
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSWFScriptVar idSWFScriptFunction_Script : : Call ( idSWFScriptObject * thisObject , const idSWFParmList & parms )
{
2012-11-26 18:58:24 +00:00
idSWFBitStream bitstream ( data , length , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// We assume scope[0] is the global scope
assert ( scope . Num ( ) > 0 ) ;
2012-11-28 15:47:07 +00:00
if ( thisObject = = NULL )
{
2012-11-26 18:58:24 +00:00
thisObject = scope [ 0 ] ;
}
2012-11-28 15:47:07 +00:00
idSWFScriptObject * locals = idSWFScriptObject : : Alloc ( ) ;
2012-11-26 18:58:24 +00:00
idSWFStack stack ;
stack . SetNum ( parms . Num ( ) + 1 ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < parms . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
stack [ parms . Num ( ) - i - 1 ] = parms [ i ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Unfortunately at this point we don't have the function name anymore, so our warning messages aren't very detailed
2012-11-28 15:47:07 +00:00
if ( i < parameters . Num ( ) )
{
if ( parameters [ i ] . reg > 0 & & parameters [ i ] . reg < registers . Num ( ) )
{
2012-11-26 18:58:24 +00:00
registers [ parameters [ i ] . reg ] = parms [ i ] ;
}
locals - > Set ( parameters [ i ] . name , parms [ i ] ) ;
}
}
// Set any additional parameters to undefined
2012-11-28 15:47:07 +00:00
for ( int i = parms . Num ( ) ; i < parameters . Num ( ) ; i + + )
{
if ( parameters [ i ] . reg > 0 & & parameters [ i ] . reg < registers . Num ( ) )
{
2012-11-26 18:58:24 +00:00
registers [ parameters [ i ] . reg ] . SetUndefined ( ) ;
}
locals - > Set ( parameters [ i ] . name , idSWFScriptVar ( ) ) ;
}
stack . A ( ) . SetInteger ( parms . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int preloadReg = 1 ;
2012-11-28 15:47:07 +00:00
if ( flags & BIT ( 0 ) )
{
2012-11-26 18:58:24 +00:00
// load "this" into a register
registers [ preloadReg ] . SetObject ( thisObject ) ;
preloadReg + + ;
}
2012-11-28 15:47:07 +00:00
if ( ( flags & BIT ( 1 ) ) = = 0 )
{
2012-11-26 18:58:24 +00:00
// create "this"
locals - > Set ( " this " , idSWFScriptVar ( thisObject ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( flags & BIT ( 2 ) )
{
idSWFScriptObject * arguments = idSWFScriptObject : : Alloc ( ) ;
2012-11-26 18:58:24 +00:00
// load "arguments" into a register
arguments - > MakeArray ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int numElements = parms . Num ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numElements ; i + + )
{
2012-11-26 18:58:24 +00:00
arguments - > Set ( i , parms [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
registers [ preloadReg ] . SetObject ( arguments ) ;
preloadReg + + ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
arguments - > Release ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( ( flags & BIT ( 3 ) ) = = 0 )
{
idSWFScriptObject * arguments = idSWFScriptObject : : Alloc ( ) ;
2012-11-26 18:58:24 +00:00
// create "arguments"
arguments - > MakeArray ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int numElements = parms . Num ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numElements ; i + + )
{
2012-11-26 18:58:24 +00:00
arguments - > Set ( i , parms [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
locals - > Set ( " arguments " , idSWFScriptVar ( arguments ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
arguments - > Release ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( flags & BIT ( 4 ) )
{
2012-11-26 18:58:24 +00:00
// load "super" into a register
registers [ preloadReg ] . SetObject ( thisObject - > GetPrototype ( ) ) ;
preloadReg + + ;
}
2012-11-28 15:47:07 +00:00
if ( ( flags & BIT ( 5 ) ) = = 0 )
{
2012-11-26 18:58:24 +00:00
// create "super"
locals - > Set ( " super " , idSWFScriptVar ( thisObject - > GetPrototype ( ) ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( flags & BIT ( 6 ) )
{
2012-11-26 18:58:24 +00:00
// preload _root
registers [ preloadReg ] = scope [ 0 ] - > Get ( " _root " ) ;
preloadReg + + ;
}
2012-11-28 15:47:07 +00:00
if ( flags & BIT ( 7 ) )
{
2012-11-26 18:58:24 +00:00
// preload _parent
2012-11-28 15:47:07 +00:00
if ( thisObject - > GetSprite ( ) ! = NULL & & thisObject - > GetSprite ( ) - > parent ! = NULL )
{
2012-11-26 18:58:24 +00:00
registers [ preloadReg ] . SetObject ( thisObject - > GetSprite ( ) - > parent - > scriptObject ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
registers [ preloadReg ] . SetNULL ( ) ;
}
preloadReg + + ;
}
2012-11-28 15:47:07 +00:00
if ( flags & BIT ( 8 ) )
{
2012-11-26 18:58:24 +00:00
// load "_global" into a register
registers [ preloadReg ] . SetObject ( scope [ 0 ] ) ;
preloadReg + + ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int scopeSize = scope . Num ( ) ;
scope . Append ( locals ) ;
locals - > AddRef ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idSWFScriptVar retVal = Run ( thisObject , stack , bitstream ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( scope . Num ( ) = = scopeSize + 1 ) ;
2012-11-28 15:47:07 +00:00
for ( int i = scopeSize ; i < scope . Num ( ) ; i + + )
{
if ( verify ( scope [ i ] ) )
{
2012-11-26 18:58:24 +00:00
scope [ i ] - > Release ( ) ;
}
}
scope . SetNum ( scopeSize ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
locals - > Release ( ) ;
locals = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return retVal ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
< anonymous > : : Split
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
namespace
{
const char * GetPropertyName ( int index )
{
switch ( index )
{
case 0 :
return " _x " ;
case 1 :
return " _y " ;
case 2 :
return " _xscale " ;
case 3 :
return " _yscale " ;
case 4 :
return " _currentframe " ;
case 5 :
return " _totalframes " ;
case 6 :
return " _alpha " ;
case 7 :
return " _visible " ;
case 8 :
return " _width " ;
case 9 :
return " _height " ;
case 10 :
return " _rotation " ;
case 11 :
return " _target " ;
case 12 :
return " _framesloaded " ;
case 13 :
return " _name " ;
case 14 :
return " _droptarget " ;
case 15 :
return " _url " ;
case 16 :
return " _highquality " ;
case 17 :
return " _focusrect " ;
case 18 :
return " _soundbuftime " ;
case 19 :
return " _quality " ;
case 20 :
return " _mousex " ;
case 21 :
return " _mousey " ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
return " " ;
}
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
const char * GetSwfActionName ( swfAction_t code )
{
switch ( code )
2012-11-26 18:58:24 +00:00
{
2012-11-28 15:47:07 +00:00
case Action_End :
return " Action_End " ;
2012-11-26 18:58:24 +00:00
// swf 3
2012-11-28 15:47:07 +00:00
case Action_NextFrame :
return " Action_NextFrame " ;
case Action_PrevFrame :
return " Action_PrevFrame " ;
case Action_Play :
return " Action_Play " ;
case Action_Stop :
return " Action_Stop " ;
case Action_ToggleQuality :
return " Action_ToggleQuality " ;
case Action_StopSounds :
return " Action_StopSounds " ;
case Action_GotoFrame :
return " Action_GotoFrame " ;
case Action_GetURL :
return " Action_GetURL " ;
case Action_WaitForFrame :
return " Action_WaitForFrame " ;
case Action_SetTarget :
return " Action_SetTarget " ;
case Action_GoToLabel :
return " Action_GoToLabel " ;
2012-11-26 18:58:24 +00:00
// swf 4
2012-11-28 15:47:07 +00:00
case Action_Add :
return " Action_Add " ;
case Action_Subtract :
return " Action_Subtract " ;
case Action_Multiply :
return " Action_Multiply " ;
case Action_Divide :
return " Action_Divide " ;
case Action_Equals :
return " Action_Equals " ;
case Action_Less :
return " Action_Less " ;
case Action_And :
return " Action_And " ;
case Action_Or :
return " Action_Or " ;
case Action_Not :
return " Action_Not " ;
case Action_StringEquals :
return " Action_StringEquals " ;
case Action_StringLength :
return " Action_StringLength " ;
case Action_StringExtract :
return " Action_StringExtract " ;
case Action_Pop :
return " Action_Pop " ;
case Action_ToInteger :
return " Action_ToInteger " ;
case Action_GetVariable :
return " Action_GetVariable " ;
case Action_SetVariable :
return " Action_SetVariable " ;
case Action_SetTarget2 :
return " Action_SetTarget2 " ;
case Action_StringAdd :
return " Action_StringAdd " ;
case Action_GetProperty :
return " Action_GetProperty " ;
case Action_SetProperty :
return " Action_SetProperty " ;
case Action_CloneSprite :
return " Action_CloneSprite " ;
case Action_RemoveSprite :
return " Action_RemoveSprite " ;
case Action_Trace :
return " Action_Trace " ;
case Action_StartDrag :
return " Action_StartDrag " ;
case Action_EndDrag :
return " Action_EndDrag " ;
case Action_StringLess :
return " Action_StringLess " ;
case Action_RandomNumber :
return " Action_RandomNumber " ;
case Action_MBStringLength :
return " Action_MBStringLength " ;
case Action_CharToAscii :
return " Action_CharToAscii " ;
case Action_AsciiToChar :
return " Action_AsciiToChar " ;
case Action_GetTime :
return " Action_GetTime " ;
case Action_MBStringExtract :
return " Action_MBStringExtract " ;
case Action_MBCharToAscii :
return " Action_MBCharToAscii " ;
case Action_MBAsciiToChar :
return " Action_MBAsciiToChar " ;
case Action_WaitForFrame2 :
return " Action_WaitForFrame2 " ;
case Action_Push :
return " Action_Push " ;
case Action_Jump :
return " Action_Jump " ;
case Action_GetURL2 :
return " Action_GetURL2 " ;
case Action_If :
return " Action_If " ;
case Action_Call :
return " Action_Call " ;
case Action_GotoFrame2 :
return " Action_GotoFrame2 " ;
2012-11-26 18:58:24 +00:00
// swf 5
2012-11-28 15:47:07 +00:00
case Action_Delete :
return " Action_Delete " ;
case Action_Delete2 :
return " Action_Delete2 " ;
case Action_DefineLocal :
return " Action_DefineLocal " ;
case Action_CallFunction :
return " Action_CallFunction " ;
case Action_Return :
return " Action_Return " ;
case Action_Modulo :
return " Action_Modulo " ;
case Action_NewObject :
return " Action_NewObject " ;
case Action_DefineLocal2 :
return " Action_DefineLocal2 " ;
case Action_InitArray :
return " Action_InitArray " ;
case Action_InitObject :
return " Action_InitObject " ;
case Action_TypeOf :
return " Action_TypeOf " ;
case Action_TargetPath :
return " Action_TargetPath " ;
case Action_Enumerate :
return " Action_Enumerate " ;
case Action_Add2 :
return " Action_Add2 " ;
case Action_Less2 :
return " Action_Less2 " ;
case Action_Equals2 :
return " Action_Equals2 " ;
case Action_ToNumber :
return " Action_ToNumber " ;
case Action_ToString :
return " Action_ToString " ;
case Action_PushDuplicate :
return " Action_PushDuplicate " ;
case Action_StackSwap :
return " Action_StackSwap " ;
case Action_GetMember :
return " Action_GetMember " ;
case Action_SetMember :
return " Action_SetMember " ;
case Action_Increment :
return " Action_Increment " ;
case Action_Decrement :
return " Action_Decrement " ;
case Action_CallMethod :
return " Action_CallMethod " ;
case Action_NewMethod :
return " Action_NewMethod " ;
case Action_BitAnd :
return " Action_BitAnd " ;
case Action_BitOr :
return " Action_BitOr " ;
case Action_BitXor :
return " Action_BitXor " ;
case Action_BitLShift :
return " Action_BitLShift " ;
case Action_BitRShift :
return " Action_BitRShift " ;
case Action_BitURShift :
return " Action_BitURShift " ;
case Action_StoreRegister :
return " Action_StoreRegister " ;
case Action_ConstantPool :
return " Action_ConstantPool " ;
case Action_With :
return " Action_With " ;
case Action_DefineFunction :
return " Action_DefineFunction " ;
2012-11-26 18:58:24 +00:00
// swf 6
2012-11-28 15:47:07 +00:00
case Action_InstanceOf :
return " Action_InstanceOf " ;
case Action_Enumerate2 :
return " Action_Enumerate2 " ;
case Action_StrictEquals :
return " Action_StrictEquals " ;
case Action_Greater :
return " Action_Greater " ;
case Action_StringGreater :
return " Action_StringGreater " ;
2012-11-26 18:58:24 +00:00
// swf 7
2012-11-28 15:47:07 +00:00
case Action_Extends :
return " Action_Extends " ;
case Action_CastOp :
return " Action_CastOp " ;
case Action_ImplementsOp :
return " Action_ImplementsOp " ;
case Action_Throw :
return " Action_Throw " ;
case Action_Try :
return " Action_Try " ;
case Action_DefineFunction2 :
return " Action_DefineFunction2 " ;
2012-11-26 18:58:24 +00:00
default :
return " UNKNOWN CODE " ;
}
}
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSWFScriptFunction_Script : : Run
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSWFScriptVar idSWFScriptFunction_Script : : Run ( idSWFScriptObject * thisObject , idSWFStack & stack , idSWFBitStream & bitstream )
{
2012-11-26 18:58:24 +00:00
static int callstackLevel = - 1 ;
2012-11-28 15:47:07 +00:00
idSWFSpriteInstance * thisSprite = thisObject - > GetSprite ( ) ;
idSWFSpriteInstance * currentTarget = thisSprite ;
if ( currentTarget = = NULL )
{
2012-11-26 18:58:24 +00:00
thisSprite = currentTarget = defaultSprite ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
callstackLevel + + ;
2012-11-28 15:47:07 +00:00
while ( bitstream . Tell ( ) < bitstream . Length ( ) )
{
swfAction_t code = ( swfAction_t ) bitstream . ReadU8 ( ) ;
2012-11-26 18:58:24 +00:00
uint16 recordLength = 0 ;
2012-11-28 15:47:07 +00:00
if ( code > = 0x80 )
{
2012-11-26 18:58:24 +00:00
recordLength = bitstream . ReadU16 ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( swf_debug . GetInteger ( ) > = 3 )
{
2012-11-26 18:58:24 +00:00
// stack[0] is always 0 so don't read it
2012-11-28 15:47:07 +00:00
if ( swf_debug . GetInteger ( ) > = 4 )
{
for ( int i = stack . Num ( ) - 1 ; i > = 0 ; i - - )
{
idLib : : Printf ( " %c: %s (%s) \n " , ( char ) ( 64 + stack . Num ( ) - i ) , stack [ i ] . ToString ( ) . c_str ( ) , stack [ i ] . TypeOf ( ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < registers . Num ( ) ; i + + )
{
if ( ! registers [ i ] . IsUndefined ( ) )
{
idLib : : Printf ( " R%d: %s (%s) \n " , i , registers [ i ] . ToString ( ) . c_str ( ) , registers [ i ] . TypeOf ( ) ) ;
2012-11-26 18:58:24 +00:00
}
}
}
2012-11-28 15:47:07 +00:00
idLib : : Printf ( " SWF%d: code %s \n " , callstackLevel , GetSwfActionName ( code ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
switch ( code )
{
case Action_Return :
2012-11-26 18:58:24 +00:00
callstackLevel - - ;
return stack . A ( ) ;
2012-11-28 15:47:07 +00:00
case Action_End :
2012-11-26 18:58:24 +00:00
callstackLevel - - ;
return idSWFScriptVar ( ) ;
case Action_NextFrame :
2012-11-28 15:47:07 +00:00
if ( verify ( currentTarget ! = NULL ) )
{
2012-11-26 18:58:24 +00:00
currentTarget - > NextFrame ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( swf_debug . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: no target movie clip for nextFrame \n " ) ;
}
break ;
case Action_PrevFrame :
2012-11-28 15:47:07 +00:00
if ( verify ( currentTarget ! = NULL ) )
{
2012-11-26 18:58:24 +00:00
currentTarget - > PrevFrame ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( swf_debug . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: no target movie clip for prevFrame \n " ) ;
}
break ;
case Action_Play :
2012-11-28 15:47:07 +00:00
if ( verify ( currentTarget ! = NULL ) )
{
2012-11-26 18:58:24 +00:00
currentTarget - > Play ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( swf_debug . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: no target movie clip for play \n " ) ;
}
break ;
case Action_Stop :
2012-11-28 15:47:07 +00:00
if ( verify ( currentTarget ! = NULL ) )
{
2012-11-26 18:58:24 +00:00
currentTarget - > Stop ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( swf_debug . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: no target movie clip for stop \n " ) ;
}
break ;
2012-11-28 15:47:07 +00:00
case Action_ToggleQuality :
break ;
case Action_StopSounds :
break ;
case Action_GotoFrame :
{
2012-11-26 18:58:24 +00:00
assert ( recordLength = = 2 ) ;
int frameNum = bitstream . ReadU16 ( ) + 1 ;
2012-11-28 15:47:07 +00:00
if ( verify ( currentTarget ! = NULL ) )
{
2012-11-26 18:58:24 +00:00
currentTarget - > RunTo ( frameNum ) ;
2012-11-28 15:47:07 +00:00
}
else if ( swf_debug . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: no target movie clip for runTo %d \n " , frameNum ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case Action_SetTarget :
{
const char * targetName = ( const char * ) bitstream . ReadData ( recordLength ) ;
if ( verify ( thisSprite ! = NULL ) )
{
2012-11-26 18:58:24 +00:00
currentTarget = thisSprite - > ResolveTarget ( targetName ) ;
2012-11-28 15:47:07 +00:00
}
else if ( swf_debug . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: no target movie clip for setTarget %s \n " , targetName ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case Action_GoToLabel :
{
const char * targetName = ( const char * ) bitstream . ReadData ( recordLength ) ;
if ( verify ( currentTarget ! = NULL ) )
{
2012-11-26 18:58:24 +00:00
currentTarget - > RunTo ( currentTarget - > FindFrame ( targetName ) ) ;
2012-11-28 15:47:07 +00:00
}
else if ( swf_debug . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: no target movie clip for runTo %s \n " , targetName ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case Action_Push :
{
2012-11-26 18:58:24 +00:00
idSWFBitStream pushstream ( bitstream . ReadData ( recordLength ) , recordLength , false ) ;
2012-11-28 15:47:07 +00:00
while ( pushstream . Tell ( ) < pushstream . Length ( ) )
{
2012-11-26 18:58:24 +00:00
uint8 type = pushstream . ReadU8 ( ) ;
2012-11-28 15:47:07 +00:00
switch ( type )
{
case 0 :
stack . Alloc ( ) . SetString ( pushstream . ReadString ( ) ) ;
break ;
case 1 :
stack . Alloc ( ) . SetFloat ( pushstream . ReadFloat ( ) ) ;
break ;
case 2 :
stack . Alloc ( ) . SetNULL ( ) ;
break ;
case 3 :
stack . Alloc ( ) . SetUndefined ( ) ;
break ;
case 4 :
stack . Alloc ( ) = registers [ pushstream . ReadU8 ( ) ] ;
break ;
case 5 :
stack . Alloc ( ) . SetBool ( pushstream . ReadU8 ( ) ! = 0 ) ;
break ;
case 6 :
stack . Alloc ( ) . SetFloat ( ( float ) pushstream . ReadDouble ( ) ) ;
break ;
case 7 :
stack . Alloc ( ) . SetInteger ( pushstream . ReadS32 ( ) ) ;
break ;
case 8 :
stack . Alloc ( ) . SetString ( constants . Get ( pushstream . ReadU8 ( ) ) ) ;
break ;
case 9 :
stack . Alloc ( ) . SetString ( constants . Get ( pushstream . ReadU16 ( ) ) ) ;
break ;
2012-11-26 18:58:24 +00:00
}
}
break ;
}
case Action_Pop :
stack . Pop ( 1 ) ;
break ;
case Action_Add :
stack . B ( ) . SetFloat ( stack . B ( ) . ToFloat ( ) + stack . A ( ) . ToFloat ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_Subtract :
stack . B ( ) . SetFloat ( stack . B ( ) . ToFloat ( ) - stack . A ( ) . ToFloat ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_Multiply :
stack . B ( ) . SetFloat ( stack . B ( ) . ToFloat ( ) * stack . A ( ) . ToFloat ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_Divide :
stack . B ( ) . SetFloat ( stack . B ( ) . ToFloat ( ) / stack . A ( ) . ToFloat ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_Equals :
stack . B ( ) . SetBool ( stack . B ( ) . ToFloat ( ) = = stack . A ( ) . ToFloat ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_Less :
stack . B ( ) . SetBool ( stack . B ( ) . ToFloat ( ) < stack . A ( ) . ToFloat ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_And :
stack . B ( ) . SetBool ( stack . B ( ) . ToBool ( ) & & stack . A ( ) . ToBool ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_Or :
stack . B ( ) . SetBool ( stack . B ( ) . ToBool ( ) | | stack . A ( ) . ToBool ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_Not :
stack . A ( ) . SetBool ( ! stack . A ( ) . ToBool ( ) ) ;
break ;
case Action_StringEquals :
stack . B ( ) . SetBool ( stack . B ( ) . ToString ( ) = = stack . A ( ) . ToString ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_StringLength :
stack . A ( ) . SetInteger ( stack . A ( ) . ToString ( ) . Length ( ) ) ;
break ;
case Action_StringAdd :
stack . B ( ) . SetString ( stack . B ( ) . ToString ( ) + stack . A ( ) . ToString ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_StringExtract :
stack . C ( ) . SetString ( stack . C ( ) . ToString ( ) . Mid ( stack . B ( ) . ToInteger ( ) , stack . A ( ) . ToInteger ( ) ) ) ;
stack . Pop ( 2 ) ;
break ;
case Action_StringLess :
stack . B ( ) . SetBool ( stack . B ( ) . ToString ( ) < stack . A ( ) . ToString ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_StringGreater :
stack . B ( ) . SetBool ( stack . B ( ) . ToString ( ) > stack . A ( ) . ToString ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_ToInteger :
stack . A ( ) . SetInteger ( stack . A ( ) . ToInteger ( ) ) ;
break ;
case Action_CharToAscii :
stack . A ( ) . SetInteger ( stack . A ( ) . ToString ( ) [ 0 ] ) ;
break ;
case Action_AsciiToChar :
stack . A ( ) . SetString ( va ( " %c " , stack . A ( ) . ToInteger ( ) ) ) ;
break ;
case Action_Jump :
bitstream . Seek ( bitstream . ReadS16 ( ) ) ;
break ;
2012-11-28 15:47:07 +00:00
case Action_If :
{
2012-11-26 18:58:24 +00:00
int16 offset = bitstream . ReadS16 ( ) ;
2012-11-28 15:47:07 +00:00
if ( stack . A ( ) . ToBool ( ) )
{
2012-11-26 18:58:24 +00:00
bitstream . Seek ( offset ) ;
}
stack . Pop ( 1 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_GetVariable :
{
2012-11-26 18:58:24 +00:00
idStr variableName = stack . A ( ) . ToString ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = scope . Num ( ) - 1 ; i > = 0 ; i - - )
{
2012-11-26 18:58:24 +00:00
stack . A ( ) = scope [ i ] - > Get ( variableName ) ;
2012-11-28 15:47:07 +00:00
if ( ! stack . A ( ) . IsUndefined ( ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( stack . A ( ) . IsUndefined ( ) & & swf_debug . GetInteger ( ) > 1 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: unknown variable %s \n " , variableName . c_str ( ) ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case Action_SetVariable :
{
2012-11-26 18:58:24 +00:00
idStr variableName = stack . B ( ) . ToString ( ) ;
bool found = false ;
2012-11-28 15:47:07 +00:00
for ( int i = scope . Num ( ) - 1 ; i > = 0 ; i - - )
{
if ( scope [ i ] - > HasProperty ( variableName ) )
{
2012-11-26 18:58:24 +00:00
scope [ i ] - > Set ( variableName , stack . A ( ) ) ;
found = true ;
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! found )
{
2012-11-26 18:58:24 +00:00
thisObject - > Set ( variableName , stack . A ( ) ) ;
}
stack . Pop ( 2 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_GotoFrame2 :
{
2012-11-26 18:58:24 +00:00
uint32 frameNum = 0 ;
uint8 flags = bitstream . ReadU8 ( ) ;
2012-11-28 15:47:07 +00:00
if ( flags & 2 )
{
2012-11-26 18:58:24 +00:00
frameNum + = bitstream . ReadU16 ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( verify ( thisSprite ! = NULL ) )
{
if ( stack . A ( ) . IsString ( ) )
{
2012-11-26 18:58:24 +00:00
frameNum + = thisSprite - > FindFrame ( stack . A ( ) . ToString ( ) ) ;
}
2012-11-28 15:47:07 +00:00
else
{
frameNum + = ( uint32 ) stack . A ( ) . ToInteger ( ) ;
}
if ( ( flags & 1 ) ! = 0 )
{
2012-11-26 18:58:24 +00:00
thisSprite - > Play ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
thisSprite - > Stop ( ) ;
}
thisSprite - > RunTo ( frameNum ) ;
2012-11-28 15:47:07 +00:00
}
else if ( swf_debug . GetInteger ( ) > 0 )
{
if ( ( flags & 1 ) ! = 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: no target movie clip for gotoAndPlay \n " ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: no target movie clip for gotoAndStop \n " ) ;
}
}
stack . Pop ( 1 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_GetProperty :
{
if ( verify ( thisSprite ! = NULL ) )
{
idSWFSpriteInstance * target = thisSprite - > ResolveTarget ( stack . B ( ) . ToString ( ) ) ;
2012-11-26 18:58:24 +00:00
stack . B ( ) = target - > scriptObject - > Get ( GetPropertyName ( stack . A ( ) . ToInteger ( ) ) ) ;
2012-11-28 15:47:07 +00:00
}
else if ( swf_debug . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: no target movie clip for getProperty \n " ) ;
}
stack . Pop ( 1 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_SetProperty :
{
if ( verify ( thisSprite ! = NULL ) )
{
idSWFSpriteInstance * target = thisSprite - > ResolveTarget ( stack . C ( ) . ToString ( ) ) ;
2012-11-26 18:58:24 +00:00
target - > scriptObject - > Set ( GetPropertyName ( stack . B ( ) . ToInteger ( ) ) , stack . A ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else if ( swf_debug . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: no target movie clip for setProperty \n " ) ;
}
stack . Pop ( 3 ) ;
break ;
}
case Action_Trace :
idLib : : PrintfIf ( swf_debug . GetInteger ( ) > 0 , " SWF Trace: %s \n " , stack . A ( ) . ToString ( ) . c_str ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_GetTime :
stack . Alloc ( ) . SetInteger ( Sys_Milliseconds ( ) ) ;
break ;
case Action_RandomNumber :
assert ( thisSprite & & thisSprite - > sprite & & thisSprite - > sprite - > GetSWF ( ) ) ;
stack . A ( ) . SetInteger ( thisSprite - > sprite - > GetSWF ( ) - > GetRandom ( ) . RandomInt ( stack . A ( ) . ToInteger ( ) ) ) ;
break ;
2012-11-28 15:47:07 +00:00
case Action_CallFunction :
{
2012-11-26 18:58:24 +00:00
idStr functionName = stack . A ( ) . ToString ( ) ;
idSWFScriptVar function ;
2012-11-28 15:47:07 +00:00
idSWFScriptObject * object = NULL ;
for ( int i = scope . Num ( ) - 1 ; i > = 0 ; i - - )
{
2012-11-26 18:58:24 +00:00
function = scope [ i ] - > Get ( functionName ) ;
2012-11-28 15:47:07 +00:00
if ( ! function . IsUndefined ( ) )
{
2012-11-26 18:58:24 +00:00
object = scope [ i ] ;
break ;
}
}
stack . Pop ( 1 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idSWFParmList parms ;
parms . SetNum ( stack . A ( ) . ToInteger ( ) ) ;
stack . Pop ( 1 ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < parms . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
parms [ i ] = stack . A ( ) ;
stack . Pop ( 1 ) ;
}
2012-11-28 15:47:07 +00:00
if ( function . IsFunction ( ) & & verify ( object ) )
{
2012-11-26 18:58:24 +00:00
stack . Alloc ( ) = function . GetFunction ( ) - > Call ( object , parms ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idLib : : PrintfIf ( swf_debug . GetInteger ( ) > 0 , " SWF: unknown function %s \n " , functionName . c_str ( ) ) ;
stack . Alloc ( ) . SetUndefined ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
case Action_CallMethod :
{
2012-11-26 18:58:24 +00:00
idStr functionName = stack . A ( ) . ToString ( ) ;
// If the top stack is undefined but there is an object, it's calling the constructor
2012-11-28 15:47:07 +00:00
if ( functionName . IsEmpty ( ) | | stack . A ( ) . IsUndefined ( ) | | stack . A ( ) . IsNULL ( ) )
{
2012-11-26 18:58:24 +00:00
functionName = " __constructor__ " ;
}
2012-11-28 15:47:07 +00:00
idSWFScriptObject * object = NULL ;
2012-11-26 18:58:24 +00:00
idSWFScriptVar function ;
2012-11-28 15:47:07 +00:00
if ( stack . B ( ) . IsObject ( ) )
{
2012-11-26 18:58:24 +00:00
object = stack . B ( ) . GetObject ( ) ;
function = object - > Get ( functionName ) ;
2012-11-28 15:47:07 +00:00
if ( ! function . IsFunction ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : PrintfIf ( swf_debug . GetInteger ( ) > 1 , " SWF: unknown method %s on %s \n " , functionName . c_str ( ) , object - > DefaultValue ( true ) . ToString ( ) . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idLib : : PrintfIf ( swf_debug . GetInteger ( ) > 1 , " SWF: NULL object for method %s \n " , functionName . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
stack . Pop ( 2 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idSWFParmList parms ;
parms . SetNum ( stack . A ( ) . ToInteger ( ) ) ;
stack . Pop ( 1 ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < parms . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
parms [ i ] = stack . A ( ) ;
stack . Pop ( 1 ) ;
}
2012-11-28 15:47:07 +00:00
if ( function . IsFunction ( ) )
{
2012-11-26 18:58:24 +00:00
stack . Alloc ( ) = function . GetFunction ( ) - > Call ( object , parms ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
stack . Alloc ( ) . SetUndefined ( ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case Action_ConstantPool :
{
2012-11-26 18:58:24 +00:00
constants . Clear ( ) ;
uint16 numConstants = bitstream . ReadU16 ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numConstants ; i + + )
{
2012-11-26 18:58:24 +00:00
constants . Append ( idSWFScriptString : : Alloc ( bitstream . ReadString ( ) ) ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case Action_DefineFunction :
{
2012-11-26 18:58:24 +00:00
idStr functionName = bitstream . ReadString ( ) ;
2012-11-28 15:47:07 +00:00
idSWFScriptFunction_Script * newFunction = idSWFScriptFunction_Script : : Alloc ( ) ;
2012-11-26 18:58:24 +00:00
newFunction - > SetScope ( scope ) ;
newFunction - > SetConstants ( constants ) ;
newFunction - > SetDefaultSprite ( defaultSprite ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
uint16 numParms = bitstream . ReadU16 ( ) ;
newFunction - > AllocParameters ( numParms ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numParms ; i + + )
{
2012-11-26 18:58:24 +00:00
newFunction - > SetParameter ( i , 0 , bitstream . ReadString ( ) ) ;
}
uint16 codeSize = bitstream . ReadU16 ( ) ;
newFunction - > SetData ( bitstream . ReadData ( codeSize ) , codeSize ) ;
2012-11-28 15:47:07 +00:00
if ( functionName . IsEmpty ( ) )
{
2012-11-26 18:58:24 +00:00
stack . Alloc ( ) . SetFunction ( newFunction ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
thisObject - > Set ( functionName , idSWFScriptVar ( newFunction ) ) ;
}
newFunction - > Release ( ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_DefineFunction2 :
{
2012-11-26 18:58:24 +00:00
idStr functionName = bitstream . ReadString ( ) ;
2012-11-28 15:47:07 +00:00
idSWFScriptFunction_Script * newFunction = idSWFScriptFunction_Script : : Alloc ( ) ;
2012-11-26 18:58:24 +00:00
newFunction - > SetScope ( scope ) ;
newFunction - > SetConstants ( constants ) ;
newFunction - > SetDefaultSprite ( defaultSprite ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
uint16 numParms = bitstream . ReadU16 ( ) ;
2012-11-28 15:47:07 +00:00
// The number of registers is from 0 to 255, although valid values are 1 to 256.
2012-11-26 18:58:24 +00:00
// There must always be at least one register for DefineFunction2, to hold "this" or "super" when required.
2012-11-28 15:47:07 +00:00
uint8 numRegs = bitstream . ReadU8 ( ) + 1 ;
2012-11-26 18:58:24 +00:00
// Note that SWF byte-ordering causes the flag bits to be reversed per-byte
// from how the swf_file_format_spec_v10.pdf document describes the ordering in ActionDefineFunction2.
2012-11-28 15:47:07 +00:00
// PreloadThisFlag is byte 0, not 7, PreloadGlobalFlag is 8, not 15.
2012-11-26 18:58:24 +00:00
uint16 flags = bitstream . ReadU16 ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
newFunction - > AllocParameters ( numParms ) ;
newFunction - > AllocRegisters ( numRegs ) ;
newFunction - > SetFlags ( flags ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numParms ; i + + )
{
2012-11-26 18:58:24 +00:00
uint8 reg = bitstream . ReadU8 ( ) ;
2012-11-28 15:47:07 +00:00
const char * name = bitstream . ReadString ( ) ;
if ( reg > = numRegs )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " SWF: Parameter %s in function %s bound to out of range register %d " , name , functionName . c_str ( ) , reg ) ;
reg = 0 ;
}
newFunction - > SetParameter ( i , reg , name ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
uint16 codeSize = bitstream . ReadU16 ( ) ;
newFunction - > SetData ( bitstream . ReadData ( codeSize ) , codeSize ) ;
2012-11-28 15:47:07 +00:00
if ( functionName . IsEmpty ( ) )
{
2012-11-26 18:58:24 +00:00
stack . Alloc ( ) . SetFunction ( newFunction ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
thisObject - > Set ( functionName , idSWFScriptVar ( newFunction ) ) ;
}
newFunction - > Release ( ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_Enumerate :
{
2012-11-26 18:58:24 +00:00
idStr variableName = stack . A ( ) . ToString ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = scope . Num ( ) - 1 ; i > = 0 ; i - - )
{
2012-11-26 18:58:24 +00:00
stack . A ( ) = scope [ i ] - > Get ( variableName ) ;
2012-11-28 15:47:07 +00:00
if ( ! stack . A ( ) . IsUndefined ( ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! stack . A ( ) . IsObject ( ) )
{
2012-11-26 18:58:24 +00:00
stack . A ( ) . SetNULL ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
idSWFScriptObject * object = stack . A ( ) . GetObject ( ) ;
2012-11-26 18:58:24 +00:00
object - > AddRef ( ) ;
stack . A ( ) . SetNULL ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < object - > NumVariables ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
stack . Alloc ( ) . SetString ( object - > EnumVariable ( i ) ) ;
}
object - > Release ( ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case Action_Enumerate2 :
{
if ( ! stack . A ( ) . IsObject ( ) )
{
2012-11-26 18:58:24 +00:00
stack . A ( ) . SetNULL ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
idSWFScriptObject * object = stack . A ( ) . GetObject ( ) ;
2012-11-26 18:58:24 +00:00
object - > AddRef ( ) ;
stack . A ( ) . SetNULL ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < object - > NumVariables ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
stack . Alloc ( ) . SetString ( object - > EnumVariable ( i ) ) ;
}
object - > Release ( ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case Action_Equals2 :
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetBool ( stack . A ( ) . AbstractEquals ( stack . B ( ) ) ) ;
stack . Pop ( 1 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_StrictEquals :
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetBool ( stack . A ( ) . StrictEquals ( stack . B ( ) ) ) ;
stack . Pop ( 1 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_GetMember :
{
if ( ( stack . B ( ) . IsUndefined ( ) | | stack . B ( ) . IsNULL ( ) ) & & swf_debug . GetInteger ( ) > 1 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: tried to get member %s on an invalid object in sprite '%s' \n " , stack . A ( ) . ToString ( ) . c_str ( ) , thisSprite ! = NULL ? thisSprite - > GetName ( ) : " " ) ;
}
2012-11-28 15:47:07 +00:00
if ( stack . B ( ) . IsObject ( ) )
{
idSWFScriptObject * object = stack . B ( ) . GetObject ( ) ;
if ( stack . A ( ) . IsNumeric ( ) )
{
2012-11-26 18:58:24 +00:00
stack . B ( ) = object - > Get ( stack . A ( ) . ToInteger ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
stack . B ( ) = object - > Get ( stack . A ( ) . ToString ( ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( stack . B ( ) . IsUndefined ( ) & & swf_debug . GetInteger ( ) > 1 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: unknown member %s \n " , stack . A ( ) . ToString ( ) . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( stack . B ( ) . IsString ( ) )
{
2012-11-26 18:58:24 +00:00
idStr propertyName = stack . A ( ) . ToString ( ) ;
2012-11-28 15:47:07 +00:00
if ( propertyName . Cmp ( " length " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetInteger ( stack . B ( ) . ToString ( ) . Length ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else if ( propertyName . Cmp ( " value " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
// Do nothing
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetUndefined ( ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( stack . B ( ) . IsFunction ( ) )
{
2012-11-26 18:58:24 +00:00
idStr propertyName = stack . A ( ) . ToString ( ) ;
2012-11-28 15:47:07 +00:00
if ( propertyName . Cmp ( " prototype " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
// if this is a function, it's a class definition function, and it just wants the prototype object
// create it if it hasn't been already, and return it
2012-11-28 15:47:07 +00:00
idSWFScriptFunction * sfs = stack . B ( ) . GetFunction ( ) ;
idSWFScriptObject * object = sfs - > GetPrototype ( ) ;
if ( object = = NULL )
{
2012-11-26 18:58:24 +00:00
object = idSWFScriptObject : : Alloc ( ) ;
// Set the __proto__ to the main Object prototype
idSWFScriptVar baseObjConstructor = scope [ 0 ] - > Get ( " Object " ) ;
2012-11-28 15:47:07 +00:00
idSWFScriptFunction * baseObj = baseObjConstructor . GetFunction ( ) ;
2012-11-26 18:58:24 +00:00
object - > Set ( " __proto__ " , baseObj - > GetPrototype ( ) ) ;
sfs - > SetPrototype ( object ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
stack . B ( ) = idSWFScriptVar ( object ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetUndefined ( ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetUndefined ( ) ;
}
stack . Pop ( 1 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_SetMember :
{
if ( stack . C ( ) . IsObject ( ) )
{
idSWFScriptObject * object = stack . C ( ) . GetObject ( ) ;
if ( stack . B ( ) . IsNumeric ( ) )
{
2012-11-26 18:58:24 +00:00
object - > Set ( stack . B ( ) . ToInteger ( ) , stack . A ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
object - > Set ( stack . B ( ) . ToString ( ) , stack . A ( ) ) ;
}
}
stack . Pop ( 3 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_InitArray :
{
idSWFScriptObject * object = idSWFScriptObject : : Alloc ( ) ;
2012-11-26 18:58:24 +00:00
object - > MakeArray ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int numElements = stack . A ( ) . ToInteger ( ) ;
stack . Pop ( 1 ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numElements ; i + + )
{
2012-11-26 18:58:24 +00:00
object - > Set ( i , stack . A ( ) ) ;
stack . Pop ( 1 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
stack . Alloc ( ) . SetObject ( object ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
object - > Release ( ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_InitObject :
{
idSWFScriptObject * object = idSWFScriptObject : : Alloc ( ) ;
2012-11-26 18:58:24 +00:00
int numElements = stack . A ( ) . ToInteger ( ) ;
stack . Pop ( 1 ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numElements ; i + + )
{
2012-11-26 18:58:24 +00:00
object - > Set ( stack . B ( ) . ToString ( ) , stack . A ( ) ) ;
stack . Pop ( 2 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
stack . Alloc ( ) . SetObject ( object ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
object - > Release ( ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_NewObject :
{
idSWFScriptObject * object = idSWFScriptObject : : Alloc ( ) ;
2012-11-26 18:58:24 +00:00
idStr functionName = stack . A ( ) . ToString ( ) ;
stack . Pop ( 1 ) ;
2012-11-28 15:47:07 +00:00
if ( functionName . Cmp ( " Array " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
object - > MakeArray ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int numElements = stack . A ( ) . ToInteger ( ) ;
stack . Pop ( 1 ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numElements ; i + + )
{
2012-11-26 18:58:24 +00:00
object - > Set ( i , stack . A ( ) ) ;
stack . Pop ( 1 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idSWFScriptVar baseObjConstructor = scope [ 0 ] - > Get ( " Object " ) ;
2012-11-28 15:47:07 +00:00
idSWFScriptFunction * baseObj = baseObjConstructor . GetFunction ( ) ;
2012-11-26 18:58:24 +00:00
object - > Set ( " __proto__ " , baseObj - > GetPrototype ( ) ) ;
// object prototype is not set here because it will be auto created from Object later
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idSWFParmList parms ;
parms . SetNum ( stack . A ( ) . ToInteger ( ) ) ;
stack . Pop ( 1 ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < parms . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
parms [ i ] = stack . A ( ) ;
stack . Pop ( 1 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idSWFScriptVar objdef = scope [ 0 ] - > Get ( functionName ) ;
2012-11-28 15:47:07 +00:00
if ( objdef . IsFunction ( ) )
{
idSWFScriptFunction * constructorFunction = objdef . GetFunction ( ) ;
2012-11-26 18:58:24 +00:00
object - > Set ( " __proto__ " , constructorFunction - > GetPrototype ( ) ) ;
object - > SetPrototype ( constructorFunction - > GetPrototype ( ) ) ;
constructorFunction - > Call ( object , parms ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " SWF: Unknown class definition %s " , functionName . c_str ( ) ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
stack . Alloc ( ) . SetObject ( object ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
object - > Release ( ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_Extends :
{
idSWFScriptFunction * superclassConstructorFunction = stack . A ( ) . GetFunction ( ) ;
idSWFScriptFunction * subclassConstructorFunction = stack . B ( ) . GetFunction ( ) ;
2012-11-26 18:58:24 +00:00
stack . Pop ( 2 ) ;
2012-11-28 15:47:07 +00:00
idSWFScriptObject * scriptObject = idSWFScriptObject : : Alloc ( ) ;
2012-11-26 18:58:24 +00:00
scriptObject - > SetPrototype ( superclassConstructorFunction - > GetPrototype ( ) ) ;
scriptObject - > Set ( " __proto__ " , idSWFScriptVar ( superclassConstructorFunction - > GetPrototype ( ) ) ) ;
scriptObject - > Set ( " __constructor__ " , idSWFScriptVar ( superclassConstructorFunction ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
subclassConstructorFunction - > SetPrototype ( scriptObject ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
scriptObject - > Release ( ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_TargetPath :
{
if ( ! stack . A ( ) . IsObject ( ) )
{
2012-11-26 18:58:24 +00:00
stack . A ( ) . SetUndefined ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
idSWFScriptObject * object = stack . A ( ) . GetObject ( ) ;
if ( object - > GetSprite ( ) = = NULL )
{
2012-11-26 18:58:24 +00:00
stack . A ( ) . SetUndefined ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idStr dotName = object - > GetSprite ( ) - > name . c_str ( ) ;
2012-11-28 15:47:07 +00:00
for ( idSWFSpriteInstance * target = object - > GetSprite ( ) - > parent ; target ! = NULL ; target = target - > parent )
{
2012-11-26 18:58:24 +00:00
dotName = target - > name + " . " + dotName ;
}
stack . A ( ) . SetString ( dotName ) ;
}
}
break ;
}
2012-11-28 15:47:07 +00:00
case Action_With :
{
2012-11-26 18:58:24 +00:00
int withSize = bitstream . ReadU16 ( ) ;
idSWFBitStream bitstream2 ( bitstream . ReadData ( withSize ) , withSize , false ) ;
2012-11-28 15:47:07 +00:00
if ( stack . A ( ) . IsObject ( ) )
{
idSWFScriptObject * withObject = stack . A ( ) . GetObject ( ) ;
2012-11-26 18:58:24 +00:00
withObject - > AddRef ( ) ;
stack . Pop ( 1 ) ;
scope . Append ( withObject ) ;
Run ( thisObject , stack , bitstream2 ) ;
scope . SetNum ( scope . Num ( ) - 1 ) ;
withObject - > Release ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
if ( swf_debug . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: with() invalid object specified \n " ) ;
}
stack . Pop ( 1 ) ;
}
break ;
}
case Action_ToNumber :
stack . A ( ) . SetFloat ( stack . A ( ) . ToFloat ( ) ) ;
break ;
case Action_ToString :
stack . A ( ) . SetString ( stack . A ( ) . ToString ( ) ) ;
break ;
case Action_TypeOf :
stack . A ( ) . SetString ( stack . A ( ) . TypeOf ( ) ) ;
break ;
2012-11-28 15:47:07 +00:00
case Action_Add2 :
{
if ( stack . A ( ) . IsString ( ) | | stack . B ( ) . IsString ( ) )
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetString ( stack . B ( ) . ToString ( ) + stack . A ( ) . ToString ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetFloat ( stack . B ( ) . ToFloat ( ) + stack . A ( ) . ToFloat ( ) ) ;
}
stack . Pop ( 1 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_Less2 :
{
if ( stack . A ( ) . IsString ( ) & & stack . B ( ) . IsString ( ) )
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetBool ( stack . B ( ) . ToString ( ) < stack . A ( ) . ToString ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetBool ( stack . B ( ) . ToFloat ( ) < stack . A ( ) . ToFloat ( ) ) ;
}
stack . Pop ( 1 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_Greater :
{
if ( stack . A ( ) . IsString ( ) & & stack . B ( ) . IsString ( ) )
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetBool ( stack . B ( ) . ToString ( ) > stack . A ( ) . ToString ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetBool ( stack . B ( ) . ToFloat ( ) > stack . A ( ) . ToFloat ( ) ) ;
}
stack . Pop ( 1 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_Modulo :
{
2012-11-26 18:58:24 +00:00
int32 a = stack . A ( ) . ToInteger ( ) ;
int32 b = stack . B ( ) . ToInteger ( ) ;
2012-11-28 15:47:07 +00:00
if ( a = = 0 )
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetUndefined ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
stack . B ( ) . SetInteger ( b % a ) ;
}
stack . Pop ( 1 ) ;
break ;
}
case Action_BitAnd :
stack . B ( ) . SetInteger ( stack . B ( ) . ToInteger ( ) & stack . A ( ) . ToInteger ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_BitLShift :
stack . B ( ) . SetInteger ( stack . B ( ) . ToInteger ( ) < < stack . A ( ) . ToInteger ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_BitOr :
stack . B ( ) . SetInteger ( stack . B ( ) . ToInteger ( ) | stack . A ( ) . ToInteger ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_BitRShift :
stack . B ( ) . SetInteger ( stack . B ( ) . ToInteger ( ) > > stack . A ( ) . ToInteger ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_BitURShift :
2012-11-28 15:47:07 +00:00
stack . B ( ) . SetInteger ( ( uint32 ) stack . B ( ) . ToInteger ( ) > > stack . A ( ) . ToInteger ( ) ) ;
2012-11-26 18:58:24 +00:00
stack . Pop ( 1 ) ;
break ;
case Action_BitXor :
stack . B ( ) . SetInteger ( stack . B ( ) . ToInteger ( ) ^ stack . A ( ) . ToInteger ( ) ) ;
stack . Pop ( 1 ) ;
break ;
case Action_Decrement :
stack . A ( ) . SetFloat ( stack . A ( ) . ToFloat ( ) - 1.0f ) ;
break ;
case Action_Increment :
stack . A ( ) . SetFloat ( stack . A ( ) . ToFloat ( ) + 1.0f ) ;
break ;
2012-11-28 15:47:07 +00:00
case Action_PushDuplicate :
{
2012-11-26 18:58:24 +00:00
idSWFScriptVar dup = stack . A ( ) ;
stack . Alloc ( ) = dup ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_StackSwap :
{
2012-11-26 18:58:24 +00:00
idSWFScriptVar temp = stack . A ( ) ;
stack . A ( ) = stack . B ( ) ;
stack . A ( ) = temp ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_StoreRegister :
{
2012-11-26 18:58:24 +00:00
uint8 registerNumber = bitstream . ReadU8 ( ) ;
registers [ registerNumber ] = stack . A ( ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_DefineLocal :
{
scope [ scope . Num ( ) - 1 ] - > Set ( stack . B ( ) . ToString ( ) , stack . A ( ) ) ;
2012-11-26 18:58:24 +00:00
stack . Pop ( 2 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_DefineLocal2 :
{
scope [ scope . Num ( ) - 1 ] - > Set ( stack . A ( ) . ToString ( ) , idSWFScriptVar ( ) ) ;
2012-11-26 18:58:24 +00:00
stack . Pop ( 1 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_Delete :
{
if ( swf_debug . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: Delete ignored \n " ) ;
}
// We no longer support deleting variables because the performance cost of updating the hash tables is not worth it
stack . Pop ( 2 ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case Action_Delete2 :
{
if ( swf_debug . GetInteger ( ) > 0 )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: Delete2 ignored \n " ) ;
}
// We no longer support deleting variables because the performance cost of updating the hash tables is not worth it
stack . Pop ( 1 ) ;
break ;
}
// These are functions we just don't support because we never really needed to
case Action_CloneSprite :
case Action_RemoveSprite :
case Action_Call :
case Action_SetTarget2 :
case Action_NewMethod :
default :
idLib : : Warning ( " SWF: Unhandled Action %s " , idSWF : : GetActionName ( code ) ) ;
// We have to abort here because the rest of the script is basically meaningless now
assert ( false ) ;
callstackLevel - - ;
return idSWFScriptVar ( ) ;
}
}
callstackLevel - - ;
return idSWFScriptVar ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSWF : : Invoke
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSWF : : Invoke ( const char * functionName , const idSWFParmList & parms )
{
idSWFScriptObject * obj = mainspriteInstance - > GetScriptObject ( ) ;
2012-11-26 18:58:24 +00:00
idSWFScriptVar scriptVar = obj - > Get ( functionName ) ;
2012-11-28 15:47:07 +00:00
if ( swf_debugInvoke . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: Invoke %s with %d parms (%s) \n " , functionName , parms . Num ( ) , GetName ( ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( scriptVar . IsFunction ( ) )
{
2012-11-26 18:58:24 +00:00
scriptVar . GetFunction ( ) - > Call ( NULL , parms ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSWF : : Invoke
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSWF : : Invoke ( const char * functionName , const idSWFParmList & parms , idSWFScriptVar & scriptVar )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( scriptVar . IsFunction ( ) )
{
2012-11-26 18:58:24 +00:00
scriptVar . GetFunction ( ) - > Call ( NULL , parms ) ;
2012-11-28 15:47:07 +00:00
}
else
{
idSWFScriptObject * obj = mainspriteInstance - > GetScriptObject ( ) ;
2012-11-26 18:58:24 +00:00
scriptVar = obj - > Get ( functionName ) ;
2012-11-28 15:47:07 +00:00
if ( scriptVar . IsFunction ( ) )
{
2012-11-26 18:58:24 +00:00
scriptVar . GetFunction ( ) - > Call ( NULL , parms ) ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSWF : : Invoke
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSWF : : Invoke ( const char * functionName , const idSWFParmList & parms , bool & functionExists )
{
idSWFScriptObject * obj = mainspriteInstance - > GetScriptObject ( ) ;
2012-11-26 18:58:24 +00:00
idSWFScriptVar scriptVar = obj - > Get ( functionName ) ;
2012-11-28 15:47:07 +00:00
if ( swf_debugInvoke . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " SWF: Invoke %s with %d parms (%s) \n " , functionName , parms . Num ( ) , GetName ( ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( scriptVar . IsFunction ( ) )
{
2012-11-26 18:58:24 +00:00
scriptVar . GetFunction ( ) - > Call ( NULL , parms ) ;
functionExists = true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
functionExists = false ;
}
}