avm1: Log errors/unimplemented actions
This commit is contained in:
parent
9d962fd634
commit
91a0272773
293
core/src/avm1.rs
293
core/src/avm1.rs
|
@ -39,119 +39,118 @@ impl Avm1 {
|
||||||
|
|
||||||
while let Some(action) = reader.read_action()? {
|
while let Some(action) = reader.read_action()? {
|
||||||
use swf::avm1::types::Action;
|
use swf::avm1::types::Action;
|
||||||
match action {
|
let result = match action {
|
||||||
Action::Add => self.action_add(context)?,
|
Action::Add => self.action_add(context),
|
||||||
Action::Add2 => self.action_add_2(context)?,
|
Action::Add2 => self.action_add_2(context),
|
||||||
Action::And => self.action_and(context)?,
|
Action::And => self.action_and(context),
|
||||||
Action::AsciiToChar => self.action_ascii_to_char(context)?,
|
Action::AsciiToChar => self.action_ascii_to_char(context),
|
||||||
Action::BitAnd => self.action_bit_and(context)?,
|
Action::BitAnd => self.action_bit_and(context),
|
||||||
Action::BitLShift => self.action_bit_lshift(context)?,
|
Action::BitLShift => self.action_bit_lshift(context),
|
||||||
Action::BitOr => self.action_bit_or(context)?,
|
Action::BitOr => self.action_bit_or(context),
|
||||||
Action::BitRShift => self.action_bit_rshift(context)?,
|
Action::BitRShift => self.action_bit_rshift(context),
|
||||||
Action::BitURShift => self.action_bit_urshift(context)?,
|
Action::BitURShift => self.action_bit_urshift(context),
|
||||||
Action::BitXor => self.action_bit_xor(context)?,
|
Action::BitXor => self.action_bit_xor(context),
|
||||||
Action::Call => self.action_call(context)?,
|
Action::Call => self.action_call(context),
|
||||||
Action::CallFunction => self.action_call_function(context)?,
|
Action::CallFunction => self.action_call_function(context),
|
||||||
Action::CallMethod => self.action_call_method(context)?,
|
Action::CallMethod => self.action_call_method(context),
|
||||||
Action::CharToAscii => self.action_char_to_ascii(context)?,
|
Action::CharToAscii => self.action_char_to_ascii(context),
|
||||||
Action::ConstantPool(constant_pool) => {
|
Action::ConstantPool(constant_pool) => {
|
||||||
self.action_constant_pool(context, &constant_pool[..])?
|
self.action_constant_pool(context, &constant_pool[..])
|
||||||
}
|
}
|
||||||
Action::Decrement => self.action_decrement(context)?,
|
Action::Decrement => self.action_decrement(context),
|
||||||
Action::DefineFunction {
|
Action::DefineFunction {
|
||||||
name,
|
name,
|
||||||
params,
|
params,
|
||||||
actions,
|
actions,
|
||||||
} => self.action_define_function(context, &name, ¶ms[..], &actions[..])?,
|
} => self.action_define_function(context, &name, ¶ms[..], &actions[..]),
|
||||||
Action::DefineLocal => self.action_define_local(context)?,
|
Action::DefineLocal => self.action_define_local(context),
|
||||||
Action::DefineLocal2 => self.action_define_local_2(context)?,
|
Action::DefineLocal2 => self.action_define_local_2(context),
|
||||||
Action::Delete => self.action_delete(context)?,
|
Action::Delete => self.action_delete(context),
|
||||||
Action::Delete2 => self.action_delete_2(context)?,
|
Action::Delete2 => self.action_delete_2(context),
|
||||||
Action::Divide => self.action_divide(context)?,
|
Action::Divide => self.action_divide(context),
|
||||||
Action::EndDrag => self.action_end_drag(context)?,
|
Action::EndDrag => self.action_end_drag(context),
|
||||||
Action::Enumerate => self.action_enumerate(context)?,
|
Action::Enumerate => self.action_enumerate(context),
|
||||||
Action::Equals => self.action_equals(context)?,
|
Action::Equals => self.action_equals(context),
|
||||||
Action::Equals2 => self.action_equals_2(context)?,
|
Action::Equals2 => self.action_equals_2(context),
|
||||||
Action::GetMember => self.action_get_member(context)?,
|
Action::GetMember => self.action_get_member(context),
|
||||||
Action::GetProperty => self.action_get_property(context)?,
|
Action::GetProperty => self.action_get_property(context),
|
||||||
Action::GetTime => self.action_get_time(context)?,
|
Action::GetTime => self.action_get_time(context),
|
||||||
Action::GetVariable => self.action_get_variable(context)?,
|
Action::GetVariable => self.action_get_variable(context),
|
||||||
Action::GetUrl { url, target } => self.action_get_url(context, &url, &target)?,
|
Action::GetUrl { url, target } => self.action_get_url(context, &url, &target),
|
||||||
Action::GetUrl2 {
|
Action::GetUrl2 {
|
||||||
send_vars_method,
|
send_vars_method,
|
||||||
is_target_sprite,
|
is_target_sprite,
|
||||||
is_load_vars,
|
is_load_vars,
|
||||||
} => self.action_get_url_2(
|
} => {
|
||||||
context,
|
self.action_get_url_2(context, send_vars_method, is_target_sprite, is_load_vars)
|
||||||
send_vars_method,
|
}
|
||||||
is_target_sprite,
|
Action::GotoFrame(frame) => self.action_goto_frame(context, frame),
|
||||||
is_load_vars,
|
|
||||||
)?,
|
|
||||||
Action::GotoFrame(frame) => self.action_goto_frame(context, frame)?,
|
|
||||||
Action::GotoFrame2 {
|
Action::GotoFrame2 {
|
||||||
set_playing,
|
set_playing,
|
||||||
scene_offset,
|
scene_offset,
|
||||||
} => self.action_goto_frame_2(context, set_playing, scene_offset)?,
|
} => self.action_goto_frame_2(context, set_playing, scene_offset),
|
||||||
Action::GotoLabel(label) => self.action_goto_label(context, &label)?,
|
Action::GotoLabel(label) => self.action_goto_label(context, &label),
|
||||||
Action::If { offset } => self.action_if(context, offset, &mut reader)?,
|
Action::If { offset } => self.action_if(context, offset, &mut reader),
|
||||||
Action::Increment => self.action_increment(context)?,
|
Action::Increment => self.action_increment(context),
|
||||||
Action::InitArray => self.action_init_array(context)?,
|
Action::InitArray => self.action_init_array(context),
|
||||||
Action::InitObject => self.action_init_object(context)?,
|
Action::InitObject => self.action_init_object(context),
|
||||||
Action::Jump { offset } => self.action_jump(context, offset, &mut reader)?,
|
Action::Jump { offset } => self.action_jump(context, offset, &mut reader),
|
||||||
Action::Less => self.action_less(context)?,
|
Action::Less => self.action_less(context),
|
||||||
Action::Less2 => self.action_less_2(context)?,
|
Action::Less2 => self.action_less_2(context),
|
||||||
Action::MBAsciiToChar => self.action_mb_ascii_to_char(context)?,
|
Action::MBAsciiToChar => self.action_mb_ascii_to_char(context),
|
||||||
Action::MBCharToAscii => self.action_mb_char_to_ascii(context)?,
|
Action::MBCharToAscii => self.action_mb_char_to_ascii(context),
|
||||||
Action::MBStringLength => self.action_mb_string_length(context)?,
|
Action::MBStringLength => self.action_mb_string_length(context),
|
||||||
Action::MBStringExtract => self.action_mb_string_extract(context)?,
|
Action::MBStringExtract => self.action_mb_string_extract(context),
|
||||||
Action::Modulo => self.action_modulo(context)?,
|
Action::Modulo => self.action_modulo(context),
|
||||||
Action::Multiply => self.action_multiply(context)?,
|
Action::Multiply => self.action_multiply(context),
|
||||||
Action::NextFrame => self.action_next_frame(context)?,
|
Action::NextFrame => self.action_next_frame(context),
|
||||||
Action::NewMethod => self.action_new_method(context)?,
|
Action::NewMethod => self.action_new_method(context),
|
||||||
Action::NewObject => self.action_new_object(context)?,
|
Action::NewObject => self.action_new_object(context),
|
||||||
Action::Not => self.action_not(context)?,
|
Action::Not => self.action_not(context),
|
||||||
Action::Or => self.action_or(context)?,
|
Action::Or => self.action_or(context),
|
||||||
Action::Play => self.play(context)?,
|
Action::Play => self.play(context),
|
||||||
Action::Pop => self.action_pop(context)?,
|
Action::Pop => self.action_pop(context),
|
||||||
Action::PreviousFrame => self.prev_frame(context)?,
|
Action::PreviousFrame => self.prev_frame(context),
|
||||||
Action::Push(values) => self.action_push(context, &values[..])?,
|
Action::Push(values) => self.action_push(context, &values[..]),
|
||||||
Action::PushDuplicate => self.action_push_duplicate(context)?,
|
Action::PushDuplicate => self.action_push_duplicate(context),
|
||||||
Action::RandomNumber => self.action_random_number(context)?,
|
Action::RandomNumber => self.action_random_number(context),
|
||||||
Action::RemoveSprite => self.action_remove_sprite(context)?,
|
Action::RemoveSprite => self.action_remove_sprite(context),
|
||||||
Action::Return => self.action_return(context)?,
|
Action::Return => self.action_return(context),
|
||||||
Action::SetMember => self.action_set_member(context)?,
|
Action::SetMember => self.action_set_member(context),
|
||||||
Action::SetProperty => self.action_set_property(context)?,
|
Action::SetProperty => self.action_set_property(context),
|
||||||
Action::SetTarget(target) => self.action_set_target(context, &target)?,
|
Action::SetTarget(target) => self.action_set_target(context, &target),
|
||||||
Action::SetVariable => self.action_set_variable(context)?,
|
Action::SetVariable => self.action_set_variable(context),
|
||||||
Action::StackSwap => self.action_stack_swap(context)?,
|
Action::StackSwap => self.action_stack_swap(context),
|
||||||
Action::StartDrag => self.action_start_drag(context)?,
|
Action::StartDrag => self.action_start_drag(context),
|
||||||
Action::Stop => self.action_stop(context)?,
|
Action::Stop => self.action_stop(context),
|
||||||
Action::StopSounds => self.action_stop_sounds(context)?,
|
Action::StopSounds => self.action_stop_sounds(context),
|
||||||
Action::StoreRegister(register) => self.action_store_register(context, register)?,
|
Action::StoreRegister(register) => self.action_store_register(context, register),
|
||||||
Action::StringAdd => self.action_string_add(context)?,
|
Action::StringAdd => self.action_string_add(context),
|
||||||
Action::StringEquals => self.action_string_equals(context)?,
|
Action::StringEquals => self.action_string_equals(context),
|
||||||
Action::StringExtract => self.action_string_extract(context)?,
|
Action::StringExtract => self.action_string_extract(context),
|
||||||
Action::StringLength => self.action_string_length(context)?,
|
Action::StringLength => self.action_string_length(context),
|
||||||
Action::StringLess => self.action_string_less(context)?,
|
Action::StringLess => self.action_string_less(context),
|
||||||
Action::Subtract => self.action_subtract(context)?,
|
Action::Subtract => self.action_subtract(context),
|
||||||
Action::TargetPath => self.action_target_path(context)?,
|
Action::TargetPath => self.action_target_path(context),
|
||||||
Action::ToggleQuality => self.toggle_quality(context)?,
|
Action::ToggleQuality => self.toggle_quality(context),
|
||||||
Action::ToInteger => self.action_to_integer(context)?,
|
Action::ToInteger => self.action_to_integer(context),
|
||||||
Action::ToNumber => self.action_to_number(context)?,
|
Action::ToNumber => self.action_to_number(context),
|
||||||
Action::ToString => self.action_to_string(context)?,
|
Action::ToString => self.action_to_string(context),
|
||||||
Action::Trace => self.action_trace(context)?,
|
Action::Trace => self.action_trace(context),
|
||||||
Action::TypeOf => self.action_type_of(context)?,
|
Action::TypeOf => self.action_type_of(context),
|
||||||
Action::WaitForFrame {
|
Action::WaitForFrame {
|
||||||
frame,
|
frame,
|
||||||
num_actions_to_skip,
|
num_actions_to_skip,
|
||||||
} => {
|
} => self.action_wait_for_frame(context, frame, num_actions_to_skip, &mut reader),
|
||||||
self.action_wait_for_frame(context, frame, num_actions_to_skip, &mut reader)?
|
|
||||||
}
|
|
||||||
Action::WaitForFrame2 {
|
Action::WaitForFrame2 {
|
||||||
num_actions_to_skip,
|
num_actions_to_skip,
|
||||||
} => self.action_wait_for_frame_2(context, num_actions_to_skip, &mut reader)?,
|
} => self.action_wait_for_frame_2(context, num_actions_to_skip, &mut reader),
|
||||||
Action::With { .. } => self.action_with(context)?,
|
Action::With { .. } => self.action_with(context),
|
||||||
_ => self.unknown_op(context, action)?,
|
_ => self.unknown_op(context, action),
|
||||||
|
};
|
||||||
|
if let Err(ref e) = result {
|
||||||
|
log::error!("AVM1 error: {}", e);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,8 +194,10 @@ impl Avm1 {
|
||||||
let mut var_iter = path.splitn(2, ':');
|
let mut var_iter = path.splitn(2, ':');
|
||||||
match (var_iter.next(), var_iter.next()) {
|
match (var_iter.next(), var_iter.next()) {
|
||||||
(Some(var_name), None) => return Some((start, var_name)),
|
(Some(var_name), None) => return Some((start, var_name)),
|
||||||
(Some(path), Some(var_name)) => if let Some(node) = Self::resolve_slash_path(start, root, path) {
|
(Some(path), Some(var_name)) => {
|
||||||
return Some((node, var_name));
|
if let Some(node) = Self::resolve_slash_path(start, root, path) {
|
||||||
|
return Some((node, var_name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -321,8 +322,8 @@ impl Avm1 {
|
||||||
|
|
||||||
fn action_call(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_call(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
let _val = self.pop()?;
|
let _val = self.pop()?;
|
||||||
unimplemented!();
|
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
|
Err("Unimplemented action: Call".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_call_function(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_call_function(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
@ -334,7 +335,7 @@ impl Avm1 {
|
||||||
|
|
||||||
self.stack.push(Value::Undefined);
|
self.stack.push(Value::Undefined);
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
unimplemented!();
|
Err("Unimplemented action: CallFunction".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_call_method(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_call_method(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
@ -347,7 +348,7 @@ impl Avm1 {
|
||||||
|
|
||||||
self.stack.push(Value::Undefined);
|
self.stack.push(Value::Undefined);
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
unimplemented!();
|
Err("Unimplemented action: CallMethod".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_constant_pool(
|
fn action_constant_pool(
|
||||||
|
@ -373,7 +374,7 @@ impl Avm1 {
|
||||||
_actions: &[swf::avm1::types::Action],
|
_actions: &[swf::avm1::types::Action],
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
unimplemented!();
|
Err("Unimplemented action: DefineFunction".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_define_local(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_define_local(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
@ -393,13 +394,13 @@ impl Avm1 {
|
||||||
fn action_delete(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_delete(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
let _name = self.pop()?.as_string()?;
|
let _name = self.pop()?.as_string()?;
|
||||||
let _object = self.pop()?.as_object()?;
|
let _object = self.pop()?.as_object()?;
|
||||||
unimplemented!();
|
Err("Unimplemented action: Delete".into())
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_delete_2(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_delete_2(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
let _name = self.pop()?.as_string()?;
|
let _name = self.pop()?.as_string()?;
|
||||||
unimplemented!();
|
Err("Unimplemented action: Delete2".into())
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,14 +419,14 @@ impl Avm1 {
|
||||||
|
|
||||||
fn action_end_drag(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_end_drag(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
unimplemented!()
|
Err("Unimplemented action: EndDrag".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_enumerate(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_enumerate(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
let _name = self.pop()?.as_string()?;
|
let _name = self.pop()?.as_string()?;
|
||||||
self.push(Value::Null); // Sentinel that indicates end of enumeration
|
self.push(Value::Null); // Sentinel that indicates end of enumeration
|
||||||
// TODO(Herschel): Push each property name onto the stack
|
// TODO(Herschel): Push each property name onto the stack
|
||||||
unimplemented!()
|
Err("Unimplemented action: Enumerate".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::float_cmp)]
|
#[allow(clippy::float_cmp)]
|
||||||
|
@ -463,7 +464,7 @@ impl Avm1 {
|
||||||
let _name = self.pop()?.as_string()?;
|
let _name = self.pop()?.as_string()?;
|
||||||
let _object = self.pop()?.as_object()?;
|
let _object = self.pop()?.as_object()?;
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
unimplemented!();
|
Err("Unimplemented action: GetMember".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_get_property(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
fn action_get_property(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
@ -482,7 +483,10 @@ impl Avm1 {
|
||||||
5 => Value::Number(f64::from(clip.total_frames())),
|
5 => Value::Number(f64::from(clip.total_frames())),
|
||||||
10 => Value::Number(f64::from(clip.rotation())),
|
10 => Value::Number(f64::from(clip.rotation())),
|
||||||
12 => Value::Number(f64::from(clip.frames_loaded())),
|
12 => Value::Number(f64::from(clip.frames_loaded())),
|
||||||
_ => unimplemented!("{}", prop_index),
|
_ => {
|
||||||
|
log::error!("GetProperty: Unimplemented property index {}", prop_index);
|
||||||
|
Value::Undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Value::Undefined
|
Value::Undefined
|
||||||
|
@ -502,7 +506,11 @@ impl Avm1 {
|
||||||
fn action_get_variable(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
fn action_get_variable(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
||||||
// Flash 4-style variable
|
// Flash 4-style variable
|
||||||
let var_path = self.pop()?;
|
let var_path = self.pop()?;
|
||||||
if let Some((node, var_name)) = Self::resolve_slash_path_variable(context.active_clip, context.root, var_path.as_string()?) {
|
if let Some((node, var_name)) = Self::resolve_slash_path_variable(
|
||||||
|
context.active_clip,
|
||||||
|
context.root,
|
||||||
|
var_path.as_string()?,
|
||||||
|
) {
|
||||||
if let Some(clip) = node.read().as_movie_clip() {
|
if let Some(clip) = node.read().as_movie_clip() {
|
||||||
self.push(clip.get_variable(var_name));
|
self.push(clip.get_variable(var_name));
|
||||||
}
|
}
|
||||||
|
@ -562,7 +570,11 @@ impl Avm1 {
|
||||||
if let Some(frame) = clip.frame_label_to_number(&frame_label) {
|
if let Some(frame) = clip.frame_label_to_number(&frame_label) {
|
||||||
clip.goto_frame(scene_offset + frame, !set_playing)
|
clip.goto_frame(scene_offset + frame, !set_playing)
|
||||||
} else {
|
} else {
|
||||||
log::warn!("ActionGotoFrame2 failed: Movie clip {} does not contain frame label '{}'", clip.id(), frame_label);
|
log::warn!(
|
||||||
|
"ActionGotoFrame2 failed: Movie clip {} does not contain frame label '{}'",
|
||||||
|
clip.id(),
|
||||||
|
frame_label
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return Err("Expected frame number or label".into()),
|
_ => return Err("Expected frame number or label".into()),
|
||||||
|
@ -570,11 +582,7 @@ impl Avm1 {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_goto_label(
|
fn action_goto_label(&mut self, context: &mut ActionContext, label: &str) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
context: &mut ActionContext,
|
|
||||||
label: &str,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let mut display_object = context.active_clip.write(context.gc_context);
|
let mut display_object = context.active_clip.write(context.gc_context);
|
||||||
if let Some(clip) = display_object.as_movie_clip_mut() {
|
if let Some(clip) = display_object.as_movie_clip_mut() {
|
||||||
if let Some(frame) = clip.frame_label_to_number(label) {
|
if let Some(frame) = clip.frame_label_to_number(label) {
|
||||||
|
@ -617,7 +625,7 @@ impl Avm1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
unimplemented!("Action::InitArray");
|
Err("Unimplemented action: InitArray".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_init_object(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_init_object(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
@ -628,7 +636,7 @@ impl Avm1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
unimplemented!("Action::InitArray");
|
Err("Unimplemented action: InitObject".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_jump(
|
fn action_jump(
|
||||||
|
@ -738,7 +746,7 @@ impl Avm1 {
|
||||||
let _num_args = self.pop()?.as_i64()?;
|
let _num_args = self.pop()?.as_i64()?;
|
||||||
self.push(Value::Undefined);
|
self.push(Value::Undefined);
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
unimplemented!("Action::NewMethod");
|
Err("Unimplemented action: NewMethod".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_new_object(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_new_object(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
@ -749,7 +757,7 @@ impl Avm1 {
|
||||||
}
|
}
|
||||||
self.push(Value::Undefined);
|
self.push(Value::Undefined);
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
unimplemented!("Action::NewObject");
|
Err("Unimplemented action: NewObject".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_or(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_or(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
@ -795,12 +803,19 @@ impl Avm1 {
|
||||||
SwfValue::Float(v) => Value::Number(f64::from(*v)),
|
SwfValue::Float(v) => Value::Number(f64::from(*v)),
|
||||||
SwfValue::Double(v) => Value::Number(*v),
|
SwfValue::Double(v) => Value::Number(*v),
|
||||||
SwfValue::Str(v) => Value::String(v.clone()),
|
SwfValue::Str(v) => Value::String(v.clone()),
|
||||||
SwfValue::Register(_v) => unimplemented!(),
|
SwfValue::Register(_v) => {
|
||||||
|
log::error!("Register push unimplemented");
|
||||||
|
Value::Undefined
|
||||||
|
}
|
||||||
SwfValue::ConstantPool(i) => {
|
SwfValue::ConstantPool(i) => {
|
||||||
if let Some(value) = self.constant_pool.get(*i as usize) {
|
if let Some(value) = self.constant_pool.get(*i as usize) {
|
||||||
Value::String(value.clone())
|
Value::String(value.clone())
|
||||||
} else {
|
} else {
|
||||||
log::warn!("ActionPush: Constant pool index {} out of range (len = {})", i, self.constant_pool.len());
|
log::warn!(
|
||||||
|
"ActionPush: Constant pool index {} out of range (len = {})",
|
||||||
|
i,
|
||||||
|
self.constant_pool.len()
|
||||||
|
);
|
||||||
Value::Undefined
|
Value::Undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -826,13 +841,13 @@ impl Avm1 {
|
||||||
fn action_remove_sprite(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_remove_sprite(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
let _target = self.pop()?.into_string();
|
let _target = self.pop()?.into_string();
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
unimplemented!("Action::RemoveSprite");
|
Err("Unimplemented action: RemoveSprite".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_return(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_return(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
let _result = self.pop()?;
|
let _result = self.pop()?;
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
unimplemented!("Action::Return");
|
Err("Unimplemented action: Return".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_set_member(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_set_member(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
@ -840,7 +855,7 @@ impl Avm1 {
|
||||||
let _name = self.pop()?;
|
let _name = self.pop()?;
|
||||||
let _object = self.pop()?;
|
let _object = self.pop()?;
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
unimplemented!("Action::SetMember");
|
Err("Unimplemented action: SetMember".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_set_property(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
fn action_set_property(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
@ -848,9 +863,7 @@ impl Avm1 {
|
||||||
let prop_index = self.pop()?.as_u32()? as usize;
|
let prop_index = self.pop()?.as_u32()? as usize;
|
||||||
let clip_path = self.pop()?;
|
let clip_path = self.pop()?;
|
||||||
let path = clip_path.as_string()?;
|
let path = clip_path.as_string()?;
|
||||||
if let Some(clip) =
|
if let Some(clip) = Avm1::resolve_slash_path(context.active_clip, context.root, path) {
|
||||||
Avm1::resolve_slash_path(context.active_clip, context.root, path)
|
|
||||||
{
|
|
||||||
if let Some(clip) = clip.write(context.gc_context).as_movie_clip_mut() {
|
if let Some(clip) = clip.write(context.gc_context).as_movie_clip_mut() {
|
||||||
match prop_index {
|
match prop_index {
|
||||||
0 => clip.set_x(value),
|
0 => clip.set_x(value),
|
||||||
|
@ -858,7 +871,10 @@ impl Avm1 {
|
||||||
2 => clip.set_x_scale(value),
|
2 => clip.set_x_scale(value),
|
||||||
3 => clip.set_y_scale(value),
|
3 => clip.set_y_scale(value),
|
||||||
10 => clip.set_rotation(value),
|
10 => clip.set_rotation(value),
|
||||||
_ => log::warn!("ActionSetProperty: Unimplemented property index {}", prop_index),
|
_ => log::error!(
|
||||||
|
"ActionSetProperty: Unimplemented property index {}",
|
||||||
|
prop_index
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -871,7 +887,11 @@ impl Avm1 {
|
||||||
// Flash 4-style variable
|
// Flash 4-style variable
|
||||||
let value = self.pop()?;
|
let value = self.pop()?;
|
||||||
let var_path = self.pop()?;
|
let var_path = self.pop()?;
|
||||||
if let Some((node, var_name)) = Self::resolve_slash_path_variable(context.active_clip, context.root, var_path.as_string()?) {
|
if let Some((node, var_name)) = Self::resolve_slash_path_variable(
|
||||||
|
context.active_clip,
|
||||||
|
context.root,
|
||||||
|
var_path.as_string()?,
|
||||||
|
) {
|
||||||
if let Some(clip) = node.write(context.gc_context).as_movie_clip_mut() {
|
if let Some(clip) = node.write(context.gc_context).as_movie_clip_mut() {
|
||||||
clip.set_variable(var_name, value);
|
clip.set_variable(var_name, value);
|
||||||
}
|
}
|
||||||
|
@ -906,8 +926,7 @@ impl Avm1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_start_drag(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_start_drag(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
// TODO(Herschel):
|
Err("Unimplemented action: StartDrag".into())
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_stop(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
fn action_stop(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
@ -918,8 +937,7 @@ impl Avm1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_stop_sounds(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_stop_sounds(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
// TODO(Herschel)
|
Err("Unimplemented action: StopSounds".into())
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_store_register(
|
fn action_store_register(
|
||||||
|
@ -929,7 +947,7 @@ impl Avm1 {
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// Does NOT pop the value from the stack.
|
// Does NOT pop the value from the stack.
|
||||||
let _val = self.stack.last().ok_or("Stack underflow")?;
|
let _val = self.stack.last().ok_or("Stack underflow")?;
|
||||||
unimplemented!("Action::StoreRegister");
|
Err("Unimplemented action: StoreRegister".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_string_add(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_string_add(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
@ -999,7 +1017,7 @@ impl Avm1 {
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
let _clip = self.pop()?.as_object()?;
|
let _clip = self.pop()?.as_object()?;
|
||||||
self.push(Value::Undefined);
|
self.push(Value::Undefined);
|
||||||
unimplemented!("Action::TargetPath");
|
Err("Unimplemented action: TargetPath".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_quality(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn toggle_quality(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
@ -1084,7 +1102,7 @@ impl Avm1 {
|
||||||
|
|
||||||
fn action_with(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_with(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
let _object = self.pop()?.as_object()?;
|
let _object = self.pop()?.as_object()?;
|
||||||
unimplemented!("Action::With");
|
Err("Unimplemented action: With".into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1121,7 +1139,10 @@ impl Value {
|
||||||
Value::Bool(true) => 1.0,
|
Value::Bool(true) => 1.0,
|
||||||
Value::Number(v) => v,
|
Value::Number(v) => v,
|
||||||
Value::String(v) => v.parse().unwrap_or(NAN), // TODO(Herschel): Handle Infinity/etc.?
|
Value::String(v) => v.parse().unwrap_or(NAN), // TODO(Herschel): Handle Infinity/etc.?
|
||||||
Value::Object(_object) => unimplemented!(), // TODO(Herschel)
|
Value::Object(_object) => {
|
||||||
|
log::error!("Unimplemented: Object ToNumber");
|
||||||
|
0.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue