Actual Usage
I'll be using the GBA game, River City Ransom EX, as an example. I've been using this game for TAS optimization testing/RNG manipulating for a while.
Let's say, you (as ALEX, the main character) are about to enter a new area zone, and you wanted to know how the game uses the registers and the game assembly instructions to set the values up, to prepare the data and information it needs to know about the new area's enemy types (Generic Dudes, Frat Boys, Locals, Jocks, etc.)
The first thing you would do is to use the TAStudio in Bizhawk to rewind / fast-forward to a frame just before the area transition begins. You would stop your pointer to this current frame, and pause the game.
The next step is for you to bring out the Bizhawk Debugger and have it attach to the EmuHawk instance, so that the Debugger is ready to start animating the instructions.
The first thing we need to do is to choose the ARM instruction set for our game. Since we are playing this game on a GBA platform, we need to set the mode to ARMv4 (Thumb).
In the debugger, you would then choose the animation intervals (or called "Intervals" for short), to say, how many milliseconds the debugger would wait until it advances to the next instruction. 1000 is typically 1 second, so when you set the intervals to be 1000, the Debugger will update the register values, the PC, and finally advance to the next instruction in the disassembler list every second.
After the animation interval is set, we then press the Animate button, to let the Debugger begin its "animation". Note that this game has a ton of branch operations (or "opcodes"), so that is why you sometimes see the instructions jump to a different address often.
This is 5 milliseconds intervals:
This is me changing the intervals on the fly after I realized I made it too slow:
That is how you would use the Variable Disassembler Animation. You can change how fast or slow the disassembler is animating, be it updating the game logic, or updating the rendering frame.
How This is Achieved
This requires updating the Bizhawk mGBA core submodule code, to expose the unmanaged code's interface to call directly to the function:
mDebuggerRun()
endrift, the developer of mGBA, mentioned how Bizhawk typically calls on the other function:
mDebuggerRunFrame()
That function would then execute a do...while loop that runs continuously for a duration of 1 frame tick (≈13.333 seconds) invoking the mDebuggerRun() function mentioned above.
What I did is I exposed this function interface, and then created boolean flag to check whether the UI button, "Animate", is toggled on. If yes, it goes into a code loop that executes the mDebuggerRun() function per interval, instead of going to the mDebuggerRunFrame(). I then make sure I keep the Debugger information updated after each instruction has been executed/advanced to the next instruction.
To do this sort of execution loop, I implemented a simple "Unity C# Coroutines" in Bizhawk. It's a very simple concept of invoking the enumeration of the code, and then yielding the execution to the main UI thread, so that the Debugger UI doesn't become unresponsive while the Debugger is actively executing instructions in the background.
If there is anything you wished to know, please feel free to let me know as replies below.