2 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301 USA
23 #include "swfdec_as_interpret.h"
24 #include "swfdec_as_array.h"
25 #include "swfdec_as_context.h"
26 #include "swfdec_as_frame_internal.h"
27 #include "swfdec_as_function.h"
28 #include "swfdec_as_script_function.h"
29 #include "swfdec_as_stack.h"
30 #include "swfdec_as_string.h"
31 #include "swfdec_as_strings.h"
32 #include "swfdec_as_super.h"
33 #include "swfdec_as_with.h"
34 #include "swfdec_debug.h"
39 #include "swfdec_decoder.h"
40 #include "swfdec_movie.h"
41 #include "swfdec_player_internal.h"
42 #include "swfdec_sprite.h"
43 #include "swfdec_sprite_movie.h"
44 #include "swfdec_swf_instance.h"
46 /* Define this to get SWFDEC_WARN'd about missing properties of objects.
47 * This can be useful to find out about unimplemented native properties,
48 * but usually just causes a lot of spam. */
49 //#define SWFDEC_WARN_MISSING_PROPERTIES
51 /*** SUPPORT FUNCTIONS ***/
53 #define swfdec_action_has_register(cx, i) \
54 ((i) < (cx)->frame->n_registers)
56 /*** ALL THE ACTION IS HERE ***/
59 swfdec_action_stop (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
61 if (SWFDEC_IS_SPRITE_MOVIE (cx
->frame
->target
))
62 SWFDEC_SPRITE_MOVIE (cx
->frame
->target
)->playing
= FALSE
;
64 SWFDEC_ERROR ("no movie to stop");
68 swfdec_action_play (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
70 if (SWFDEC_IS_SPRITE_MOVIE (cx
->frame
->target
))
71 SWFDEC_SPRITE_MOVIE (cx
->frame
->target
)->playing
= TRUE
;
73 SWFDEC_ERROR ("no movie to play");
77 swfdec_action_next_frame (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
79 if (SWFDEC_IS_SPRITE_MOVIE (cx
->frame
->target
)) {
80 SwfdecSpriteMovie
*movie
= SWFDEC_SPRITE_MOVIE (cx
->frame
->target
);
81 if (movie
->frame
< movie
->n_frames
) {
82 swfdec_sprite_movie_goto (movie
, movie
->frame
+ 1);
84 SWFDEC_INFO ("can't execute nextFrame, already at last frame");
87 SWFDEC_ERROR ("no movie to nextFrame on");
92 swfdec_action_previous_frame (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
94 if (SWFDEC_IS_SPRITE_MOVIE (cx
->frame
->target
)) {
95 SwfdecSpriteMovie
*movie
= SWFDEC_SPRITE_MOVIE (cx
->frame
->target
);
96 if (movie
->frame
> 1) {
97 swfdec_sprite_movie_goto (movie
, movie
->frame
- 1);
99 SWFDEC_INFO ("can't execute previousFrame, already at first frame");
102 SWFDEC_ERROR ("no movie to previousFrame on");
107 swfdec_action_goto_frame (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
112 SWFDEC_ERROR ("GotoFrame action length invalid (is %u, should be 2", len
);
115 frame
= GUINT16_FROM_LE (*((guint16
*) data
));
116 if (SWFDEC_IS_SPRITE_MOVIE (cx
->frame
->target
)) {
117 SwfdecSpriteMovie
*movie
= SWFDEC_SPRITE_MOVIE (cx
->frame
->target
);
118 swfdec_sprite_movie_goto (movie
, frame
+ 1);
119 movie
->playing
= FALSE
;
121 SWFDEC_ERROR ("no movie to goto on");
126 swfdec_action_goto_label (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
128 if (!memchr (data
, 0, len
)) {
129 SWFDEC_ERROR ("GotoLabel action does not specify a string");
133 if (SWFDEC_IS_SPRITE_MOVIE (cx
->frame
->target
)) {
134 SwfdecSpriteMovie
*movie
= SWFDEC_SPRITE_MOVIE (cx
->frame
->target
);
136 if (movie
->sprite
== NULL
||
137 (frame
= swfdec_sprite_get_frame (movie
->sprite
, (const char *) data
)) == -1)
139 swfdec_sprite_movie_goto (movie
, frame
+ 1);
140 movie
->playing
= FALSE
;
142 SWFDEC_ERROR ("no movie to goto on");
146 /* returns: frame to go to or 0 on error */
148 swfdec_value_to_frame (SwfdecAsContext
*cx
, SwfdecSpriteMovie
*movie
, SwfdecAsValue
*val
)
152 if (movie
->sprite
== NULL
)
154 if (SWFDEC_AS_VALUE_IS_STRING (val
)) {
155 const char *name
= SWFDEC_AS_VALUE_GET_STRING (val
);
157 if (strchr (name
, ':')) {
158 SWFDEC_ERROR ("FIXME: handle targets");
160 /* treat valid encoded numbers as numbers, otherwise assume it's a frame label */
161 d
= swfdec_as_value_to_number (cx
, val
);
163 frame
= swfdec_sprite_get_frame (movie
->sprite
, name
) + 1;
166 } else if (SWFDEC_AS_VALUE_IS_NUMBER (val
)) {
167 frame
= swfdec_as_value_to_integer (cx
, val
);
169 SWFDEC_WARNING ("cannot convert value to frame number");
170 /* FIXME: how do we treat undefined etc? */
173 return frame
<= 0 ? 0 : frame
;
177 swfdec_action_goto_frame2 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
184 swfdec_bits_init_data (&bits
, data
, len
);
185 if (swfdec_bits_getbits (&bits
, 6)) {
186 SWFDEC_WARNING ("reserved bits in GotoFrame2 aren't 0");
188 bias
= swfdec_bits_getbit (&bits
);
189 play
= swfdec_bits_getbit (&bits
);
191 bias
= swfdec_bits_get_u16 (&bits
);
193 val
= swfdec_as_stack_peek (cx
, 1);
195 if (SWFDEC_IS_SPRITE_MOVIE (cx
->frame
->target
)) {
196 SwfdecSpriteMovie
*movie
= SWFDEC_SPRITE_MOVIE (cx
->frame
->target
);
197 guint frame
= swfdec_value_to_frame (cx
, movie
, val
);
200 frame
= CLAMP (frame
, 1, movie
->n_frames
);
201 swfdec_sprite_movie_goto (movie
, frame
);
202 movie
->playing
= play
;
205 SWFDEC_ERROR ("no movie to GotoFrame2 on");
207 swfdec_as_stack_pop (cx
);
211 swfdec_script_skip_actions (SwfdecAsContext
*cx
, guint jump
)
213 SwfdecScript
*script
= cx
->frame
->script
;
214 guint8
*pc
= cx
->frame
->pc
;
215 guint8
*endpc
= script
->buffer
->data
+ script
->buffer
->length
;
217 /* jump instructions */
224 pc
+= 3 + GUINT16_FROM_LE (*((guint16
*) (pc
+ 1)));
228 } while (jump
-- > 0);
234 swfdec_action_wait_for_frame2 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
239 SWFDEC_ERROR ("WaitForFrame2 needs a 1-byte data");
242 val
= cx
->fp
->sp
[-1];
244 if (SWFDEC_IS_SPRITE_MOVIE (cx
->frame
->target
))
245 SwfdecMovie
*movie
= SWFDEC_MOVIE (cx
->frame
->target
);
246 int frame
= swfdec_value_to_frame (cx
, movie
, val
);
247 guint jump
= data
[2];
251 if (SWFDEC_IS_ROOT_MOVIE (movie
)) {
252 SwfdecDecoder
*dec
= SWFDEC_ROOT_MOVIE (movie
)->decoder
;
253 loaded
= dec
->frames_loaded
;
254 g_assert (loaded
<= movie
->n_frames
);
256 loaded
= movie
->n_frames
;
258 if (loaded
<= (guint
) frame
)
259 swfdec_script_skip_actions (cx
, jump
);
261 SWFDEC_ERROR ("no movie to WaitForFrame2 on");
268 swfdec_action_wait_for_frame (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
270 SwfdecSpriteMovie
*movie
;
271 guint frame
, jump
, loaded
;
274 SWFDEC_ERROR ("WaitForFrame action length invalid (is %u, should be 3", len
);
277 if (!SWFDEC_IS_SPRITE_MOVIE (cx
->frame
->target
)) {
278 SWFDEC_ERROR ("no movie for WaitForFrame");
282 movie
= SWFDEC_SPRITE_MOVIE (cx
->frame
->target
);
283 frame
= data
[0] || (data
[1] << 8);
285 if (SWFDEC_MOVIE (movie
)->swf
->movie
== movie
) {
286 SwfdecDecoder
*dec
= SWFDEC_MOVIE (movie
)->swf
->decoder
;
287 loaded
= dec
->frames_loaded
;
288 g_assert (loaded
<= movie
->n_frames
);
289 if (loaded
== dec
->frames_total
)
295 swfdec_script_skip_actions (cx
, jump
);
299 swfdec_action_constant_pool (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
301 SwfdecConstantPool
*pool
;
302 SwfdecAsFrame
*frame
;
305 pool
= swfdec_constant_pool_new_from_action (data
, len
, cx
->version
);
308 swfdec_constant_pool_attach_to_context (pool
, cx
);
309 if (frame
->constant_pool
)
310 swfdec_constant_pool_free (frame
->constant_pool
);
311 frame
->constant_pool
= pool
;
312 if (frame
->constant_pool_buffer
)
313 swfdec_buffer_unref (frame
->constant_pool_buffer
);
314 frame
->constant_pool_buffer
= swfdec_buffer_new_subbuffer (frame
->script
->buffer
,
315 data
- frame
->script
->buffer
->data
, len
);
319 swfdec_action_push (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
323 swfdec_bits_init_data (&bits
, data
, len
);
324 while (swfdec_bits_left (&bits
)) {
325 guint type
= swfdec_bits_get_u8 (&bits
);
326 SWFDEC_LOG ("push type %u", type
);
327 swfdec_as_stack_ensure_free (cx
, 1);
331 char *s
= swfdec_bits_get_string_with_version (&bits
, cx
->version
);
334 SWFDEC_AS_VALUE_SET_STRING (swfdec_as_stack_push (cx
),
335 swfdec_as_context_give_string (cx
, s
));
339 SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_push (cx
),
340 swfdec_bits_get_float (&bits
));
343 SWFDEC_AS_VALUE_SET_NULL (swfdec_as_stack_push (cx
));
345 case 3: /* undefined */
346 SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_push (cx
));
348 case 4: /* register */
350 guint regnum
= swfdec_bits_get_u8 (&bits
);
351 if (!swfdec_action_has_register (cx
, regnum
)) {
352 SWFDEC_ERROR ("cannot Push register %u: not enough registers", regnum
);
353 SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_push (cx
));
355 *swfdec_as_stack_push (cx
) = cx
->frame
->registers
[regnum
];
359 case 5: /* boolean */
360 SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_push (cx
),
361 swfdec_bits_get_u8 (&bits
) ? TRUE
: FALSE
);
364 SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_push (cx
),
365 swfdec_bits_get_double (&bits
));
367 case 7: /* 32bit int */
368 SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_push (cx
),
369 (int) swfdec_bits_get_u32 (&bits
));
371 case 8: /* 8bit ConstantPool address */
373 guint i
= swfdec_bits_get_u8 (&bits
);
374 SwfdecConstantPool
*pool
= cx
->frame
->constant_pool
;
376 SWFDEC_ERROR ("no constant pool to push from");
379 if (i
>= swfdec_constant_pool_size (pool
)) {
380 SWFDEC_ERROR ("constant pool index %u too high - only %u elements",
381 i
, swfdec_constant_pool_size (pool
));
384 SWFDEC_AS_VALUE_SET_STRING (swfdec_as_stack_push (cx
),
385 swfdec_constant_pool_get (pool
, i
));
388 case 9: /* 16bit ConstantPool address */
390 guint i
= swfdec_bits_get_u16 (&bits
);
391 SwfdecConstantPool
*pool
= cx
->frame
->constant_pool
;
393 SWFDEC_ERROR ("no constant pool to push from");
396 if (i
>= swfdec_constant_pool_size (pool
)) {
397 SWFDEC_ERROR ("constant pool index %u too high - only %u elements",
398 i
, swfdec_constant_pool_size (pool
));
401 SWFDEC_AS_VALUE_SET_STRING (swfdec_as_stack_push (cx
),
402 swfdec_constant_pool_get (pool
, i
));
406 SWFDEC_ERROR ("Push: type %u not implemented", type
);
413 swfdec_action_get_variable (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
417 s
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 1));
418 swfdec_as_context_eval (cx
, NULL
, s
, swfdec_as_stack_peek (cx
, 1));
419 #ifdef SWFDEC_WARN_MISSING_PROPERTIES
420 if (SWFDEC_AS_VALUE_IS_UNDEFINED (swfdec_as_stack_peek (cx
, 1))) {
421 SWFDEC_WARNING ("no variable named %s", s
);
427 swfdec_action_set_variable (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
431 s
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 2));
432 swfdec_as_context_eval_set (cx
, NULL
, s
, swfdec_as_stack_peek (cx
, 1));
433 swfdec_as_stack_pop_n (cx
, 2);
437 swfdec_as_interpret_eval (SwfdecAsContext
*cx
, SwfdecAsObject
*obj
,
440 if (SWFDEC_AS_VALUE_IS_STRING (val
)) {
441 const char *s
= SWFDEC_AS_VALUE_GET_STRING (val
);
442 if (s
!= SWFDEC_AS_STR_EMPTY
) {
443 swfdec_as_context_eval (cx
, obj
, s
, val
);
448 SWFDEC_AS_VALUE_SET_OBJECT (val
, obj
);
450 SWFDEC_AS_VALUE_SET_UNDEFINED (val
);
451 return SWFDEC_AS_STR_EMPTY
;
454 /* FIXME: this sucks */
456 gboolean needs_movie
;
457 const char * name
; /* GC'd */
458 void (* get
) (SwfdecMovie
*movie
, SwfdecAsValue
*ret
);
459 void (* set
) (SwfdecMovie
*movie
, const SwfdecAsValue
*val
);
460 } swfdec_movieclip_props
[];
462 swfdec_action_get_property (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
468 id
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_pop (cx
));
469 if (id
> (cx
->version
> 4 ? 21 : 18)) {
470 SWFDEC_WARNING ("trying to SetProperty %u, not allowed", id
);
473 val
= swfdec_as_stack_peek (cx
, 1);
474 swfdec_as_interpret_eval (cx
, NULL
, val
);
475 if (SWFDEC_AS_VALUE_IS_UNDEFINED (val
)) {
476 obj
= cx
->frame
->target
;
477 } else if (SWFDEC_AS_VALUE_IS_OBJECT (val
)) {
478 obj
= SWFDEC_AS_VALUE_GET_OBJECT (val
);
480 SWFDEC_WARNING ("not an object, can't GetProperty");
483 swfdec_as_object_get_variable (obj
, swfdec_movieclip_props
[id
].name
,
484 swfdec_as_stack_peek (cx
, 1));
488 SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx
, 1));
492 swfdec_action_set_property (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
498 id
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_peek (cx
, 2));
499 if (id
> (cx
->version
> 4 ? 21 : 18)) {
500 SWFDEC_WARNING ("trying to SetProperty %u, not allowed", id
);
503 val
= swfdec_as_stack_peek (cx
, 3);
504 swfdec_as_interpret_eval (cx
, NULL
, val
);
505 if (SWFDEC_AS_VALUE_IS_UNDEFINED (val
)) {
506 obj
= cx
->frame
->target
;
507 } else if (SWFDEC_AS_VALUE_IS_OBJECT (val
)) {
508 obj
= SWFDEC_AS_VALUE_GET_OBJECT (val
);
510 SWFDEC_WARNING ("not an object, can't get SetProperty");
513 swfdec_as_object_set_variable (obj
, swfdec_movieclip_props
[id
].name
,
514 swfdec_as_stack_peek (cx
, 1));
516 swfdec_as_stack_pop_n (cx
, 3);
520 swfdec_action_get_member (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
522 SwfdecAsObject
*object
= swfdec_as_value_to_object (cx
, swfdec_as_stack_peek (cx
, 2));
525 name
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 1));
526 swfdec_as_object_get_variable (object
, name
, swfdec_as_stack_peek (cx
, 2));
527 #ifdef SWFDEC_WARN_MISSING_PROPERTIES
528 if (SWFDEC_AS_VALUE_IS_UNDEFINED (swfdec_as_stack_peek (cx
, 2))) {
529 SWFDEC_WARNING ("no variable named %s:%s", G_OBJECT_TYPE_NAME (object
), name
);
533 SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx
, 2));
535 swfdec_as_stack_pop (cx
);
539 swfdec_action_set_member (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
541 if (SWFDEC_AS_VALUE_IS_OBJECT (swfdec_as_stack_peek (cx
, 3))) {
542 const char *name
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 2));
543 swfdec_as_object_set_variable (SWFDEC_AS_VALUE_GET_OBJECT (swfdec_as_stack_peek (cx
, 3)),
544 name
, swfdec_as_stack_peek (cx
, 1));
546 swfdec_as_stack_pop_n (cx
, 3);
550 swfdec_action_trace (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
555 val
= swfdec_as_stack_peek (cx
, 1);
556 if (val
->type
== SWFDEC_AS_TYPE_UNDEFINED
) {
557 s
= SWFDEC_AS_STR_undefined
;
558 } else if (val
->type
== SWFDEC_AS_TYPE_OBJECT
&&
559 SWFDEC_IS_AS_STRING (swfdec_as_value_to_object (cx
, val
))) {
560 s
= SWFDEC_AS_STRING (swfdec_as_value_to_object (cx
, val
))->string
;
562 s
= swfdec_as_value_to_string (cx
, val
);
564 swfdec_as_stack_pop (cx
);
565 g_signal_emit_by_name (cx
, "trace", s
);
568 /* stack looks like this: [ function, this, arg1, arg2, ... ] */
569 /* stack must be at least 2 elements big */
571 swfdec_action_call (SwfdecAsContext
*cx
, guint n_args
)
573 SwfdecAsFunction
*fun
;
574 SwfdecAsObject
*thisp
;
576 if (!SWFDEC_AS_VALUE_IS_OBJECT (swfdec_as_stack_peek (cx
, 1)))
578 fun
= (SwfdecAsFunction
*) SWFDEC_AS_VALUE_GET_OBJECT (swfdec_as_stack_peek (cx
, 1));
579 if (!SWFDEC_IS_AS_FUNCTION (fun
))
581 if (!SWFDEC_AS_VALUE_IS_OBJECT (swfdec_as_stack_peek (cx
, 2))) {
584 thisp
= SWFDEC_AS_VALUE_GET_OBJECT (swfdec_as_stack_peek (cx
, 2));
586 swfdec_as_stack_pop_n (cx
, 2);
587 /* sanitize argument count */
588 if (n_args
>= swfdec_as_stack_get_size (cx
))
589 n_args
= swfdec_as_stack_get_size (cx
);
590 swfdec_as_function_call (fun
, thisp
, n_args
, NULL
, NULL
);
591 if (SWFDEC_IS_AS_SUPER (fun
)) {
592 SWFDEC_LOG ("replacing super object on frame");
593 swfdec_as_super_replace (SWFDEC_AS_SUPER (fun
), NULL
);
599 if (n_args
> swfdec_as_stack_get_size (cx
))
600 n_args
= swfdec_as_stack_get_size (cx
);
601 swfdec_as_stack_pop_n (cx
, n_args
);
602 SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_push (cx
));
607 swfdec_action_call_function (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
609 SwfdecAsFrame
*frame
= cx
->frame
;
613 SwfdecAsValue
*fun
, *thisp
;
615 swfdec_as_stack_ensure_size (cx
, 2);
616 n_args
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_peek (cx
, 2));
617 name
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 1));
618 thisp
= swfdec_as_stack_peek (cx
, 2);
619 fun
= swfdec_as_stack_peek (cx
, 1);
620 obj
= swfdec_as_frame_find_variable (frame
, name
);
622 swfdec_as_object_get_variable (obj
, name
, fun
);
623 SWFDEC_AS_VALUE_SET_OBJECT (thisp
, obj
);
625 SWFDEC_AS_VALUE_SET_NULL (thisp
);
626 SWFDEC_AS_VALUE_SET_UNDEFINED (fun
);
628 if (!swfdec_action_call (cx
, n_args
)) {
629 SWFDEC_ERROR ("no function named %s", name
);
634 swfdec_action_call_method (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
636 SwfdecAsFrame
*frame
= cx
->frame
;
640 const char *name
= NULL
;
642 swfdec_as_stack_ensure_size (cx
, 3);
643 obj
= swfdec_as_value_to_object (cx
, swfdec_as_stack_peek (cx
, 2));
644 n_args
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_peek (cx
, 3));
645 val
= swfdec_as_stack_peek (cx
, 1);
646 /* FIXME: this is a hack for constructors calling super - is this correct? */
647 if (SWFDEC_AS_VALUE_IS_UNDEFINED (val
)) {
648 SWFDEC_AS_VALUE_SET_STRING (val
, SWFDEC_AS_STR_EMPTY
);
651 if (SWFDEC_AS_VALUE_IS_STRING (val
) &&
652 SWFDEC_AS_VALUE_GET_STRING (val
) == SWFDEC_AS_STR_EMPTY
) {
653 SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx
, 3));
654 SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_peek (cx
, 2), obj
);
656 SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_peek (cx
, 3), obj
);
657 name
= swfdec_as_value_to_string (cx
, val
);
658 swfdec_as_object_get_variable (obj
, name
, swfdec_as_stack_peek (cx
, 2));
661 if (SWFDEC_AS_VALUE_IS_STRING (val
))
662 name
= SWFDEC_AS_VALUE_GET_STRING (val
);
663 SWFDEC_AS_VALUE_SET_NULL (swfdec_as_stack_peek (cx
, 3));
664 SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx
, 2));
666 swfdec_as_stack_pop (cx
);
667 if (swfdec_action_call (cx
, n_args
)) {
668 /* setup super to point to the right prototype */
670 if (SWFDEC_IS_AS_SUPER (obj
)) {
671 swfdec_as_super_replace (SWFDEC_AS_SUPER (obj
), name
);
672 } else if (frame
->super
) {
673 SwfdecAsSuper
*super
= SWFDEC_AS_SUPER (frame
->super
);
676 swfdec_as_object_get_variable_and_flags (frame
->thisp
,
677 name
, NULL
, NULL
, &super
->object
) &&
678 super
->object
== frame
->thisp
) {
679 super
->object
= super
->object
->prototype
;
683 SWFDEC_ERROR ("no function named %s on object %s", name
? name
: "unknown", obj
? G_OBJECT_TYPE_NAME(obj
) : "unknown");
688 swfdec_action_pop (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
690 swfdec_as_stack_pop (cx
);
694 swfdec_action_binary (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
698 r
= swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 1));
699 l
= swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 2));
701 case SWFDEC_AS_ACTION_ADD
:
704 case SWFDEC_AS_ACTION_SUBTRACT
:
707 case SWFDEC_AS_ACTION_MULTIPLY
:
710 case SWFDEC_AS_ACTION_DIVIDE
:
711 if (cx
->version
< 5) {
713 SWFDEC_AS_VALUE_SET_STRING (swfdec_as_stack_peek (cx
, 1), SWFDEC_AS_STR__ERROR_
);
729 g_assert_not_reached ();
732 swfdec_as_stack_pop (cx
);
733 SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx
, 1), l
);
737 swfdec_action_add2 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
739 SwfdecAsValue
*rval
, *lval
, rtmp
, ltmp
;
741 rval
= swfdec_as_stack_peek (cx
, 1);
742 lval
= swfdec_as_stack_peek (cx
, 2);
745 swfdec_as_value_to_primitive (&rtmp
);
746 if (!SWFDEC_AS_VALUE_IS_OBJECT (&rtmp
) || SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (&rtmp
)))
748 swfdec_as_value_to_primitive (<mp
);
749 if (!SWFDEC_AS_VALUE_IS_OBJECT (<mp
) || SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (<mp
)))
752 if (SWFDEC_AS_VALUE_IS_STRING (lval
) || SWFDEC_AS_VALUE_IS_STRING (rval
)) {
753 const char *lstr
, *rstr
;
754 lstr
= swfdec_as_value_to_string (cx
, lval
);
755 rstr
= swfdec_as_value_to_string (cx
, rval
);
756 lstr
= swfdec_as_str_concat (cx
, lstr
, rstr
);
757 swfdec_as_stack_pop (cx
);
758 SWFDEC_AS_VALUE_SET_STRING (swfdec_as_stack_peek (cx
, 1), lstr
);
761 d
= swfdec_as_value_to_number (cx
, lval
);
762 d2
= swfdec_as_value_to_number (cx
, rval
);
764 swfdec_as_stack_pop (cx
);
765 SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx
, 1), d
);
770 swfdec_action_new_comparison (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
772 SwfdecAsValue
*lval
, *rval
;
775 rval
= swfdec_as_stack_peek (cx
, 1);
776 lval
= swfdec_as_stack_peek (cx
, 2);
778 /* swap if we do a greater comparison */
779 if (action
== SWFDEC_AS_ACTION_GREATER
) {
780 SwfdecAsValue
*tmp
= lval
;
784 /* comparison with object is always false */
785 swfdec_as_value_to_primitive (lval
);
786 if (SWFDEC_AS_VALUE_IS_OBJECT (lval
) &&
787 !SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (lval
))) {
788 swfdec_as_stack_pop (cx
);
789 SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx
, 1), FALSE
);
792 /* same for the rval */
793 swfdec_as_value_to_primitive (rval
);
794 if (SWFDEC_AS_VALUE_IS_OBJECT (rval
) &&
795 !SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (rval
))) {
796 swfdec_as_stack_pop (cx
);
797 SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx
, 1), FALSE
);
800 /* movieclips are not objects, but they evaluate to NaN, so we can handle them here */
801 if (SWFDEC_AS_VALUE_IS_OBJECT (rval
) ||
802 SWFDEC_AS_VALUE_IS_OBJECT (lval
)) {
803 swfdec_as_stack_pop (cx
);
804 SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx
, 1));
807 /* if both are strings, compare strings */
808 if (SWFDEC_AS_VALUE_IS_STRING (rval
) &&
809 SWFDEC_AS_VALUE_IS_STRING (lval
)) {
810 const char *ls
= SWFDEC_AS_VALUE_GET_STRING (lval
);
811 const char *rs
= SWFDEC_AS_VALUE_GET_STRING (rval
);
813 if (ls
== SWFDEC_AS_STR_EMPTY
) {
814 cmp
= rs
== SWFDEC_AS_STR_EMPTY
? 0 : 1;
815 } else if (rs
== SWFDEC_AS_STR_EMPTY
) {
818 cmp
= strcmp (ls
, rs
);
820 swfdec_as_stack_pop (cx
);
821 SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx
, 1), cmp
< 0);
824 /* convert to numbers and compare those */
825 l
= swfdec_as_value_to_number (cx
, lval
);
826 r
= swfdec_as_value_to_number (cx
, rval
);
827 swfdec_as_stack_pop (cx
);
828 /* NaN results in undefined */
829 if (isnan (l
) || isnan (r
)) {
830 SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx
, 1));
833 SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx
, 1), l
< r
);
837 swfdec_action_not_4 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
841 d
= swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 1));
842 SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx
, 1), d
== 0 ? 1 : 0);
846 swfdec_action_not_5 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
848 SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx
, 1),
849 !swfdec_as_value_to_boolean (cx
, swfdec_as_stack_peek (cx
, 1)));
853 swfdec_action_jump (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
856 SWFDEC_ERROR ("Jump action length invalid (is %u, should be 2", len
);
859 cx
->frame
->pc
+= 5 + GINT16_FROM_LE (*((gint16
*) data
));
863 swfdec_action_if (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
866 SWFDEC_ERROR ("Jump action length invalid (is %u, should be 2", len
);
869 if (swfdec_as_value_to_boolean (cx
, swfdec_as_stack_peek (cx
, 1)))
870 cx
->frame
->pc
+= 5 + GINT16_FROM_LE (*((gint16
*) data
));
871 swfdec_as_stack_pop (cx
);
875 swfdec_action_decrement (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
879 val
= swfdec_as_stack_peek (cx
, 1);
880 SWFDEC_AS_VALUE_SET_NUMBER (val
, swfdec_as_value_to_number (cx
, val
) - 1);
884 swfdec_action_increment (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
888 val
= swfdec_as_stack_peek (cx
, 1);
889 SWFDEC_AS_VALUE_SET_NUMBER (val
, swfdec_as_value_to_number (cx
, val
) + 1);
893 swfdec_action_get_url (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
898 swfdec_bits_init_data (&bits
, data
, len
);
899 url
= swfdec_bits_get_string_with_version (&bits
, cx
->version
);
900 target
= swfdec_bits_get_string_with_version (&bits
, cx
->version
);
901 if (url
== NULL
|| target
== NULL
) {
902 SWFDEC_ERROR ("not enough data in GetURL");
907 if (swfdec_bits_left (&bits
)) {
908 SWFDEC_WARNING ("leftover bytes in GetURL action");
910 if (SWFDEC_IS_MOVIE (cx
->frame
->target
))
911 swfdec_movie_load (SWFDEC_MOVIE (cx
->frame
->target
), url
, target
,
912 SWFDEC_LOADER_REQUEST_DEFAULT
, NULL
, 0);
914 SWFDEC_WARNING ("no movie to load");
920 swfdec_action_get_url2 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
922 const char *target
, *url
;
926 SWFDEC_ERROR ("GetURL2 requires 1 byte of data, not %u", len
);
929 target
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 1));
930 url
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 2));
931 method
= data
[0] >> 6;
933 SWFDEC_ERROR ("GetURL method 3 invalid");
937 SWFDEC_FIXME ("implement LoadTarget");
940 SWFDEC_FIXME ("implement LoadVariables");
942 if (SWFDEC_IS_MOVIE (cx
->frame
->target
))
943 swfdec_movie_load (SWFDEC_MOVIE (cx
->frame
->target
), url
, target
, method
, NULL
, 0);
945 SWFDEC_WARNING ("no movie to load");
946 swfdec_as_stack_pop_n (cx
, 2);
950 swfdec_action_string_add (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
952 const char *lval
, *rval
;
954 rval
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 1));
955 lval
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 2));
956 lval
= swfdec_as_str_concat (cx
, lval
, rval
);
957 SWFDEC_AS_VALUE_SET_STRING (swfdec_as_stack_peek (cx
, 2), lval
);
958 swfdec_as_stack_pop (cx
);
962 swfdec_action_push_duplicate (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
964 *swfdec_as_stack_push (cx
) = *swfdec_as_stack_peek (cx
, 1);
968 swfdec_action_random_number (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
973 val
= swfdec_as_stack_peek (cx
, 1);
974 max
= swfdec_as_value_to_integer (cx
, val
);
977 SWFDEC_AS_VALUE_SET_NUMBER (val
, 0);
979 SWFDEC_AS_VALUE_SET_NUMBER (val
, g_rand_int_range (cx
->rand
, 0, max
));
983 swfdec_action_old_compare (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
988 l
= swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 2));
989 r
= swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 1));
991 case SWFDEC_AS_ACTION_EQUALS
:
994 case SWFDEC_AS_ACTION_LESS
:
998 g_assert_not_reached ();
1001 swfdec_as_stack_pop (cx
);
1002 if (cx
->version
< 5) {
1003 SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx
, 1), cond
? 1 : 0);
1005 SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx
, 1), cond
);
1010 swfdec_action_string_length (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1015 v
= swfdec_as_stack_peek (cx
, 1);
1016 s
= swfdec_as_value_to_string (cx
, v
);
1017 SWFDEC_AS_VALUE_SET_INT (v
, g_utf8_strlen (s
, -1));
1021 swfdec_action_string_compare (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1026 r
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 1));
1027 l
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 2));
1029 case SWFDEC_AS_ACTION_STRING_EQUALS
:
1032 case SWFDEC_AS_ACTION_STRING_LESS
:
1033 cond
= strcmp (l
, r
) < 0;
1036 g_assert_not_reached ();
1039 swfdec_as_stack_pop (cx
);
1040 if (cx
->version
< 5) {
1041 SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx
, 1), cond
? 1 : 0);
1043 SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx
, 1), cond
);
1048 swfdec_action_equals2_5 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1050 SwfdecAsValue
*rval
, *lval
;
1051 SwfdecAsValue rtmp
, ltmp
;
1052 SwfdecAsValueType ltype
, rtype
;
1056 rval
= swfdec_as_stack_peek (cx
, 1);
1057 lval
= swfdec_as_stack_peek (cx
, 2);
1060 swfdec_as_value_to_primitive (&rtmp
);
1061 swfdec_as_value_to_primitive (<mp
);
1065 /* get objects compared */
1066 if (ltype
== SWFDEC_AS_TYPE_OBJECT
&& rtype
== SWFDEC_AS_TYPE_OBJECT
) {
1067 SwfdecAsObject
*lo
= SWFDEC_AS_VALUE_GET_OBJECT (<mp
);
1068 SwfdecAsObject
*ro
= SWFDEC_AS_VALUE_GET_OBJECT (&rtmp
);
1070 if (!SWFDEC_IS_MOVIE (lo
))
1071 lo
= SWFDEC_AS_VALUE_GET_OBJECT (lval
);
1072 if (!SWFDEC_IS_MOVIE (ro
))
1073 ro
= SWFDEC_AS_VALUE_GET_OBJECT (rval
);
1075 if (SWFDEC_IS_MOVIE (lo
) && SWFDEC_IS_MOVIE (ro
)) {
1077 } else if (SWFDEC_IS_MOVIE (lo
)) {
1078 swfdec_as_value_to_primitive (rval
);
1080 if (rtype
!= SWFDEC_AS_TYPE_OBJECT
) {
1084 ro
= SWFDEC_AS_VALUE_GET_OBJECT (rval
);
1085 } else if (SWFDEC_IS_MOVIE (ro
)) {
1086 swfdec_as_value_to_primitive (lval
);
1088 if (ltype
!= SWFDEC_AS_TYPE_OBJECT
) {
1092 lo
= SWFDEC_AS_VALUE_GET_OBJECT (lval
);
1098 /* compare strings */
1099 if (ltype
== SWFDEC_AS_TYPE_STRING
&& rtype
== SWFDEC_AS_TYPE_STRING
) {
1100 /* FIXME: flash 5 case insensitive? */
1101 cond
= SWFDEC_AS_VALUE_GET_STRING (<mp
) == SWFDEC_AS_VALUE_GET_STRING (&rtmp
);
1105 /* convert to numbers */
1106 if (SWFDEC_AS_VALUE_IS_OBJECT (<mp
) && !SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (<mp
))) {
1107 l
= swfdec_as_value_to_number (cx
, lval
);
1109 l
= swfdec_as_value_to_number (cx
, <mp
);
1111 if (SWFDEC_AS_VALUE_IS_OBJECT (&rtmp
) && !SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (&rtmp
))) {
1112 r
= swfdec_as_value_to_number (cx
, rval
);
1114 r
= swfdec_as_value_to_number (cx
, &rtmp
);
1117 /* get rid of undefined and null */
1118 cond
= rtype
== SWFDEC_AS_TYPE_UNDEFINED
|| rtype
== SWFDEC_AS_TYPE_NULL
;
1119 if (ltype
== SWFDEC_AS_TYPE_UNDEFINED
|| ltype
== SWFDEC_AS_TYPE_NULL
) {
1126 /* else compare as numbers */
1127 if (isnan (l
) && isnan (r
))
1128 cond
= ltype
== rtype
;
1133 swfdec_as_stack_pop (cx
);
1134 SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx
, 1), cond
);
1138 swfdec_action_equals2 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1140 SwfdecAsValue
*rval
, *lval
;
1141 SwfdecAsValueType ltype
, rtype
;
1145 rval
= swfdec_as_stack_peek (cx
, 1);
1146 lval
= swfdec_as_stack_peek (cx
, 2);
1150 /* get objects compared */
1151 if (ltype
== SWFDEC_AS_TYPE_OBJECT
&& rtype
== SWFDEC_AS_TYPE_OBJECT
) {
1152 SwfdecAsObject
*lo
= SWFDEC_AS_VALUE_GET_OBJECT (lval
);
1153 SwfdecAsObject
*ro
= SWFDEC_AS_VALUE_GET_OBJECT (rval
);
1155 if (SWFDEC_IS_MOVIE (lo
) && SWFDEC_IS_MOVIE (ro
)) {
1157 } else if (SWFDEC_IS_MOVIE (lo
)) {
1158 swfdec_as_value_to_primitive (rval
);
1160 if (rtype
!= SWFDEC_AS_TYPE_OBJECT
) {
1164 ro
= SWFDEC_AS_VALUE_GET_OBJECT (rval
);
1165 } else if (SWFDEC_IS_MOVIE (ro
)) {
1166 swfdec_as_value_to_primitive (lval
);
1168 if (ltype
!= SWFDEC_AS_TYPE_OBJECT
) {
1172 lo
= SWFDEC_AS_VALUE_GET_OBJECT (lval
);
1178 /* if one of the values is an object, call valueOf.
1179 * If it's still an object, return FALSE */
1180 swfdec_as_value_to_primitive (lval
);
1182 if (ltype
== SWFDEC_AS_TYPE_OBJECT
) {
1186 swfdec_as_value_to_primitive (rval
);
1188 if (rtype
== SWFDEC_AS_TYPE_OBJECT
) {
1192 /* now we have a comparison without objects */
1194 /* get rid of undefined and null */
1195 cond
= rtype
== SWFDEC_AS_TYPE_UNDEFINED
|| rtype
== SWFDEC_AS_TYPE_NULL
;
1196 if (ltype
== SWFDEC_AS_TYPE_UNDEFINED
|| ltype
== SWFDEC_AS_TYPE_NULL
) {
1203 /* compare strings */
1204 if (ltype
== SWFDEC_AS_TYPE_STRING
&& rtype
== SWFDEC_AS_TYPE_STRING
) {
1205 /* FIXME: flash 5 case insensitive? */
1206 cond
= SWFDEC_AS_VALUE_GET_STRING (lval
) == SWFDEC_AS_VALUE_GET_STRING (rval
);
1210 /* else compare as numbers */
1211 l
= swfdec_as_value_to_number (cx
, lval
);
1212 r
= swfdec_as_value_to_number (cx
, rval
);
1214 if (isnan (l
) && isnan (r
))
1215 cond
= ltype
== rtype
;
1220 swfdec_as_stack_pop (cx
);
1221 SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx
, 1), cond
);
1225 swfdec_action_strict_equals (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1227 SwfdecAsValue
*rval
, *lval
;
1230 rval
= swfdec_as_stack_peek (cx
, 1);
1231 lval
= swfdec_as_stack_peek (cx
, 2);
1233 if (rval
->type
!= lval
->type
) {
1236 switch (rval
->type
) {
1237 case SWFDEC_AS_TYPE_UNDEFINED
:
1238 case SWFDEC_AS_TYPE_NULL
:
1241 case SWFDEC_AS_TYPE_BOOLEAN
:
1242 cond
= SWFDEC_AS_VALUE_GET_BOOLEAN (rval
) == SWFDEC_AS_VALUE_GET_BOOLEAN (lval
);
1244 case SWFDEC_AS_TYPE_NUMBER
:
1247 r
= SWFDEC_AS_VALUE_GET_NUMBER (rval
);
1248 l
= SWFDEC_AS_VALUE_GET_NUMBER (lval
);
1249 cond
= (l
== r
) || (isnan (l
) && isnan (r
));
1252 case SWFDEC_AS_TYPE_STRING
:
1253 cond
= SWFDEC_AS_VALUE_GET_STRING (rval
) == SWFDEC_AS_VALUE_GET_STRING (lval
);
1255 case SWFDEC_AS_TYPE_OBJECT
:
1256 cond
= SWFDEC_AS_VALUE_GET_OBJECT (rval
) == SWFDEC_AS_VALUE_GET_OBJECT (lval
);
1259 g_assert_not_reached ();
1264 swfdec_as_stack_pop (cx
);
1265 SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx
, 1), cond
);
1269 swfdec_action_set_target (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1271 if (!memchr (data
, 0, len
)) {
1272 SWFDEC_ERROR ("SetTarget action does not specify a string");
1275 if (*data
== '\0') {
1276 swfdec_as_frame_set_target (cx
->frame
, NULL
);
1278 SwfdecAsValue target
;
1279 swfdec_as_context_eval (cx
, NULL
, (const char *) data
, &target
);
1280 if (!SWFDEC_AS_VALUE_IS_OBJECT (&target
)) {
1281 SWFDEC_WARNING ("target is not an object");
1284 /* FIXME: allow non-movieclips as targets? */
1285 swfdec_as_frame_set_target (cx
->frame
, SWFDEC_AS_VALUE_GET_OBJECT (&target
));
1290 swfdec_action_set_target2 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1293 val
= swfdec_as_stack_peek (cx
, 1);
1294 if (!SWFDEC_AS_VALUE_IS_OBJECT (val
)) {
1295 SWFDEC_WARNING ("target is not an object");
1297 /* FIXME: allow non-movieclips as targets? */
1298 swfdec_as_frame_set_target (cx
->frame
, SWFDEC_AS_VALUE_GET_OBJECT (val
));
1300 swfdec_as_stack_pop (cx
);
1304 swfdec_action_start_drag (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1306 SwfdecRect rect
, *rectp
= NULL
;
1309 guint stack_size
= 3;
1311 swfdec_as_stack_ensure_size (cx
, 3);
1312 if (swfdec_as_interpret_eval (cx
, NULL
, swfdec_as_stack_peek (cx
, 1)) == SWFDEC_AS_STR_EMPTY
) {
1313 SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_peek (cx
, 1), cx
->frame
->target
);
1315 center
= swfdec_as_value_to_boolean (cx
, swfdec_as_stack_peek (cx
, 2));
1316 if (swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 3))) {
1317 swfdec_as_stack_ensure_size (cx
, 7);
1318 rect
.x0
= swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 7));
1319 rect
.y0
= swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 6));
1320 rect
.x1
= swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 5));
1321 rect
.y1
= swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 4));
1322 swfdec_rect_scale (&rect
, &rect
, SWFDEC_TWIPS_SCALE_FACTOR
);
1326 if (SWFDEC_AS_VALUE_IS_OBJECT (swfdec_as_stack_peek (cx
, 1)) &&
1327 SWFDEC_IS_MOVIE (movie
= (SwfdecMovie
*) SWFDEC_AS_VALUE_GET_OBJECT (swfdec_as_stack_peek (cx
, 1)))) {
1328 swfdec_player_set_drag_movie (SWFDEC_PLAYER (cx
), movie
, center
, &rect
);
1330 SWFDEC_ERROR ("startDrag on something not a Movie");
1332 swfdec_as_stack_pop_n (cx
, stack_size
);
1336 swfdec_action_end_drag (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1338 if (SWFDEC_IS_PLAYER (cx
)) {
1339 swfdec_player_set_drag_movie (SWFDEC_PLAYER (cx
), NULL
, FALSE
, NULL
);
1341 SWFDEC_WARNING ("can't end a drag on non-players");
1346 swfdec_action_stop_sounds (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1348 if (SWFDEC_IS_PLAYER (cx
)) {
1349 swfdec_player_stop_all_sounds (SWFDEC_PLAYER (cx
));
1354 swfdec_action_new_object (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1356 SwfdecAsValue
*constructor
;
1357 SwfdecAsFunction
*fun
;
1361 swfdec_as_stack_ensure_size (cx
, 2);
1362 constructor
= swfdec_as_stack_peek (cx
, 1);
1363 name
= swfdec_as_interpret_eval (cx
, NULL
, constructor
);
1364 n_args
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_peek (cx
, 2));
1365 n_args
= MIN (swfdec_as_stack_get_size (cx
) - 2, n_args
);
1366 if (!SWFDEC_AS_VALUE_IS_OBJECT (constructor
) ||
1367 !SWFDEC_IS_AS_FUNCTION (fun
= (SwfdecAsFunction
*) SWFDEC_AS_VALUE_GET_OBJECT (constructor
))) {
1368 SWFDEC_WARNING ("%s is not a constructor", name
);
1372 swfdec_as_stack_pop_n (cx
, 2);
1373 swfdec_as_object_create (fun
, n_args
, NULL
);
1377 swfdec_as_stack_pop_n (cx
, n_args
+ 1);
1378 SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx
, 1));
1382 swfdec_action_new_method (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1384 SwfdecAsValue
*constructor
;
1385 SwfdecAsFunction
*fun
;
1389 swfdec_as_stack_ensure_size (cx
, 3);
1390 name
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 1));
1392 constructor
= swfdec_as_stack_peek (cx
, 2);
1393 n_args
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_peek (cx
, 3));
1394 n_args
= MIN (swfdec_as_stack_get_size (cx
) - 3, n_args
);
1395 if (name
!= SWFDEC_AS_STR_EMPTY
) {
1396 if (!SWFDEC_AS_VALUE_IS_OBJECT (constructor
)) {
1397 SWFDEC_WARNING ("NewMethod called without an object to get variable %s from", name
);
1400 swfdec_as_object_get_variable (SWFDEC_AS_VALUE_GET_OBJECT (constructor
),
1403 if (!SWFDEC_AS_VALUE_IS_OBJECT (constructor
) ||
1404 !SWFDEC_IS_AS_FUNCTION (fun
= (SwfdecAsFunction
*) SWFDEC_AS_VALUE_GET_OBJECT (constructor
))) {
1405 SWFDEC_WARNING ("%s is not a constructor", name
);
1409 swfdec_as_stack_pop_n (cx
, 3);
1410 swfdec_as_object_create (fun
, n_args
, NULL
);
1414 swfdec_as_stack_pop_n (cx
, n_args
+ 2);
1415 SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx
, 1));
1419 swfdec_action_init_object (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1421 SwfdecAsObject
*object
;
1422 guint i
, n_args
, size
;
1424 n_args
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_peek (cx
, 1));
1425 swfdec_as_stack_pop (cx
);
1426 if (n_args
* 2 > swfdec_as_stack_get_size (cx
)) {
1427 size
= swfdec_as_stack_get_size (cx
);
1428 SWFDEC_FIXME ("InitObject action with too small stack, help!");
1435 object
= swfdec_as_object_new (cx
);
1438 for (i
= 0; i
< n_args
; i
++) {
1439 const char *s
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 2));
1440 swfdec_as_object_set_variable (object
, s
, swfdec_as_stack_peek (cx
, 1));
1441 swfdec_as_stack_pop_n (cx
, 2);
1443 swfdec_as_stack_pop_n (cx
, size
);
1444 SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_push (cx
), object
);
1448 swfdec_action_init_array (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1451 SwfdecAsObject
*array
;
1453 swfdec_as_stack_ensure_size (cx
, 1);
1454 n
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_peek (cx
, 1));
1455 swfdec_as_stack_pop (cx
);
1456 array
= swfdec_as_array_new (cx
);
1459 /* NB: we can't increase the stack here, as the number can easily be MAXINT */
1460 for (i
= 0; i
< n
&& swfdec_as_stack_get_size (cx
) > 0; i
++) {
1461 swfdec_as_stack_ensure_size (cx
, 1);
1462 swfdec_as_array_push (SWFDEC_AS_ARRAY (array
), swfdec_as_stack_pop (cx
));
1466 SWFDEC_AS_VALUE_SET_INT (&val
, i
);
1467 swfdec_as_object_set_variable (array
, SWFDEC_AS_STR_length
, &val
);
1469 SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_push (cx
), array
);
1473 swfdec_action_define_function (SwfdecAsContext
*cx
, guint action
,
1474 const guint8
*data
, guint len
)
1476 char *function_name
;
1477 const char *name
= NULL
;
1478 guint i
, n_args
, size
, n_registers
;
1479 SwfdecBuffer
*buffer
;
1481 SwfdecAsFunction
*fun
;
1482 SwfdecAsFrame
*frame
;
1483 SwfdecScript
*script
;
1485 SwfdecScriptArgument
*args
;
1486 gboolean v2
= (action
== 0x8e);
1489 swfdec_bits_init_data (&bits
, data
, len
);
1490 function_name
= swfdec_bits_get_string_with_version (&bits
, cx
->version
);
1491 if (function_name
== NULL
) {
1492 SWFDEC_ERROR ("could not parse function name");
1495 n_args
= swfdec_bits_get_u16 (&bits
);
1497 n_registers
= swfdec_bits_get_u8 (&bits
);
1498 if (n_registers
== 0)
1500 flags
= swfdec_bits_get_u16 (&bits
);
1505 args
= g_new0 (SwfdecScriptArgument
, n_args
);
1506 for (i
= 0; i
< n_args
&& swfdec_bits_left (&bits
); i
++) {
1508 args
[i
].preload
= swfdec_bits_get_u8 (&bits
);
1509 if (args
[i
].preload
&& args
[i
].preload
>= n_registers
) {
1510 SWFDEC_ERROR ("argument %u cannot be preloaded into register %u out of %u",
1511 i
, args
[i
].preload
, n_registers
);
1512 /* FIXME: figure out correct error handling here */
1513 args
[i
].preload
= 0;
1516 args
[i
].name
= swfdec_bits_get_string_with_version (&bits
, cx
->version
);
1517 if (args
[i
].name
== NULL
|| args
[i
].name
== '\0') {
1518 SWFDEC_ERROR ("empty argument name not allowed");
1522 /* FIXME: check duplicate arguments */
1527 size
= swfdec_bits_get_u16 (&bits
);
1528 /* check the script can be created */
1529 if (frame
->script
->buffer
->data
+ frame
->script
->buffer
->length
< frame
->pc
+ 3 + len
+ size
) {
1530 SWFDEC_ERROR ("size of function is too big");
1532 g_free (function_name
);
1535 /* create the script */
1536 buffer
= swfdec_buffer_new_subbuffer (frame
->script
->buffer
,
1537 frame
->pc
+ 3 + len
- frame
->script
->buffer
->data
, size
);
1538 swfdec_bits_init (&bits
, buffer
);
1539 if (*function_name
) {
1540 name
= function_name
;
1541 } else if (swfdec_as_stack_get_size (cx
) > 0) {
1542 /* This is kind of a hack that uses a feature of the Adobe compiler:
1543 * foo = function () {} is compiled as these actions:
1544 * Push "foo", DefineFunction, SetVariable/SetMember
1545 * With this knowledge we can inspect the topmost stack member, since
1546 * it will contain the name this function will soon be assigned to.
1548 if (SWFDEC_AS_VALUE_IS_STRING (swfdec_as_stack_peek (cx
, 1)))
1549 name
= SWFDEC_AS_VALUE_GET_STRING (swfdec_as_stack_peek (cx
, 1));
1552 name
= "unnamed_function";
1553 script
= swfdec_script_new_from_bits (&bits
, name
, cx
->version
);
1554 swfdec_buffer_unref (buffer
);
1555 if (script
== NULL
) {
1556 SWFDEC_ERROR ("failed to create script");
1558 g_free (function_name
);
1561 if (frame
->constant_pool_buffer
)
1562 script
->constant_pool
= swfdec_buffer_ref (frame
->constant_pool_buffer
);
1563 script
->flags
= flags
;
1564 script
->n_registers
= n_registers
;
1565 script
->n_arguments
= n_args
;
1566 script
->arguments
= args
;
1567 /* see function-scope tests */
1568 if (cx
->version
> 5) {
1569 /* FIXME: or original target? */
1570 fun
= swfdec_as_script_function_new (frame
->scope
? frame
->scope
: SWFDEC_AS_SCOPE (frame
), frame
->target
, script
);
1572 SwfdecAsScope
*scope
= frame
->scope
? frame
->scope
: SWFDEC_AS_SCOPE (frame
);
1574 scope
= scope
->next
;
1575 fun
= swfdec_as_script_function_new (scope
, frame
->target
, script
);
1579 /* attach the function */
1580 if (*function_name
== '\0') {
1581 swfdec_as_stack_ensure_free (cx
, 1);
1582 SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_push (cx
), SWFDEC_AS_OBJECT (fun
));
1584 SwfdecAsValue funval
;
1585 /* FIXME: really varobj? Not eval or sth like that? */
1586 name
= swfdec_as_context_get_string (cx
, function_name
);
1587 SWFDEC_AS_VALUE_SET_OBJECT (&funval
, SWFDEC_AS_OBJECT (fun
));
1588 swfdec_as_object_set_variable (frame
->target
, name
, &funval
);
1591 /* update current context */
1592 frame
->pc
+= 3 + len
+ size
;
1593 g_free (function_name
);
1597 swfdec_action_bitwise (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1601 a
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_peek (cx
, 1));
1602 b
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_peek (cx
, 2));
1615 g_assert_not_reached ();
1619 swfdec_as_stack_pop (cx
);
1620 SWFDEC_AS_VALUE_SET_INT (swfdec_as_stack_peek (cx
, 1), a
);
1624 swfdec_action_shift (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1628 amount
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_peek (cx
, 1));
1630 value
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_peek (cx
, 2));
1634 value
= value
<< amount
;
1637 value
= ((gint
) value
) >> amount
;
1640 value
= ((guint
) value
) >> amount
;
1643 g_assert_not_reached ();
1646 swfdec_as_stack_pop (cx
);
1647 SWFDEC_AS_VALUE_SET_INT (swfdec_as_stack_peek (cx
, 1), value
);
1651 swfdec_action_to_integer (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1653 SwfdecAsValue
*val
= swfdec_as_stack_peek (cx
, 1);
1655 SWFDEC_AS_VALUE_SET_INT (val
, swfdec_as_value_to_integer (cx
, val
));
1659 swfdec_action_target_path (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1665 val
= swfdec_as_stack_peek (cx
, 1);
1667 if (!SWFDEC_AS_VALUE_IS_OBJECT (val
) ||
1668 !SWFDEC_IS_MOVIE (movie
= (SwfdecMovie
*) SWFDEC_AS_VALUE_GET_OBJECT (val
))) {
1669 SWFDEC_FIXME ("What's the TargetPath for non-movies?");
1670 SWFDEC_AS_VALUE_SET_UNDEFINED (val
);
1673 s
= swfdec_movie_get_path (movie
);
1674 SWFDEC_AS_VALUE_SET_STRING (val
, swfdec_as_context_give_string (cx
, s
));
1678 swfdec_action_define_local (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1680 SwfdecAsObject
*target
;
1683 name
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 2));
1684 if (cx
->frame
->is_local
) {
1685 target
= SWFDEC_AS_OBJECT (cx
->frame
);
1687 target
= cx
->frame
->target
;
1689 swfdec_as_object_set_variable (target
, name
,
1690 swfdec_as_stack_peek (cx
, 1));
1691 swfdec_as_stack_pop_n (cx
, 2);
1695 swfdec_action_define_local2 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1697 SwfdecAsValue val
= { 0, };
1698 SwfdecAsObject
*target
;
1701 name
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 1));
1702 if (cx
->frame
->is_local
) {
1703 target
= SWFDEC_AS_OBJECT (cx
->frame
);
1705 target
= cx
->frame
->target
;
1707 swfdec_as_object_set_variable (target
, name
, &val
);
1708 swfdec_as_stack_pop (cx
);
1712 swfdec_action_return (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1714 swfdec_as_frame_return (cx
->frame
, swfdec_as_stack_pop (cx
));
1718 swfdec_action_delete (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1722 gboolean success
= FALSE
;
1724 name
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 1));
1725 val
= swfdec_as_stack_peek (cx
, 2);
1726 if (SWFDEC_AS_VALUE_IS_OBJECT (val
)) {
1727 success
= swfdec_as_object_delete_variable (
1728 SWFDEC_AS_VALUE_GET_OBJECT (val
), name
) == SWFDEC_AS_DELETE_DELETED
;
1730 SWFDEC_AS_VALUE_SET_BOOLEAN (val
, success
);
1731 swfdec_as_stack_pop_n (cx
, 1);
1735 swfdec_action_delete2 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1739 gboolean success
= FALSE
;
1741 val
= swfdec_as_stack_peek (cx
, 1);
1742 name
= swfdec_as_value_to_string (cx
, val
);
1743 success
= swfdec_as_frame_delete_variable (cx
->frame
, name
) == SWFDEC_AS_DELETE_DELETED
;
1744 SWFDEC_AS_VALUE_SET_BOOLEAN (val
, success
);
1748 swfdec_action_store_register (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1751 SWFDEC_ERROR ("StoreRegister action requires a length of 1, but got %u", len
);
1754 if (!swfdec_action_has_register (cx
, *data
)) {
1755 SWFDEC_ERROR ("Cannot store into register %u, not enough registers", (guint
) *data
);
1758 cx
->frame
->registers
[*data
] = *swfdec_as_stack_peek (cx
, 1);
1762 swfdec_action_modulo (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1766 y
= swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 1));
1767 x
= swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 2));
1768 /* yay, we're portable! */
1775 SWFDEC_FIXME ("errno set after fmod");
1778 swfdec_as_stack_pop (cx
);
1779 SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx
, 1), x
);
1783 swfdec_action_swap (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1785 swfdec_as_stack_swap (cx
, 1, 2);
1789 swfdec_action_to_number (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1791 SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx
, 1),
1792 swfdec_as_value_to_number (cx
, swfdec_as_stack_peek (cx
, 1)));
1796 swfdec_action_to_string (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1798 SWFDEC_AS_VALUE_SET_STRING (swfdec_as_stack_peek (cx
, 1),
1799 swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 1)));
1803 swfdec_action_type_of (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1808 val
= swfdec_as_stack_peek (cx
, 1);
1809 switch (val
->type
) {
1810 case SWFDEC_AS_TYPE_NUMBER
:
1811 type
= SWFDEC_AS_STR_number
;
1813 case SWFDEC_AS_TYPE_BOOLEAN
:
1814 type
= SWFDEC_AS_STR_boolean
;
1816 case SWFDEC_AS_TYPE_STRING
:
1817 type
= SWFDEC_AS_STR_string
;
1819 case SWFDEC_AS_TYPE_UNDEFINED
:
1820 type
= SWFDEC_AS_STR_undefined
;
1822 case SWFDEC_AS_TYPE_NULL
:
1823 type
= SWFDEC_AS_STR_null
;
1825 case SWFDEC_AS_TYPE_OBJECT
:
1827 SwfdecAsObject
*obj
= SWFDEC_AS_VALUE_GET_OBJECT (val
);
1828 if (SWFDEC_IS_MOVIE (obj
)) {
1829 type
= SWFDEC_AS_STR_movieclip
;
1830 } else if (SWFDEC_IS_AS_FUNCTION (obj
)) {
1831 type
= SWFDEC_AS_STR_function
;
1833 type
= SWFDEC_AS_STR_object
;
1838 g_assert_not_reached ();
1839 type
= SWFDEC_AS_STR_EMPTY
;
1842 SWFDEC_AS_VALUE_SET_STRING (val
, type
);
1846 swfdec_action_get_time (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1851 swfdec_as_context_get_time (cx
, &tv
);
1852 /* we assume here that swfdec_as_context_get_time always returns a tv > start_time */
1853 diff
= tv
.tv_sec
- cx
->start_time
.tv_sec
;
1854 if (diff
> G_MAXULONG
/ 1000 - 1) {
1855 SWFDEC_ERROR ("FIXME: time overflow");
1858 diff
= diff
+ (tv
.tv_usec
- cx
->start_time
.tv_usec
) / 1000;
1860 SWFDEC_AS_VALUE_SET_INT (swfdec_as_stack_push (cx
), diff
);
1864 swfdec_action_extends (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1866 SwfdecAsValue
*superclass
, *subclass
, proto
;
1867 SwfdecAsObject
*prototype
;
1868 SwfdecAsObject
*super
;
1870 superclass
= swfdec_as_stack_peek (cx
, 1);
1871 subclass
= swfdec_as_stack_peek (cx
, 2);
1872 if (!SWFDEC_AS_VALUE_IS_OBJECT (superclass
) ||
1873 !SWFDEC_IS_AS_FUNCTION (SWFDEC_AS_VALUE_GET_OBJECT (superclass
))) {
1874 SWFDEC_ERROR ("superclass is not a function");
1877 if (!SWFDEC_AS_VALUE_IS_OBJECT (subclass
)) {
1878 SWFDEC_ERROR ("subclass is not an object");
1881 super
= SWFDEC_AS_VALUE_GET_OBJECT (superclass
);
1882 prototype
= swfdec_as_object_new_empty (cx
);
1883 if (prototype
== NULL
)
1885 swfdec_as_object_get_variable (super
, SWFDEC_AS_STR_prototype
, &proto
);
1886 swfdec_as_object_set_variable (prototype
, SWFDEC_AS_STR___proto__
, &proto
);
1887 swfdec_as_object_set_variable_and_flags (prototype
, SWFDEC_AS_STR___constructor__
,
1888 superclass
, SWFDEC_AS_VARIABLE_HIDDEN
);
1889 SWFDEC_AS_VALUE_SET_OBJECT (&proto
, prototype
);
1890 swfdec_as_object_set_variable (SWFDEC_AS_VALUE_GET_OBJECT (subclass
),
1891 SWFDEC_AS_STR_prototype
, &proto
);
1893 swfdec_as_stack_pop_n (cx
, 2);
1897 swfdec_action_do_enumerate (SwfdecAsObject
*object
, const char *variable
,
1898 SwfdecAsValue
*value
, guint flags
, gpointer cxp
)
1900 SwfdecAsContext
*cx
= cxp
;
1902 if (flags
& SWFDEC_AS_VARIABLE_HIDDEN
)
1904 swfdec_as_stack_ensure_free (cx
, 1);
1905 SWFDEC_AS_VALUE_SET_STRING (swfdec_as_stack_push (cx
), variable
);
1910 swfdec_action_enumerate (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1913 SwfdecAsObject
*obj
;
1915 val
= swfdec_as_stack_peek (cx
, 1);
1917 swfdec_as_interpret_eval (cx
, NULL
, val
);
1918 if (!SWFDEC_AS_VALUE_IS_OBJECT (val
)) {
1919 SWFDEC_ERROR ("Enumerate not pointing to an object");
1920 SWFDEC_AS_VALUE_SET_NULL (val
);
1923 obj
= SWFDEC_AS_VALUE_GET_OBJECT (val
);
1924 SWFDEC_AS_VALUE_SET_NULL (val
);
1925 swfdec_as_object_foreach (obj
, swfdec_action_do_enumerate
, cx
);
1929 swfdec_action_enumerate2 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1932 SwfdecAsObject
*obj
;
1934 val
= swfdec_as_stack_peek (cx
, 1);
1935 if (!SWFDEC_AS_VALUE_IS_OBJECT (val
)) {
1936 SWFDEC_ERROR ("Enumerate2 called without an object");
1937 SWFDEC_AS_VALUE_SET_NULL (val
);
1940 obj
= SWFDEC_AS_VALUE_GET_OBJECT (val
);
1941 SWFDEC_AS_VALUE_SET_NULL (val
);
1942 swfdec_as_object_foreach (obj
, swfdec_action_do_enumerate
, cx
);
1946 swfdec_action_logical (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1951 l
= swfdec_as_value_to_boolean (cx
, swfdec_as_stack_peek (cx
, 1));
1952 val
= swfdec_as_stack_peek (cx
, 2);
1953 r
= swfdec_as_value_to_boolean (cx
, val
);
1955 SWFDEC_AS_VALUE_SET_BOOLEAN (val
, (action
== 0x10) ? (l
&& r
) : (l
|| r
));
1956 swfdec_as_stack_pop (cx
);
1960 swfdec_action_char_to_ascii_5 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1962 SwfdecAsValue
*val
= swfdec_as_stack_peek (cx
, 1);
1963 const char *s
= swfdec_as_value_to_string (cx
, val
);
1966 ascii
= g_convert (s
, -1, "LATIN1", "UTF-8", NULL
, NULL
, NULL
);
1967 if (ascii
== NULL
) {
1968 /* This can happen if a Flash 5 movie gets loaded into a Flash 7 movie */
1969 SWFDEC_FIXME ("Someone threw unconvertible text %s at Flash <= 5", s
);
1970 SWFDEC_AS_VALUE_SET_INT (val
, 0); /* FIXME: what to return??? */
1972 SWFDEC_AS_VALUE_SET_INT (val
, (guchar
) ascii
[0]);
1978 swfdec_action_char_to_ascii (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1980 SwfdecAsValue
*val
= swfdec_as_stack_peek (cx
, 1);
1981 const char *s
= swfdec_as_value_to_string(cx
, val
);
1984 uni
= g_utf8_to_ucs4_fast (s
, -1, NULL
);
1986 /* This should never happen, everything is valid UTF-8 in here */
1987 g_warning ("conversion of character %s failed", s
);
1988 SWFDEC_AS_VALUE_SET_INT (val
, 0);
1990 SWFDEC_AS_VALUE_SET_INT (val
, uni
[0]);
1996 swfdec_action_ascii_to_char (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
1999 SwfdecAsValue
*val
= swfdec_as_stack_peek (cx
, 1);
2000 gunichar c
= ((guint
) swfdec_as_value_to_integer (cx
, val
)) % 65536;
2002 s
= g_ucs4_to_utf8 (&c
, 1, NULL
, NULL
, NULL
);
2004 g_warning ("conversion of character %u failed", (guint
) c
);
2005 SWFDEC_AS_VALUE_SET_STRING (val
, SWFDEC_AS_STR_EMPTY
);
2007 SWFDEC_AS_VALUE_SET_STRING (val
, swfdec_as_context_get_string (cx
, s
));
2013 swfdec_action_ascii_to_char_5 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
2015 SwfdecAsValue
*val
= swfdec_as_stack_peek (cx
, 1);
2019 s
[0] = ((guint
) swfdec_as_value_to_integer (cx
, val
)) % 256;
2022 utf8
= g_convert (s
, -1, "UTF-8", "LATIN1", NULL
, NULL
, NULL
);
2024 g_warning ("conversion of character %u failed", (guint
) s
[0]);
2025 SWFDEC_AS_VALUE_SET_STRING (val
, SWFDEC_AS_STR_EMPTY
);
2027 SWFDEC_AS_VALUE_SET_STRING (val
, swfdec_as_context_get_string (cx
, utf8
));
2033 swfdec_action_mb_ascii_to_char_5 (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
2035 SwfdecAsValue
*val
= swfdec_as_stack_peek (cx
, 1);
2040 i
= ((guint
) swfdec_as_value_to_integer (cx
, val
));
2049 utf8
= g_convert (s
, -1, "UTF-8", "LATIN1", NULL
, NULL
, NULL
);
2051 g_warning ("conversion of character %u failed", i
);
2052 SWFDEC_AS_VALUE_SET_STRING (val
, SWFDEC_AS_STR_EMPTY
);
2054 SWFDEC_AS_VALUE_SET_STRING (val
, swfdec_as_context_get_string (cx
, utf8
));
2060 swfdec_action_with (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
2062 SwfdecAsObject
*object
;
2066 SWFDEC_ERROR ("With action requires a length of 2, but got %u", len
);
2067 swfdec_as_stack_pop (cx
);
2070 offset
= data
[0] | (data
[1] << 8);
2071 object
= swfdec_as_value_to_object (cx
, swfdec_as_stack_peek (cx
, 1));
2072 if (object
== NULL
) {
2073 SWFDEC_INFO ("With called without an object, skipping");
2074 cx
->frame
->pc
= (guint8
*) data
+ len
+ offset
;
2076 swfdec_as_with_new (object
, data
+ len
, offset
);
2078 swfdec_as_stack_pop (cx
);
2082 swfdec_action_remove_sprite (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
2084 SwfdecAsValue
*val
= swfdec_as_stack_peek (cx
, 1);
2085 SwfdecAsObject
*sprite
;
2088 if (SWFDEC_AS_VALUE_IS_STRING (val
)) {
2089 const char *name
= SWFDEC_AS_VALUE_GET_STRING (val
);
2091 swfdec_as_context_eval (cx
, NULL
, name
, val
);
2093 if (SWFDEC_AS_VALUE_IS_OBJECT (val
)) {
2094 sprite
= SWFDEC_AS_VALUE_GET_OBJECT (val
);
2096 SWFDEC_FIXME ("unknown type in RemoveSprite");
2099 if (!SWFDEC_IS_MOVIE (sprite
)) {
2100 SWFDEC_FIXME ("cannot remove non movieclip objects");
2103 movie
= SWFDEC_MOVIE (sprite
);
2104 if (swfdec_depth_classify (movie
->depth
) == SWFDEC_DEPTH_CLASS_DYNAMIC
) {
2105 SWFDEC_LOG ("removing clip %s", movie
->name
);
2106 swfdec_movie_remove (movie
);
2109 swfdec_as_stack_pop (cx
);
2113 swfdec_action_clone_sprite (SwfdecAsContext
*cx
, guint action
, const guint8
*data
, guint len
)
2115 SwfdecMovie
*movie
, *new_movie
;
2116 SwfdecAsObject
*obj
;
2117 const char *new_name
;
2120 depth
= swfdec_as_value_to_integer (cx
, swfdec_as_stack_peek (cx
, 1)) - 16384;
2121 new_name
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 2));
2122 if (SWFDEC_AS_VALUE_IS_STRING (swfdec_as_stack_peek (cx
, 3))) {
2124 name
= swfdec_as_value_to_string (cx
, swfdec_as_stack_peek (cx
, 3));
2125 swfdec_as_context_eval (cx
, NULL
, name
, swfdec_as_stack_peek (cx
, 3));
2127 obj
= swfdec_as_value_to_object (cx
, swfdec_as_stack_peek (cx
, 3));
2128 if (!SWFDEC_IS_MOVIE(obj
)) {
2129 SWFDEC_ERROR ("Object is not an SwfdecMovie object");
2130 swfdec_as_stack_pop_n (cx
, 3);
2133 movie
= SWFDEC_MOVIE(obj
);
2134 new_movie
= swfdec_movie_duplicate (movie
, new_name
, depth
);
2136 SWFDEC_LOG ("duplicated %s as %s to depth %u", movie
->name
, new_movie
->name
, new_movie
->depth
);
2137 if (SWFDEC_IS_SPRITE_MOVIE (new_movie
)) {
2138 g_queue_push_tail (SWFDEC_PLAYER (cx
)->init_queue
, new_movie
);
2139 swfdec_movie_queue_script (new_movie
, SWFDEC_EVENT_LOAD
);
2140 swfdec_movie_run_construct (new_movie
);
2142 swfdec_movie_initialize (new_movie
);
2144 swfdec_as_stack_pop_n (cx
, 3);
2147 /*** PRINT FUNCTIONS ***/
2150 swfdec_action_print_with (guint action
, const guint8
*data
, guint len
)
2153 SWFDEC_ERROR ("With action requires a length of 2, but got %u", len
);
2156 return g_strdup_printf ("With %u", data
[0] | (data
[1] << 8));
2160 swfdec_action_print_store_register (guint action
, const guint8
*data
, guint len
)
2163 SWFDEC_ERROR ("StoreRegister action requires a length of 1, but got %u", len
);
2166 return g_strdup_printf ("StoreRegister %u", (guint
) *data
);
2170 swfdec_action_print_set_target (guint action
, const guint8
*data
, guint len
)
2172 if (!memchr (data
, 0, len
)) {
2173 SWFDEC_ERROR ("SetTarget action does not specify a string");
2176 return g_strconcat ("SetTarget ", data
, NULL
);
2180 swfdec_action_print_define_function (guint action
, const guint8
*data
, guint len
)
2184 const char *function_name
;
2185 guint i
, n_args
, size
;
2186 gboolean v2
= (action
== 0x8e);
2188 string
= g_string_new (v2
? "DefineFunction2 " : "DefineFunction ");
2189 swfdec_bits_init_data (&bits
, data
, len
);
2190 function_name
= swfdec_bits_get_string (&bits
);
2191 if (function_name
== NULL
) {
2192 SWFDEC_ERROR ("could not parse function name");
2193 g_string_free (string
, TRUE
);
2196 if (*function_name
) {
2197 g_string_append (string
, function_name
);
2198 g_string_append_c (string
, ' ');
2200 n_args
= swfdec_bits_get_u16 (&bits
);
2201 g_string_append_c (string
, '(');
2203 /* n_regs = */ swfdec_bits_get_u8 (&bits
);
2204 /* flags = */ swfdec_bits_get_u16 (&bits
);
2207 for (i
= 0; i
< n_args
; i
++) {
2209 const char *arg_name
;
2211 preload
= swfdec_bits_get_u8 (&bits
);
2214 arg_name
= swfdec_bits_get_string (&bits
);
2215 if (preload
== 0 && (arg_name
== NULL
|| *arg_name
== '\0')) {
2216 SWFDEC_ERROR ("empty argument name not allowed");
2217 g_string_free (string
, TRUE
);
2221 g_string_append (string
, ", ");
2222 g_string_append (string
, arg_name
);
2224 g_string_append_printf (string
, " (%u)", preload
);
2226 g_string_append_c (string
, ')');
2227 size
= swfdec_bits_get_u16 (&bits
);
2228 g_string_append_printf (string
, " %u", size
);
2229 return g_string_free (string
, FALSE
);
2233 swfdec_action_print_get_url2 (guint action
, const guint8
*data
, guint len
)
2238 SWFDEC_ERROR ("GetURL2 requires 1 byte of data, not %u", len
);
2241 method
= data
[0] >> 6;
2243 SWFDEC_ERROR ("GetURL method 3 invalid");
2247 SWFDEC_FIXME ("implement encoding variables using %s", method
== 1 ? "GET" : "POST");
2249 return g_strdup_printf ("GetURL2%s%s%s", method
== 0 ? "" : (method
== 1 ? " GET" : " POST"),
2250 data
[0] & 2 ? " LoadTarget" : "", data
[0] & 1 ? " LoadVariables" : "");
2254 swfdec_action_print_get_url (guint action
, const guint8
*data
, guint len
)
2257 char *url
, *target
, *ret
;
2259 swfdec_bits_init_data (&bits
, data
, len
);
2260 url
= swfdec_bits_get_string (&bits
);
2261 target
= swfdec_bits_get_string (&bits
);
2263 SWFDEC_ERROR ("not enough data in GetURL");
2264 url
= g_strdup ("???");
2266 if (target
== NULL
) {
2267 SWFDEC_ERROR ("not enough data in GetURL");
2268 target
= g_strdup ("???");
2270 if (swfdec_bits_left (&bits
)) {
2271 SWFDEC_WARNING ("leftover bytes in GetURL action");
2273 ret
= g_strdup_printf ("GetURL %s %s", url
, target
);
2280 swfdec_action_print_if (guint action
, const guint8
*data
, guint len
)
2283 SWFDEC_ERROR ("If action length invalid (is %u, should be 2", len
);
2286 return g_strdup_printf ("If %d", GINT16_FROM_LE (*((gint16
*) data
)));
2290 swfdec_action_print_jump (guint action
, const guint8
*data
, guint len
)
2293 SWFDEC_ERROR ("Jump action length invalid (is %u, should be 2", len
);
2296 return g_strdup_printf ("Jump %d", GINT16_FROM_LE (*((gint16
*) data
)));
2300 swfdec_action_print_push (guint action
, const guint8
*data
, guint len
)
2302 gboolean first
= TRUE
;
2304 GString
*string
= g_string_new ("Push");
2306 swfdec_bits_init_data (&bits
, data
, len
);
2307 while (swfdec_bits_left (&bits
)) {
2308 guint type
= swfdec_bits_get_u8 (&bits
);
2310 g_string_append (string
, " ");
2312 g_string_append (string
, ", ");
2315 case 0: /* string */
2317 /* FIXME: need version! */
2318 char *s
= swfdec_bits_get_string (&bits
);
2320 g_string_free (string
, TRUE
);
2323 g_string_append_c (string
, '"');
2324 g_string_append (string
, s
);
2325 g_string_append_c (string
, '"');
2330 g_string_append_printf (string
, "%g", swfdec_bits_get_float (&bits
));
2333 g_string_append (string
, "null");
2335 case 3: /* undefined */
2336 g_string_append (string
, "void");
2338 case 4: /* register */
2339 g_string_append_printf (string
, "Register %u", swfdec_bits_get_u8 (&bits
));
2341 case 5: /* boolean */
2342 g_string_append (string
, swfdec_bits_get_u8 (&bits
) ? "True" : "False");
2344 case 6: /* double */
2345 g_string_append_printf (string
, "%g", swfdec_bits_get_double (&bits
));
2347 case 7: /* 32bit int */
2348 g_string_append_printf (string
, "%d", swfdec_bits_get_u32 (&bits
));
2350 case 8: /* 8bit ConstantPool address */
2351 g_string_append_printf (string
, "Pool %u", swfdec_bits_get_u8 (&bits
));
2353 case 9: /* 16bit ConstantPool address */
2354 g_string_append_printf (string
, "Pool %u", swfdec_bits_get_u16 (&bits
));
2357 SWFDEC_ERROR ("Push: type %u not implemented", type
);
2361 return g_string_free (string
, FALSE
);
2364 /* NB: constant pool actions are special in that they are called at init time */
2366 swfdec_action_print_constant_pool (guint action
, const guint8
*data
, guint len
)
2370 SwfdecConstantPool
*pool
;
2372 /* FIXME: version */
2373 pool
= swfdec_constant_pool_new_from_action (data
, len
, 6);
2375 return g_strdup ("ConstantPool (invalid)");
2376 string
= g_string_new ("ConstantPool");
2377 for (i
= 0; i
< swfdec_constant_pool_size (pool
); i
++) {
2378 g_string_append (string
, i
? ", " : " ");
2379 g_string_append (string
, swfdec_constant_pool_get (pool
, i
));
2380 g_string_append_printf (string
, " (%u)", i
);
2382 return g_string_free (string
, FALSE
);
2387 swfdec_action_print_wait_for_frame2 (guint action
, const guint8
*data
, guint len
)
2390 SWFDEC_ERROR ("WaitForFrame2 needs a 1-byte data");
2393 return g_strdup_printf ("WaitForFrame2 %u", (guint
) *data
);
2398 swfdec_action_print_goto_frame2 (guint action
, const guint8
*data
, guint len
)
2400 gboolean play
, bias
;
2403 swfdec_bits_init_data (&bits
, data
, len
);
2404 if (swfdec_bits_getbits (&bits
, 6)) {
2405 SWFDEC_WARNING ("reserved bits in GotoFrame2 aren't 0");
2407 bias
= swfdec_bits_getbit (&bits
);
2408 play
= swfdec_bits_getbit (&bits
);
2410 return g_strdup_printf ("GotoFrame2 %s +%u", play
? "play" : "stop",
2411 swfdec_bits_get_u16 (&bits
));
2413 return g_strdup_printf ("GotoFrame2 %s", play
? "play" : "stop");
2418 swfdec_action_print_goto_frame (guint action
, const guint8
*data
, guint len
)
2425 frame
= data
[0] | (data
[1] << 8);
2426 return g_strdup_printf ("GotoFrame %u", frame
);
2430 swfdec_action_print_goto_label (guint action
, const guint8
*data
, guint len
)
2432 if (!memchr (data
, 0, len
)) {
2433 SWFDEC_ERROR ("GotoLabel action does not specify a string");
2437 return g_strdup_printf ("GotoLabel %s", data
);
2441 swfdec_action_print_wait_for_frame (guint action
, const guint8
*data
, guint len
)
2448 frame
= data
[0] | (data
[1] << 8);
2450 return g_strdup_printf ("WaitForFrame %u %u", frame
, jump
);
2453 /*** BIG FUNCTION TABLE ***/
2455 const SwfdecActionSpec swfdec_as_actions
[256] = {
2457 [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
} },
2458 [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
} },
2459 [SWFDEC_AS_ACTION_PLAY
] = { "Play", NULL
, 0, 0, { swfdec_action_play
, swfdec_action_play
, swfdec_action_play
, swfdec_action_play
, swfdec_action_play
} },
2460 [SWFDEC_AS_ACTION_STOP
] = { "Stop", NULL
, 0, 0, { swfdec_action_stop
, swfdec_action_stop
, swfdec_action_stop
, swfdec_action_stop
, swfdec_action_stop
} },
2461 [SWFDEC_AS_ACTION_TOGGLE_QUALITY
] = { "ToggleQuality", NULL
},
2462 [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
} },
2464 [SWFDEC_AS_ACTION_ADD
] = { "Add", NULL
, 2, 1, { NULL
, swfdec_action_binary
, swfdec_action_binary
, swfdec_action_binary
, swfdec_action_binary
} },
2465 [SWFDEC_AS_ACTION_SUBTRACT
] = { "Subtract", NULL
, 2, 1, { NULL
, swfdec_action_binary
, swfdec_action_binary
, swfdec_action_binary
, swfdec_action_binary
} },
2466 [SWFDEC_AS_ACTION_MULTIPLY
] = { "Multiply", NULL
, 2, 1, { NULL
, swfdec_action_binary
, swfdec_action_binary
, swfdec_action_binary
, swfdec_action_binary
} },
2467 [SWFDEC_AS_ACTION_DIVIDE
] = { "Divide", NULL
, 2, 1, { NULL
, swfdec_action_binary
, swfdec_action_binary
, swfdec_action_binary
, swfdec_action_binary
} },
2468 [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
} },
2469 [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
} },
2470 [SWFDEC_AS_ACTION_AND
] = { "And", NULL
, 2, 1, { NULL
, /* FIXME */NULL
, swfdec_action_logical
, swfdec_action_logical
, swfdec_action_logical
} },
2471 [SWFDEC_AS_ACTION_OR
] = { "Or", NULL
, 2, 1, { NULL
, /* FIXME */NULL
, swfdec_action_logical
, swfdec_action_logical
, swfdec_action_logical
} },
2472 [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
} },
2473 [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
} },
2474 [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
} },
2475 [SWFDEC_AS_ACTION_STRING_EXTRACT
] = { "StringExtract", NULL
},
2476 [SWFDEC_AS_ACTION_POP
] = { "Pop", NULL
, 1, 0, { NULL
, swfdec_action_pop
, swfdec_action_pop
, swfdec_action_pop
, swfdec_action_pop
} },
2477 [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
} },
2478 [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
} },
2479 [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
} },
2480 [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
} },
2481 [0x21] = { "StringAdd", NULL
, 2, 1, { NULL
, swfdec_action_string_add
, swfdec_action_string_add
, swfdec_action_string_add
, swfdec_action_string_add
} },
2482 [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
} },
2483 [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
} },
2484 [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
} },
2485 [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
} },
2486 [SWFDEC_AS_ACTION_TRACE
] = { "Trace", NULL
, 1, 0, { NULL
, swfdec_action_trace
, swfdec_action_trace
, swfdec_action_trace
, swfdec_action_trace
} },
2487 [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
} },
2488 [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
} },
2489 [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
} },
2491 [SWFDEC_AS_ACTION_THROW
] = { "Throw", NULL
},
2492 [SWFDEC_AS_ACTION_CAST
] = { "Cast", NULL
},
2493 [SWFDEC_AS_ACTION_IMPLEMENTS
] = { "Implements", NULL
},
2495 [0x30] = { "RandomNumber", NULL
, 1, 1, { NULL
, swfdec_action_random_number
, swfdec_action_random_number
, swfdec_action_random_number
, swfdec_action_random_number
} },
2496 [SWFDEC_AS_ACTION_MB_STRING_LENGTH
] = { "MBStringLength", NULL
},
2497 [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
} },
2498 [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
} },
2499 [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
} },
2500 [SWFDEC_AS_ACTION_MB_STRING_EXTRACT
] = { "MBStringExtract", NULL
},
2501 [SWFDEC_AS_ACTION_MB_CHAR_TO_ASCII
] = { "MBCharToAscii", NULL
},
2502 [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
} },
2504 [SWFDEC_AS_ACTION_DELETE
] = { "Delete", NULL
, 2, 1, { NULL
, NULL
, swfdec_action_delete
, swfdec_action_delete
, swfdec_action_delete
} },
2505 [SWFDEC_AS_ACTION_DELETE2
] = { "Delete2", NULL
, 1, 1, { NULL
, NULL
, swfdec_action_delete2
, swfdec_action_delete2
, swfdec_action_delete2
} },
2506 [SWFDEC_AS_ACTION_DEFINE_LOCAL
] = { "DefineLocal", NULL
, 2, 0, { NULL
, NULL
, swfdec_action_define_local
, swfdec_action_define_local
, swfdec_action_define_local
} },
2507 [SWFDEC_AS_ACTION_CALL_FUNCTION
] = { "CallFunction", NULL
, -1, 1, { NULL
, NULL
, swfdec_action_call_function
, swfdec_action_call_function
, swfdec_action_call_function
} },
2508 [SWFDEC_AS_ACTION_RETURN
] = { "Return", NULL
, 1, 0, { NULL
, NULL
, swfdec_action_return
, swfdec_action_return
, swfdec_action_return
} },
2509 [SWFDEC_AS_ACTION_MODULO
] = { "Modulo", NULL
, 2, 1, { NULL
, NULL
, swfdec_action_modulo
, swfdec_action_modulo
, swfdec_action_modulo
} },
2510 [SWFDEC_AS_ACTION_NEW_OBJECT
] = { "NewObject", NULL
, -1, 1, { NULL
, NULL
, swfdec_action_new_object
, swfdec_action_new_object
, swfdec_action_new_object
} },
2511 [SWFDEC_AS_ACTION_DEFINE_LOCAL2
] = { "DefineLocal2", NULL
, 1, 0, { NULL
, NULL
, swfdec_action_define_local2
, swfdec_action_define_local2
, swfdec_action_define_local2
} },
2512 [SWFDEC_AS_ACTION_INIT_ARRAY
] = { "InitArray", NULL
, -1, 1, { NULL
, NULL
, swfdec_action_init_array
, swfdec_action_init_array
, swfdec_action_init_array
} },
2513 [SWFDEC_AS_ACTION_INIT_OBJECT
] = { "InitObject", NULL
, -1, 1, { NULL
, NULL
, swfdec_action_init_object
, swfdec_action_init_object
, swfdec_action_init_object
} },
2514 [SWFDEC_AS_ACTION_TYPE_OF
] = { "TypeOf", NULL
, 1, 1, { NULL
, NULL
, swfdec_action_type_of
, swfdec_action_type_of
, swfdec_action_type_of
} },
2515 [SWFDEC_AS_ACTION_TARGET_PATH
] = { "TargetPath", NULL
, 1, 1, { NULL
, NULL
, swfdec_action_target_path
, swfdec_action_target_path
, swfdec_action_target_path
} },
2516 [SWFDEC_AS_ACTION_ENUMERATE
] = { "Enumerate", NULL
, 1, -1, { NULL
, NULL
, swfdec_action_enumerate
, swfdec_action_enumerate
, swfdec_action_enumerate
} },
2517 [SWFDEC_AS_ACTION_ADD2
] = { "Add2", NULL
, 2, 1, { NULL
, NULL
, swfdec_action_add2
, swfdec_action_add2
, swfdec_action_add2
} },
2518 [SWFDEC_AS_ACTION_LESS2
] = { "Less2", NULL
, 2, 1, { NULL
, NULL
, swfdec_action_new_comparison
, swfdec_action_new_comparison
, swfdec_action_new_comparison
} },
2519 [SWFDEC_AS_ACTION_EQUALS2
] = { "Equals2", NULL
, 2, 1, { NULL
, NULL
, swfdec_action_equals2_5
, swfdec_action_equals2
, swfdec_action_equals2
} },
2520 [SWFDEC_AS_ACTION_TO_NUMBER
] = { "ToNumber", NULL
, 1, 1, { NULL
, NULL
, swfdec_action_to_number
, swfdec_action_to_number
, swfdec_action_to_number
} },
2521 [SWFDEC_AS_ACTION_TO_STRING
] = { "ToString", NULL
, 1, 1, { NULL
, NULL
, swfdec_action_to_string
, swfdec_action_to_string
, swfdec_action_to_string
} },
2522 [SWFDEC_AS_ACTION_PUSH_DUPLICATE
] = { "PushDuplicate", NULL
, 1, 2, { NULL
, NULL
, swfdec_action_push_duplicate
, swfdec_action_push_duplicate
, swfdec_action_push_duplicate
} },
2523 [SWFDEC_AS_ACTION_SWAP
] = { "Swap", NULL
, 2, 2, { NULL
, NULL
, swfdec_action_swap
, swfdec_action_swap
, swfdec_action_swap
} },
2524 [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
} },
2525 [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
} },
2526 [SWFDEC_AS_ACTION_INCREMENT
] = { "Increment", NULL
, 1, 1, { NULL
, NULL
, swfdec_action_increment
, swfdec_action_increment
, swfdec_action_increment
} },
2527 [SWFDEC_AS_ACTION_DECREMENT
] = { "Decrement", NULL
, 1, 1, { NULL
, NULL
, swfdec_action_decrement
, swfdec_action_decrement
, swfdec_action_decrement
} },
2528 [SWFDEC_AS_ACTION_CALL_METHOD
] = { "CallMethod", NULL
, -1, 1, { NULL
, NULL
, swfdec_action_call_method
, swfdec_action_call_method
, swfdec_action_call_method
} },
2529 [SWFDEC_AS_ACTION_NEW_METHOD
] = { "NewMethod", NULL
, -1, 1, { NULL
, NULL
, swfdec_action_new_method
, swfdec_action_new_method
, swfdec_action_new_method
} },
2531 [SWFDEC_AS_ACTION_INSTANCE_OF
] = { "InstanceOf", NULL
},
2532 [SWFDEC_AS_ACTION_ENUMERATE2
] = { "Enumerate2", NULL
, 1, -1, { NULL
, NULL
, NULL
, swfdec_action_enumerate2
, swfdec_action_enumerate2
} },
2534 [SWFDEC_AS_ACTION_BIT_AND
] = { "BitAnd", NULL
, 2, 1, { NULL
, NULL
, swfdec_action_bitwise
, swfdec_action_bitwise
, swfdec_action_bitwise
} },
2535 [SWFDEC_AS_ACTION_BIT_OR
] = { "BitOr", NULL
, 2, 1, { NULL
, NULL
, swfdec_action_bitwise
, swfdec_action_bitwise
, swfdec_action_bitwise
} },
2536 [SWFDEC_AS_ACTION_BIT_XOR
] = { "BitXor", NULL
, 2, 1, { NULL
, NULL
, swfdec_action_bitwise
, swfdec_action_bitwise
, swfdec_action_bitwise
} },
2537 [SWFDEC_AS_ACTION_BIT_LSHIFT
] = { "BitLShift", NULL
, 2, 1, { NULL
, NULL
, swfdec_action_shift
, swfdec_action_shift
, swfdec_action_shift
} },
2538 [SWFDEC_AS_ACTION_BIT_RSHIFT
] = { "BitRShift", NULL
, 2, 1, { NULL
, NULL
, swfdec_action_shift
, swfdec_action_shift
, swfdec_action_shift
} },
2539 [SWFDEC_AS_ACTION_BIT_URSHIFT
] = { "BitURShift", NULL
, 2, 1, { NULL
, NULL
, swfdec_action_shift
, swfdec_action_shift
, swfdec_action_shift
} },
2541 [SWFDEC_AS_ACTION_STRICT_EQUALS
] = { "StrictEquals", NULL
, 2, 1, { NULL
, NULL
, NULL
, swfdec_action_strict_equals
, swfdec_action_strict_equals
} },
2542 [SWFDEC_AS_ACTION_GREATER
] = { "Greater", NULL
, 2, 1, { NULL
, NULL
, NULL
, swfdec_action_new_comparison
, swfdec_action_new_comparison
} },
2543 [SWFDEC_AS_ACTION_STRING_GREATER
] = { "StringGreater", NULL
},
2545 [SWFDEC_AS_ACTION_EXTENDS
] = { "Extends", NULL
, 2, 0, { NULL
, NULL
, NULL
, swfdec_action_extends
, swfdec_action_extends
} },
2547 [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
} },
2548 [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
} },
2550 [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
} },
2551 [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
} },
2553 [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
} },
2554 [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
} },
2555 [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
} },
2558 [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
} },
2561 [SWFDEC_AS_ACTION_DEFINE_FUNCTION2
] = { "DefineFunction2", swfdec_action_print_define_function
, 0, -1, { NULL
, NULL
, NULL
, swfdec_action_define_function
, swfdec_action_define_function
} },
2562 [SWFDEC_AS_ACTION_TRY
] = { "Try", NULL
},
2564 [SWFDEC_AS_ACTION_WITH
] = { "With", swfdec_action_print_with
, 1, 0, { NULL
, NULL
, swfdec_action_with
, swfdec_action_with
, swfdec_action_with
} },
2566 [SWFDEC_AS_ACTION_PUSH
] = { "Push", swfdec_action_print_push
, 0, -1, { NULL
, swfdec_action_push
, swfdec_action_push
, swfdec_action_push
, swfdec_action_push
} },
2567 [SWFDEC_AS_ACTION_JUMP
] = { "Jump", swfdec_action_print_jump
, 0, 0, { NULL
, swfdec_action_jump
, swfdec_action_jump
, swfdec_action_jump
, swfdec_action_jump
} },
2568 [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
} },
2570 [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
} },
2572 [SWFDEC_AS_ACTION_IF
] = { "If", swfdec_action_print_if
, 1, 0, { NULL
, swfdec_action_if
, swfdec_action_if
, swfdec_action_if
, swfdec_action_if
} },
2573 [SWFDEC_AS_ACTION_CALL
] = { "Call", NULL
},
2574 [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
} }