Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 12 additions & 32 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,47 +69,27 @@ There is still much Flash functionality that is unimplemented. Check for the ["u

## Debugging ActionScript Content

To enable debug logging, set `RUST_LOG=warn,ruffle=info,ruffle_core=debug,avm_trace=info` and run Ruffle from the command line.
This will also enable printing `trace()` statements.

Additionally, if you build Ruffle with `--features avm_debug` then you will activate a few more built-in debugging utilities inside Ruffle, listed below.
To enable debug logging, set `RUST_LOG=warn,ruffle=info,ruffle_core=debug,avm_trace=info` and run Ruffle from the command line. This will also enable printing `trace()` statements.

### Logging caught exceptions

Some SWFs may catch and suppress exceptions, which can hide the fact that the SWF is trying to use an unimplemented definition. To log call caught exceptions, build ruffle with `--features avm_debug`.
Some AVM2 SWFs may catch and suppress exceptions, which can hide the fact that the SWF is trying to use an unimplemented definition. To log call caught exceptions, build ruffle with `--features avm2_debug`. Caught exceptions will then be logged as "Caught exception: ...".

Caught exceptions will be logged as "Caught exception: <exception object>"
Note that some SWFs throw and catch exceptions as part of their normal control flow, so a caught exception
does not necessarily indicate a bug in Ruffle.
Note that some SWFs throw and catch exceptions as part of their normal control flow, so a caught exception does not necessarily indicate a bug in Ruffle.

### Warnings and Errors

All AVM errors and warnings will print their stack trace so that you can view where they are in relation to the
ActionScript inside the movie.

### Step-By-Step Output

The hotkey <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>D</kbd> toggles verbose AVM debugging output on and off (default off).
You will be able to follow the flow of ActionScript inside of a SWF movie, as each action is performed.
Please note that this will likely slow down Ruffle, and it may significantly spam output. Please use sparingly.

When paired with a tool such as [JPEXS](https://github.com/jindrapetrik/jpexs-decompiler), you can compare the ActionScript
you see being executed in Ruffle with the actual ActionScript inside of a SWF movie, and attempt to find whatever problem
it is that you're looking for.

### Complete Variable Dumping

The hotkey <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>V</kbd> dumps every variable inside the AVM at the moment you press it.
This can be very useful to inspect the internal state of games and see, for example, if a coordinate is NaN, your lives
are negative, or maybe an important object just didn't get initialized.

This only works for AVM1. For AVM2 content, use the Debug Tools menu in the desktop player instead, which lets you
inspect display objects and the properties of AVM2 objects.
All AVM2 errors will print their stack trace so that you can view where they are in relation to the ActionScript inside the movie.

### Render Tree Dumping
### Debug Tools

The hotkey <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>F</kbd> dumps the DisplayObject render tree at the moment you press it.
This allows you to see Ruffle's representation of the objects on the Stage.
The Debug Tools in the desktop player provide several functions that aid debugging. These include:
- inspecting the properties of AVM1 and AVM2 objects
- viewing the display object hierarchy
- searching for display objects
- viewing and editing the properties of display objects
- viewing all loaded AVM2 classes and domains
- viewing all loaded SWF movies

## Reporting Bugs

Expand Down
2 changes: 1 addition & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ version = "0.4.70"
[features]
default = []
lzma = ["lzma-rs", "swf/lzma"]
avm_debug = []
avm2_debug = []
tracy_avm = ["dep:tracy-client"]
timeline_debug = []
mp3 = ["symphonia", "symphonia/mp3"]
Expand Down
14 changes: 2 additions & 12 deletions core/src/avm1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ mod activation;
mod amf;
mod callable_value;
mod clamp;
mod debug;
mod error;
mod flv;
mod fscommand;
Expand All @@ -29,7 +28,6 @@ mod value;
mod xml;

pub use activation::{Activation, ActivationIdentifier};
pub use debug::VariableDumper;
pub use error::Error;
pub use flv::FlvValueAvm1Ext;
pub use function::ExecutionReason;
Expand All @@ -47,22 +45,14 @@ pub use value::Value;
#[macro_export]
macro_rules! avm_warn {
($activation: ident, $($arg:tt)*) => (
if cfg!(feature = "avm_debug") {
tracing::warn!("{} -- in {}", format!($($arg)*), $activation.id)
} else {
tracing::warn!($($arg)*)
}
tracing::warn!($($arg)*)
)
}

#[macro_export]
macro_rules! avm_error {
($activation: ident, $($arg:tt)*) => (
if cfg!(feature = "avm_debug") {
tracing::error!("{} -- in {}", format!($($arg)*), $activation.id)
} else {
tracing::error!($($arg)*)
}
tracing::error!($($arg)*)
)
}

Expand Down
32 changes: 2 additions & 30 deletions core/src/avm1/activation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,6 @@ use web_time::Instant;

use super::object_reference::MovieClipReference;

macro_rules! avm_debug {
($avm: expr, $($arg:tt)*) => (
if $avm.show_debug_output() {
tracing::debug!($($arg)*)
}
)
}

#[derive(Clone)]
pub enum ReturnType<'gc> {
Implicit,
Expand Down Expand Up @@ -223,12 +215,6 @@ pub struct Activation<'a, 'gc: 'a> {
_tracy_span: tracy_client::Span,
}

impl Drop for Activation<'_, '_> {
fn drop(&mut self) {
avm_debug!(self.context.avm1, "END {}", self.id);
}
}

impl<'gc> HasStringContext<'gc> for Activation<'_, 'gc> {
#[inline(always)]
fn strings_ref(&self) -> &StringContext<'gc> {
Expand Down Expand Up @@ -329,7 +315,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
local_registers: &'a [Cell<Value<'gc>>],
) -> Self {
debug_assert!(swf_version > 0, "cannot execute code with SWF version 0");
avm_debug!(context.avm1, "START {id}");

#[cfg(feature = "tracy_avm")]
let tracy_span = {
let span = tracy_client::Client::running()
Expand Down Expand Up @@ -361,7 +347,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
scope: Gc<'gc, Scope<'gc>>,
) -> Activation<'b, 'gc> {
let id = self.id.child(name);
avm_debug!(self.context.avm1, "START {id}");

#[cfg(feature = "tracy_avm")]
let tracy_span = {
let span = tracy_client::Client::running()
Expand Down Expand Up @@ -398,8 +384,6 @@ impl<'a, 'gc> Activation<'a, 'gc> {
id: ActivationIdentifier<'a>,
base_clip: DisplayObject<'gc>,
) -> Self {
avm_debug!(context.avm1, "START {id}");

let swf_version = base_clip.swf_version();
debug_assert!(swf_version > 0, "cannot execute code with SWF version 0");
let scope = context.avm1.global_scope(swf_version);
Expand Down Expand Up @@ -558,11 +542,6 @@ impl<'a, 'gc> Activation<'a, 'gc> {
Ok(FrameControl::Return(ReturnType::Implicit))
} else {
let action = reader.read_action()?;
avm_debug!(
self.context.avm1,
"({}) Action: {action:?}",
self.id.depth(),
);

match action {
Action::Add => self.action_add(),
Expand Down Expand Up @@ -2250,13 +2229,6 @@ impl<'a, 'gc> Activation<'a, 'gc> {

fn action_throw(&mut self) -> Result<FrameControl<'gc>, Error<'gc>> {
let value = self.context.avm1.pop();
avm_debug!(
self.context.avm1,
"Thrown exception: {}",
value
.coerce_to_string(self)
.unwrap_or_else(|_| istr!(self, "undefined"))
);
Err(Error::ThrownValue(value))
}

Expand Down
188 changes: 0 additions & 188 deletions core/src/avm1/debug.rs

This file was deleted.

2 changes: 1 addition & 1 deletion core/src/avm1/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ impl<'gc> Avm1Function<'gc> {
// The caller is the previous callee.
let arguments_caller = activation.callee;

let name = if cfg!(any(feature = "avm_debug", feature = "tracy_avm")) {
let name = if cfg!(feature = "tracy_avm") {
Cow::Owned(self.debug_string_for_call(activation, name, args))
} else {
Cow::Borrowed("[Anonymous]")
Expand Down
Loading
Loading