[Swfdec] Branch 'interpreter' - libswfdec/swfdec_script.c
Benjamin Otte
company at kemper.freedesktop.org
Thu Feb 1 07:10:31 PST 2007
libswfdec/swfdec_script.c | 136 ++++++++++++++++++++++++++++++++--------------
1 files changed, 97 insertions(+), 39 deletions(-)
New commits:
diff-tree 94e07c556a4e4f471f6700af54f35e55edf79a85 (from 18aff9069e571bda0bf49290c7ad415597d1d16e)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 16:11:16 2007 +0100
implement WaitForFrame2
videostar.swf works now
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 39b3b8b..c416f64 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -267,6 +267,27 @@ swfdec_action_goto_label (JSContext *cx,
return JS_TRUE;
}
+static int
+swfdec_value_to_frame (JSContext *cx, SwfdecMovie *movie, jsval val)
+{
+ int frame;
+
+ if (JSVAL_IS_STRING (val)) {
+ const char *name = swfdec_js_to_string (cx, val);
+ if (name == NULL ||
+ !SWFDEC_IS_SPRITE_MOVIE (movie))
+ return -1;
+ if (strchr (name, ':')) {
+ SWFDEC_ERROR ("FIXME: handle targets");
+ }
+ frame = swfdec_sprite_get_frame (SWFDEC_SPRITE_MOVIE (movie)->sprite, name);
+ } else {
+ /* FIXME: how do we treat undefined etc? */
+ frame = swfdec_action_to_number (cx, val);
+ }
+ return frame;
+}
+
static JSBool
swfdec_action_goto_frame2 (JSContext *cx, guint action, const guint8 *data, guint len)
{
@@ -274,7 +295,6 @@ swfdec_action_goto_frame2 (JSContext *cx
guint bias;
gboolean play;
jsval val;
- int frame;
SwfdecMovie *movie;
swfdec_bits_init_data (&bits, data, len);
@@ -288,24 +308,13 @@ swfdec_action_goto_frame2 (JSContext *cx
}
val = cx->fp->sp[-1];
cx->fp->sp--;
- if (JSVAL_IS_STRING (val)) {
- const char *name = swfdec_js_to_string (cx, val);
- if (name == NULL)
- return JS_FALSE;
- if (strchr (name, ':')) {
- SWFDEC_ERROR ("FIXME: handle targets");
- }
- frame = swfdec_sprite_get_frame (SWFDEC_SPRITE_MOVIE (movie)->sprite, name);
- if (frame == -1)
- return JS_TRUE;
- } else {
- /* FIXME: how do we treat undefined etc? */
- frame = swfdec_action_to_number (cx, val);
- }
- frame += bias;
- /* now set it */
movie = swfdec_action_get_target (cx);
+ /* now set it */
if (movie) {
+ int frame = swfdec_value_to_frame (cx, movie, val);
+ if (frame < 0)
+ return JS_TRUE;
+ frame += bias;
frame = CLAMP (frame, 0, (int) movie->n_frames - 1);
swfdec_movie_goto (movie, frame);
movie->stopped = !play;
@@ -315,6 +324,63 @@ swfdec_action_goto_frame2 (JSContext *cx
return JS_TRUE;
}
+static void
+swfdec_script_skip_actions (JSContext *cx, guint jump)
+{
+ SwfdecScript *script = cx->fp->swf;
+ guint8 *pc = cx->fp->pc;
+ guint8 *endpc = script->buffer->data + script->buffer->length;
+
+ /* jump instructions */
+ g_assert (script);
+ do {
+ if (pc >= endpc)
+ break;
+ if (*pc & 0x80) {
+ if (pc + 2 >= endpc)
+ break;
+ pc += 3 + GUINT16_FROM_LE (*((guint16 *) (pc + 1)));
+ } else {
+ pc++;
+ }
+ } while (jump-- > 0);
+ cx->fp->pc = pc;
+}
+
+static JSBool
+swfdec_action_wait_for_frame2 (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval val;
+ SwfdecMovie *movie;
+
+ if (len != 1) {
+ SWFDEC_ERROR ("WaitForFrame2 needs a 1-byte data");
+ return JS_FALSE;
+ }
+ val = cx->fp->sp[-1];
+ cx->fp->sp--;
+ movie = swfdec_action_get_target (cx);
+ if (movie) {
+ int frame = swfdec_value_to_frame (cx, movie, val);
+ guint jump = data[2];
+ guint loaded;
+ if (frame < 0)
+ return JS_TRUE;
+ if (SWFDEC_IS_ROOT_MOVIE (movie)) {
+ SwfdecDecoder *dec = SWFDEC_ROOT_MOVIE (movie)->decoder;
+ loaded = dec->frames_loaded;
+ g_assert (loaded <= movie->n_frames);
+ } else {
+ loaded = movie->n_frames;
+ }
+ if (loaded < (guint) frame)
+ swfdec_script_skip_actions (cx, jump);
+ } else {
+ SWFDEC_ERROR ("no movie to WaitForFrame2 on");
+ }
+ return JS_TRUE;
+}
+
static JSBool
swfdec_action_wait_for_frame (JSContext *cx, guint action, const guint8 *data, guint len)
{
@@ -333,32 +399,14 @@ swfdec_action_wait_for_frame (JSContext
frame = GUINT16_FROM_LE (*((guint16 *) data));
jump = data[2];
if (SWFDEC_IS_ROOT_MOVIE (movie)) {
- SwfdecDecoder *dec = SWFDEC_ROOT_MOVIE (movie->root)->decoder;
+ SwfdecDecoder *dec = SWFDEC_ROOT_MOVIE (movie)->decoder;
loaded = dec->frames_loaded;
g_assert (loaded <= movie->n_frames);
} else {
loaded = movie->n_frames;
}
- if (loaded < frame) {
- SwfdecScript *script = cx->fp->swf;
- guint8 *pc = cx->fp->pc;
- guint8 *endpc = script->buffer->data + script->buffer->length;
-
- /* jump instructions */
- g_assert (script);
- do {
- if (pc >= endpc)
- break;
- if (*pc & 0x80) {
- if (pc + 2 >= endpc)
- break;
- pc += 3 + GUINT16_FROM_LE (*((guint16 *) (pc + 1)));
- } else {
- pc++;
- }
- } while (jump-- > 0);
- cx->fp->pc = pc;
- }
+ if (loaded < frame)
+ swfdec_script_skip_actions (cx, jump);
return JS_TRUE;
}
@@ -1693,6 +1741,16 @@ swfdec_action_print_constant_pool (guint
}
static char *
+swfdec_action_print_wait_for_frame2 (guint action, const guint8 *data, guint len)
+{
+ if (len != 1) {
+ SWFDEC_ERROR ("WaitForFrame2 needs a 1-byte data");
+ return NULL;
+ }
+ return g_strdup_printf ("WaitForFrame2 %u", (guint) *data);
+}
+
+static char *
swfdec_action_print_goto_frame2 (guint action, const guint8 *data, guint len)
{
gboolean play, bias;
@@ -1868,7 +1926,7 @@ static const SwfdecActionSpec actions[25
[0x8b] = { "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 } },
[0x8c] = { "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 } },
/* version 4 */
- [0x8d] = { "WaitForFrame2", NULL },
+ [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 } },
/* version 7 */
[0x8e] = { "DefineFunction2", NULL },
[0x8f] = { "Try", NULL },
More information about the Swfdec
mailing list