From 7f7281493f1f90bf908ac4080e940d6fd5ef3c98 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Thu, 23 Jul 2020 22:19:52 +0200 Subject: [PATCH] core: Allow toggling avm_debug output on and off with ctrl+alt+d, defaults to off --- core/src/avm1.rs | 36 +++++++++++++++++++++++++++++++----- core/src/avm1/activation.rs | 18 ++++++++++-------- core/src/avm1/function.rs | 2 +- core/src/avm2.rs | 36 +++++++++++++++++++++++++++++++----- core/src/avm2/activation.rs | 16 ++++++++-------- core/src/avm2/object.rs | 1 + core/src/player.rs | 26 ++++++++++++++++++++++++++ 7 files changed, 108 insertions(+), 27 deletions(-) diff --git a/core/src/avm1.rs b/core/src/avm1.rs index 8f542c671..40f6c3f24 100644 --- a/core/src/avm1.rs +++ b/core/src/avm1.rs @@ -47,9 +47,10 @@ pub use timer::Timers; pub use value::Value; macro_rules! avm_debug { - ($($arg:tt)*) => ( - #[cfg(feature = "avm_debug")] - log::debug!($($arg)*) + ($avm: expr, $($arg:tt)*) => ( + if $avm.show_debug_output() { + log::debug!($($arg)*) + } ) } @@ -87,6 +88,9 @@ pub struct Avm1<'gc> { /// The maximum amount of functions that can be called before a `Error::FunctionRecursionLimit` /// is raised. This defaults to 256 but can be changed per movie. max_recursion_depth: u16, + + #[cfg(feature = "avm_debug")] + pub debug_output: bool, } unsafe impl<'gc> gc_arena::Collect for Avm1<'gc> { @@ -125,6 +129,9 @@ impl<'gc> Avm1<'gc> { ], halted: false, max_recursion_depth: 255, + + #[cfg(feature = "avm_debug")] + debug_output: false, } } @@ -346,7 +353,7 @@ impl<'gc> Avm1<'gc> { fn push(&mut self, value: impl Into>) { let value = value.into(); - avm_debug!("Stack push {}: {:?}", self.stack.len(), value); + avm_debug!(self, "Stack push {}: {:?}", self.stack.len(), value); self.stack.push(value); } @@ -357,7 +364,7 @@ impl<'gc> Avm1<'gc> { Value::Undefined }); - avm_debug!("Stack pop {}: {:?}", self.stack.len(), value); + avm_debug!(self, "Stack pop {}: {:?}", self.stack.len(), value); value } @@ -384,6 +391,25 @@ impl<'gc> Avm1<'gc> { pub fn set_max_recursion_depth(&mut self, max_recursion_depth: u16) { self.max_recursion_depth = max_recursion_depth } + + #[cfg(feature = "avm_debug")] + #[inline] + pub fn show_debug_output(&self) -> bool { + self.debug_output + } + + #[cfg(not(feature = "avm_debug"))] + pub const fn show_debug_output(&self) -> bool { + false + } + + #[cfg(feature = "avm_debug")] + pub fn set_show_debug_output(&mut self, visible: bool) { + self.debug_output = visible; + } + + #[cfg(not(feature = "avm_debug"))] + pub const fn set_show_debug_output(&self, _visible: bool) {} } pub fn root_error_handler<'gc>( diff --git a/core/src/avm1/activation.rs b/core/src/avm1/activation.rs index db50421c4..402f451a0 100644 --- a/core/src/avm1/activation.rs +++ b/core/src/avm1/activation.rs @@ -24,9 +24,10 @@ use swf::avm1::types::{Action, CatchVar, Function, TryBlock}; use url::form_urlencoded; macro_rules! avm_debug { - ($($arg:tt)*) => ( - #[cfg(feature = "avm_debug")] - log::debug!($($arg)*) + ($avm: expr, $($arg:tt)*) => ( + if $avm.show_debug_output() { + log::debug!($($arg)*) + } ) } @@ -227,7 +228,7 @@ pub struct Activation<'a, 'gc: 'a> { impl Drop for Activation<'_, '_> { fn drop(&mut self) { - avm_debug!("END {}", self.id); + avm_debug!(self.avm, "END {}", self.id); } } @@ -243,7 +244,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { this: Object<'gc>, arguments: Option>, ) -> Self { - avm_debug!("START {}", id); + avm_debug!(avm, "START {}", id); Self { avm, id, @@ -265,7 +266,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { scope: GcCell<'gc, Scope<'gc>>, ) -> Activation<'b, 'gc> { let id = self.id.child(name); - avm_debug!("START {}", id); + avm_debug!(self.avm, "START {}", id); Activation { avm: self.avm, id, @@ -295,7 +296,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { let global_scope = GcCell::allocate(mc, Scope::from_global_object(globals)); let child_scope = GcCell::allocate(mc, Scope::new_local_scope(global_scope, mc)); let empty_constant_pool = GcCell::allocate(mc, Vec::new()); - avm_debug!("START {}", id); + avm_debug!(avm, "START {}", id); Self { avm, @@ -419,7 +420,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { //Executing beyond the end of a function constitutes an implicit return. Ok(FrameControl::Return(ReturnType::Implicit)) } else if let Some(action) = reader.read_action()? { - avm_debug!("({}) Action: {:?}", self.id.depth(), action); + avm_debug!(self.avm, "({}) Action: {:?}", self.id.depth(), action); match action { Action::Add => self.action_add(context), @@ -2368,6 +2369,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { ) -> Result, Error<'gc>> { let value = self.avm.pop(); avm_debug!( + self.avm, "Thrown exception: {}", value .coerce_to_string(self, context) diff --git a/core/src/avm1/function.rs b/core/src/avm1/function.rs index 5cc6be7f1..0a67185fb 100644 --- a/core/src/avm1/function.rs +++ b/core/src/avm1/function.rs @@ -282,7 +282,7 @@ impl<'gc> Executable<'gc> { .unwrap_or(ac.player_version) }; - let name = if cfg!(feature = "avm_debug") { + let name = if activation.avm.show_debug_output() { let mut result = match &af.name { None => name.to_string(), Some(name) => name.to_string(), diff --git a/core/src/avm2.rs b/core/src/avm2.rs index 31d797234..7a8493420 100644 --- a/core/src/avm2.rs +++ b/core/src/avm2.rs @@ -15,9 +15,10 @@ use swf::avm2::read::Reader; #[macro_export] macro_rules! avm_debug { - ($($arg:tt)*) => ( - #[cfg(feature = "avm_debug")] - log::debug!($($arg)*) + ($avm: expr, $($arg:tt)*) => ( + if $avm.show_debug_output() { + log::debug!($($arg)*) + } ) } @@ -57,6 +58,9 @@ pub struct Avm2<'gc> { /// System prototypes. system_prototypes: SystemPrototypes<'gc>, + + #[cfg(feature = "avm_debug")] + pub debug_output: bool, } impl<'gc> Avm2<'gc> { @@ -68,6 +72,9 @@ impl<'gc> Avm2<'gc> { stack: Vec::new(), globals, system_prototypes, + + #[cfg(feature = "avm_debug")] + debug_output: false, } } @@ -135,7 +142,7 @@ impl<'gc> Avm2<'gc> { /// Push a value onto the operand stack. fn push(&mut self, value: impl Into>) { let value = value.into(); - avm_debug!("Stack push {}: {:?}", self.stack.len(), value); + avm_debug!(self, "Stack push {}: {:?}", self.stack.len(), value); self.stack.push(value); } @@ -147,7 +154,7 @@ impl<'gc> Avm2<'gc> { Value::Undefined }); - avm_debug!("Stack pop {}: {:?}", self.stack.len(), value); + avm_debug!(self, "Stack pop {}: {:?}", self.stack.len(), value); value } @@ -161,4 +168,23 @@ impl<'gc> Avm2<'gc> { args } + + #[cfg(feature = "avm_debug")] + #[inline] + pub fn show_debug_output(&self) -> bool { + self.debug_output + } + + #[cfg(not(feature = "avm_debug"))] + pub const fn show_debug_output(&self) -> bool { + false + } + + #[cfg(feature = "avm_debug")] + pub fn set_show_debug_output(&mut self, visible: bool) { + self.debug_output = visible; + } + + #[cfg(not(feature = "avm_debug"))] + pub const fn set_show_debug_output(&self, _visible: bool) {} } diff --git a/core/src/avm2/activation.rs b/core/src/avm2/activation.rs index cc8a04f29..8dc88be5e 100644 --- a/core/src/avm2/activation.rs +++ b/core/src/avm2/activation.rs @@ -415,7 +415,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { ) -> Result, Error> { let op = reader.read_op(); if let Ok(Some(op)) = op { - avm_debug!("Opcode: {:?}", op); + avm_debug!(self.avm2, "Opcode: {:?}", op); let result = match op { Op::PushByte { value } => self.op_push_byte(value), @@ -1093,7 +1093,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { index: Index, ) -> Result, Error> { let multiname = self.pool_multiname(method, index, context.gc_context)?; - avm_debug!("Resolving {:?}", multiname); + avm_debug!(self.avm2, "Resolving {:?}", multiname); let result = if let Some(scope) = self.scope() { scope.read().find(&multiname, self, context)? } else { @@ -1113,7 +1113,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { index: Index, ) -> Result, Error> { let multiname = self.pool_multiname(method, index, context.gc_context)?; - avm_debug!("Resolving {:?}", multiname); + avm_debug!(self.avm2, "Resolving {:?}", multiname); let found: Result, Error> = if let Some(scope) = self.scope() { scope.read().find(&multiname, self, context)? } else { @@ -1134,7 +1134,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { index: Index, ) -> Result, Error> { let multiname = self.pool_multiname_static(method, index, context.gc_context)?; - avm_debug!("Resolving {:?}", multiname); + avm_debug!(self.avm2, "Resolving {:?}", multiname); let found: Result, Error> = if let Some(scope) = self.scope() { scope .write(context.gc_context) @@ -1607,9 +1607,9 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { let register_name = self.pool_string(method, register_name)?; let value = self.local_register(register as u32)?; - avm_debug!("Debug: {} = {:?}", register_name, value); + avm_debug!(self.avm2, "Debug: {} = {:?}", register_name, value); } else { - avm_debug!("Unknown debugging mode!"); + avm_debug!(self.avm2, "Unknown debugging mode!"); } Ok(FrameControl::Continue) @@ -1636,7 +1636,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { ) -> Result, Error> { let file_name = self.pool_string(method, file_name)?; - avm_debug!("File: {}", file_name); + avm_debug!(self.avm2, "File: {}", file_name); Ok(FrameControl::Continue) } @@ -1653,7 +1653,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { #[allow(unused_variables)] fn op_debug_line(&mut self, line_num: u32) -> Result, Error> { - avm_debug!("Line: {}", line_num); + avm_debug!(self.avm2, "Line: {}", line_num); Ok(FrameControl::Continue) } diff --git a/core/src/avm2/object.rs b/core/src/avm2/object.rs index 46f6a38cc..b1c27c499 100644 --- a/core/src/avm2/object.rs +++ b/core/src/avm2/object.rs @@ -431,6 +431,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into> + Clone + Copy let fn_proto = activation.avm2().prototypes().function; let trait_name = trait_entry.name().clone(); avm_debug!( + activation.avm2(), "Installing trait {:?} of kind {:?}", trait_name, trait_entry.kind() diff --git a/core/src/player.rs b/core/src/player.rs index 5ced943ba..0211a90e3 100644 --- a/core/src/player.rs +++ b/core/src/player.rs @@ -451,6 +451,32 @@ impl Player { } } + if cfg!(feature = "avm_debug") { + if let PlayerEvent::KeyDown { + key_code: KeyCode::D, + } = event + { + if self.input.is_key_down(KeyCode::Control) && self.input.is_key_down(KeyCode::Alt) + { + self.mutate_with_update_context(|avm1, avm2, _context| { + if avm1.show_debug_output() { + log::info!( + "AVM Debugging turned off! Press CTRL+ALT+D to turn off again." + ); + avm1.set_show_debug_output(false); + avm2.set_show_debug_output(false); + } else { + log::info!( + "AVM Debugging turned on! Press CTRL+ALT+D to turn on again." + ); + avm1.set_show_debug_output(true); + avm2.set_show_debug_output(true); + } + }); + } + } + } + // Update mouse position from mouse events. if let PlayerEvent::MouseMove { x, y } | PlayerEvent::MouseDown { x, y }