Flash bytecode to Lua

This commit is contained in:
Robert Beckebans 2015-06-06 16:28:43 +02:00
parent 71e339a83b
commit 21de748801
7 changed files with 391 additions and 119 deletions

View file

@ -1085,7 +1085,7 @@ void idSWF::WriteXML( const char* filename )
case SWF_DICT_SPRITE: case SWF_DICT_SPRITE:
{ {
dictionary[i].sprite->WriteXML( file, "\t\t", i ); dictionary[i].sprite->WriteXML( file, i, "\t\t" );
break; break;
} }
@ -1235,7 +1235,7 @@ void idSWF::WriteXML( const char* filename )
file->WriteFloatString( "\t</Dictionary>\n" ); file->WriteFloatString( "\t</Dictionary>\n" );
mainsprite->WriteXML( file, "\t" ); mainsprite->WriteXML( file, dictionary.Num(), "\t" );
file->WriteFloatString( "</XSWF>\n" ); file->WriteFloatString( "</XSWF>\n" );
} }

View file

@ -266,7 +266,7 @@ idSWFScriptVar idSWFScriptFunction_Script::Call( idSWFScriptObject* thisObject,
} }
// RB begin // RB begin
idStr idSWFScriptFunction_Script::CallToScript( idSWFScriptObject* thisObject, const idSWFParmList& parms ) idStr idSWFScriptFunction_Script::CallToScript( idSWFScriptObject* thisObject, const idSWFParmList& parms, const char* filename, int characterID, int actionID )
{ {
idSWFBitStream bitstream( data, length, false ); idSWFBitStream bitstream( data, length, false );
@ -396,7 +396,7 @@ idStr idSWFScriptFunction_Script::CallToScript( idSWFScriptObject* thisObject, c
scope.Append( locals ); scope.Append( locals );
locals->AddRef(); locals->AddRef();
idStr retVal = ExportToScript( thisObject, stack, bitstream ); idStr retVal = ExportToScript( thisObject, stack, bitstream, filename, characterID, actionID );
assert( scope.Num() == scopeSize + 1 ); assert( scope.Num() == scopeSize + 1 );
for( int i = scopeSize; i < scope.Num(); i++ ) for( int i = scopeSize; i < scope.Num(); i++ )
@ -1723,7 +1723,68 @@ idSWFScriptVar idSWFScriptFunction_Script::Run( idSWFScriptObject* thisObject, i
} }
// RB begin // RB begin
idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject, idSWFStack& stack, idSWFBitStream& bitstream ) idStr idSWFScriptFunction_Script::UpdateIndent( int indentLevel ) const
{
idStr indent;
for( int i = 0; i < indentLevel; i++ )
{
indent += '\t';
}
return indent;
}
void idSWFScriptFunction_Script::AddLine( const idStr& line )
{
ActionBlock& block = currentBlock->blocks.Alloc();
block.parent = currentBlock;
block.line = line;
}
void idSWFScriptFunction_Script::AddBlock( const idStr& line )
{
ActionBlock& block = currentBlock->blocks.Alloc();
block.parent = currentBlock;
block.line = line;
currentBlock = &block;
}
void idSWFScriptFunction_Script::QuitCurrentBlock()
{
if( currentBlock->parent != NULL )
{
currentBlock = currentBlock->parent;
}
}
idStr idSWFScriptFunction_Script::BuildActionCode( const idList<ActionBlock>& blocks, int level )
{
idStr ret;
idStr prefix = UpdateIndent( level );
for( int i = 0; i < blocks.Num(); i++ )
{
const ActionBlock& block = blocks[i];
if( !block.line.IsEmpty() )
{
ret += prefix + block.line + "\n";
}
if( block.blocks.Num() )
{
ret += BuildActionCode( block.blocks, ++level );
ret += prefix + "end\n";
}
}
return ret;
}
idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject, idSWFStack& stack, idSWFBitStream& bitstream, const char* filename, int characterID, int actionID )
{ {
static int callstackLevel = -1; static int callstackLevel = -1;
idSWFSpriteInstance* thisSprite = thisObject->GetSprite(); idSWFSpriteInstance* thisSprite = thisObject->GetSprite();
@ -1736,9 +1797,14 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
callstackLevel++; callstackLevel++;
idStr actionScript; // idStr actionScript;
actionBlocks.Clear();
currentBlock = &actionBlocks.Alloc();
currentBlock->line = va( "function sprite%i_action%i()", characterID, actionID );
//idStr line; //int indentLevel = 0;
//idStr indent;
while( bitstream.Tell() < bitstream.Length() ) while( bitstream.Tell() < bitstream.Length() )
{ {
@ -1754,9 +1820,11 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
// stack[0] is always 0 so don't read it // stack[0] is always 0 so don't read it
//if( swf_debug.GetInteger() >= 4 ) //if( swf_debug.GetInteger() >= 4 )
{ {
//idLib::Printf( "%s.Sprite%i script:\n%s\n", filename, characterID, actionScript.c_str() );
for( int i = stack.Num() - 1; i >= 0 ; i-- ) 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() ); idLib::Printf( "%s.Sprite%i %c: %s (%s)\n", filename, characterID, ( char )( 64 + stack.Num() - i ), stack[i].ToString().c_str(), stack[i].TypeOf() );
} }
#if 0 #if 0
@ -1770,45 +1838,33 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
#endif #endif
} }
idLib::Printf( "SWF%d: code %s\n", callstackLevel, GetSwfActionName( code ) ); idLib::Printf( "%s.Sprite%i SWF%d: code %s\n", filename, characterID, callstackLevel, GetSwfActionName( code ) );
} }
switch( code ) switch( code )
{ {
case Action_Return: case Action_Return:
callstackLevel--; callstackLevel--;
actionScript += "return " + stack.A().ToString() + "\n"; AddLine( "return " + stack.A().ToString() );
return actionScript; goto finish;
case Action_End: case Action_End:
QuitCurrentBlock();
//actionScript += indent + "end\n";
callstackLevel--; callstackLevel--;
return actionScript; goto finish;
case Action_NextFrame: case Action_NextFrame:
//if( verify( currentTarget != NULL ) ) AddLine( "nextFrame()" );
//{
// currentTarget->NextFrame();
//}
actionScript += "nextFrame();\n";
break; break;
case Action_PrevFrame: case Action_PrevFrame:
//if( verify( currentTarget != NULL ) ) AddLine( "prevFrame()" );
//{
// currentTarget->PrevFrame();
//}
actionScript += "prevFrame();\n";
break; break;
case Action_Play: case Action_Play:
//if( verify( currentTarget != NULL ) ) AddLine( "play()" );
//{
// currentTarget->Play();
//}
actionScript += "play();\n";
break; break;
case Action_Stop: case Action_Stop:
//if( verify( currentTarget != NULL ) ) AddLine( "stop()" );
//{
// currentTarget->Stop();
//}
actionScript += "stop();\n";
break; break;
case Action_ToggleQuality: case Action_ToggleQuality:
break; break;
@ -1819,33 +1875,19 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
assert( recordLength == 2 ); assert( recordLength == 2 );
int frameNum = bitstream.ReadU16() + 1; int frameNum = bitstream.ReadU16() + 1;
actionScript += va( "gotoAndPlay( %i );\n", frameNum ); AddLine( va( "gotoAndPlay( %i )", frameNum ) );
break; break;
} }
case Action_SetTarget: case Action_SetTarget:
{ {
const char* targetName = ( const char* )bitstream.ReadData( recordLength ); const char* targetName = ( const char* )bitstream.ReadData( recordLength );
if( verify( thisSprite != NULL ) ) AddLine( va( "setTarget( \"%s\" )", targetName ) );
{
currentTarget = thisSprite->ResolveTarget( targetName );
}
else if( swf_debug.GetInteger() > 0 )
{
idLib::Printf( "SWF: no target movie clip for setTarget %s\n", targetName );
}
break; break;
} }
case Action_GoToLabel: case Action_GoToLabel:
{ {
const char* targetName = ( const char* )bitstream.ReadData( recordLength ); const char* targetName = ( const char* )bitstream.ReadData( recordLength );
if( verify( currentTarget != NULL ) ) AddLine( va( "gotoLabel( \"%s\" )", targetName ) );
{
currentTarget->RunTo( currentTarget->FindFrame( targetName ) );
}
else if( swf_debug.GetInteger() > 0 )
{
idLib::Printf( "SWF: no target movie clip for runTo %s\n", targetName );
}
break; break;
} }
case Action_Push: case Action_Push:
@ -1891,75 +1933,83 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
break; break;
} }
case Action_Pop: case Action_Pop:
{
if( stack.A().IsString() ) if( stack.A().IsString() || stack.A().IsResult() )
{ {
actionScript += stack.A().ToString() + ";\n"; AddLine( stack.A().ToString() );
//line.Empty(); //line.Empty();
} }
if( stack.A().IsNumeric() )
{
QuitCurrentBlock();
//*block += indent + "end\n";
}
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
}
case Action_Add: case Action_Add:
//stack.B().SetFloat( stack.B().ToFloat() + stack.A().ToFloat() ); //stack.B().SetFloat( stack.B().ToFloat() + stack.A().ToFloat() );
stack.B().SetString( va( "%s + %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) ); stack.B().SetResult( va( "%s + %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
case Action_Subtract: case Action_Subtract:
//stack.B().SetFloat( stack.B().ToFloat() - stack.A().ToFloat() ); //stack.B().SetFloat( stack.B().ToFloat() - stack.A().ToFloat() );
stack.B().SetString( va( "%s - %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) ); stack.B().SetResult( va( "%s - %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
case Action_Multiply: case Action_Multiply:
//stack.B().SetFloat( stack.B().ToFloat() * stack.A().ToFloat() ); //stack.B().SetFloat( stack.B().ToFloat() * stack.A().ToFloat() );
stack.B().SetString( va( "%s * %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) ); stack.B().SetResult( va( "%s * %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
case Action_Divide: case Action_Divide:
//stack.B().SetFloat( stack.B().ToFloat() / stack.A().ToFloat() ); //stack.B().SetFloat( stack.B().ToFloat() / stack.A().ToFloat() );
stack.B().SetString( va( "%s == %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) ); stack.B().SetResult( va( "%s == %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
case Action_Equals: case Action_Equals:
//stack.B().SetBool( stack.B().ToFloat() == stack.A().ToFloat() ); //stack.B().SetBool( stack.B().ToFloat() == stack.A().ToFloat() );
stack.B().SetString( va( "%s == %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) ); stack.B().SetResult( va( "%s == %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
case Action_Less: case Action_Less:
//stack.B().SetBool( stack.B().ToFloat() < stack.A().ToFloat() ); //stack.B().SetBool( stack.B().ToFloat() < stack.A().ToFloat() );
stack.B().SetString( va( "%s < %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) ); stack.B().SetResult( va( "%s < %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
case Action_And: case Action_And:
//stack.B().SetBool( stack.B().ToBool() && stack.A().ToBool() ); //stack.B().SetBool( stack.B().ToBool() && stack.A().ToBool() );
stack.B().SetString( va( "%s && %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) ); stack.B().SetResult( va( "%s && %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
case Action_Or: case Action_Or:
//stack.B().SetBool( stack.B().ToBool() || stack.A().ToBool() ); //stack.B().SetBool( stack.B().ToBool() || stack.A().ToBool() );
stack.B().SetString( va( "%s || %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) ); stack.B().SetResult( va( "%s || %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
case Action_Not: case Action_Not:
//stack.A().SetBool( !stack.A().ToBool() ); //stack.A().SetBool( !stack.A().ToBool() );
stack.A().SetString( va( "!( %s )", stack.A().ToString().c_str() ) ); stack.A().SetResult( va( "!( %s )", stack.A().ToString().c_str() ) );
break; break;
case Action_StringEquals: case Action_StringEquals:
//stack.B().SetBool( stack.B().ToString() == stack.A().ToString() ); //stack.B().SetBool( stack.B().ToString() == stack.A().ToString() );
stack.B().SetString( va( "%s == %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) ); stack.B().SetResult( va( "%s == %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
case Action_StringLength: case Action_StringLength:
//stack.A().SetInteger( stack.A().ToString().Length() ); //stack.A().SetInteger( stack.A().ToString().Length() );
stack.A().SetString( va( "%s:len()", stack.A().ToString().c_str() ) ); stack.A().SetResult( va( "%s:len()", stack.A().ToString().c_str() ) );
break; break;
case Action_StringAdd: case Action_StringAdd:
//stack.B().SetString( stack.B().ToString() + stack.A().ToString() ); //stack.B().SetString( stack.B().ToString() + stack.A().ToString() );
stack.B().SetString( stack.B().ToString() + stack.A().ToString() ); stack.B().SetResult( stack.B().ToString() + stack.A().ToString() );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
case Action_StringExtract: case Action_StringExtract:
stack.C().SetString( stack.C().ToString().Mid( stack.B().ToInteger(), stack.A().ToInteger() ) ); stack.C().SetResult( stack.C().ToString().Mid( stack.B().ToInteger(), stack.A().ToInteger() ) );
stack.Pop( 2 ); stack.Pop( 2 );
break; break;
case Action_StringLess: case Action_StringLess:
@ -1980,20 +2030,22 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
stack.A().SetString( va( "%c", stack.A().ToInteger() ) ); stack.A().SetString( va( "%c", stack.A().ToInteger() ) );
break; break;
case Action_Jump: case Action_Jump:
bitstream.Seek( bitstream.ReadS16() ); // RB: do not jump and continue translating to Lua or ActionScript
bitstream.ReadS16();
actionScript += "\n--FIXME Action_Jump not implemented"; //bitstream.Seek( bitstream.ReadS16() );
return actionScript;
QuitCurrentBlock();
break; break;
case Action_If: case Action_If:
{ {
actionScript += va( "if( %s )\n{\n", stack.A().ToString().c_str() ) ; AddBlock( va( "if( %s ) then\n", stack.A().ToString().c_str() ) );
int16 offset = bitstream.ReadS16(); int16 offset = bitstream.ReadS16();
if( stack.A().ToBool() ) //if( stack.A().ToBool() )
{ //{
bitstream.Seek( offset ); // bitstream.Seek( offset );
} //}
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
} }
@ -2026,6 +2078,7 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
case Action_SetVariable: case Action_SetVariable:
{ {
idStr variableName = stack.B().ToString(); idStr variableName = stack.B().ToString();
/*
bool found = false; bool found = false;
for( int i = scope.Num() - 1; i >= 0; i-- ) for( int i = scope.Num() - 1; i >= 0; i-- )
{ {
@ -2040,6 +2093,17 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
{ {
thisObject->Set( variableName, stack.A() ); thisObject->Set( variableName, stack.A() );
} }
*/
if( stack.A().IsString() )
{
AddLine( va( "%s = \"%s\"\n", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
}
else
{
AddLine( va( "%s = %s\n", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
}
stack.Pop( 2 ); stack.Pop( 2 );
break; break;
} }
@ -2053,6 +2117,7 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
frameNum += bitstream.ReadU16(); frameNum += bitstream.ReadU16();
} }
/*
if( verify( thisSprite != NULL ) ) if( verify( thisSprite != NULL ) )
{ {
if( stack.A().IsString() ) if( stack.A().IsString() )
@ -2084,6 +2149,18 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
idLib::Printf( "SWF: no target movie clip for gotoAndStop\n" ); idLib::Printf( "SWF: no target movie clip for gotoAndStop\n" );
} }
} }
*/
if( ( flags & 1 ) != 0 )
{
AddLine( va( "gotoAndPlay( %i )", frameNum ) );
}
else
{
AddLine( va( "gotoAndStop( %i )", frameNum ) );
}
AddLine( va( "gotoAndPlay( %i )", frameNum ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
} }
@ -2116,7 +2193,14 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
break; break;
} }
case Action_Trace: case Action_Trace:
idLib::PrintfIf( swf_debug.GetInteger() > 0, "SWF Trace: %s\n", stack.A().ToString().c_str() ); if( stack.A().IsString() )
{
AddLine( va( "trace( \"%s\" )\n", stack.A().ToString().c_str() ) );
}
else
{
AddLine( va( "trace( %s )\n", stack.A().ToString().c_str() ) );
}
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
case Action_GetTime: case Action_GetTime:
@ -2173,7 +2257,7 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
{ {
idLib::PrintfIf( swf_debug.GetInteger() > 0, "SWF: unknown function %s\n", functionName.c_str() ); idLib::PrintfIf( swf_debug.GetInteger() > 0, "SWF: unknown function %s\n", functionName.c_str() );
stack.Alloc().SetString( line ); stack.Alloc().SetResult( line );
} }
break; break;
@ -2233,7 +2317,7 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
} }
else else
{ {
stack.Alloc().SetString( line ); stack.Alloc().SetResult( line );
} }
//line.Empty(); //line.Empty();
@ -2258,15 +2342,46 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
newFunction->SetConstants( constants ); newFunction->SetConstants( constants );
newFunction->SetDefaultSprite( defaultSprite ); newFunction->SetDefaultSprite( defaultSprite );
idStr line;
if( functionName.IsEmpty() )
{
line = "function( ";
}
else
{
line = va( "function %( ", functionName.c_str() );
}
uint16 numParms = bitstream.ReadU16(); uint16 numParms = bitstream.ReadU16();
newFunction->AllocParameters( numParms ); newFunction->AllocParameters( numParms );
for( int i = 0; i < numParms; i++ ) for( int i = 0; i < numParms; i++ )
{ {
newFunction->SetParameter( i, 0, bitstream.ReadString() ); const char* parm = bitstream.ReadString();
if( stack.A().IsString() )
{
line += va( "\"%s\"%s", parm, ( i < ( numParms - 1 ) ) ? ", " : " " );
}
else
{
line += va( "%s%s", parm, ( i < ( numParms - 1 ) ) ? ", " : " " );
}
newFunction->SetParameter( i, 0, parm );
} }
line += ")";
uint16 codeSize = bitstream.ReadU16(); uint16 codeSize = bitstream.ReadU16();
newFunction->SetData( bitstream.ReadData( codeSize ), codeSize ); newFunction->SetData( bitstream.ReadData( codeSize ), codeSize );
if( functionName.IsEmpty() )
{
stack.Alloc().SetResult( line );
}
AddBlock( line );
/*
if( functionName.IsEmpty() ) if( functionName.IsEmpty() )
{ {
stack.Alloc().SetFunction( newFunction ); stack.Alloc().SetFunction( newFunction );
@ -2275,6 +2390,7 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
{ {
thisObject->Set( functionName, idSWFScriptVar( newFunction ) ); thisObject->Set( functionName, idSWFScriptVar( newFunction ) );
} }
*/
newFunction->Release(); newFunction->Release();
break; break;
} }
@ -2302,6 +2418,16 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
newFunction->AllocRegisters( numRegs ); newFunction->AllocRegisters( numRegs );
newFunction->SetFlags( flags ); newFunction->SetFlags( flags );
idStr line;
if( functionName.IsEmpty() )
{
line = "function( ";
}
else
{
line = va( "function %( ", functionName.c_str() );
}
for( int i = 0; i < numParms; i++ ) for( int i = 0; i < numParms; i++ )
{ {
uint8 reg = bitstream.ReadU8(); uint8 reg = bitstream.ReadU8();
@ -2312,11 +2438,29 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
reg = 0; reg = 0;
} }
newFunction->SetParameter( i, reg, name ); newFunction->SetParameter( i, reg, name );
if( stack.A().IsString() )
{
line += va( "\"%s\"%s", name, ( i < ( numParms - 1 ) ) ? ", " : " " );
}
else
{
line += va( "%s%s", name, ( i < ( numParms - 1 ) ) ? ", " : " " );
}
} }
line += ")";
if( functionName.IsEmpty() )
{
stack.Alloc().SetResult( line );
}
AddBlock( line );
uint16 codeSize = bitstream.ReadU16(); uint16 codeSize = bitstream.ReadU16();
newFunction->SetData( bitstream.ReadData( codeSize ), codeSize ); newFunction->SetData( bitstream.ReadData( codeSize ), codeSize );
/*
if( functionName.IsEmpty() ) if( functionName.IsEmpty() )
{ {
stack.Alloc().SetFunction( newFunction ); stack.Alloc().SetFunction( newFunction );
@ -2325,6 +2469,8 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
{ {
thisObject->Set( functionName, idSWFScriptVar( newFunction ) ); thisObject->Set( functionName, idSWFScriptVar( newFunction ) );
} }
*/
newFunction->Release(); newFunction->Release();
break; break;
} }
@ -2378,7 +2524,7 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
case Action_Equals2: case Action_Equals2:
{ {
//stack.B().SetBool( stack.A().AbstractEquals( stack.B() ) ); //stack.B().SetBool( stack.A().AbstractEquals( stack.B() ) );
stack.B().SetString( va( "%s == %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) ); stack.B().SetResult( va( "%s == %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
@ -2386,7 +2532,7 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
case Action_StrictEquals: case Action_StrictEquals:
{ {
//stack.B().SetBool( stack.A().StrictEquals( stack.B() ) ); //stack.B().SetBool( stack.A().StrictEquals( stack.B() ) );
stack.B().SetString( va( "%s == %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) ); stack.B().SetResult( va( "%s == %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
@ -2471,7 +2617,20 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
//actionScript += line; //actionScript += line;
//line.Empty(); //line.Empty();
stack.B().SetString( va( "%s.%s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) ); idStr& member = stack.A().ToString();
//if( stack.A().IsString() )
//{
// stack.B().SetResult( va( "%s[\"%s\"]", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
//}
//else
if( member.Find( ' ' ) > 0 || member.Find( '\"' ) > 0 )
{
stack.B().SetResult( va( "%s[%s]", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
}
else
{
stack.B().SetResult( va( "%s.%s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
}
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
@ -2489,7 +2648,15 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
//} //}
//else //else
actionScript += va( "%s.%s = %s;\n", stack.C().ToString().c_str(), stack.B().ToString().c_str(), stack.A().ToString().c_str() ); if( stack.A().IsString() )
{
AddLine( va( "%s.%s = \"%s\"\n", stack.C().ToString().c_str(), stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
}
else
{
AddLine( va( "%s.%s = %s\n", stack.C().ToString().c_str(), stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
}
} }
stack.Pop( 3 ); stack.Pop( 3 );
break; break;
@ -2652,49 +2819,75 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
break; break;
} }
case Action_ToNumber: case Action_ToNumber:
stack.A().SetFloat( stack.A().ToFloat() ); if( stack.A().IsString() )
break;
case Action_ToString:
stack.A().SetString( stack.A().ToString() );
break;
case Action_TypeOf:
stack.A().SetString( stack.A().TypeOf() );
break;
case Action_Add2:
{
if( stack.A().IsString() || stack.B().IsString() )
{ {
stack.B().SetString( stack.B().ToString() + stack.A().ToString() ); stack.A().SetResult( va( "tonumber( \"%s\" )", stack.A().ToString().c_str() ) );
} }
else else
{ {
stack.B().SetFloat( stack.B().ToFloat() + stack.A().ToFloat() ); stack.A().SetResult( va( "tonumber( %s )", stack.A().ToString().c_str() ) );
}
break;
case Action_ToString:
stack.A().SetResult( va( "tostring( %s )", stack.A().ToString().c_str() ) );
break;
case Action_TypeOf:
if( stack.A().IsString() )
{
stack.A().SetResult( va( "type( \"%s\" )", stack.A().ToString().c_str() ) );
}
else
{
stack.A().SetResult( va( "type( %s )", stack.A().ToString().c_str() ) );
}
break;
case Action_Add2:
{
if( stack.B().IsString() && stack.A().IsString() )
{
stack.B().SetResult( va( "\"%s\" .. \"%s\"", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
}
else if( stack.B().IsString() && !stack.A().IsString() )
{
stack.B().SetResult( va( "\"%s\" + %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
}
else if( !stack.B().IsString() && stack.A().IsString() )
{
stack.B().SetResult( va( "%s + \"%s\"", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
}
else
{
stack.B().SetResult( va( "%s + %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
} }
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
} }
case Action_Less2: case Action_Less2:
{ {
/*
if( stack.A().IsString() && stack.B().IsString() ) if( stack.A().IsString() && stack.B().IsString() )
{ {
stack.B().SetBool( stack.B().ToString() < stack.A().ToString() ); stack.B().SetString( va( "%s < %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
} }
else else
*/
{ {
stack.B().SetBool( stack.B().ToFloat() < stack.A().ToFloat() ); stack.B().SetResult( va( "%s < %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
} }
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
} }
case Action_Greater: case Action_Greater:
{ {
/*
if( stack.A().IsString() && stack.B().IsString() ) if( stack.A().IsString() && stack.B().IsString() )
{ {
stack.B().SetBool( stack.B().ToString() > stack.A().ToString() ); stack.B().SetBool( stack.B().ToString() > stack.A().ToString() );
} }
else else
*/
{ {
stack.B().SetBool( stack.B().ToFloat() > stack.A().ToFloat() ); stack.B().SetResult( va( "%s > %s", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
} }
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
@ -2739,11 +2932,21 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
case Action_Decrement: case Action_Decrement:
stack.A().SetFloat( stack.A().ToFloat() - 1.0f ); {
//stack.A().SetFloat( stack.A().ToFloat() - 1.0f );
const char* a = stack.A().ToString().c_str();
stack.A().SetResult( va( "%s - 1", a ) );
break; break;
}
case Action_Increment: case Action_Increment:
stack.A().SetFloat( stack.A().ToFloat() + 1.0f ); {
//stack.A().SetFloat( stack.A().ToFloat() + 1.0f );
const char* a = stack.A().ToString().c_str();
stack.A().SetResult( va( "%s + 1", a ) );
break; break;
}
case Action_PushDuplicate: case Action_PushDuplicate:
{ {
idSWFScriptVar dup = stack.A(); idSWFScriptVar dup = stack.A();
@ -2766,12 +2969,25 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
case Action_DefineLocal: case Action_DefineLocal:
{ {
scope[scope.Num() - 1]->Set( stack.B().ToString(), stack.A() ); scope[scope.Num() - 1]->Set( stack.B().ToString(), stack.A() );
if( stack.A().IsString() )
{
AddLine( va( "local %s = \"%s\"\n", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
}
else
{
AddLine( va( "local %s = %s\n", stack.B().ToString().c_str(), stack.A().ToString().c_str() ) );
}
stack.Pop( 2 ); stack.Pop( 2 );
break; break;
} }
case Action_DefineLocal2: case Action_DefineLocal2:
{ {
scope[scope.Num() - 1]->Set( stack.A().ToString(), idSWFScriptVar() ); scope[scope.Num() - 1]->Set( stack.A().ToString(), idSWFScriptVar() );
AddLine( va( "local %s = {}\n", stack.A().ToString().c_str() ) );
stack.Pop( 1 ); stack.Pop( 1 );
break; break;
} }
@ -2806,12 +3022,19 @@ idStr idSWFScriptFunction_Script::ExportToScript( idSWFScriptObject* thisObject,
// We have to abort here because the rest of the script is basically meaningless now // We have to abort here because the rest of the script is basically meaningless now
assert( false ); assert( false );
callstackLevel--; callstackLevel--;
return actionScript; goto finish;
} }
} }
callstackLevel--; callstackLevel--;
finish:
idStr actionScript = BuildActionCode( actionBlocks, 0 );
idLib::Printf( "%s.Sprite%i script:\n%s\n", filename, characterID, actionScript.c_str() );
return actionScript; return actionScript;
} }
// RB end
/* /*
======================== ========================

View file

@ -253,11 +253,30 @@ public:
virtual idSWFScriptVar Call( idSWFScriptObject* thisObject, const idSWFParmList& parms ); virtual idSWFScriptVar Call( idSWFScriptObject* thisObject, const idSWFParmList& parms );
// RB begin // RB begin
idStr CallToScript( idSWFScriptObject* thisObject, const idSWFParmList& parms ); idStr CallToScript( idSWFScriptObject* thisObject, const idSWFParmList& parms, const char* filename, int characterID, int actionID );
private: private:
idSWFScriptVar Run( idSWFScriptObject* thisObject, idSWFStack& stack, idSWFBitStream& bitstream ); idSWFScriptVar Run( idSWFScriptObject* thisObject, idSWFStack& stack, idSWFBitStream& bitstream );
idStr ExportToScript( idSWFScriptObject* thisObject, idSWFStack& stack, idSWFBitStream& bitstream );
struct ActionBlock
{
ActionBlock* parent = NULL;
idStr line;
idList<ActionBlock> blocks;
};
idList<ActionBlock> actionBlocks;
ActionBlock* currentBlock;
idStr UpdateIndent( int indentLevel ) const;
void AddLine( const idStr& line );
void AddBlock( const idStr& line );
void QuitCurrentBlock();
idStr BuildActionCode( const idList<ActionBlock>& blocks, int level );
idStr ExportToScript( idSWFScriptObject* thisObject, idSWFStack& stack, idSWFBitStream& bitstream, const char* filename, int characterID, int actionID );
// RB end // RB end
private: private:

View file

@ -292,7 +292,11 @@ idStr idSWFScriptVar::ToString() const
return idStrId( value.i ).GetLocalizedString(); return idStrId( value.i ).GetLocalizedString();
case SWF_VAR_STRING: case SWF_VAR_STRING:
return *value.string; return *value.string;
// RB begin
case SWF_VAR_RESULT:
return *value.string;
// RB end
case SWF_VAR_FLOAT: case SWF_VAR_FLOAT:
return va( "%g", value.f ); return va( "%g", value.f );
case SWF_VAR_BOOL: case SWF_VAR_BOOL:
@ -521,7 +525,11 @@ const char* idSWFScriptVar::TypeOf() const
return "stringid"; return "stringid";
case SWF_VAR_STRING: case SWF_VAR_STRING:
return "string"; return "string";
// RB begin
case SWF_VAR_RESULT:
return "result";
// RB end
case SWF_VAR_FLOAT: case SWF_VAR_FLOAT:
return "number"; return "number";
case SWF_VAR_BOOL: case SWF_VAR_BOOL:

View file

@ -138,6 +138,22 @@ public:
value.string = s; value.string = s;
s->AddRef(); s->AddRef();
} }
// RB begin
void SetResult( const idStr& s )
{
Free();
type = SWF_VAR_RESULT;
value.string = idSWFScriptString::Alloc( s );
}
void SetResult( const char* s )
{
Free();
type = SWF_VAR_RESULT;
value.string = idSWFScriptString::Alloc( s );
}
// RB end
void SetFloat( float f ) void SetFloat( float f )
{ {
Free(); Free();
@ -232,6 +248,11 @@ public:
return ( type == SWF_VAR_FLOAT ) || ( type == SWF_VAR_INTEGER ) || ( type == SWF_VAR_BOOL ); return ( type == SWF_VAR_FLOAT ) || ( type == SWF_VAR_INTEGER ) || ( type == SWF_VAR_BOOL );
} }
bool IsResult() const
{
return ( type == SWF_VAR_RESULT );
}
enum swfScriptVarType enum swfScriptVarType
{ {
SWF_VAR_STRINGID, SWF_VAR_STRINGID,
@ -242,7 +263,8 @@ public:
SWF_VAR_BOOL, SWF_VAR_BOOL,
SWF_VAR_INTEGER, SWF_VAR_INTEGER,
SWF_VAR_FUNCTION, SWF_VAR_FUNCTION,
SWF_VAR_OBJECT SWF_VAR_OBJECT,
SWF_VAR_RESULT // RB: for P-Code to Lua
}; };
swfScriptVarType GetType() const swfScriptVarType GetType() const

View file

@ -296,7 +296,7 @@ void idSWFSprite::Write( idFile* f )
idSWFSprite::WriteXML idSWFSprite::WriteXML
======================== ========================
*/ */
void idSWFSprite::WriteXML( idFile* f, const char* indentPrefix, int characterID ) void idSWFSprite::WriteXML( idFile* f, int characterID, const char* indentPrefix )
{ {
if( characterID >= 0 ) if( characterID >= 0 )
{ {
@ -344,7 +344,7 @@ void idSWFSprite::WriteXML( idFile* f, const char* indentPrefix, int characterID
// WriteXML_PlaceObject2( command.stream, indentPrefix ); // WriteXML_PlaceObject2( command.stream, indentPrefix );
// break; // break;
#define HANDLE_SWF_TAG( x ) case Tag_##x: WriteXML_##x( f, command.stream, indentPrefix ); break; #define HANDLE_SWF_TAG( x ) case Tag_##x: WriteXML_##x( f, command.stream, characterID, i, indentPrefix ); break;
HANDLE_SWF_TAG( PlaceObject2 ); HANDLE_SWF_TAG( PlaceObject2 );
HANDLE_SWF_TAG( PlaceObject3 ); HANDLE_SWF_TAG( PlaceObject3 );
HANDLE_SWF_TAG( RemoveObject2 ); HANDLE_SWF_TAG( RemoveObject2 );
@ -375,7 +375,7 @@ void idSWFSprite::WriteXML( idFile* f, const char* indentPrefix, int characterID
// RB end // RB end
======= =======
void idSWFSprite::WriteXML_PlaceObject2( idFile* file, idSWFBitStream& bitstream, const char* indentPrefix ) void idSWFSprite::WriteXML_PlaceObject2( idFile* file, idSWFBitStream& bitstream, int sourceCharacterID, int commandID, const char* indentPrefix )
{ {
uint64 flags = bitstream.ReadU8(); uint64 flags = bitstream.ReadU8();
int depth = bitstream.ReadU16(); int depth = bitstream.ReadU16();
@ -454,7 +454,7 @@ void idSWFSprite::WriteXML_PlaceObject2( idFile* file, idSWFBitStream& bitstream
} }
void idSWFSprite::WriteXML_PlaceObject3( idFile* file, idSWFBitStream& bitstream, const char* indentPrefix ) void idSWFSprite::WriteXML_PlaceObject3( idFile* file, idSWFBitStream& bitstream, int sourceCharacterID, int commandID, const char* indentPrefix )
{ {
uint64 flags1 = bitstream.ReadU8(); uint64 flags1 = bitstream.ReadU8();
uint64 flags2 = bitstream.ReadU8(); uint64 flags2 = bitstream.ReadU8();
@ -548,14 +548,14 @@ void idSWFSprite::WriteXML_PlaceObject3( idFile* file, idSWFBitStream& bitstream
file->WriteFloatString( "%s\t</PlaceObject3>\n", indentPrefix ); file->WriteFloatString( "%s\t</PlaceObject3>\n", indentPrefix );
} }
void idSWFSprite::WriteXML_RemoveObject2( idFile* file, idSWFBitStream& bitstream, const char* indentPrefix ) void idSWFSprite::WriteXML_RemoveObject2( idFile* file, idSWFBitStream& bitstream, int sourceCharacterID, int commandID, const char* indentPrefix )
{ {
int depth = bitstream.ReadU16(); int depth = bitstream.ReadU16();
file->WriteFloatString( "%s\t<RemoveObject2 depth=\"%i\"/>\n", indentPrefix, depth ); file->WriteFloatString( "%s\t<RemoveObject2 depth=\"%i\"/>\n", indentPrefix, depth );
} }
void idSWFSprite::WriteXML_DoAction( idFile* file, idSWFBitStream& bitstream, const char* indentPrefix ) void idSWFSprite::WriteXML_DoAction( idFile* file, idSWFBitStream& bitstream, int characterID, int commandID, const char* indentPrefix )
{ {
idBase64 base64; idBase64 base64;
@ -574,11 +574,11 @@ void idSWFSprite::WriteXML_DoAction( idFile* file, idSWFBitStream& bitstream, co
// actionScript->SetDefaultSprite( this ); // actionScript->SetDefaultSprite( this );
actionScript->SetData( bitstream.Ptr(), bitstream.Length() ); actionScript->SetData( bitstream.Ptr(), bitstream.Length() );
idStr scriptText = actionScript->CallToScript( scriptObject, idSWFParmList() ); idStr scriptText = actionScript->CallToScript( scriptObject, idSWFParmList(), file->GetName(), characterID, commandID );
//file->WriteFloatString( "%s\t<DoAction streamLength=\"%i\">%s</DoAction>\n", indentPrefix, bitstream.Length(), base64.c_str() ); //file->WriteFloatString( "%s\t<DoAction streamLength=\"%i\">%s</DoAction>\n", indentPrefix, bitstream.Length(), base64.c_str() );
file->WriteFloatString( "%s\t<DoAction streamLength=\"%i\">\n%s\t\t%s\n%s\t</DoAction>\n", indentPrefix, bitstream.Length(), indentPrefix, scriptText.c_str(), indentPrefix ); file->WriteFloatString( "%s\t<DoAction streamLength=\"%i\">\n%s%s\t</DoAction>\n", indentPrefix, bitstream.Length(), scriptText.c_str(), indentPrefix );
delete actionScript; delete actionScript;
delete scriptObject; delete scriptObject;

View file

@ -48,13 +48,13 @@ public:
void Write( idFile* f ); void Write( idFile* f );
// RB begin // RB begin
void WriteXML( idFile* f, const char* indentPrefix = "", int characterID = -1 ); void WriteXML( idFile* f, int characterID, const char* indentPrefix = "" );
void WriteXML_PlaceObject2( idFile* f, idSWFBitStream& bitstream, const char* indentPrefix = "" ); void WriteXML_PlaceObject2( idFile* f, idSWFBitStream& bitstream, int characterID, int commandID, const char* indentPrefix = "" );
void WriteXML_PlaceObject3( idFile* f, idSWFBitStream& bitstream, const char* indentPrefix = "" ); void WriteXML_PlaceObject3( idFile* f, idSWFBitStream& bitstream, int characterID, int commandID, const char* indentPrefix = "" );
void WriteXML_RemoveObject2( idFile* f, idSWFBitStream& bitstream, const char* indentPrefix = "" ); void WriteXML_RemoveObject2( idFile* f, idSWFBitStream& bitstream, int characterID, int commandID, const char* indentPrefix = "" );
void WriteXML_DoAction( idFile* f, idSWFBitStream& bitstream, const char* indentPrefix = "" ); void WriteXML_DoAction( idFile* f, idSWFBitStream& bitstream, int characterID, int commandID, const char* indentPrefix = "" );
void WriteSWF( idFile_SWF& f, int characterID = -1 ); void WriteSWF( idFile_SWF& f, int characterID );
uint16 GetFrameCount() uint16 GetFrameCount()
{ {