[Swfdec] 14 commits - libswfdec/swfdec_as_context.c libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_interpret.h libswfdec/swfdec_net_stream.c libswfdec/swfdec_script.c libswfdec/swfdec_sprite_movie.c libswfdec/swfdec_tag.c libswfdec/swfdec_text_field_movie.c libswfdec/swfdec_text_field_movie.h test/trace

Pekka Lampila medar at kemper.freedesktop.org
Wed Nov 7 06:54:33 PST 2007


 libswfdec/swfdec_as_context.c            |   33 --
 libswfdec/swfdec_as_interpret.c          |  397 +++++++++++++++----------------
 libswfdec/swfdec_as_interpret.h          |   10 
 libswfdec/swfdec_net_stream.c            |    1 
 libswfdec/swfdec_script.c                |   39 ---
 libswfdec/swfdec_sprite_movie.c          |   72 +++++
 libswfdec/swfdec_tag.c                   |    2 
 libswfdec/swfdec_text_field_movie.c      |   43 +++
 libswfdec/swfdec_text_field_movie.h      |    1 
 test/trace/text-field-scroll-5.swf       |binary
 test/trace/text-field-scroll-5.swf.trace |   18 -
 test/trace/text-field-scroll-6.swf       |binary
 test/trace/text-field-scroll-6.swf.trace |   16 -
 test/trace/text-field-scroll-7.swf       |binary
 test/trace/text-field-scroll-7.swf.trace |   18 -
 test/trace/text-field-scroll-8.swf       |binary
 test/trace/text-field-scroll-8.swf.trace |   18 -
 test/trace/text-field-scroll.as          |    2 
 18 files changed, 371 insertions(+), 299 deletions(-)

New commits:
commit 36309576b9c422ecbd79dc3d08bdf8cb314e1f7e
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Nov 7 16:48:42 2007 +0200

    Fix a variable used uninitialized in swfdec_net_stream_loader_target_parse

diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index 91949ef..9cfefea 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -278,6 +278,7 @@ swfdec_net_stream_loader_target_parse (SwfdecLoaderTarget *target,
   klass = SWFDEC_DECODER_GET_CLASS (stream->flvdecoder);
   g_return_if_fail (klass->parse);
 
+  status = SWFDEC_STATUS_OK;
   do {
     SwfdecBuffer *buffer = swfdec_buffer_queue_pull_buffer (loader->queue);
     status |= klass->parse (SWFDEC_DECODER (stream->flvdecoder), buffer);
commit dbedd91ab207212c1f7d20dceda14b536fb82b3c
Merge: 0c1ebc9... 61dc6a8...
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Nov 7 16:39:53 2007 +0200

    Merge branch 'master' of ssh://medar@git.freedesktop.org/git/swfdec/swfdec

commit 0c1ebc9551e7453b1c183b13d093a379d3c1bb58
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Tue Nov 6 17:29:27 2007 +0200

    Undo a change I committed by accident earlier

diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index b34aba7..2dd36be 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -168,6 +168,13 @@ swfdec_script_foreach_internal (SwfdecBits *bits, SwfdecScriptForeachFunc func,
   return TRUE;
 }
 
+static gboolean
+validate_action (gconstpointer bytecode, guint action, const guint8 *data, guint len, gpointer scriptp)
+{
+  // TODO: get rid of this function
+  return TRUE;
+}
+
 /*** PUBLIC API ***/
 
 gboolean
@@ -230,9 +237,16 @@ swfdec_script_new_from_bits (SwfdecBits *bits, const char *name, guint version)
    * DefineFunction and friends override this */
   script->flags = SWFDEC_SCRIPT_SUPPRESS_ARGS;
 
-  buffer = swfdec_bits_get_buffer (&org, -1);
-  if (buffer == NULL)
+  if (!swfdec_script_foreach_internal (bits, validate_action, script)) {
+    swfdec_script_unref (script);
+    return NULL;
+  }
+  len -= swfdec_bits_left (bits) / 8;
+  if (len == 0) {
     buffer = swfdec_buffer_new ();
+  } else {
+    buffer = swfdec_bits_get_buffer (&org, len);
+  }
 
   script->main = buffer->data;
   script->exit = buffer->data + buffer->length;
commit e1bdf2e9c34a644dab770e9f292d91d445130d11
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Mon Nov 5 16:06:38 2007 +0200

    Fix few errors I just added to the And/Or actions

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index b3cce36..299fd7f 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -2413,7 +2413,6 @@ swfdec_action_enumerate (SwfdecAsContext *cx, guint action, const guint8 *data,
 static void
 swfdec_action_logical (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  SwfdecAsValue *val;
   gboolean l, r;
 
   if (cx->version <= 4) {
@@ -2421,16 +2420,16 @@ swfdec_action_logical (SwfdecAsContext *cx, guint action, const guint8 *data, gu
     // don't call second parameter if not necessary
     if ((action == SWFDEC_AS_ACTION_AND && !l) ||
 	(action != SWFDEC_AS_ACTION_AND && l)) {
-      val = swfdec_as_stack_peek (cx, 2);
-      r = (swfdec_as_value_to_number (cx, val) != 0);
+      r = (swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx, 2)) != 0);
+    } else {
+      r = FALSE;
     }
   } else {
     l = swfdec_as_value_to_boolean (cx, swfdec_as_stack_peek (cx, 1));
-    val = swfdec_as_stack_peek (cx, 2);
-    r = swfdec_as_value_to_boolean (cx, val);
+    r = swfdec_as_value_to_boolean (cx, swfdec_as_stack_peek (cx, 2));
   }
 
-  SWFDEC_AS_VALUE_SET_BOOLEAN (val,
+  SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx, 2),
     (action == SWFDEC_AS_ACTION_AND) ? (l && r) : (l || r));
   swfdec_as_stack_pop (cx);
 }
commit 17f84b2edec6c986953d1005808cd3e456fb30fe
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Mon Nov 5 14:52:29 2007 +0200

    Make And action use swfdec_as_value_to_number in version <= 4

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 619d004..b3cce36 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -2416,14 +2416,22 @@ swfdec_action_logical (SwfdecAsContext *cx, guint action, const guint8 *data, gu
   SwfdecAsValue *val;
   gboolean l, r;
 
-  if (cx->version <= 4)
-    SWFDEC_FIXME ("Or and And actions work incorrectly in version 4");
-
-  l = swfdec_as_value_to_boolean (cx, swfdec_as_stack_peek (cx, 1));
-  val = swfdec_as_stack_peek (cx, 2);
-  r = swfdec_as_value_to_boolean (cx, val);
+  if (cx->version <= 4) {
+    l = (swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx, 1)) != 0);
+    // don't call second parameter if not necessary
+    if ((action == SWFDEC_AS_ACTION_AND && !l) ||
+	(action != SWFDEC_AS_ACTION_AND && l)) {
+      val = swfdec_as_stack_peek (cx, 2);
+      r = (swfdec_as_value_to_number (cx, val) != 0);
+    }
+  } else {
+    l = swfdec_as_value_to_boolean (cx, swfdec_as_stack_peek (cx, 1));
+    val = swfdec_as_stack_peek (cx, 2);
+    r = swfdec_as_value_to_boolean (cx, val);
+  }
 
-  SWFDEC_AS_VALUE_SET_BOOLEAN (val, (action == 0x10) ? (l && r) : (l || r));
+  SWFDEC_AS_VALUE_SET_BOOLEAN (val,
+    (action == SWFDEC_AS_ACTION_AND) ? (l && r) : (l || r));
   swfdec_as_stack_pop (cx);
 }
 
commit da0971305dd16ec6e3fc5ba393054bde89b30285
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Mon Nov 5 14:46:03 2007 +0200

    Some actions were using numbers instead of SWFDEC_AS_ACTION definitions

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 7d02680..619d004 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -3129,7 +3129,7 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   /* version 3 */
   [SWFDEC_AS_ACTION_SET_TARGET2] = { "SetTarget2", NULL, 1, 0, swfdec_action_set_target2, 3 },
   /* version 4 */
-  [0x21] = { "StringAdd", NULL, 2, 1, swfdec_action_string_add, 4 },
+  [SWFDEC_AS_ACTION_STRING_ADD] = { "StringAdd", NULL, 2, 1, swfdec_action_string_add, 4 },
   [SWFDEC_AS_ACTION_GET_PROPERTY] = { "GetProperty", NULL, 2, 1, swfdec_action_get_property, 4 },
   [SWFDEC_AS_ACTION_SET_PROPERTY] = { "SetProperty", NULL, 3, 0, swfdec_action_set_property, 4 },
   [SWFDEC_AS_ACTION_CLONE_SPRITE] = { "CloneSprite", NULL, 3, 0, swfdec_action_clone_sprite, 4 },
@@ -3143,7 +3143,7 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   [SWFDEC_AS_ACTION_CAST] = { "Cast", NULL, 2, 1, swfdec_action_cast, 7 },
   [SWFDEC_AS_ACTION_IMPLEMENTS] = { "Implements", NULL, -1, 0, swfdec_action_implements, 7 },
   /* version 4 */
-  [0x30] = { "RandomNumber", NULL, 1, 1, swfdec_action_random_number, 4 },
+  [SWFDEC_AS_ACTION_RANDOM] = { "RandomNumber", NULL, 1, 1, swfdec_action_random_number, 4 },
   [SWFDEC_AS_ACTION_MB_STRING_LENGTH] = { "MBStringLength", NULL, -1, -1, NULL, 4 },
   [SWFDEC_AS_ACTION_CHAR_TO_ASCII] = { "CharToAscii", NULL, 1, 1, swfdec_action_char_to_ascii, 4 },
   [SWFDEC_AS_ACTION_ASCII_TO_CHAR] = { "AsciiToChar", NULL, 1, 1, swfdec_action_ascii_to_char, 4 },
commit 5f1c374cc2748bafd146e2424aad14786882a7b0
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Mon Nov 5 14:43:33 2007 +0200

    text-field-scroll test was still font-dependant (oops)

diff --git a/test/trace/text-field-scroll-5.swf b/test/trace/text-field-scroll-5.swf
index a9ea84b..8b8d562 100644
Binary files a/test/trace/text-field-scroll-5.swf and b/test/trace/text-field-scroll-5.swf differ
diff --git a/test/trace/text-field-scroll-5.swf.trace b/test/trace/text-field-scroll-5.swf.trace
index 3cc5df5..6746940 100644
--- a/test/trace/text-field-scroll-5.swf.trace
+++ b/test/trace/text-field-scroll-5.swf.trace
@@ -1,53 +1,53 @@
 # EMPTY
-bottomScroll: 
+bottomScroll > scroll: false
 hscroll: 
 maxhscroll > 0: false
 maxscroll > 0: false
 scroll: 
 # WITH TEXT
-bottomScroll: 
+bottomScroll > scroll: false
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: false
 scroll: 3
 # WITH WORD WRAP
-bottomScroll: 
+bottomScroll > scroll: false
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: false
 scroll: 3
 # WITHOUT WORD WRAP
-bottomScroll: 
+bottomScroll > scroll: false
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: false
 scroll: 3
 # WITH WORD WRAP - SCROLL RESET
-bottomScroll: 
+bottomScroll > scroll: false
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: false
 scroll: 3
 # WITH WORD WRAP - FORMAT RESET
-bottomScroll: 
+bottomScroll > scroll: false
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: false
 scroll: 3
 # WITH WORD WRAP - TEXT RESET
-bottomScroll: 
+bottomScroll > scroll: false
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: false
 scroll: 3
 # WITHOUT WORD WRAP - FORMAT RESET
-bottomScroll: 
+bottomScroll > scroll: false
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: false
 scroll: 30
 # WITHOUT WORD WRAP - TEXT RESET
-bottomScroll: 
+bottomScroll > scroll: false
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: false
diff --git a/test/trace/text-field-scroll-6.swf b/test/trace/text-field-scroll-6.swf
index d5420f7..30bcc38 100644
Binary files a/test/trace/text-field-scroll-6.swf and b/test/trace/text-field-scroll-6.swf differ
diff --git a/test/trace/text-field-scroll-6.swf.trace b/test/trace/text-field-scroll-6.swf.trace
index 3c6948b..6dc3dc5 100644
--- a/test/trace/text-field-scroll-6.swf.trace
+++ b/test/trace/text-field-scroll-6.swf.trace
@@ -1,47 +1,47 @@
 # EMPTY
-bottomScroll: 1
+bottomScroll > scroll: false
 hscroll: 0
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 1
 # WITH TEXT
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: true
 maxscroll > 0: true
 scroll: 3
 # WITH WORD WRAP
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 3
 # WITHOUT WORD WRAP
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: true
 maxscroll > 0: true
 scroll: 3
 # WITH WORD WRAP - SCROLL RESET
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 3
 # WITH WORD WRAP - TEXT RESET
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 0
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 3
 # WITHOUT WORD WRAP - FORMAT RESET
