Skip to content

Commit

Permalink
Merge pull request magicalhobo#44 from alucas/push_definebutton2
Browse files Browse the repository at this point in the history
Add DefineButtonTag and DefineButton2Tag.
  • Loading branch information
Sean Fujiwara committed Aug 15, 2013
2 parents 186d307 + bc66089 commit fe2bce9
Show file tree
Hide file tree
Showing 12 changed files with 323 additions and 84 deletions.
1 change: 1 addition & 0 deletions SWFWireDecompiler/.flexLibProperties
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@
<classEntry path="com.swfwire.decompiler.abc.ABCInstructionWriter"/>
<classEntry path="com.swfwire.decompiler.abc.ABCWriterContext"/>
<classEntry path="com.swfwire.decompiler.abc.ABCWriterMetadata"/>
<classEntry path="com.swfwire.decompiler.data.swf3.records.BlendModeRecord"/>
</includeClasses>
<includeResources/>
<namespaceManifests/>
Expand Down
120 changes: 72 additions & 48 deletions SWFWireDecompiler/src/com/swfwire/decompiler/SWF3Reader.as
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package com.swfwire.decompiler
import com.swfwire.decompiler.data.swf.tags.EndTag;
import com.swfwire.decompiler.data.swf.tags.SWFTag;
import com.swfwire.decompiler.data.swf2.records.FillStyleArrayRecord2;
import com.swfwire.decompiler.data.swf3.actions.ButtonCondAction;
import com.swfwire.decompiler.data.swf3.records.*;
import com.swfwire.decompiler.data.swf3.tags.*;

Expand Down Expand Up @@ -38,9 +39,6 @@ package com.swfwire.decompiler
case 45: tag = readSoundStreamHead2Tag(context, header);
case 46: tag = readDefineMorphShapeTag(context, header);
case 48: tag = readDefineFont2Tag(context, header);
case 34:
tag = readDefineButton2Tag(context, header);
break;
*/
case 12:
tag = readDoActionTag(context, header);
Expand All @@ -51,6 +49,9 @@ package com.swfwire.decompiler
case 32:
tag = readDefineShape3Tag(context, header);
break;
case 34:
tag = readDefineButton2Tag(context, header);
break;
case 35:
tag = readDefineBitsJPEG3Tag(context, header);
break;
Expand Down Expand Up @@ -339,60 +340,49 @@ package com.swfwire.decompiler
tag.buttonId = context.bytes.readUI16();
tag.reserved = context.bytes.readUB(7);
tag.trackAsMenu = context.bytes.readFlag();
var actionOffsetPosition:uint = context.bytes.getBytePosition();
tag.actionOffset = context.bytes.readUI16();
tag.characters = new Vector.<ButtonRecord2>();
while(true)
do
{
var reserved:uint = context.bytes.readUB(2);
var hasBlendMode:Boolean = context.bytes.readFlag();
var hasFilterList:Boolean = context.bytes.readFlag();
var stateHitTest:Boolean = context.bytes.readFlag();
var stateDown:Boolean = context.bytes.readFlag();
var stateOver:Boolean = context.bytes.readFlag();
var stateUp:Boolean = context.bytes.readFlag();
if(reserved == 0 &&
!hasBlendMode &&
!hasFilterList &&
!stateHitTest &&
!stateDown &&
!stateOver &&
!stateUp)
tag.characters.push(readButtonRecord2(context));
// Test if next byte is CharacterEndFlag
if (!context.bytes.readUI8())
{
break;
}
else
context.bytes.unreadBytes(1);
}
while(true);
tag.actions = new Vector.<ButtonCondAction>();
if (tag.actionOffset == 0)
{
return tag;
}
if ((actionOffsetPosition + tag.actionOffset) != context.bytes.getBytePosition())
{
throw new Error("Wrong ActionOffset value: " + tag.actionOffset + " instead of " + (context.bytes.getBytePosition() - actionOffsetPosition));
}
do
{
var actionPosition:uint = context.bytes.getBytePosition();
var action:ButtonCondAction = readButtonCondAction(context);
tag.actions.push(action);
if (action.condActionSize && ((actionPosition + action.condActionSize) != context.bytes.getBytePosition()))
{
tag.characters.push(readButtonRecord2(context, reserved, hasBlendMode, hasFilterList,
stateHitTest, stateDown, stateOver, stateUp));
throw new Error("Wrong CondActionSize value: " + action.condActionSize + " instead of " + (context.bytes.getBytePosition() - actionPosition));
}
}
//tag.actions = readButtonCondAction();
while(action.condActionSize)
return tag;
}

