core: Allow toggling avm_debug output on and off with ctrl+alt+d, defaults to off
This commit is contained in:
parent
2df3b81f92
commit
7f7281493f
|
@ -47,9 +47,10 @@ pub use timer::Timers;
|
||||||
pub use value::Value;
|
pub use value::Value;
|
||||||
|
|
||||||
macro_rules! avm_debug {
|
macro_rules! avm_debug {
|
||||||
($($arg:tt)*) => (
|
($avm: expr, $($arg:tt)*) => (
|
||||||
#[cfg(feature = "avm_debug")]
|
if $avm.show_debug_output() {
|
||||||
log::debug!($($arg)*)
|
log::debug!($($arg)*)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +88,9 @@ pub struct Avm1<'gc> {
|
||||||
/// The maximum amount of functions that can be called before a `Error::FunctionRecursionLimit`
|
/// 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.
|
/// is raised. This defaults to 256 but can be changed per movie.
|
||||||
max_recursion_depth: u16,
|
max_recursion_depth: u16,
|
||||||
|
|
||||||
|
#[cfg(feature = "avm_debug")]
|
||||||
|
pub debug_output: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<'gc> gc_arena::Collect for Avm1<'gc> {
|
unsafe impl<'gc> gc_arena::Collect for Avm1<'gc> {
|
||||||
|
@ -125,6 +129,9 @@ impl<'gc> Avm1<'gc> {
|
||||||
],
|
],
|
||||||
halted: false,
|
halted: false,
|
||||||
max_recursion_depth: 255,
|
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<Value<'gc>>) {
|
fn push(&mut self, value: impl Into<Value<'gc>>) {
|
||||||
let value = value.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);
|
self.stack.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,7 +364,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
Value::Undefined
|
Value::Undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
avm_debug!("Stack pop {}: {:?}", self.stack.len(), value);
|
avm_debug!(self, "Stack pop {}: {:?}", self.stack.len(), value);
|
||||||
|
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
@ -384,6 +391,25 @@ impl<'gc> Avm1<'gc> {
|
||||||
pub fn set_max_recursion_depth(&mut self, max_recursion_depth: u16) {
|
pub fn set_max_recursion_depth(&mut self, max_recursion_depth: u16) {
|
||||||
self.max_recursion_depth = max_recursion_depth
|
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>(
|
pub fn root_error_handler<'gc>(
|
||||||
|
|
|
@ -24,9 +24,10 @@ use swf::avm1::types::{Action, CatchVar, Function, TryBlock};
|
||||||
use url::form_urlencoded;
|
use url::form_urlencoded;
|
||||||
|
|
||||||
macro_rules! avm_debug {
|
macro_rules! avm_debug {
|
||||||
($($arg:tt)*) => (
|
($avm: expr, $($arg:tt)*) => (
|
||||||
#[cfg(feature = "avm_debug")]
|
if $avm.show_debug_output() {
|
||||||
log::debug!($($arg)*)
|
log::debug!($($arg)*)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +228,7 @@ pub struct Activation<'a, 'gc: 'a> {
|
||||||
|
|
||||||
impl Drop for Activation<'_, '_> {
|
impl Drop for Activation<'_, '_> {
|
||||||
fn drop(&mut self) {
|
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>,
|
this: Object<'gc>,
|
||||||
arguments: Option<Object<'gc>>,
|
arguments: Option<Object<'gc>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
avm_debug!("START {}", id);
|
avm_debug!(avm, "START {}", id);
|
||||||
Self {
|
Self {
|
||||||
avm,
|
avm,
|
||||||
id,
|
id,
|
||||||
|
@ -265,7 +266,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
scope: GcCell<'gc, Scope<'gc>>,
|
scope: GcCell<'gc, Scope<'gc>>,
|
||||||
) -> Activation<'b, 'gc> {
|
) -> Activation<'b, 'gc> {
|
||||||
let id = self.id.child(name);
|
let id = self.id.child(name);
|
||||||
avm_debug!("START {}", id);
|
avm_debug!(self.avm, "START {}", id);
|
||||||
Activation {
|
Activation {
|
||||||
avm: self.avm,
|
avm: self.avm,
|
||||||
id,
|
id,
|
||||||
|
@ -295,7 +296,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
let global_scope = GcCell::allocate(mc, Scope::from_global_object(globals));
|
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 child_scope = GcCell::allocate(mc, Scope::new_local_scope(global_scope, mc));
|
||||||
let empty_constant_pool = GcCell::allocate(mc, Vec::new());
|
let empty_constant_pool = GcCell::allocate(mc, Vec::new());
|
||||||
avm_debug!("START {}", id);
|
avm_debug!(avm, "START {}", id);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
avm,
|
avm,
|
||||||
|
@ -419,7 +420,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
//Executing beyond the end of a function constitutes an implicit return.
|
//Executing beyond the end of a function constitutes an implicit return.
|
||||||
Ok(FrameControl::Return(ReturnType::Implicit))
|
Ok(FrameControl::Return(ReturnType::Implicit))
|
||||||
} else if let Some(action) = reader.read_action()? {
|
} 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 {
|
match action {
|
||||||
Action::Add => self.action_add(context),
|
Action::Add => self.action_add(context),
|
||||||
|
@ -2368,6 +2369,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let value = self.avm.pop();
|
let value = self.avm.pop();
|
||||||
avm_debug!(
|
avm_debug!(
|
||||||
|
self.avm,
|
||||||
"Thrown exception: {}",
|
"Thrown exception: {}",
|
||||||
value
|
value
|
||||||
.coerce_to_string(self, context)
|
.coerce_to_string(self, context)
|
||||||
|
|
|
@ -282,7 +282,7 @@ impl<'gc> Executable<'gc> {
|
||||||
.unwrap_or(ac.player_version)
|
.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 {
|
let mut result = match &af.name {
|
||||||
None => name.to_string(),
|
None => name.to_string(),
|
||||||
Some(name) => name.to_string(),
|
Some(name) => name.to_string(),
|
||||||
|
|
|
@ -15,9 +15,10 @@ use swf::avm2::read::Reader;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! avm_debug {
|
macro_rules! avm_debug {
|
||||||
($($arg:tt)*) => (
|
($avm: expr, $($arg:tt)*) => (
|
||||||
#[cfg(feature = "avm_debug")]
|
if $avm.show_debug_output() {
|
||||||
log::debug!($($arg)*)
|
log::debug!($($arg)*)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +58,9 @@ pub struct Avm2<'gc> {
|
||||||
|
|
||||||
/// System prototypes.
|
/// System prototypes.
|
||||||
system_prototypes: SystemPrototypes<'gc>,
|
system_prototypes: SystemPrototypes<'gc>,
|
||||||
|
|
||||||
|
#[cfg(feature = "avm_debug")]
|
||||||
|
pub debug_output: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'gc> Avm2<'gc> {
|
impl<'gc> Avm2<'gc> {
|
||||||
|
@ -68,6 +72,9 @@ impl<'gc> Avm2<'gc> {
|
||||||
stack: Vec::new(),
|
stack: Vec::new(),
|
||||||
globals,
|
globals,
|
||||||
system_prototypes,
|
system_prototypes,
|
||||||
|
|
||||||
|
#[cfg(feature = "avm_debug")]
|
||||||
|
debug_output: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +142,7 @@ impl<'gc> Avm2<'gc> {
|
||||||
/// Push a value onto the operand stack.
|
/// Push a value onto the operand stack.
|
||||||
fn push(&mut self, value: impl Into<Value<'gc>>) {
|
fn push(&mut self, value: impl Into<Value<'gc>>) {
|
||||||
let value = value.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);
|
self.stack.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +154,7 @@ impl<'gc> Avm2<'gc> {
|
||||||
Value::Undefined
|
Value::Undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
avm_debug!("Stack pop {}: {:?}", self.stack.len(), value);
|
avm_debug!(self, "Stack pop {}: {:?}", self.stack.len(), value);
|
||||||
|
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
@ -161,4 +168,23 @@ impl<'gc> Avm2<'gc> {
|
||||||
|
|
||||||
args
|
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) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -415,7 +415,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
) -> Result<FrameControl<'gc>, Error> {
|
) -> Result<FrameControl<'gc>, Error> {
|
||||||
let op = reader.read_op();
|
let op = reader.read_op();
|
||||||
if let Ok(Some(op)) = op {
|
if let Ok(Some(op)) = op {
|
||||||
avm_debug!("Opcode: {:?}", op);
|
avm_debug!(self.avm2, "Opcode: {:?}", op);
|
||||||
|
|
||||||
let result = match op {
|
let result = match op {
|
||||||
Op::PushByte { value } => self.op_push_byte(value),
|
Op::PushByte { value } => self.op_push_byte(value),
|
||||||
|
@ -1093,7 +1093,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
index: Index<AbcMultiname>,
|
index: Index<AbcMultiname>,
|
||||||
) -> Result<FrameControl<'gc>, Error> {
|
) -> Result<FrameControl<'gc>, Error> {
|
||||||
let multiname = self.pool_multiname(method, index, context.gc_context)?;
|
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() {
|
let result = if let Some(scope) = self.scope() {
|
||||||
scope.read().find(&multiname, self, context)?
|
scope.read().find(&multiname, self, context)?
|
||||||
} else {
|
} else {
|
||||||
|
@ -1113,7 +1113,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
index: Index<AbcMultiname>,
|
index: Index<AbcMultiname>,
|
||||||
) -> Result<FrameControl<'gc>, Error> {
|
) -> Result<FrameControl<'gc>, Error> {
|
||||||
let multiname = self.pool_multiname(method, index, context.gc_context)?;
|
let multiname = self.pool_multiname(method, index, context.gc_context)?;
|
||||||
avm_debug!("Resolving {:?}", multiname);
|
avm_debug!(self.avm2, "Resolving {:?}", multiname);
|
||||||
let found: Result<Object<'gc>, Error> = if let Some(scope) = self.scope() {
|
let found: Result<Object<'gc>, Error> = if let Some(scope) = self.scope() {
|
||||||
scope.read().find(&multiname, self, context)?
|
scope.read().find(&multiname, self, context)?
|
||||||
} else {
|
} else {
|
||||||
|
@ -1134,7 +1134,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
index: Index<AbcMultiname>,
|
index: Index<AbcMultiname>,
|
||||||
) -> Result<FrameControl<'gc>, Error> {
|
) -> Result<FrameControl<'gc>, Error> {
|
||||||
let multiname = self.pool_multiname_static(method, index, context.gc_context)?;
|
let multiname = self.pool_multiname_static(method, index, context.gc_context)?;
|
||||||
avm_debug!("Resolving {:?}", multiname);
|
avm_debug!(self.avm2, "Resolving {:?}", multiname);
|
||||||
let found: Result<Value<'gc>, Error> = if let Some(scope) = self.scope() {
|
let found: Result<Value<'gc>, Error> = if let Some(scope) = self.scope() {
|
||||||
scope
|
scope
|
||||||
.write(context.gc_context)
|
.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 register_name = self.pool_string(method, register_name)?;
|
||||||
let value = self.local_register(register as u32)?;
|
let value = self.local_register(register as u32)?;
|
||||||
|
|
||||||
avm_debug!("Debug: {} = {:?}", register_name, value);
|
avm_debug!(self.avm2, "Debug: {} = {:?}", register_name, value);
|
||||||
} else {
|
} else {
|
||||||
avm_debug!("Unknown debugging mode!");
|
avm_debug!(self.avm2, "Unknown debugging mode!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
|
@ -1636,7 +1636,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
) -> Result<FrameControl<'gc>, Error> {
|
) -> Result<FrameControl<'gc>, Error> {
|
||||||
let file_name = self.pool_string(method, file_name)?;
|
let file_name = self.pool_string(method, file_name)?;
|
||||||
|
|
||||||
avm_debug!("File: {}", file_name);
|
avm_debug!(self.avm2, "File: {}", file_name);
|
||||||
|
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
@ -1653,7 +1653,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> {
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn op_debug_line(&mut self, line_num: u32) -> Result<FrameControl<'gc>, Error> {
|
fn op_debug_line(&mut self, line_num: u32) -> Result<FrameControl<'gc>, Error> {
|
||||||
avm_debug!("Line: {}", line_num);
|
avm_debug!(self.avm2, "Line: {}", line_num);
|
||||||
|
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
|
|
@ -431,6 +431,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
||||||
let fn_proto = activation.avm2().prototypes().function;
|
let fn_proto = activation.avm2().prototypes().function;
|
||||||
let trait_name = trait_entry.name().clone();
|
let trait_name = trait_entry.name().clone();
|
||||||
avm_debug!(
|
avm_debug!(
|
||||||
|
activation.avm2(),
|
||||||
"Installing trait {:?} of kind {:?}",
|
"Installing trait {:?} of kind {:?}",
|
||||||
trait_name,
|
trait_name,
|
||||||
trait_entry.kind()
|
trait_entry.kind()
|
||||||
|
|
|
@ -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.
|
// Update mouse position from mouse events.
|
||||||
if let PlayerEvent::MouseMove { x, y }
|
if let PlayerEvent::MouseMove { x, y }
|
||||||
| PlayerEvent::MouseDown { x, y }
|
| PlayerEvent::MouseDown { x, y }
|
||||||
|
|
Loading…
Reference in New Issue