Basic ASM Code Debugging and Analysis for the Beginner Coder
#1
Basic ASM Code Debugging and Analysis for the Beginner Coder

Chapter 1: Intro

After learning how to make very basic ASM Codes, the beginner coder may have trouble progressing to a higher skill level. Analyzing other already made ASM codes is one of the best ways to improve your ASM coding skills. Dolphin comes with many features to assist you.



Chapter 2: Setting up Hot Keys & Info About Other Features

Hotkeys (keyboard button shortcuts) are very useful for quick debugging. Open up your Dolphin Emulator. Under Options, select Hotkey Settings.

[Image: options.png]

There's basically only 2 hotkeys that are useful for debugging. In the general tab, there is a hotkey setting for 'Toggle Pause'.

[Image: togglepause.png]

Right click on the button for Toggle Pause to bring up the window to change its HotKey configuration.

[Image: confighotkey.png]

Whenever you bring up the Configure Input window for a Hotkey, you can select from a list or just type it in the lower larger box. Click Apply, then OK to save changes.

For the next hotkey, go to the Debugging tab.

[Image: debugtabclick.png]

There is a hotkey setting for 'Step-In'. This is by far the most important feature of debugging anything in Dolphin, and you will be using this hotkey a ton. Set this to w/e suits you, I use the 'Insert' button.

[Image: stepinto.png]

What is Step In?

'Step In' is to make Dolphin execute just one ASM instruction normally when the emulation is paused. 'Step In' is usually called 'stepping' by coders. When a coder says 'step by step' the code, they mean to debug the code utilizing the 'Step In' feature of Dolphin.



Chapter 3: Understanding How the Gecko Code Handler implements ASM Codes into Memory

According to the Gecko Documentation HERE, ASM Codes (C2 type) have the name of 'Insert ASM'. This name is misleading as it's impossible to insert within memory itself. What actually happens is this...

1. At the code's address, a branch instruction (replacing the default instruction) is placed in by the code handler (a backwards branch). View the following picture...
2. The branch instruction jumps to the first instruction of the ASM code (of the source) where the code's instructions are placed into memory by the code handler (codes dumped usually around 0x800022xx thru 0x800023xx)
3. The amount to jump for the branch instruction itself is auto calculated by the code handler
4. The code instructions are thus executed. After the last instruction of the source, a branch instruction (also auto added by the code handler) will automatically jump back to the address right after the code's address, thus continuing the game's instructions.

For example let's take a look at the ever so known shared item code (PAL version, with 00 for the WW value) - https://mariokartwii.com/showthread.php?tid=111


Code:
C27BA164 00000002
38600000 90770020
60000000 00000000


So at the address 807BA164 is a backwards branch instruction that will jump to where the code's contents reside in memory (where the code contents were dumped by the code handler). Some coder's call this the 'C2 Hook' or 'C2 Hook Address'. So when another coder/dev says what's the hook address? You now understand what they are saying, they are simply wanting the ASM Code's Static Memory address.

[Image: shareditemcodeview2.png]

To follow where any branch-type instruction leads to, right click on the instruction and choose Follow Branch.

The branch leads to the ASM code's contents (first instruction of the code highlighted in blue).

[Image: lir3zero.png]

The following is the code's contents plus the branch instruction that will jump back to where the CPU execution came from to continue running the game.

Code:
Address    Instruction
80002348  li r3, 0
8000234C  stw r3, 0x0020 (r23)
80002350  nop
80002354  b => 0x807BA168

The '00000000' word of the compiled Shared Item code is read by the code handler and the code handler knows to replace it with a branch (to address after code's address) instruction after the last instruction of the ASM source. The amount of branch at Hook Address and at the end of the code's contents, is auto-calculated by the Code Handler.

If you follow the 'b => 0x807BA168', it will lead to the instruction highlighted in blue in the following pic...

[Image: lisaftershared.png]

Let's go back to the Dolphin's Code View of the code itself but zoomed out just a bit.

[Image: c2codeview.png]

You will see there are other instructions nearby the code. In this tutorial, I simply applied just the Shared Item Code via Dolphin's Cheat Manager and nothing else. Dolphin simulates the code being contained in a GCT file (like how codes are normally loaded to a real Wii from an SD card).

The nop at 80002334 is placed by the Gecko Code Handler. I haven't gone over the entire source of the Gecko code handler personally, so I'm not sure what the purpose of this nop is.

The next two 'instructions' after that are both '(ill) 00d0code'. (ill) stands for illegal instruction. The (ill) is given to any compiled word in memory that isn't a valid PPC instruction. Dolphin will slap the (ill) tag and then display the hex contents of that particular word value.

'00d0code 00d0code' is the header of the GCT file. Every GCT file has on (if created correctly ofc). The lfs instruction at 80002340 is not an lfs instruction, it is actually the 'C27BA164' part of the Shared Item Code. Dolphin is attempting to decompile that word as a PPC instruction. The '(ill) 00000002' is what you would expect, it's the '000000002' part of the Shared Item code. Next 4 lines are the code contents plus the branch instruction to branch back to right after where the C2 code was 'hooked' to. 

The psq_st instruction at 80002358 is the 1st half of the Final Terminator of the GCT file. The final terminator of every proper GCT file is 'F0000000 00000000. Any time there is a word of null in memory, Dolphin's Code View will simply place ' --- '. Hence why you see ' --- ' at 8000235C.

Understanding how C2 Codes get executed:
This is important to know if you haven't figured this out by now. C2 ASM Codes only get executed whenever its address gets executed by the CPU. They are NOT constantly executing every time the Code Handler itself is being executed by the CPU. The amount of times different C2 codes gets executed in a specific time period varies so much, it's based on so many elements. For example, the Shared Item Code. It's address only gets executed whenever a player picks up a box. Some C2 ASM Codes may execute every frame, some only once per race, some only once during the booting of the game, it all depends on the address.



Chapter 4. Debugging/Analyzing ASM Codes

First apply w/e code you want to debug/analyze. If the code's address gets executed during boot or is executed every frame, we need to adjust a dolphin setting (unless you don't mind the address+code getting executed multiple times before analyzing the code). At the top of the Dolphin main menu, click Options. Select 'Boot to Pause'. This will cause the game to halt when it executes its very first instruction.