protected function readButtonRecord2(context:SWFReaderContext, reserved:uint, hasBlendMode:Boolean, hasFilterList:Boolean,
stateHitTest:Boolean, stateDown:Boolean, stateOver:Boolean, stateUp:Boolean):ButtonRecord2
{
var record:ButtonRecord2 = new ButtonRecord2();
record.reserved = reserved;
record.hasBlendMode = hasBlendMode;
record.hasFilterList = hasFilterList;
record.stateHitTest = stateHitTest;
record.stateDown = stateDown;
record.stateOver = stateOver;
record.stateUp = stateUp;
record.characterId = context.bytes.readUI16();
record.placeDepth = context.bytes.readUI16();
record.placeMatrix = readMatrixRecord(context);
protected function readButtonRecord2(context:SWFReaderContext):ButtonRecord2
{
var record:ButtonRecord2 = new ButtonRecord2(readButtonRecord(context));
record.colorTransform = readCXFormWithAlphaRecord(context);
if(hasFilterList)
{
record.filterList = readFilterListRecord(context);
}
if(hasBlendMode)
{
record.blendMode = readBlendModeRecord(context);
}
record.filterList = readFilterListRecord(context);
record.blendMode = context.bytes.readUI8();
return record;
}

Expand All @@ -417,6 +407,7 @@ package com.swfwire.decompiler
case 0:
record.dropShadowFilter = readDropShadowFilterRecord(context);
break;
// TODO : Add others filters
}
return record;
}
Expand Down Expand Up @@ -447,11 +438,44 @@ package com.swfwire.decompiler
return record;
}