-bottomScroll: 30
+bottomScroll > scroll: false
 hscroll: 0
 maxhscroll > 0: true
 maxscroll > 0: true
 scroll: 30
 # WITHOUT WORD WRAP - TEXT RESET
-bottomScroll: 16
+bottomScroll > scroll: true
 hscroll: 0
 maxhscroll > 0: true
 maxscroll > 0: true
diff --git a/test/trace/text-field-scroll-7.swf b/test/trace/text-field-scroll-7.swf
index 90292cf..7c47d65 100644
Binary files a/test/trace/text-field-scroll-7.swf and b/test/trace/text-field-scroll-7.swf differ
diff --git a/test/trace/text-field-scroll-7.swf.trace b/test/trace/text-field-scroll-7.swf.trace
index abccb32..6cd8b93 100644
--- a/test/trace/text-field-scroll-7.swf.trace
+++ b/test/trace/text-field-scroll-7.swf.trace
@@ -1,53 +1,53 @@
 # EMPTY
-bottomScroll: 1
+bottomScroll > scroll: false
 hscroll: 0
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 1
 # WITH TEXT
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: true
 maxscroll > 0: true
 scroll: 3
 # WITH WORD WRAP
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 3
 # WITHOUT WORD WRAP
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: true
 maxscroll > 0: true
 scroll: 3
 # WITH WORD WRAP - SCROLL RESET
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 3
 # WITH WORD WRAP - FORMAT RESET
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 3
 # WITH WORD WRAP - TEXT RESET
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 0
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 3
 # WITHOUT WORD WRAP - FORMAT RESET
-bottomScroll: 30
+bottomScroll > scroll: false
 hscroll: 0
 maxhscroll > 0: true
 maxscroll > 0: true
 scroll: 30
 # WITHOUT WORD WRAP - TEXT RESET
-bottomScroll: 16
+bottomScroll > scroll: true
 hscroll: 0
 maxhscroll > 0: true
 maxscroll > 0: true
diff --git a/test/trace/text-field-scroll-8.swf b/test/trace/text-field-scroll-8.swf
index f78ca7d..5fb8e80 100644
Binary files a/test/trace/text-field-scroll-8.swf and b/test/trace/text-field-scroll-8.swf differ
diff --git a/test/trace/text-field-scroll-8.swf.trace b/test/trace/text-field-scroll-8.swf.trace
index abccb32..6cd8b93 100644
--- a/test/trace/text-field-scroll-8.swf.trace
+++ b/test/trace/text-field-scroll-8.swf.trace
@@ -1,53 +1,53 @@
 # EMPTY
-bottomScroll: 1
+bottomScroll > scroll: false
 hscroll: 0
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 1
 # WITH TEXT
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: true
 maxscroll > 0: true
 scroll: 3
 # WITH WORD WRAP
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 3
 # WITHOUT WORD WRAP
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: true
 maxscroll > 0: true
 scroll: 3
 # WITH WORD WRAP - SCROLL RESET
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 3
 # WITH WORD WRAP - FORMAT RESET
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 200
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 3
 # WITH WORD WRAP - TEXT RESET
-bottomScroll: 8
+bottomScroll > scroll: true
 hscroll: 0
 maxhscroll > 0: false
 maxscroll > 0: true
 scroll: 3
 # WITHOUT WORD WRAP - FORMAT RESET
-bottomScroll: 30
+bottomScroll > scroll: false
 hscroll: 0
 maxhscroll > 0: true
 maxscroll > 0: true
 scroll: 30
 # WITHOUT WORD WRAP - TEXT RESET
-bottomScroll: 16
+bottomScroll > scroll: true
 hscroll: 0
 maxhscroll > 0: true
 maxscroll > 0: true
diff --git a/test/trace/text-field-scroll.as b/test/trace/text-field-scroll.as
index 77cbb82..a375f29 100644
--- a/test/trace/text-field-scroll.as
+++ b/test/trace/text-field-scroll.as
@@ -1,7 +1,7 @@
 // makeswf -v 7 -r 1 -o test-7.swf test.as
 
 function trace_scroll_properties () {
-  trace ("bottomScroll: " + t.bottomScroll);
+  trace ("bottomScroll > scroll: " + (t.bottomScroll > t.scroll));
   trace ("hscroll: " + t.hscroll);
   trace ("maxhscroll > 0: " + (t.maxhscroll > 0));
   trace ("maxscroll > 0: " + (t.maxscroll > 0));
commit 43716ea67233c1a9214d5fd0870d00990ecfa02e
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Mon Nov 5 14:41:11 2007 +0200

    Fix version numbers for some actions (version 1 and 2)

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index efd8ce4..7d02680 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -3101,13 +3101,14 @@ swfdec_action_print_wait_for_frame (guint action, const guint8 *data, guint len)
 /*** BIG FUNCTION TABLE ***/
 
 const SwfdecActionSpec swfdec_as_actions[256] = {
-  /* version 3 */
-  [SWFDEC_AS_ACTION_NEXT_FRAME] = { "NextFrame", NULL, 0, 0, swfdec_action_next_frame, 3 },
-  [SWFDEC_AS_ACTION_PREVIOUS_FRAME] = { "PreviousFrame", NULL, 0, 0, swfdec_action_previous_frame, 3 },
-  [SWFDEC_AS_ACTION_PLAY] = { "Play", NULL, 0, 0, swfdec_action_play, 3 },
-  [SWFDEC_AS_ACTION_STOP] = { "Stop", NULL, 0, 0, swfdec_action_stop, 3 },
-  [SWFDEC_AS_ACTION_TOGGLE_QUALITY] = { "ToggleQuality", NULL, -1, -1, NULL, 3 },
-  [SWFDEC_AS_ACTION_STOP_SOUNDS] = { "StopSounds", NULL, 0, 0, swfdec_action_stop_sounds, 3 },
+  /* version 1 */
+  [SWFDEC_AS_ACTION_NEXT_FRAME] = { "NextFrame", NULL, 0, 0, swfdec_action_next_frame, 1 },
+  [SWFDEC_AS_ACTION_PREVIOUS_FRAME] = { "PreviousFrame", NULL, 0, 0, swfdec_action_previous_frame, 1 },
+  [SWFDEC_AS_ACTION_PLAY] = { "Play", NULL, 0, 0, swfdec_action_play, 1 },
+  [SWFDEC_AS_ACTION_STOP] = { "Stop", NULL, 0, 0, swfdec_action_stop, 1 },
+  [SWFDEC_AS_ACTION_TOGGLE_QUALITY] = { "ToggleQuality", NULL, -1, -1, NULL, 1 },
+  /* version 2 */
+  [SWFDEC_AS_ACTION_STOP_SOUNDS] = { "StopSounds", NULL, 0, 0, swfdec_action_stop_sounds, 2 },
   /* version 4 */
   [SWFDEC_AS_ACTION_ADD] = { "Add", NULL, 2, 1, swfdec_action_binary, 4 },
   [SWFDEC_AS_ACTION_SUBTRACT] = { "Subtract", NULL, 2, 1, swfdec_action_binary, 4 },
@@ -3196,16 +3197,17 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   [SWFDEC_AS_ACTION_STRING_GREATER] = { "StringGreater", NULL, -1, -1, NULL, 6 },
   /* version 7 */
   [SWFDEC_AS_ACTION_EXTENDS] = { "Extends", NULL, 2, 0, swfdec_action_extends, 7 },
-  /* version 3 */
-  [SWFDEC_AS_ACTION_GOTO_FRAME] = { "GotoFrame", swfdec_action_print_goto_frame, 0, 0, swfdec_action_goto_frame, 3 },
-  [SWFDEC_AS_ACTION_GET_URL] = { "GetURL", swfdec_action_print_get_url, 0, 0, swfdec_action_get_url, 3 },
+  /* version 1 */
+  [SWFDEC_AS_ACTION_GOTO_FRAME] = { "GotoFrame", swfdec_action_print_goto_frame, 0, 0, swfdec_action_goto_frame, 1 },
+  [SWFDEC_AS_ACTION_GET_URL] = { "GetURL", swfdec_action_print_get_url, 0, 0, swfdec_action_get_url, 1 },
   /* version 5 */
   [SWFDEC_AS_ACTION_STORE_REGISTER] = { "StoreRegister", swfdec_action_print_store_register, 1, 1, swfdec_action_store_register, 5 },
   [SWFDEC_AS_ACTION_CONSTANT_POOL] = { "ConstantPool", swfdec_action_print_constant_pool, 0, 0, swfdec_action_constant_pool, 5 },
+  [SWFDEC_AS_ACTION_STRICT_MODE] = { "StrictMode", NULL, -1, -1, NULL, 5 },
+  /* version 1 */
+  [SWFDEC_AS_ACTION_WAIT_FOR_FRAME] = { "WaitForFrame", swfdec_action_print_wait_for_frame, 0, 0, swfdec_action_wait_for_frame, 1 },
+  [SWFDEC_AS_ACTION_SET_TARGET] = { "SetTarget", swfdec_action_print_set_target, 0, 0, swfdec_action_set_target, 1 },
   /* version 3 */
-  [SWFDEC_AS_ACTION_STRICT_MODE] = { "StrictMode", NULL, -1, -1, NULL, 3 },
-  [SWFDEC_AS_ACTION_WAIT_FOR_FRAME] = { "WaitForFrame", swfdec_action_print_wait_for_frame, 0, 0, swfdec_action_wait_for_frame, 3 },
-  [SWFDEC_AS_ACTION_SET_TARGET] = { "SetTarget", swfdec_action_print_set_target, 0, 0, swfdec_action_set_target, 3 },
   [SWFDEC_AS_ACTION_GOTO_LABEL] = { "GotoLabel", swfdec_action_print_goto_label, 0, 0, swfdec_action_goto_label, 3 },
 #if 0
   /* version 4 */
commit fa858b9e2e67e82bcddbd93326d72c8aa74ed139
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Mon Nov 5 14:36:50 2007 +0200

    Fix an error from last commit that broke everything

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index ed10124..efd8ce4 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -3106,7 +3106,7 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   [SWFDEC_AS_ACTION_PREVIOUS_FRAME] = { "PreviousFrame", NULL, 0, 0, swfdec_action_previous_frame, 3 },
   [SWFDEC_AS_ACTION_PLAY] = { "Play", NULL, 0, 0, swfdec_action_play, 3 },
   [SWFDEC_AS_ACTION_STOP] = { "Stop", NULL, 0, 0, swfdec_action_stop, 3 },
-  [SWFDEC_AS_ACTION_TOGGLE_QUALITY] = { "ToggleQuality", NULL, },
+  [SWFDEC_AS_ACTION_TOGGLE_QUALITY] = { "ToggleQuality", NULL, -1, -1, NULL, 3 },
   [SWFDEC_AS_ACTION_STOP_SOUNDS] = { "StopSounds", NULL, 0, 0, swfdec_action_stop_sounds, 3 },
   /* version 4 */
   [SWFDEC_AS_ACTION_ADD] = { "Add", NULL, 2, 1, swfdec_action_binary, 4 },
@@ -3143,12 +3143,12 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   [SWFDEC_AS_ACTION_IMPLEMENTS] = { "Implements", NULL, -1, 0, swfdec_action_implements, 7 },
   /* version 4 */
   [0x30] = { "RandomNumber", NULL, 1, 1, swfdec_action_random_number, 4 },
-  [SWFDEC_AS_ACTION_MB_STRING_LENGTH] = { "MBStringLength", NULL },
+  [SWFDEC_AS_ACTION_MB_STRING_LENGTH] = { "MBStringLength", NULL, -1, -1, NULL, 4 },
   [SWFDEC_AS_ACTION_CHAR_TO_ASCII] = { "CharToAscii", NULL, 1, 1, swfdec_action_char_to_ascii, 4 },
   [SWFDEC_AS_ACTION_ASCII_TO_CHAR] = { "AsciiToChar", NULL, 1, 1, swfdec_action_ascii_to_char, 4 },
   [SWFDEC_AS_ACTION_GET_TIME] = { "GetTime", NULL, 0, 1, swfdec_action_get_time, 4 },
   [SWFDEC_AS_ACTION_MB_STRING_EXTRACT] = { "MBStringExtract", NULL, 3, 1, swfdec_action_string_extract, 4 },
-  [SWFDEC_AS_ACTION_MB_CHAR_TO_ASCII] = { "MBCharToAscii", NULL },
+  [SWFDEC_AS_ACTION_MB_CHAR_TO_ASCII] = { "MBCharToAscii", NULL, -1, -1, NULL, 4 },
   [SWFDEC_AS_ACTION_MB_ASCII_TO_CHAR] = { "MBAsciiToChar", NULL, 1, 1, swfdec_action_ascii_to_char, 4 },
   /* version 5 */
   [SWFDEC_AS_ACTION_DELETE] = { "Delete", NULL, 2, 1, swfdec_action_delete, 5 },
@@ -3182,7 +3182,7 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   /* version 6 */
   [SWFDEC_AS_ACTION_INSTANCE_OF] = { "InstanceOf", NULL, 2, 1, swfdec_action_instance_of, 6 },
   [SWFDEC_AS_ACTION_ENUMERATE2] = { "Enumerate2", NULL, 1, -1, swfdec_action_enumerate2, 6 },
-  [SWFDEC_AS_ACTION_BREAKPOINT] = { "Breakpoint", NULL, },
+  [SWFDEC_AS_ACTION_BREAKPOINT] = { "Breakpoint", NULL, -1, -1, NULL, 6 },
   /* version 5 */
   [SWFDEC_AS_ACTION_BIT_AND] = { "BitAnd", NULL, 2, 1, swfdec_action_bitwise, 5 },
   [SWFDEC_AS_ACTION_BIT_OR] = { "BitOr", NULL, 2, 1, swfdec_action_bitwise, 5 },
@@ -3193,7 +3193,7 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   /* version 6 */
   [SWFDEC_AS_ACTION_STRICT_EQUALS] = { "StrictEquals", NULL, 2, 1, swfdec_action_strict_equals, 6 },
   [SWFDEC_AS_ACTION_GREATER] = { "Greater", NULL, 2, 1, swfdec_action_new_comparison, 6 },
-  [SWFDEC_AS_ACTION_STRING_GREATER] = { "StringGreater", NULL },
+  [SWFDEC_AS_ACTION_STRING_GREATER] = { "StringGreater", NULL, -1, -1, NULL, 6 },
   /* version 7 */
   [SWFDEC_AS_ACTION_EXTENDS] = { "Extends", NULL, 2, 0, swfdec_action_extends, 7 },
   /* version 3 */
@@ -3203,7 +3203,7 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   [SWFDEC_AS_ACTION_STORE_REGISTER] = { "StoreRegister", swfdec_action_print_store_register, 1, 1, swfdec_action_store_register, 5 },
   [SWFDEC_AS_ACTION_CONSTANT_POOL] = { "ConstantPool", swfdec_action_print_constant_pool, 0, 0, swfdec_action_constant_pool, 5 },
   /* version 3 */
-  [SWFDEC_AS_ACTION_STRICT_MODE] = { "StrictMode", NULL, },
+  [SWFDEC_AS_ACTION_STRICT_MODE] = { "StrictMode", NULL, -1, -1, NULL, 3 },
   [SWFDEC_AS_ACTION_WAIT_FOR_FRAME] = { "WaitForFrame", swfdec_action_print_wait_for_frame, 0, 0, swfdec_action_wait_for_frame, 3 },
   [SWFDEC_AS_ACTION_SET_TARGET] = { "SetTarget", swfdec_action_print_set_target, 0, 0, swfdec_action_set_target, 3 },
   [SWFDEC_AS_ACTION_GOTO_LABEL] = { "GotoLabel", swfdec_action_print_goto_label, 0, 0, swfdec_action_goto_label, 3 },
@@ -3224,7 +3224,7 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   [SWFDEC_AS_ACTION_DEFINE_FUNCTION] = { "DefineFunction", swfdec_action_print_define_function, 0, -1, swfdec_action_define_function, 5 },
   /* version 4 */
   [SWFDEC_AS_ACTION_IF] = { "If", swfdec_action_print_if, 1, 0, swfdec_action_if, 4 },
-  [SWFDEC_AS_ACTION_CALL] = { "Call", NULL },
+  [SWFDEC_AS_ACTION_CALL] = { "Call", NULL, -1, -1, NULL, 4 },
   [SWFDEC_AS_ACTION_GOTO_FRAME2] = { "GotoFrame2", swfdec_action_print_goto_frame2, 1, 0, swfdec_action_goto_frame2, 4 }
 };
 
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 6e1edf4..b34aba7 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -230,12 +230,10 @@ swfdec_script_new_from_bits (SwfdecBits *bits, const char *name, guint version)
    * DefineFunction and friends override this */
   script->flags = SWFDEC_SCRIPT_SUPPRESS_ARGS;
 
-  len -= swfdec_bits_left (bits) / 8;
-  if (len == 0) {
+  buffer = swfdec_bits_get_buffer (&org, -1);
+  if (buffer == NULL)
     buffer = swfdec_buffer_new ();
-  } else {
-    buffer = swfdec_bits_get_buffer (&org, len);
-  }
+
   script->main = buffer->data;
   script->exit = buffer->data + buffer->length;
   script->buffer = swfdec_buffer_ref (swfdec_buffer_get_super (buffer));
commit 1d08537e1500f35edf20b19134c65d41b2c8d30d
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Mon Nov 5 12:21:04 2007 +0200

    Finish getting rid of version specific functions for actions
    
    And things compile again

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 4ef1dcd..ed10124 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -1075,19 +1075,15 @@ swfdec_action_new_comparison (SwfdecAsContext *cx, guint action, const guint8 *d
 }
 
 static void
-swfdec_action_not_4 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
+swfdec_action_not (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  double d;
-
-  d = swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx, 1));
-  SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx, 1), d == 0 ? 1 : 0);
-}
-
-static void
-swfdec_action_not_5 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
-{
-  SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx, 1), 
-      !swfdec_as_value_to_boolean (cx, swfdec_as_stack_peek (cx, 1)));
+  if (cx->version <= 4) {
+    double d = swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx, 1));
+    SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx, 1), d == 0 ? 1 : 0);
+  } else {
+    SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx, 1), 
+	!swfdec_as_value_to_boolean (cx, swfdec_as_stack_peek (cx, 1)));
+  }
 }
 
 static void