Open up your Breakpoint tab/window. Set an Instruction Breakpoint using the value for the code's address. Once set, un-pause the emulation if it was paused if you used 'Boot to Pause'. After Dolphin pauses from the BP being hit, take a look at the Code View. You will be at the code's address and you will see the branch-back instruction that was mentioned earlier.

Remember the Hotkey you configured for Stepping? Use that hotkey to make the code execute one instruction at a time at w/e pace you like. When you execute the first instruction, the branch backwards jump will be preformed, and you will be at the beginning of the ASM code's instructions.

Things to note during stepping:
Whatever instruction highlighted in Green in Code View is the instruction that is GOING to execute. However, this is NOT true for any Memory Breakpoint hits! This is because Dolphin has no idea that the Memory BP was hit until after the responsible store/load instruction gets executed.

You could also look at the PC register in the Registers Tab/Window, that will also tell you what instruction is GOING to execute, but once again this does NOT apply on any Memory Breakpoint hit. PC register will function correctly once you step just one time after a Memory Breakpoint hit.

When you execute a Step-In (aka just step once), if a register gets modified, it will turn red in color on the Registers tab/window. That red register will go back to black if it's not modified if you decide to step again.

FYI, on your first emulation pause after launching a game on Dolphin, any registers not zero will start off as red color. This is on any first-time emulation pause, regardless of how the pause occurred.



Chapter 5: More Tips

To quickly set an Instruction BP on an address, simply left click to the immediate left of the Address value in code view. A grey dot will appear signaling an Instruction BP has been set for that particular address.

Need to quickly copy an address value? Right click on the address in Code View, select Copy Address.

You can also use this right-click method to quickly replace instructions. Right click on an address, you will see shortcuts to quickly replace the address's instruction with a nop or a blr. The nop feature can be really handy for beginner coders. You may not know what a blr is. If not, don't worry about that til you get to the point of learning about function calls. Or even better, use this guide on a code that has a blr instruction and analyze it to understand what it does.

You can also edit in any custom valid PPC instruction you want with the 'Replace Instruction' feature, but you will need to enter in the compiled form. If you set in a custom instruction of any kind, or a quick nop/blr, you can use the 'Restore Instruction' feature to bring back the address's original instruction.

Need to edit register values by hand? Easy to to do. Simply double click within the register you need to edit, and type in the custom value.

Btw, on the left side of the Code View is the call stack. It's a trace back of function calls. Once again, if you are a beginner coder, you don't need to worry about this as this deals with function calls.



Chapter 6. Conclusion

As I always tell person after person, the best way to get better at coding, is to take other ppl's codes (that are a little above your own skill level) and analyze them on Dolphin. Set the BPs, step by step necessary instructions, and take plenty of notes. Happy coding!
Reply
#2
If you want, I can write out/post something like this for advanced users so you and I can both work on it
Super Mario Eclipse, what Super Mario Sunshine could've been.
Reply
#3
Feel free, since this thread is here now I will be updating some of my more advanced threads. Such as in the Calling Function threads, including how to set BPs to allow a function to execute w/o a stepping thru the entire thing (which a beginner might try to do, lol).

One thread we need is something about working with the call stack. Another thread the site needs is anything that will cover advanced work w/ Floats.The only thread I've done on floats is basic conversion to integers.

A small quick thread on the condition register could help too, but advanced work for the CR is very rare in MKWii codes.
Reply
#4
I will help contribute then Smile
Super Mario Eclipse, what Super Mario Sunshine could've been.
Reply
#5
how would this work on a C0 code?
Reply
#6
Great question. It's a bit tedious. For the specific C0 code you wanna step thru, make sure it's your very first code in your Cheat-Manager. Then in Dolphin, set the Boot to Pause flag (can't remember where this is at). Make sure your codes are applied, boot your game. The emulation will auto pause on the very first executable instruction of the game.

Then go to 0x800018A8 in Code View. This is the start of the Code Handler. Once at 0x800018A8, start to scroll down and search for the following two instructions..


mtlr r15
blrl


These are the instructions that the Handler uses to execute all C0 Codes. Once you find these two instructions, set an Instruction BP on blrl. Unpause the emulation. Once that BP gets hit, your emulation will pause itself then you need to simply use 'Step-In' just one time. You are now at the first instruction of your C0 Code. Set a new BP on said instruction and remove the previous BP. Thus you only get a BP hit on that specific C0 code again if you decide to let the emulation run again.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)