protected function readBlendModeRecord(context:SWFReaderContext):*
{
throw new Error('readBlendModeRecord not implemented');
protected function readButtonCondAction(context:SWFReaderContext):ButtonCondAction
{
var action:ButtonCondAction = new ButtonCondAction();
action.condActionSize = context.bytes.readUI16();
var size:uint = action.condActionSize - 2;
if (size > 0)
{
action.condIdleToOverDown = context.bytes.readFlag();
action.condOutDownToldle = context.bytes.readFlag();
action.condOutDownToOverDown = context.bytes.readFlag();
action.condOverDownToOutDown = context.bytes.readFlag();
action.condOverDownToOverUp = context.bytes.readFlag();
action.condOverUpToOverDown = context.bytes.readFlag();
action.condOverUpToIdle = context.bytes.readFlag();
action.condIdleToOverUp = context.bytes.readFlag();
size--;
}
if (size > 0)
{
action.condKeyPress = context.bytes.readUB(7);
action.condOverDownToIdle = context.bytes.readFlag();
size--;
}
while(size > 0)
{
var startPosition:uint = context.bytes.getBytePosition();
if (!context.bytes.readUI8())
{
size--;
break;
}
context.bytes.unreadBytes(1);
action.actions.push(readActionRecord(context));
size -= (context.bytes.getBytePosition() - startPosition);
}
return action;
}


protected function readDefineSpriteTag(context:SWFReaderContext, header:TagHeaderRecord):DefineSpriteTag
{
var tag:DefineSpriteTag = new DefineSpriteTag();
Expand Down
117 changes: 116 additions & 1 deletion SWFWireDecompiler/src/com/swfwire/decompiler/SWF3Writer.as
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package com.swfwire.decompiler
{
import com.swfwire.decompiler.data.swf.records.CurvedEdgeRecord;
import com.swfwire.decompiler.data.swf.records.DropShadowFilterRecord;
import com.swfwire.decompiler.data.swf.records.EndShapeRecord;
import com.swfwire.decompiler.data.swf.records.FilterListRecord;
import com.swfwire.decompiler.data.swf.records.FilterRecord;
import com.swfwire.decompiler.data.swf.records.IShapeRecord;
import com.swfwire.decompiler.data.swf.records.StraightEdgeRecord;
import com.swfwire.decompiler.data.swf.records.TagHeaderRecord;
import com.swfwire.decompiler.data.swf.tags.EndTag;
import com.swfwire.decompiler.data.swf.tags.SWFTag;
import com.swfwire.decompiler.data.swf3.actions.ButtonCondAction;
import com.swfwire.decompiler.data.swf3.records.*;
import com.swfwire.decompiler.data.swf3.tags.*;

import flash.utils.ByteArray;

public class SWF3Writer extends SWF2Writer
{
public static const TAG_IDS:Object = {
Expand Down Expand Up @@ -60,6 +64,9 @@ package com.swfwire.decompiler
case DefineBitsLossless2Tag:
writeDefineBitsLossless2Tag(context, DefineBitsLossless2Tag(tag));
break;
case DefineButton2Tag:
writeDefineButton2Tag(context, DefineButton2Tag(tag));
break;
default:
super.writeTag(context, tag);
break;
Expand Down Expand Up @@ -470,5 +477,113 @@ package com.swfwire.decompiler
writeGradientControlPointRecord2(context, record.gradientRecords[iter]);
}
}

protected function writeDefineButton2Tag(context:SWFWriterContext, tag:DefineButton2Tag):void
{
context.bytes.writeUI16(tag.buttonId);
context.bytes.writeUB(7, 0);
context.bytes.writeFlag(tag.trackAsMenu);
context.bytes.writeUI16(tag.actionOffset); // todo : set the right value
for each (var character:ButtonRecord2 in tag.characters)
{
writeButtonRecord2(context, character);
}
context.bytes.writeUI8(0);
var actionsLength:uint = tag.actions.length;
for (var actionIndex:uint = 0; actionIndex < actionsLength; actionIndex++)
{
writeButtonCondAction(context, tag.actions[actionIndex], (actionIndex == (actionsLength - 1)));
}
}

protected function writeButtonRecord2(context:SWFWriterContext, record:ButtonRecord2):void
{
writeButtonRecord(context, record);
writeCXFormWithAlphaRecord(context, record.colorTransform);
writeFilterListRecord(context, record.filterList);
context.bytes.writeUI8(record.blendMode);
}

protected function writeFilterListRecord(context:SWFWriterContext, record:FilterListRecord):void
{
context.bytes.writeUI8(record.filters.length);
for each (var filter:FilterRecord in record.filters)
{
writeFilterRecord(context, filter);
}
}

protected function writeFilterRecord(context:SWFWriterContext, record:FilterRecord):void
{
context.bytes.writeUI8(record.filterId);
switch(record.filterId)
{
case 0:
writeDropShadowFilterRecord(context, record.dropShadowFilter);
break;
// TODO : Add others filters
}
}

protected function writeDropShadowFilterRecord(context:SWFWriterContext, record:DropShadowFilterRecord):void
{
writeRGBARecord(context, record.color);
context.bytes.writeFixed16_16(record.blurX);
context.bytes.writeFixed16_16(record.blurY);
context.bytes.writeFixed16_16(record.angle);
context.bytes.writeFixed16_16(record.distance);
context.bytes.writeFixed8_8(record.strength);
context.bytes.writeFlag(record.innerShadow);
context.bytes.writeFlag(record.knockout);
context.bytes.writeFlag(record.compositeSource);
context.bytes.writeUB(5, record.passes);
}

protected function writeButtonCondAction(context:SWFWriterContext, action:ButtonCondAction, isLastRecord:Boolean):void
{
context.bytes.writeUI16(isLastRecord ? 0 : action.condActionSize);
var size:uint = action.condActionSize - 2;
if (size > 0)
{
context.bytes.writeFlag(action.condIdleToOverDown);
context.bytes.writeFlag(action.condOutDownToldle);
context.bytes.writeFlag(action.condOutDownToOverDown);
context.bytes.writeFlag(action.condOverDownToOutDown);
context.bytes.writeFlag(action.condOverDownToOverUp);
context.bytes.writeFlag(action.condOverUpToOverDown);
context.bytes.writeFlag(action.condOverUpToIdle);
context.bytes.writeFlag(action.condIdleToOverUp);
size--;
}
if (size > 0)
{
context.bytes.writeUB(7, action.condKeyPress);
context.bytes.writeFlag(action.condOverDownToIdle);
size--;
}
if (size > 0)
{
for each (var record:ActionRecord in action.actions)
{
var startPosition:uint = context.bytes.getBytePosition();
action.actions.push(writeActionRecord(context, record));
size -= (context.bytes.getBytePosition() - startPosition);
if (size == 0)
{
break;
}
if (size < 0)
{
throw new Error("Wrong CondActionSize value");
}
}
}
context.bytes.writeUI8(0);
}

protected function writeActionRecord(context:SWFWriterContext, record:ActionRecord):void
{
throw("Writing ActionRecord not implemented");
}
}
}
20 changes: 20 additions & 0 deletions SWFWireDecompiler/src/com/swfwire/decompiler/SWFByteArray.as
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,16 @@ package com.swfwire.decompiler

return result;
}
public function writeFixed16_16(value:Number):void
{
alignBytes();

var integer:uint = int(value);
var decimal:uint = uint((value - integer) * 0xFFFF);

bytes.writeShort(int(decimal));
bytes.writeShort(int(integer));
}

/*
* Floating point numbers
Expand Down Expand Up @@ -628,5 +638,15 @@ package com.swfwire.decompiler
value = value.substr(0, length);
bytes.writeUTFBytes(value);
}
public function unreadBytes(length:uint):void
{
alignBytes();
if (length >= bytes.position)
{
bytes.position = 0;
return;
}
bytes.position -= length;
}
}
}
Loading

0 comments on commit fe2bce9

Please sign in to comment.