@@ -1423,7 +1419,7 @@ out:
 }
 
 static void
-swfdec_action_equals2 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
+swfdec_action_equals2_6 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
   SwfdecAsValue *rval, *lval;
   SwfdecAsValueType ltype, rtype;
@@ -1510,6 +1506,16 @@ out:
 }
 
 static void
+swfdec_action_equals2 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
+{
+  if (cx->version <= 5) {
+    swfdec_action_equals2_5 (cx, action, data, len);
+  } else {
+    swfdec_action_equals2_6 (cx, action, data, len);
+  }
+}
+
+static void
 swfdec_action_strict_equals (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
   SwfdecAsValue *rval, *lval;
@@ -2410,6 +2416,9 @@ swfdec_action_logical (SwfdecAsContext *cx, guint action, const guint8 *data, gu
   SwfdecAsValue *val;
   gboolean l, r;
 
+  if (cx->version <= 4)
+    SWFDEC_FIXME ("Or and And actions work incorrectly in version 4");
+
   l = swfdec_as_value_to_boolean (cx, swfdec_as_stack_peek (cx, 1));
   val = swfdec_as_stack_peek (cx, 2);
   r = swfdec_as_value_to_boolean (cx, val);
@@ -2419,102 +2428,83 @@ swfdec_action_logical (SwfdecAsContext *cx, guint action, const guint8 *data, gu
 }
 
 static void
-swfdec_action_char_to_ascii_5 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
+swfdec_action_char_to_ascii (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
   SwfdecAsValue *val = swfdec_as_stack_peek (cx, 1);
   const char *s = swfdec_as_value_to_string (cx, val);
 
-  char *ascii;
-  ascii = g_convert (s, -1, "LATIN1", "UTF-8", NULL, NULL, NULL);
-  if (ascii == NULL) {
-    /* This can happen if a Flash 5 movie gets loaded into a Flash 7 movie */
-    SWFDEC_FIXME ("Someone threw unconvertible text %s at Flash <= 5", s);
-    SWFDEC_AS_VALUE_SET_INT (val, 0); /* FIXME: what to return??? */
-  } else {
-    SWFDEC_AS_VALUE_SET_INT (val, (guchar) ascii[0]);
-    g_free (ascii);
-  }
-}
+  if (cx->version <= 5) {
+    char *ascii = g_convert (s, -1, "LATIN1", "UTF-8", NULL, NULL, NULL);
 
-static void
-swfdec_action_char_to_ascii (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
-{
-  SwfdecAsValue *val = swfdec_as_stack_peek (cx, 1);
-  const char *s = swfdec_as_value_to_string(cx, val);
-  gunichar *uni;
-  
-  uni = g_utf8_to_ucs4_fast (s, -1, NULL);
-  if (uni == NULL) {
-    /* This should never happen, everything is valid UTF-8 in here */
-    g_warning ("conversion of character %s failed", s);
-    SWFDEC_AS_VALUE_SET_INT (val, 0);
+    if (ascii == NULL) {
+      /* This can happen if a Flash 5 movie gets loaded into a Flash 7 movie */
+      SWFDEC_FIXME ("Someone threw unconvertible text %s at Flash <= 5", s);
+      SWFDEC_AS_VALUE_SET_INT (val, 0); /* FIXME: what to return??? */
+    } else {
+      SWFDEC_AS_VALUE_SET_INT (val, (guchar) ascii[0]);
+      g_free (ascii);
+    }
   } else {
-    SWFDEC_AS_VALUE_SET_INT (val, uni[0]);
-    g_free (uni);
+    gunichar *uni = g_utf8_to_ucs4_fast (s, -1, NULL);
+
+    if (uni == NULL) {
+      /* This should never happen, everything is valid UTF-8 in here */
+      g_warning ("conversion of character %s failed", s);
+      SWFDEC_AS_VALUE_SET_INT (val, 0);
+    } else {
+      SWFDEC_AS_VALUE_SET_INT (val, uni[0]);
+      g_free (uni);
+    }
   }
 }
 
 static void
 swfdec_action_ascii_to_char (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  char *s;
   SwfdecAsValue *val = swfdec_as_stack_peek (cx, 1);
-  gunichar c = ((guint) swfdec_as_value_to_integer (cx, val)) % 65536;
 
-  s = g_ucs4_to_utf8 (&c, 1, NULL, NULL, NULL);
-  if (s == NULL) {
-    g_warning ("conversion of character %u failed", (guint) c);
-    SWFDEC_AS_VALUE_SET_STRING (val, SWFDEC_AS_STR_EMPTY);
-  } else {
-    SWFDEC_AS_VALUE_SET_STRING (val, swfdec_as_context_get_string (cx, s));
-    g_free (s);
-  }
-}
+  if (cx->version <= 5) {
+    char s[3];
+    char *utf8;
+    guint i;
 
-static void
-swfdec_action_ascii_to_char_5 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
-{
-  SwfdecAsValue *val = swfdec_as_stack_peek (cx, 1);
-  char s[2];
-  char *utf8;
-  
-  s[0] = ((guint) swfdec_as_value_to_integer (cx, val)) % 256;
-  s[1] = 0;
+    if (action == SWFDEC_AS_ACTION_ASCII_TO_CHAR) {
+      s[0] = ((guint) swfdec_as_value_to_integer (cx, val)) % 256;
+      s[1] = 0;
+    } else {
+      g_assert (action == SWFDEC_AS_ACTION_MB_ASCII_TO_CHAR);
 
-  utf8 = g_convert (s, -1, "UTF-8", "LATIN1", NULL, NULL, NULL);
-  if (utf8 == NULL) {
-    g_warning ("conversion of character %u failed", (guint) s[0]);
-    SWFDEC_AS_VALUE_SET_STRING (val, SWFDEC_AS_STR_EMPTY);
-  } else {
-    SWFDEC_AS_VALUE_SET_STRING (val, swfdec_as_context_get_string (cx, utf8));
-    g_free (utf8);
-  }
-}
+      i = ((guint) swfdec_as_value_to_integer (cx, val));
+      if (i > 255) {
+	s[0] = i / 256;
+	s[1] = i % 256;
+	s[2] = 0;
+      } else {
+	s[0] = i;
+	s[1] = 0;
+      }
+    }
 
-static void
-swfdec_action_mb_ascii_to_char_5 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
-{
-  SwfdecAsValue *val = swfdec_as_stack_peek (cx, 1);
-  char s[3];
-  char *utf8;
-  guint i;
-  
-  i = ((guint) swfdec_as_value_to_integer (cx, val));
-  if (i > 255) {
-    s[0] = i / 256;
-    s[1] = i % 256;
-    s[2] = 0;
-  } else {
-    s[0] = i;
-    s[1] = 0;
-  }
-  utf8 = g_convert (s, -1, "UTF-8", "LATIN1", NULL, NULL, NULL);
-  if (utf8 == NULL) {
-    g_warning ("conversion of character %u failed", i);
-    SWFDEC_AS_VALUE_SET_STRING (val, SWFDEC_AS_STR_EMPTY);
+    utf8 = g_convert (s, -1, "UTF-8", "LATIN1", NULL, NULL, NULL);
+    if (utf8 == NULL) {
+      g_warning ("conversion of character %u failed", (guint) s[0]);
+      SWFDEC_AS_VALUE_SET_STRING (val, SWFDEC_AS_STR_EMPTY);
+    } else {
+      SWFDEC_AS_VALUE_SET_STRING (val, swfdec_as_context_get_string (cx, utf8));
+      g_free (utf8);
+    }
   } else {
-    SWFDEC_AS_VALUE_SET_STRING (val, swfdec_as_context_get_string (cx, utf8));
-    g_free (utf8);
+    char *s;
+    gunichar c = ((guint) swfdec_as_value_to_integer (cx, val)) % 65536;
+
+    s = g_ucs4_to_utf8 (&c, 1, NULL, NULL, NULL);
+    if (s == NULL) {
+      g_warning ("conversion of character %u failed", (guint) c);
+      SWFDEC_AS_VALUE_SET_STRING (val, SWFDEC_AS_STR_EMPTY);
+    } else {
+      SWFDEC_AS_VALUE_SET_STRING (val, swfdec_as_context_get_string (cx, s));
+      g_free (s);
+    }
   }
 }
 
@@ -3125,9 +3115,9 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   [SWFDEC_AS_ACTION_DIVIDE] = { "Divide", NULL, 2, 1, swfdec_action_binary, 4 },
   [SWFDEC_AS_ACTION_EQUALS] = { "Equals", NULL, 2, 1, swfdec_action_old_compare, 4 },
   [SWFDEC_AS_ACTION_LESS] = { "Less", NULL, 2, 1, swfdec_action_old_compare, 4 },
-  [SWFDEC_AS_ACTION_AND] = { "And", NULL, 2, 1, { NULL, /* FIXME */NULL, swfdec_action_logical, swfdec_action_logical, swfdec_action_logical } },
-  [SWFDEC_AS_ACTION_OR] = { "Or", NULL, 2, 1, { NULL, /* FIXME */NULL, swfdec_action_logical, swfdec_action_logical, swfdec_action_logical } },
-  [SWFDEC_AS_ACTION_NOT] = { "Not", NULL, 1, 1, { NULL, swfdec_action_not_4, swfdec_action_not_5, swfdec_action_not_5, swfdec_action_not_5 } },
+  [SWFDEC_AS_ACTION_AND] = { "And", NULL, 2, 1, swfdec_action_logical, 4 },
+  [SWFDEC_AS_ACTION_OR] = { "Or", NULL, 2, 1, swfdec_action_logical, 4 },
+  [SWFDEC_AS_ACTION_NOT] = { "Not", NULL, 1, 1, swfdec_action_not, 4 },
   [SWFDEC_AS_ACTION_STRING_EQUALS] = { "StringEquals", NULL, 2, 1, swfdec_action_string_compare, 4 },
   [SWFDEC_AS_ACTION_STRING_LENGTH] = { "StringLength", NULL, 1, 1, swfdec_action_string_length, 4 },
   [SWFDEC_AS_ACTION_STRING_EXTRACT] = { "StringExtract", NULL, 3, 1, swfdec_action_string_extract, 4 },
@@ -3154,12 +3144,12 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   /* version 4 */
   [0x30] = { "RandomNumber", NULL, 1, 1, swfdec_action_random_number, 4 },
   [SWFDEC_AS_ACTION_MB_STRING_LENGTH] = { "MBStringLength", NULL },
-  [SWFDEC_AS_ACTION_CHAR_TO_ASCII] = { "CharToAscii", NULL, 1, 1, { NULL, swfdec_action_char_to_ascii_5, swfdec_action_char_to_ascii_5, swfdec_action_char_to_ascii, swfdec_action_char_to_ascii } },
-  [SWFDEC_AS_ACTION_ASCII_TO_CHAR] = { "AsciiToChar", NULL, 1, 1, { NULL, swfdec_action_ascii_to_char_5, swfdec_action_ascii_to_char_5, swfdec_action_ascii_to_char, swfdec_action_ascii_to_char } },
+  [SWFDEC_AS_ACTION_CHAR_TO_ASCII] = { "CharToAscii", NULL, 1, 1, swfdec_action_char_to_ascii, 4 },
+  [SWFDEC_AS_ACTION_ASCII_TO_CHAR] = { "AsciiToChar", NULL, 1, 1, swfdec_action_ascii_to_char, 4 },
   [SWFDEC_AS_ACTION_GET_TIME] = { "GetTime", NULL, 0, 1, swfdec_action_get_time, 4 },
   [SWFDEC_AS_ACTION_MB_STRING_EXTRACT] = { "MBStringExtract", NULL, 3, 1, swfdec_action_string_extract, 4 },
   [SWFDEC_AS_ACTION_MB_CHAR_TO_ASCII] = { "MBCharToAscii", NULL },
-  [SWFDEC_AS_ACTION_MB_ASCII_TO_CHAR] = { "MBAsciiToChar", NULL, 1, 1, { NULL, swfdec_action_mb_ascii_to_char_5, swfdec_action_mb_ascii_to_char_5, swfdec_action_ascii_to_char, swfdec_action_ascii_to_char }  },
+  [SWFDEC_AS_ACTION_MB_ASCII_TO_CHAR] = { "MBAsciiToChar", NULL, 1, 1, swfdec_action_ascii_to_char, 4 },
   /* version 5 */
   [SWFDEC_AS_ACTION_DELETE] = { "Delete", NULL, 2, 1, swfdec_action_delete, 5 },
   [SWFDEC_AS_ACTION_DELETE2] = { "Delete2", NULL, 1, 1, swfdec_action_delete2, 5 },
@@ -3176,7 +3166,7 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   [SWFDEC_AS_ACTION_ENUMERATE] = { "Enumerate", NULL, 1, -1, swfdec_action_enumerate, 5 },
   [SWFDEC_AS_ACTION_ADD2] = { "Add2", NULL, 2, 1, swfdec_action_add2, 5 },
   [SWFDEC_AS_ACTION_LESS2] = { "Less2", NULL, 2, 1, swfdec_action_new_comparison, 5 },
-  [SWFDEC_AS_ACTION_EQUALS2] = { "Equals2", NULL, 2, 1, swfdec_action_equals2_5, 5 },
+  [SWFDEC_AS_ACTION_EQUALS2] = { "Equals2", NULL, 2, 1, swfdec_action_equals2, 5 },
   [SWFDEC_AS_ACTION_TO_NUMBER] = { "ToNumber", NULL, 1, 1, swfdec_action_to_number, 5 },
   [SWFDEC_AS_ACTION_TO_STRING] = { "ToString", NULL, 1, 1, swfdec_action_to_string, 5 },
   [SWFDEC_AS_ACTION_PUSH_DUPLICATE] = { "PushDuplicate", NULL, 1, 2, swfdec_action_push_duplicate, 5 },
@@ -3205,7 +3195,7 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
   [SWFDEC_AS_ACTION_GREATER] = { "Greater", NULL, 2, 1, swfdec_action_new_comparison, 6 },
   [SWFDEC_AS_ACTION_STRING_GREATER] = { "StringGreater", NULL },
   /* version 7 */
-  [SWFDEC_AS_ACTION_EXTENDS] = { "Extends", NULL, 2, 0, { NULL, NULL, NULL, swfdec_action_extends, swfdec_action_extends } },
+  [SWFDEC_AS_ACTION_EXTENDS] = { "Extends", NULL, 2, 0, swfdec_action_extends, 7 },
   /* version 3 */
   [SWFDEC_AS_ACTION_GOTO_FRAME] = { "GotoFrame", swfdec_action_print_goto_frame, 0, 0, swfdec_action_goto_frame, 3 },
   [SWFDEC_AS_ACTION_GET_URL] = { "GetURL", swfdec_action_print_get_url, 0, 0, swfdec_action_get_url, 3 },
@@ -3223,7 +3213,7 @@ const SwfdecActionSpec swfdec_as_actions[256] = {
 #endif
   /* version 7 */
   [SWFDEC_AS_ACTION_DEFINE_FUNCTION2] = { "DefineFunction2", swfdec_action_print_define_function, 0, -1, swfdec_action_define_function, 7 },
-  [SWFDEC_AS_ACTION_TRY] = { "Try", NULL, 0, 0, { NULL, NULL, NULL, NULL, swfdec_action_try } },
+  [SWFDEC_AS_ACTION_TRY] = { "Try", NULL, 0, 0, swfdec_action_try, 7 },
   /* version 5 */
   [SWFDEC_AS_ACTION_WITH] = { "With", swfdec_action_print_with, 1, 0, swfdec_action_with, 5 },
   /* version 4 */
diff --git a/libswfdec/swfdec_as_interpret.h b/libswfdec/swfdec_as_interpret.h
index 2877635..6b9402b 100644
--- a/libswfdec/swfdec_as_interpret.h
+++ b/libswfdec/swfdec_as_interpret.h
@@ -30,7 +30,7 @@ typedef struct {
   int			remove;		/* values removed from stack or -1 for dynamic */
   int			add;		/* values added to the stack or -1 for dynamic */
   void			(* exec)	(SwfdecAsContext *cx, guint action, const guint8 *data, guint len);
-  int			version;	/* the version this action was introduced in */
+  guint			version;	/* the version this action was introduced in */
 } SwfdecActionSpec;
 
 extern const SwfdecActionSpec swfdec_as_actions[256];
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 0fa373d..6e1edf4 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -183,30 +183,6 @@ swfdec_script_foreach (SwfdecScript *script, SwfdecScriptForeachFunc func, gpoin
   return swfdec_script_foreach_internal (&bits, func, user_data);
 }
 
-static gboolean
-validate_action (gconstpointer bytecode, guint action, const guint8 *data, guint len, gpointer scriptp)
-{
-  SwfdecScript *script = scriptp;
-  int version = SWFDEC_AS_EXTRACT_SCRIPT_VERSION (script->version);
-
-  /* warn if there's no function to execute this opcode */
-  if (swfdec_as_actions[action].exec[version] == NULL) {
-    SWFDEC_ERROR ("no function for %3u 0x%02X %s in v%u", action, action,
-	swfdec_as_actions[action].name ? swfdec_as_actions[action].name : "Unknown",
-	script->version);
-  }
-  /* we might want to do stuff here for certain actions */
-#if 0
-  {
-    char *foo = swfdec_script_print_action (action, data, len);
-    if (foo == NULL)
-      return FALSE;
-    g_print ("%s\n", foo);
-  }
-#endif
-  return TRUE;
-}
-
 /**
  * swfdec_script_new:
  * @buffer: the #SwfdecBuffer containing the script. This function will take
@@ -239,13 +215,8 @@ swfdec_script_new_from_bits (SwfdecBits *bits, const char *name, guint version)
   SwfdecBuffer *buffer;
   SwfdecBits org;
   guint len;
-  
-  g_return_val_if_fail (bits != NULL, NULL);
 
-  if (version < SWFDEC_AS_MIN_SCRIPT_VERSION) {
-    SWFDEC_ERROR ("swfdec version %u doesn't support scripts", version);
-    return NULL;
-  }
+  g_return_val_if_fail (bits != NULL, NULL);
 
   org = *bits;
   len = swfdec_bits_left (bits) / 8;
@@ -259,10 +230,6 @@ swfdec_script_new_from_bits (SwfdecBits *bits, const char *name, guint version)
    * DefineFunction and friends override this */
   script->flags = SWFDEC_SCRIPT_SUPPRESS_ARGS;
 
-  if (!swfdec_script_foreach_internal (bits, validate_action, script)) {
-    swfdec_script_unref (script);
-    return NULL;
-  }
   len -= swfdec_bits_left (bits) / 8;
   if (len == 0) {
     buffer = swfdec_buffer_new ();
commit 97565c6e843c5fd2e203d56a8fecbf0ee5caef6d
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Mon Nov 5 12:04:45 2007 +0200

    Start removing version specific functions for actions
    
    Things don't quite compile yet

diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index 3182c08..18afbe2 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -762,14 +762,12 @@ swfdec_as_context_run (SwfdecAsContext *context)
   SwfdecAsFrame *frame, *last_frame;
   SwfdecScript *script;
   const SwfdecActionSpec *spec;
-  SwfdecActionExec exec;
   const guint8 *startpc, *pc, *endpc, *nextpc, *exitpc;
 #ifndef G_DISABLE_ASSERT
   SwfdecAsValue *check;
 #endif
   guint action, len;
   const guint8 *data;
-  int version;
   guint original_version;
   void (* step) (SwfdecAsDebugger *debugger, SwfdecAsContext *context);
   gboolean check_block; /* some opcodes avoid a scope check */
@@ -849,7 +847,6 @@ start:
   g_assert (frame->script);
   g_assert (frame->target);
   script = frame->script;
-  version = SWFDEC_AS_EXTRACT_SCRIPT_VERSION (script->version);
   context->version = script->version;
   startpc = script->buffer->data;
   endpc = startpc + script->buffer->length;
@@ -916,24 +913,16 @@ start:
       nextpc = pc + 1;
     }
     /* check action is valid */
-    exec = spec->exec[version];
-    if (!exec) {
-      guint real_version;
-      for (real_version = version + 1; !exec && 
-	  real_version <= SWFDEC_AS_MAX_SCRIPT_VERSION - SWFDEC_AS_MIN_SCRIPT_VERSION; 
-	  real_version++) {
-	exec = spec->exec[real_version];
-      }
-      if (!exec) {
-	SWFDEC_WARNING ("cannot interpret action %3u 0x%02X %s for version %u, skipping it", action,
-	    action, spec->name ? spec->name : "Unknown", script->version);
-	frame->pc = pc = nextpc;
-	check_block = TRUE;
-	continue;
-      }
-      SWFDEC_WARNING ("cannot interpret action %3u 0x%02X %s for version %u, using version %u instead", 
-	  action, action, spec->name ? spec->name : "Unknown", script->version, 
-	  script->version + real_version - version);
+    if (!spec->exec) {
+      SWFDEC_WARNING ("cannot interpret action %3u 0x%02X %s for version %u, skipping it", action,
+	  action, spec->name ? spec->name : "Unknown", script->version);
+      frame->pc = pc = nextpc;
+      check_block = TRUE;
+      continue;
+    }
+    if (script->version < spec->version) {
+      SWFDEC_WARNING ("cannot interpret action %3u 0x%02X %s for version %u, using version %u instead",
+	  action, action, spec->name ? spec->name : "Unknown", script->version, spec->version);
     }
     if (spec->remove > 0) {
       if (spec->add > spec->remove)
@@ -951,7 +940,7 @@ start:
     check = (spec->add >= 0 && spec->remove >= 0) ? context->cur + spec->add - spec->remove : NULL;
 #endif
     /* execute action */
-    exec (context, action, data, len);
+    spec->exec (context, action, data, len);
     /* adapt the pc if the action did not, otherwise, leave it alone */
     /* FIXME: do this via flag? */
     if (frame->pc == pc) {
diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index f711e19..4ef1dcd 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -3112,125 +3112,129 @@ swfdec_action_print_wait_for_frame (guint action, const guint8 *data, guint len)
 
 const SwfdecActionSpec swfdec_as_actions[256] = {
   /* version 3 */
-  [SWFDEC_AS_ACTION_NEXT_FRAME] = { "NextFrame", NULL, 0, 0, { swfdec_action_next_frame, swfdec_action_next_frame, swfdec_action_next_frame, swfdec_action_next_frame, swfdec_action_next_frame } },
-  [SWFDEC_AS_ACTION_PREVIOUS_FRAME] = { "PreviousFrame", NULL, 0, 0, { swfdec_action_previous_frame, swfdec_action_previous_frame, swfdec_action_previous_frame, swfdec_action_previous_frame, swfdec_action_previous_frame } },
-  [SWFDEC_AS_ACTION_PLAY] = { "Play", NULL, 0, 0, { swfdec_action_play, swfdec_action_play, swfdec_action_play, swfdec_action_play, swfdec_action_play } },
-  [SWFDEC_AS_ACTION_STOP] = { "Stop", NULL, 0, 0, { swfdec_action_stop, swfdec_action_stop, swfdec_action_stop, swfdec_action_stop, swfdec_action_stop } },
-  [SWFDEC_AS_ACTION_TOGGLE_QUALITY] = { "ToggleQuality", NULL },
-  [SWFDEC_AS_ACTION_STOP_SOUNDS] = { "StopSounds", NULL, 0, 0, { swfdec_action_stop_sounds, swfdec_action_stop_sounds, swfdec_action_stop_sounds, swfdec_action_stop_sounds, swfdec_action_stop_sounds } },
+  [SWFDEC_AS_ACTION_NEXT_FRAME] = { "NextFrame", NULL, 0, 0, swfdec_action_next_frame, 3 },
+  [SWFDEC_AS_ACTION_PREVIOUS_FRAME] = { "PreviousFrame", NULL, 0, 0, swfdec_action_previous_frame, 3 },
+  [SWFDEC_AS_ACTION_PLAY] = { "Play", NULL, 0, 0, swfdec_action_play, 3 },
+  [SWFDEC_AS_ACTION_STOP] = { "Stop", NULL, 0, 0, swfdec_action_stop, 3 },
+  [SWFDEC_AS_ACTION_TOGGLE_QUALITY] = { "ToggleQuality", NULL, },
+  [SWFDEC_AS_ACTION_STOP_SOUNDS] = { "StopSounds", NULL, 0, 0, swfdec_action_stop_sounds, 3 },
   /* version 4 */
-  [SWFDEC_AS_ACTION_ADD] = { "Add", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
-  [SWFDEC_AS_ACTION_SUBTRACT] = { "Subtract", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
-  [SWFDEC_AS_ACTION_MULTIPLY] = { "Multiply", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
-  [SWFDEC_AS_ACTION_DIVIDE] = { "Divide", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
-  [SWFDEC_AS_ACTION_EQUALS] = { "Equals", NULL, 2, 1, { NULL, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare } },
-  [SWFDEC_AS_ACTION_LESS] = { "Less", NULL, 2, 1, { NULL, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare } },
+  [SWFDEC_AS_ACTION_ADD] = { "Add", NULL, 2, 1, swfdec_action_binary, 4 },
+  [SWFDEC_AS_ACTION_SUBTRACT] = { "Subtract", NULL, 2, 1, swfdec_action_binary, 4 },
+  [SWFDEC_AS_ACTION_MULTIPLY] = { "Multiply", NULL, 2, 1, swfdec_action_binary, 4 },
+  [SWFDEC_AS_ACTION_DIVIDE] = { "Divide", NULL, 2, 1, swfdec_action_binary, 4 },
+  [SWFDEC_AS_ACTION_EQUALS] = { "Equals", NULL, 2, 1, swfdec_action_old_compare, 4 },
+  [SWFDEC_AS_ACTION_LESS] = { "Less", NULL, 2, 1, swfdec_action_old_compare, 4 },
   [SWFDEC_AS_ACTION_AND] = { "And", NULL, 2, 1, { NULL, /* FIXME */NULL, swfdec_action_logical, swfdec_action_logical, swfdec_action_logical } },
   [SWFDEC_AS_ACTION_OR] = { "Or", NULL, 2, 1, { NULL, /* FIXME */NULL, swfdec_action_logical, swfdec_action_logical, swfdec_action_logical } },
   [SWFDEC_AS_ACTION_NOT] = { "Not", NULL, 1, 1, { NULL, swfdec_action_not_4, swfdec_action_not_5, swfdec_action_not_5, swfdec_action_not_5 } },
-  [SWFDEC_AS_ACTION_STRING_EQUALS] = { "StringEquals", NULL, 2, 1, { NULL, swfdec_action_string_compare, swfdec_action_string_compare, swfdec_action_string_compare, swfdec_action_string_compare } },
-  [SWFDEC_AS_ACTION_STRING_LENGTH] = { "StringLength", NULL, 1, 1, { NULL, swfdec_action_string_length, swfdec_action_string_length, swfdec_action_string_length, swfdec_action_string_length } },
-  [SWFDEC_AS_ACTION_STRING_EXTRACT] = { "StringExtract", NULL, 3, 1, { NULL, swfdec_action_string_extract, swfdec_action_string_extract, swfdec_action_string_extract, swfdec_action_string_extract } },
-  [SWFDEC_AS_ACTION_POP] = { "Pop", NULL, 1, 0, { NULL, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop } },
-  [SWFDEC_AS_ACTION_TO_INTEGER] = { "ToInteger", NULL, 1, 1, { NULL, swfdec_action_to_integer, swfdec_action_to_integer, swfdec_action_to_integer, swfdec_action_to_integer } },
-  [SWFDEC_AS_ACTION_GET_VARIABLE] = { "GetVariable", NULL, 1, 1, { NULL, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable } },
-  [SWFDEC_AS_ACTION_SET_VARIABLE] = { "SetVariable", NULL, 2, 0, { NULL, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable } },
-  [SWFDEC_AS_ACTION_SET_TARGET2] = { "SetTarget2", NULL, 1, 0, { swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2 } },
-  [0x21] = { "StringAdd", NULL, 2, 1, { NULL, swfdec_action_string_add, swfdec_action_string_add, swfdec_action_string_add, swfdec_action_string_add } },
-  [SWFDEC_AS_ACTION_GET_PROPERTY] = { "GetProperty", NULL, 2, 1, { NULL, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property } },
-  [SWFDEC_AS_ACTION_SET_PROPERTY] = { "SetProperty", NULL, 3, 0, { NULL, swfdec_action_set_property, swfdec_action_set_property, swfdec_action_set_property, swfdec_action_set_property } },
-  [SWFDEC_AS_ACTION_CLONE_SPRITE] = { "CloneSprite", NULL, 3, 0, { NULL, swfdec_action_clone_sprite, swfdec_action_clone_sprite, swfdec_action_clone_sprite, swfdec_action_clone_sprite } },
-  [SWFDEC_AS_ACTION_REMOVE_SPRITE] = { "RemoveSprite", NULL, 1, 0, { NULL, swfdec_action_remove_sprite, swfdec_action_remove_sprite, swfdec_action_remove_sprite, swfdec_action_remove_sprite } },
-  [SWFDEC_AS_ACTION_TRACE] = { "Trace", NULL, 1, 0, { NULL, swfdec_action_trace, swfdec_action_trace, swfdec_action_trace, swfdec_action_trace } },
-  [SWFDEC_AS_ACTION_START_DRAG] = { "StartDrag", NULL, -1, 0, { NULL, swfdec_action_start_drag, swfdec_action_start_drag, swfdec_action_start_drag, swfdec_action_start_drag } },
-  [SWFDEC_AS_ACTION_END_DRAG] = { "EndDrag", NULL, 0, 0, { NULL, swfdec_action_end_drag, swfdec_action_end_drag, swfdec_action_end_drag, swfdec_action_end_drag } },
-  [SWFDEC_AS_ACTION_STRING_LESS] = { "StringLess", NULL, 2, 1, { NULL, swfdec_action_string_compare, swfdec_action_string_compare, swfdec_action_string_compare, swfdec_action_string_compare } },
+  [SWFDEC_AS_ACTION_STRING_EQUALS] = { "StringEquals", NULL, 2, 1, swfdec_action_string_compare, 4 },
+  [SWFDEC_AS_ACTION_STRING_LENGTH] = { "StringLength", NULL, 1, 1, swfdec_action_string_length, 4 },
+  [SWFDEC_AS_ACTION_STRING_EXTRACT] = { "StringExtract", NULL, 3, 1, swfdec_action_string_extract, 4 },
+  [SWFDEC_AS_ACTION_POP] = { "Pop", NULL, 1, 0, swfdec_action_pop, 4 },
+  [SWFDEC_AS_ACTION_TO_INTEGER] = { "ToInteger", NULL, 1, 1, swfdec_action_to_integer, 4 },
+  [SWFDEC_AS_ACTION_GET_VARIABLE] = { "GetVariable", NULL, 1, 1, swfdec_action_get_variable, 4 },
+  [SWFDEC_AS_ACTION_SET_VARIABLE] = { "SetVariable", NULL, 2, 0, swfdec_action_set_variable, 4 },
+  /* version 3 */
+  [SWFDEC_AS_ACTION_SET_TARGET2] = { "SetTarget2", NULL, 1, 0, swfdec_action_set_target2, 3 },
+  /* version 4 */
+  [0x21] = { "StringAdd", NULL, 2, 1, swfdec_action_string_add, 4 },
+  [SWFDEC_AS_ACTION_GET_PROPERTY] = { "GetProperty", NULL, 2, 1, swfdec_action_get_property, 4 },
+  [SWFDEC_AS_ACTION_SET_PROPERTY] = { "SetProperty", NULL, 3, 0, swfdec_action_set_property, 4 },
+  [SWFDEC_AS_ACTION_CLONE_SPRITE] = { "CloneSprite", NULL, 3, 0, swfdec_action_clone_sprite, 4 },
+  [SWFDEC_AS_ACTION_REMOVE_SPRITE] = { "RemoveSprite", NULL, 1, 0, swfdec_action_remove_sprite, 4 },
+  [SWFDEC_AS_ACTION_TRACE] = { "Trace", NULL, 1, 0, swfdec_action_trace, 4 },
+  [SWFDEC_AS_ACTION_START_DRAG] = { "StartDrag", NULL, -1, 0, swfdec_action_start_drag, 4 },
+  [SWFDEC_AS_ACTION_END_DRAG] = { "EndDrag", NULL, 0, 0, swfdec_action_end_drag, 4 },
+  [SWFDEC_AS_ACTION_STRING_LESS] = { "StringLess", NULL, 2, 1, swfdec_action_string_compare, 4 },
   /* version 7 */
-  [SWFDEC_AS_ACTION_THROW] = { "Throw", NULL, 1, 0, { NULL, NULL, NULL, NULL, swfdec_action_throw } },
-  [SWFDEC_AS_ACTION_CAST] = { "Cast", NULL, 2, 1, { NULL, NULL, NULL, NULL, swfdec_action_cast } },
-  [SWFDEC_AS_ACTION_IMPLEMENTS] = { "Implements", NULL, -1, 0, { NULL, NULL, NULL, NULL, swfdec_action_implements } },
+  [SWFDEC_AS_ACTION_THROW] = { "Throw", NULL, 1, 0, swfdec_action_throw, 7 },
+  [SWFDEC_AS_ACTION_CAST] = { "Cast", NULL, 2, 1, swfdec_action_cast, 7 },
+  [SWFDEC_AS_ACTION_IMPLEMENTS] = { "Implements", NULL, -1, 0, swfdec_action_implements, 7 },
   /* version 4 */
-  [0x30] = { "RandomNumber", NULL, 1, 1, { NULL, swfdec_action_random_number, swfdec_action_random_number, swfdec_action_random_number, swfdec_action_random_number } },
+  [0x30] = { "RandomNumber", NULL, 1, 1, swfdec_action_random_number, 4 },
   [SWFDEC_AS_ACTION_MB_STRING_LENGTH] = { "MBStringLength", NULL },
   [SWFDEC_AS_ACTION_CHAR_TO_ASCII] = { "CharToAscii", NULL, 1, 1, { NULL, swfdec_action_char_to_ascii_5, swfdec_action_char_to_ascii_5, swfdec_action_char_to_ascii, swfdec_action_char_to_ascii } },
   [SWFDEC_AS_ACTION_ASCII_TO_CHAR] = { "AsciiToChar", NULL, 1, 1, { NULL, swfdec_action_ascii_to_char_5, swfdec_action_ascii_to_char_5, swfdec_action_ascii_to_char, swfdec_action_ascii_to_char } },
-  [SWFDEC_AS_ACTION_GET_TIME] = { "GetTime", NULL, 0, 1, { NULL, swfdec_action_get_time, swfdec_action_get_time, swfdec_action_get_time, swfdec_action_get_time } },
-  [SWFDEC_AS_ACTION_MB_STRING_EXTRACT] = { "MBStringExtract", NULL, 3, 1, { NULL, swfdec_action_string_extract, swfdec_action_string_extract, swfdec_action_string_extract, swfdec_action_string_extract } },
+  [SWFDEC_AS_ACTION_GET_TIME] = { "GetTime", NULL, 0, 1, swfdec_action_get_time, 4 },
+  [SWFDEC_AS_ACTION_MB_STRING_EXTRACT] = { "MBStringExtract", NULL, 3, 1, swfdec_action_string_extract, 4 },
   [SWFDEC_AS_ACTION_MB_CHAR_TO_ASCII] = { "MBCharToAscii", NULL },
   [SWFDEC_AS_ACTION_MB_ASCII_TO_CHAR] = { "MBAsciiToChar", NULL, 1, 1, { NULL, swfdec_action_mb_ascii_to_char_5, swfdec_action_mb_ascii_to_char_5, swfdec_action_ascii_to_char, swfdec_action_ascii_to_char }  },
   /* version 5 */
-  [SWFDEC_AS_ACTION_DELETE] = { "Delete", NULL, 2, 1, { NULL, NULL, swfdec_action_delete, swfdec_action_delete, swfdec_action_delete } },
-  [SWFDEC_AS_ACTION_DELETE2] = { "Delete2", NULL, 1, 1, { NULL, NULL, swfdec_action_delete2, swfdec_action_delete2, swfdec_action_delete2 } },
-  [SWFDEC_AS_ACTION_DEFINE_LOCAL] = { "DefineLocal", NULL, 2, 0, { NULL, NULL, swfdec_action_define_local, swfdec_action_define_local, swfdec_action_define_local } },
-  [SWFDEC_AS_ACTION_CALL_FUNCTION] = { "CallFunction", NULL, -1, 1, { NULL, NULL, swfdec_action_call_function, swfdec_action_call_function, swfdec_action_call_function } },
-  [SWFDEC_AS_ACTION_RETURN] = { "Return", NULL, 1, 0, { NULL, NULL, swfdec_action_return, swfdec_action_return, swfdec_action_return } },
-  [SWFDEC_AS_ACTION_MODULO] = { "Modulo", NULL, 2, 1, { NULL, NULL, swfdec_action_modulo, swfdec_action_modulo, swfdec_action_modulo } },
-  [SWFDEC_AS_ACTION_NEW_OBJECT] = { "NewObject", NULL, -1, 1, { NULL, NULL, swfdec_action_new_object, swfdec_action_new_object, swfdec_action_new_object } },
-  [SWFDEC_AS_ACTION_DEFINE_LOCAL2] = { "DefineLocal2", NULL, 1, 0, { NULL, NULL, swfdec_action_define_local2, swfdec_action_define_local2, swfdec_action_define_local2 } },
-  [SWFDEC_AS_ACTION_INIT_ARRAY] = { "InitArray", NULL, -1, 1, { NULL, NULL, swfdec_action_init_array, swfdec_action_init_array, swfdec_action_init_array } },
-  [SWFDEC_AS_ACTION_INIT_OBJECT] = { "InitObject", NULL, -1, 1, { NULL, NULL, swfdec_action_init_object, swfdec_action_init_object, swfdec_action_init_object } },
-  [SWFDEC_AS_ACTION_TYPE_OF] = { "TypeOf", NULL, 1, 1, { NULL, NULL, swfdec_action_type_of, swfdec_action_type_of, swfdec_action_type_of } },
-  [SWFDEC_AS_ACTION_TARGET_PATH] = { "TargetPath", NULL, 1, 1, { NULL, NULL, swfdec_action_target_path, swfdec_action_target_path, swfdec_action_target_path } },
-  [SWFDEC_AS_ACTION_ENUMERATE] = { "Enumerate", NULL, 1, -1, { NULL, NULL, swfdec_action_enumerate, swfdec_action_enumerate, swfdec_action_enumerate } },
-  [SWFDEC_AS_ACTION_ADD2] = { "Add2", NULL, 2, 1, { NULL, NULL, swfdec_action_add2, swfdec_action_add2, swfdec_action_add2 } },
-  [SWFDEC_AS_ACTION_LESS2] = { "Less2", NULL, 2, 1, { NULL, NULL, swfdec_action_new_comparison, swfdec_action_new_comparison, swfdec_action_new_comparison } },
-  [SWFDEC_AS_ACTION_EQUALS2] = { "Equals2", NULL, 2, 1, { NULL, NULL, swfdec_action_equals2_5, swfdec_action_equals2, swfdec_action_equals2 } },
-  [SWFDEC_AS_ACTION_TO_NUMBER] = { "ToNumber", NULL, 1, 1, { NULL, NULL, swfdec_action_to_number, swfdec_action_to_number, swfdec_action_to_number } },
-  [SWFDEC_AS_ACTION_TO_STRING] = { "ToString", NULL, 1, 1, { NULL, NULL, swfdec_action_to_string, swfdec_action_to_string, swfdec_action_to_string } },
-  [SWFDEC_AS_ACTION_PUSH_DUPLICATE] = { "PushDuplicate", NULL, 1, 2, { NULL, NULL, swfdec_action_push_duplicate, swfdec_action_push_duplicate, swfdec_action_push_duplicate } },
-  [SWFDEC_AS_ACTION_SWAP] = { "Swap", NULL, 2, 2, { NULL, NULL, swfdec_action_swap, swfdec_action_swap, swfdec_action_swap } },
-  [SWFDEC_AS_ACTION_GET_MEMBER] = { "GetMember", NULL, 2, 1, { NULL, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member } },
-  [SWFDEC_AS_ACTION_SET_MEMBER] = { "SetMember", NULL, 3, 0, { NULL, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member } },
-  [SWFDEC_AS_ACTION_INCREMENT] = { "Increment", NULL, 1, 1, { NULL, NULL, swfdec_action_increment, swfdec_action_increment, swfdec_action_increment } },
-  [SWFDEC_AS_ACTION_DECREMENT] = { "Decrement", NULL, 1, 1, { NULL, NULL, swfdec_action_decrement, swfdec_action_decrement, swfdec_action_decrement } },
-  [SWFDEC_AS_ACTION_CALL_METHOD] = { "CallMethod", NULL, -1, 1, { NULL, NULL, swfdec_action_call_method, swfdec_action_call_method, swfdec_action_call_method } },
-  [SWFDEC_AS_ACTION_NEW_METHOD] = { "NewMethod", NULL, -1, 1, { NULL, NULL, swfdec_action_new_method, swfdec_action_new_method, swfdec_action_new_method } },
+  [SWFDEC_AS_ACTION_DELETE] = { "Delete", NULL, 2, 1, swfdec_action_delete, 5 },
+  [SWFDEC_AS_ACTION_DELETE2] = { "Delete2", NULL, 1, 1, swfdec_action_delete2, 5 },
+  [SWFDEC_AS_ACTION_DEFINE_LOCAL] = { "DefineLocal", NULL, 2, 0, swfdec_action_define_local, 5 },
+  [SWFDEC_AS_ACTION_CALL_FUNCTION] = { "CallFunction", NULL, -1, 1, swfdec_action_call_function, 5 },
+  [SWFDEC_AS_ACTION_RETURN] = { "Return", NULL, 1, 0, swfdec_action_return, 5 },
+  [SWFDEC_AS_ACTION_MODULO] = { "Modulo", NULL, 2, 1, swfdec_action_modulo, 5 },
+  [SWFDEC_AS_ACTION_NEW_OBJECT] = { "NewObject", NULL, -1, 1, swfdec_action_new_object, 5 },
+  [SWFDEC_AS_ACTION_DEFINE_LOCAL2] = { "DefineLocal2", NULL, 1, 0, swfdec_action_define_local2, 5 },
+  [SWFDEC_AS_ACTION_INIT_ARRAY] = { "InitArray", NULL, -1, 1, swfdec_action_init_array, 5 },
+  [SWFDEC_AS_ACTION_INIT_OBJECT] = { "InitObject", NULL, -1, 1, swfdec_action_init_object, 5 },
+  [SWFDEC_AS_ACTION_TYPE_OF] = { "TypeOf", NULL, 1, 1, swfdec_action_type_of, 5 },
+  [SWFDEC_AS_ACTION_TARGET_PATH] = { "TargetPath", NULL, 1, 1, swfdec_action_target_path, 5 },
+  [SWFDEC_AS_ACTION_ENUMERATE] = { "Enumerate", NULL, 1, -1, swfdec_action_enumerate, 5 },
+  [SWFDEC_AS_ACTION_ADD2] = { "Add2", NULL, 2, 1, swfdec_action_add2, 5 },
+  [SWFDEC_AS_ACTION_LESS2] = { "Less2", NULL, 2, 1, swfdec_action_new_comparison, 5 },
+  [SWFDEC_AS_ACTION_EQUALS2] = { "Equals2", NULL, 2, 1, swfdec_action_equals2_5, 5 },
+  [SWFDEC_AS_ACTION_TO_NUMBER] = { "ToNumber", NULL, 1, 1, swfdec_action_to_number, 5 },
+  [SWFDEC_AS_ACTION_TO_STRING] = { "ToString", NULL, 1, 1, swfdec_action_to_string, 5 },
+  [SWFDEC_AS_ACTION_PUSH_DUPLICATE] = { "PushDuplicate", NULL, 1, 2, swfdec_action_push_duplicate, 5 },
+  [SWFDEC_AS_ACTION_SWAP] = { "Swap", NULL, 2, 2, swfdec_action_swap, 5 },
+  /* version 4 */
+  [SWFDEC_AS_ACTION_GET_MEMBER] = { "GetMember", NULL, 2, 1, swfdec_action_get_member, 4 },
+  [SWFDEC_AS_ACTION_SET_MEMBER] = { "SetMember", NULL, 3, 0, swfdec_action_set_member, 4 },
+  /* version 5 */
+  [SWFDEC_AS_ACTION_INCREMENT] = { "Increment", NULL, 1, 1, swfdec_action_increment, 5 },
+  [SWFDEC_AS_ACTION_DECREMENT] = { "Decrement", NULL, 1, 1, swfdec_action_decrement, 5 },
+  [SWFDEC_AS_ACTION_CALL_METHOD] = { "CallMethod", NULL, -1, 1, swfdec_action_call_method, 5 },
+  [SWFDEC_AS_ACTION_NEW_METHOD] = { "NewMethod", NULL, -1, 1, swfdec_action_new_method, 5 },
   /* version 6 */
-  [SWFDEC_AS_ACTION_INSTANCE_OF] = { "InstanceOf", NULL, 2, 1, { NULL, NULL, NULL, swfdec_action_instance_of, swfdec_action_instance_of } },
-  [SWFDEC_AS_ACTION_ENUMERATE2] = { "Enumerate2", NULL, 1, -1, { NULL, NULL, NULL, swfdec_action_enumerate2, swfdec_action_enumerate2 } },
+  [SWFDEC_AS_ACTION_INSTANCE_OF] = { "InstanceOf", NULL, 2, 1, swfdec_action_instance_of, 6 },
+  [SWFDEC_AS_ACTION_ENUMERATE2] = { "Enumerate2", NULL, 1, -1, swfdec_action_enumerate2, 6 },
   [SWFDEC_AS_ACTION_BREAKPOINT] = { "Breakpoint", NULL, },
   /* version 5 */
-  [SWFDEC_AS_ACTION_BIT_AND] = { "BitAnd", NULL, 2, 1, { NULL, NULL, swfdec_action_bitwise, swfdec_action_bitwise, swfdec_action_bitwise } },
-  [SWFDEC_AS_ACTION_BIT_OR] = { "BitOr", NULL, 2, 1, { NULL, NULL, swfdec_action_bitwise, swfdec_action_bitwise, swfdec_action_bitwise } },
-  [SWFDEC_AS_ACTION_BIT_XOR] = { "BitXor", NULL, 2, 1, { NULL, NULL, swfdec_action_bitwise, swfdec_action_bitwise, swfdec_action_bitwise } },
-  [SWFDEC_AS_ACTION_BIT_LSHIFT] = { "BitLShift", NULL, 2, 1, { NULL, NULL, swfdec_action_shift, swfdec_action_shift, swfdec_action_shift } },
-  [SWFDEC_AS_ACTION_BIT_RSHIFT] = { "BitRShift", NULL, 2, 1, { NULL, NULL, swfdec_action_shift, swfdec_action_shift, swfdec_action_shift } },
-  [SWFDEC_AS_ACTION_BIT_URSHIFT] = { "BitURShift", NULL, 2, 1, { NULL, NULL, swfdec_action_shift, swfdec_action_shift, swfdec_action_shift } },
+  [SWFDEC_AS_ACTION_BIT_AND] = { "BitAnd", NULL, 2, 1, swfdec_action_bitwise, 5 },
+  [SWFDEC_AS_ACTION_BIT_OR] = { "BitOr", NULL, 2, 1, swfdec_action_bitwise, 5 },
+  [SWFDEC_AS_ACTION_BIT_XOR] = { "BitXor", NULL, 2, 1, swfdec_action_bitwise, 5 },
+  [SWFDEC_AS_ACTION_BIT_LSHIFT] = { "BitLShift", NULL, 2, 1, swfdec_action_shift, 5 },
+  [SWFDEC_AS_ACTION_BIT_RSHIFT] = { "BitRShift", NULL, 2, 1, swfdec_action_shift, 5 },
+  [SWFDEC_AS_ACTION_BIT_URSHIFT] = { "BitURShift", NULL, 2, 1, swfdec_action_shift, 5 },
   /* version 6 */
-  [SWFDEC_AS_ACTION_STRICT_EQUALS] = { "StrictEquals", NULL, 2, 1, { NULL, NULL, NULL, swfdec_action_strict_equals, swfdec_action_strict_equals } },
-  [SWFDEC_AS_ACTION_GREATER] = { "Greater", NULL, 2, 1, { NULL, NULL, NULL, swfdec_action_new_comparison, swfdec_action_new_comparison } },
+  [SWFDEC_AS_ACTION_STRICT_EQUALS] = { "StrictEquals", NULL, 2, 1, swfdec_action_strict_equals, 6 },
+  [SWFDEC_AS_ACTION_GREATER] = { "Greater", NULL, 2, 1, swfdec_action_new_comparison, 6 },
   [SWFDEC_AS_ACTION_STRING_GREATER] = { "StringGreater", NULL },
   /* version 7 */
   [SWFDEC_AS_ACTION_EXTENDS] = { "Extends", NULL, 2, 0, { NULL, NULL, NULL, swfdec_action_extends, swfdec_action_extends } },
   /* version 3 */
-  [SWFDEC_AS_ACTION_GOTO_FRAME] = { "GotoFrame", swfdec_action_print_goto_frame, 0, 0, { swfdec_action_goto_frame, swfdec_action_goto_frame, swfdec_action_goto_frame, swfdec_action_goto_frame, swfdec_action_goto_frame } },
-  [SWFDEC_AS_ACTION_GET_URL] = { "GetURL", swfdec_action_print_get_url, 0, 0, { swfdec_action_get_url, swfdec_action_get_url, swfdec_action_get_url, swfdec_action_get_url, swfdec_action_get_url } },
+  [SWFDEC_AS_ACTION_GOTO_FRAME] = { "GotoFrame", swfdec_action_print_goto_frame, 0, 0, swfdec_action_goto_frame, 3 },
+  [SWFDEC_AS_ACTION_GET_URL] = { "GetURL", swfdec_action_print_get_url, 0, 0, swfdec_action_get_url, 3 },
   /* version 5 */
-  [SWFDEC_AS_ACTION_STORE_REGISTER] = { "StoreRegister", swfdec_action_print_store_register, 1, 1, { NULL, NULL, swfdec_action_store_register, swfdec_action_store_register, swfdec_action_store_register } },
-  [SWFDEC_AS_ACTION_CONSTANT_POOL] = { "ConstantPool", swfdec_action_print_constant_pool, 0, 0, { NULL, NULL, swfdec_action_constant_pool, swfdec_action_constant_pool, swfdec_action_constant_pool } },
+  [SWFDEC_AS_ACTION_STORE_REGISTER] = { "StoreRegister", swfdec_action_print_store_register, 1, 1, swfdec_action_store_register, 5 },
+  [SWFDEC_AS_ACTION_CONSTANT_POOL] = { "ConstantPool", swfdec_action_print_constant_pool, 0, 0, swfdec_action_constant_pool, 5 },
   /* version 3 */
   [SWFDEC_AS_ACTION_STRICT_MODE] = { "StrictMode", NULL, },
-  [SWFDEC_AS_ACTION_WAIT_FOR_FRAME] = { "WaitForFrame", swfdec_action_print_wait_for_frame, 0, 0, { swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame } },
-  [SWFDEC_AS_ACTION_SET_TARGET] = { "SetTarget", swfdec_action_print_set_target, 0, 0, { swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target } },
-  [SWFDEC_AS_ACTION_GOTO_LABEL] = { "GotoLabel", swfdec_action_print_goto_label, 0, 0, { swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label } },
+  [SWFDEC_AS_ACTION_WAIT_FOR_FRAME] = { "WaitForFrame", swfdec_action_print_wait_for_frame, 0, 0, swfdec_action_wait_for_frame, 3 },
+  [SWFDEC_AS_ACTION_SET_TARGET] = { "SetTarget", swfdec_action_print_set_target, 0, 0, swfdec_action_set_target, 3 },
+  [SWFDEC_AS_ACTION_GOTO_LABEL] = { "GotoLabel", swfdec_action_print_goto_label, 0, 0, swfdec_action_goto_label, 3 },
 #if 0
   /* version 4 */
   [0x8d] = { "WaitForFrame2", swfdec_action_print_wait_for_frame2, 1, 0, { NULL, swfdec_action_wait_for_frame2, swfdec_action_wait_for_frame2, swfdec_action_wait_for_frame2, swfdec_action_wait_for_frame2 } },
 #endif
   /* version 7 */
-  [SWFDEC_AS_ACTION_DEFINE_FUNCTION2] = { "DefineFunction2", swfdec_action_print_define_function, 0, -1, { NULL, NULL, NULL, swfdec_action_define_function, swfdec_action_define_function } },
+  [SWFDEC_AS_ACTION_DEFINE_FUNCTION2] = { "DefineFunction2", swfdec_action_print_define_function, 0, -1, swfdec_action_define_function, 7 },
   [SWFDEC_AS_ACTION_TRY] = { "Try", NULL, 0, 0, { NULL, NULL, NULL, NULL, swfdec_action_try } },
   /* version 5 */
-  [SWFDEC_AS_ACTION_WITH] = { "With", swfdec_action_print_with, 1, 0, { NULL, NULL, swfdec_action_with, swfdec_action_with, swfdec_action_with } },
+  [SWFDEC_AS_ACTION_WITH] = { "With", swfdec_action_print_with, 1, 0, swfdec_action_with, 5 },
   /* version 4 */
-  [SWFDEC_AS_ACTION_PUSH] = { "Push", swfdec_action_print_push, 0, -1, { NULL, swfdec_action_push, swfdec_action_push, swfdec_action_push, swfdec_action_push } },
-  [SWFDEC_AS_ACTION_JUMP] = { "Jump", swfdec_action_print_jump, 0, 0, { NULL, swfdec_action_jump, swfdec_action_jump, swfdec_action_jump, swfdec_action_jump } },
-  [SWFDEC_AS_ACTION_GET_URL2] = { "GetURL2", swfdec_action_print_get_url2, 2, 0, { NULL, swfdec_action_get_url2, swfdec_action_get_url2, swfdec_action_get_url2, swfdec_action_get_url2 } },
+  [SWFDEC_AS_ACTION_PUSH] = { "Push", swfdec_action_print_push, 0, -1, swfdec_action_push, 4 },
+  [SWFDEC_AS_ACTION_JUMP] = { "Jump", swfdec_action_print_jump, 0, 0, swfdec_action_jump, 4 },
+  [SWFDEC_AS_ACTION_GET_URL2] = { "GetURL2", swfdec_action_print_get_url2, 2, 0, swfdec_action_get_url2, 4 },
   /* version 5 */
-  [SWFDEC_AS_ACTION_DEFINE_FUNCTION] = { "DefineFunction", swfdec_action_print_define_function, 0, -1, { NULL, NULL, swfdec_action_define_function, swfdec_action_define_function, swfdec_action_define_function } },
+  [SWFDEC_AS_ACTION_DEFINE_FUNCTION] = { "DefineFunction", swfdec_action_print_define_function, 0, -1, swfdec_action_define_function, 5 },
   /* version 4 */
-  [SWFDEC_AS_ACTION_IF] = { "If", swfdec_action_print_if, 1, 0, { NULL, swfdec_action_if, swfdec_action_if, swfdec_action_if, swfdec_action_if } },
+  [SWFDEC_AS_ACTION_IF] = { "If", swfdec_action_print_if, 1, 0, swfdec_action_if, 4 },
   [SWFDEC_AS_ACTION_CALL] = { "Call", NULL },
-  [SWFDEC_AS_ACTION_GOTO_FRAME2] = { "GotoFrame2", swfdec_action_print_goto_frame2, 1, 0, { NULL, swfdec_action_goto_frame2, swfdec_action_goto_frame2, swfdec_action_goto_frame2, swfdec_action_goto_frame2 } }
+  [SWFDEC_AS_ACTION_GOTO_FRAME2] = { "GotoFrame2", swfdec_action_print_goto_frame2, 1, 0, swfdec_action_goto_frame2, 4 }
 };
 
diff --git a/libswfdec/swfdec_as_interpret.h b/libswfdec/swfdec_as_interpret.h
index 37689eb..2877635 100644
--- a/libswfdec/swfdec_as_interpret.h
+++ b/libswfdec/swfdec_as_interpret.h
@@ -24,19 +24,13 @@
 
 G_BEGIN_DECLS
 
-/* defines minimum and maximum versions for which we have seperate scripts */
-#define SWFDEC_AS_MIN_SCRIPT_VERSION 3
-#define SWFDEC_AS_MAX_SCRIPT_VERSION 7
-#define SWFDEC_AS_EXTRACT_SCRIPT_VERSION(v) MIN ((v) - SWFDEC_AS_MIN_SCRIPT_VERSION, SWFDEC_AS_MAX_SCRIPT_VERSION - SWFDEC_AS_MIN_SCRIPT_VERSION)
-
-typedef void (* SwfdecActionExec) (SwfdecAsContext *cx, guint action, const guint8 *data, guint len);
 typedef struct {
   const char *		name;		/* name identifying the action */
   char *		(* print)	(guint action, const guint8 *data, guint len);
   int			remove;		/* values removed from stack or -1 for dynamic */
   int			add;		/* values added to the stack or -1 for dynamic */
-  SwfdecActionExec	exec[SWFDEC_AS_MAX_SCRIPT_VERSION - SWFDEC_AS_MIN_SCRIPT_VERSION + 1];
-					/* array is for version 3, 4, 5, 6, 7+ */
+  void			(* exec)	(SwfdecAsContext *cx, guint action, const guint8 *data, guint len);
+  int			version;	/* the version this action was introduced in */
 } SwfdecActionSpec;
 
 extern const SwfdecActionSpec swfdec_as_actions[256];
commit 710fe22f1590177fdd63942b54a36018578b32f9
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Mon Nov 5 11:28:32 2007 +0200

    Implement the PlaceObject tag (used in version 1 and 2)

diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c
index dcd01c6..0a7ebb3 100644
--- a/libswfdec/swfdec_sprite_movie.c
+++ b/libswfdec/swfdec_sprite_movie.c
@@ -63,6 +63,74 @@ swfdec_get_clipeventflags (SwfdecMovie *movie, SwfdecBits * bits)
 }
 
 static gboolean
+swfdec_sprite_movie_perform_old_place (SwfdecSpriteMovie *movie,
+    SwfdecBits *bits, guint tag)
+{
+  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  SwfdecMovie *mov = SWFDEC_MOVIE (movie);
+  SwfdecMovie *cur;
+  SwfdecSwfDecoder *dec;
+  int depth;
+  cairo_matrix_t transform;
+  gboolean has_ctrans;
+  SwfdecColorTransform ctrans;
+  guint id;
+  SwfdecGraphic *graphic;
+
+  dec = SWFDEC_SWF_DECODER (mov->resource->decoder);
+
+  SWFDEC_LOG ("performing PlaceObject on movie %s", mov->name);
+
+  id = swfdec_bits_get_u16 (bits);
+  SWFDEC_LOG ("  id = %d", id);
+
+  depth = swfdec_bits_get_u16 (bits);
+  if (depth >= 16384) {
+    SWFDEC_FIXME ("depth of placement too high: %u >= 16384", depth);
+  }
+  SWFDEC_LOG ("  depth = %d (=> %d)", depth, depth - 16384);
+  depth -= 16384;
+
+  swfdec_bits_get_matrix (bits, &transform, NULL);
+  SWFDEC_LOG ("  matrix = { %g %g, %g %g } + { %g %g }",
+      transform.xx, transform.yx,
+      transform.xy, transform.yy,
+      transform.x0, transform.y0);
+
+  if (swfdec_bits_left (bits)) {
+    has_ctrans = TRUE;
+    swfdec_bits_get_color_transform (bits, &ctrans);
+    SWFDEC_LOG ("  color transform = %d %d  %d %d  %d %d  %d %d",
+	ctrans.ra, ctrans.rb,
+	ctrans.ga, ctrans.gb,
+	ctrans.ba, ctrans.bb,
+	ctrans.aa, ctrans.ab);
+  } else {
+    has_ctrans = FALSE;
+  }
+
+  /* 3) perform the actions depending on the set properties */
+  cur = swfdec_movie_find (mov, depth);
+  graphic = swfdec_swf_decoder_get_character (dec, id);
+
+  if (!SWFDEC_IS_GRAPHIC (graphic)) {
+    SWFDEC_FIXME ("character %u is not a graphic (does it even exist?), aborting", id);
+    return FALSE;
+  }
+
+  cur = swfdec_movie_new (player, depth, mov, mov->resource, graphic, NULL);
+  swfdec_movie_set_static_properties (cur, &transform,
+      has_ctrans ? &ctrans : NULL, -1, 0, 0, NULL);
+  swfdec_movie_queue_script (cur, SWFDEC_EVENT_INITIALIZE);
+  swfdec_movie_queue_script (cur, SWFDEC_EVENT_CONSTRUCT);
+  swfdec_movie_queue_script (cur, SWFDEC_EVENT_LOAD);
+  swfdec_movie_initialize (cur);
+
+  return TRUE;
+}
+
+
+static gboolean
 swfdec_sprite_movie_perform_place (SwfdecSpriteMovie *movie, SwfdecBits *bits, guint tag)
 {
   SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
@@ -77,7 +145,7 @@ swfdec_sprite_movie_perform_place (SwfdecSpriteMovie *movie, SwfdecBits *bits, g
   gboolean has_transform;
   gboolean has_character;
   gboolean move;
-  gboolean depth;
+  int depth;
   gboolean cache;
   gboolean has_blend_mode = 0;
   gboolean has_filter = 0;
@@ -311,6 +379,8 @@ swfdec_sprite_movie_perform_one_action (SwfdecSpriteMovie *movie, guint tag, Swf
 	swfdec_player_add_action_script (player, mov, script, 2);
       }
       return TRUE;
+    case SWFDEC_TAG_PLACEOBJECT:
+      return swfdec_sprite_movie_perform_old_place (movie, &bits, tag);
     case SWFDEC_TAG_PLACEOBJECT2:
     case SWFDEC_TAG_PLACEOBJECT3:
       return swfdec_sprite_movie_perform_place (movie, &bits, tag);
diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c
index dd552e4..1b18fd2 100644
--- a/libswfdec/swfdec_tag.c
+++ b/libswfdec/swfdec_tag.c
@@ -586,7 +586,7 @@ static struct tag_func_struct tag_funcs[] = {
   [SWFDEC_TAG_SHOWFRAME] = {"ShowFrame", tag_func_show_frame, SWFDEC_TAG_DEFINE_SPRITE },
   [SWFDEC_TAG_DEFINESHAPE] = {"DefineShape", tag_define_shape, 0},
   [SWFDEC_TAG_FREECHARACTER] = {"FreeCharacter", NULL, 0},
-  [SWFDEC_TAG_PLACEOBJECT] = {"PlaceObject", NULL, SWFDEC_TAG_DEFINE_SPRITE },
+  [SWFDEC_TAG_PLACEOBJECT] = {"PlaceObject", tag_func_enqueue, SWFDEC_TAG_DEFINE_SPRITE },
   [SWFDEC_TAG_REMOVEOBJECT] = {"RemoveObject", tag_func_enqueue, SWFDEC_TAG_DEFINE_SPRITE },
   [SWFDEC_TAG_DEFINEBITSJPEG] = {"DefineBitsJPEG", tag_func_define_bits_jpeg, 0},
   [SWFDEC_TAG_DEFINEBUTTON] = {"DefineButton", tag_func_define_button, 0},
commit 0918dde13729a6e6b5fd6ad7ce3017977bef492e
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sun Nov 4 22:16:54 2007 +0200

    Draw bullets in TextField

diff --git a/libswfdec/swfdec_text_field_movie.c b/libswfdec/swfdec_text_field_movie.c
index b7b0cf2..7bcc6dd 100644
--- a/libswfdec/swfdec_text_field_movie.c
+++ b/libswfdec/swfdec_text_field_movie.c
@@ -38,6 +38,7 @@
 G_DEFINE_TYPE (SwfdecTextFieldMovie, swfdec_text_field_movie, SWFDEC_TYPE_MOVIE)
 
 #define EXTRA_MARGIN 2
+#define BULLET_MARGIN 36
 
 static void
 swfdec_text_field_movie_update_extents (SwfdecMovie *movie,
@@ -543,7 +544,7 @@ swfdec_text_field_movie_get_layouts (SwfdecTextFieldMovie *text, int *num,
       // set rendering position
       layout.offset_x = block->left_margin + block->block_indent;
       if (paragraphs[i].bullet)
-	layout.offset_x += 36 * 20;
+	layout.offset_x += SWFDEC_DOUBLE_TO_TWIPS (BULLET_MARGIN);
 
       width = SWFDEC_MOVIE (text)->original_extents.x1 -
 	SWFDEC_MOVIE (text)->original_extents.x0 - block->right_margin -
@@ -569,9 +570,10 @@ swfdec_text_field_movie_get_layouts (SwfdecTextFieldMovie *text, int *num,
       // set paragraph styles
       if (block->index_ == 0) {
 	pango_layout_set_indent (playout, paragraphs[i].indent);
-	// TODO: bullet
+	layout.bullet = paragraphs[i].bullet;
       } else {
 	pango_layout_set_indent (playout, 0);
+	layout.bullet = FALSE;
       }
 
       // set block styles
@@ -748,7 +750,6 @@ swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
   linenum = 0;
   x = movie->original_extents.x0 + EXTRA_MARGIN + text_movie->hscroll;
   y = movie->original_extents.y0 + EXTRA_MARGIN;
-  cairo_move_to (cr, x, y);
 
   for (i = 0; layouts[i].layout != NULL && y < limit.y1; i++)
   {
@@ -760,6 +761,37 @@ swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
 
     iter_line = pango_layout_get_iter (layout->layout);
 
+    if (layout->bullet && linenum + 1 >= text_movie->scroll) {
+      PangoColor color_p;
+      PangoAttribute *attr;
+      PangoAttrIterator *attr_iter;
+
+      pango_layout_iter_get_line_extents (iter_line, NULL, &rect);
+      pango_extents_to_pixels (NULL, &rect);
+
+      cairo_new_sub_path (cr);
+
+      // get current color
+      attr_iter = pango_attr_list_get_iterator (
+	  pango_layout_get_attributes (layout->layout));
+      attr = pango_attr_iterator_get (attr_iter, PANGO_ATTR_FOREGROUND);
+      color_p = ((PangoAttrColor *)attr)->color;
+      color = SWFDEC_COLOR_COMBINE (color_p.red >> 8, color_p.green >> 8,
+	  color_p.blue >> 8, 255);
+      color = swfdec_color_apply_transform (color, trans);
+      pango_attr_iterator_destroy (attr_iter);
+
+      swfdec_color_set_source (cr, color);
+
+      cairo_arc (cr, x + layout->offset_x +
+	  pango_layout_get_indent (layout->layout) -
+	  SWFDEC_DOUBLE_TO_TWIPS (BULLET_MARGIN) / 2,
+	  y + rect.height / 2, rect.height / 8, 20, 2 * M_PI);
+      cairo_fill (cr);
+    }
+
+    cairo_move_to (cr, x, y);
+
     skipped = 0;
     do {
       if (++linenum < text_movie->scroll)
diff --git a/libswfdec/swfdec_text_field_movie.h b/libswfdec/swfdec_text_field_movie.h
index c574279..8d719d3 100644
--- a/libswfdec/swfdec_text_field_movie.h
+++ b/libswfdec/swfdec_text_field_movie.h
@@ -44,6 +44,7 @@ typedef struct {
   int			last_line_offset_y;
   int			height;
   int			width;
+  gboolean		bullet;
 } SwfdecLayout;
 
 typedef struct {
commit b0e8f33ecfbc410c901d354c24c38b28d61569f2
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sun Nov 4 16:39:49 2007 +0200

    Add indentation to TextField when bullet style is used

diff --git a/libswfdec/swfdec_text_field_movie.c b/libswfdec/swfdec_text_field_movie.c
index 08afd73..b7b0cf2 100644
--- a/libswfdec/swfdec_text_field_movie.c
+++ b/libswfdec/swfdec_text_field_movie.c
@@ -542,9 +542,12 @@ swfdec_text_field_movie_get_layouts (SwfdecTextFieldMovie *text, int *num,
 
       // set rendering position
       layout.offset_x = block->left_margin + block->block_indent;
+      if (paragraphs[i].bullet)
+	layout.offset_x += 36 * 20;
+
       width = SWFDEC_MOVIE (text)->original_extents.x1 -
-	SWFDEC_MOVIE (text)->original_extents.x0 - block->left_margin -
-	block->right_margin - block->block_indent;
+	SWFDEC_MOVIE (text)->original_extents.x0 - block->right_margin -
+	layout.offset_x;
 
       if (block->index_ == 0 && paragraphs[i].indent < 0) {
 	// limit negative indent to not go over leftMargin + blockIndent


More information about the Swfdec mailing list