Mario Kart Wii Gecko Codes, Cheats, & Hacks
Tutorial on the 'BL-Trick' + Psuedo Ops - Printable Version

+- Mario Kart Wii Gecko Codes, Cheats, & Hacks (https://mariokartwii.com)
+-- Forum: Guides/Tutorials/How-To's (https://mariokartwii.com/forumdisplay.php?fid=45)
+--- Forum: PowerPC Assembly (https://mariokartwii.com/forumdisplay.php?fid=50)
+--- Thread: Tutorial on the 'BL-Trick' + Psuedo Ops (/showthread.php?tid=977)



Tutorial on the 'BL-Trick' + Psuedo Ops - Vega - 12-05-2018

Tutorial on the 'BL-Trick' + Psuedo Ops

Requirements:
Be at least a Beginner Level coder that already knows the basics and has made a few simple codes
Understand basic Loops - https://mariokartwii.com/showthread.php?tid=975



Chapter 1: Introduction

Beginner and Intermediate Coders may run into a situation where they need to overwrite a string of data in dynamic memory. The Coder may have found a Hook address that, when executed, points to the start of an important String of Data that can be edited. Once the Data has been edited, the effects are seen on the user's game.

The beginner or intermediate coder might try a method like this....

Code:
lis rX, 0xXXXX
ori rX, rX, 0xXXXX

He/she would probably use a repetitive series of lis+ori instructions to write out the string of data and then use a basic Loop to transfer the data from the registers to dynamic memory.

Another method would still include the usage of lis+ori, but instead of a loop for the transfer, a stmw instruction is used (multiple word write). The downside is that this method requires the address of the start of the Data to be divisible by 4 and it requires the 'Push/Pop' the stack method.

There is even a couple of more similar methods (stswi and stswx), but at the end of the day, there's a superior method to all of them.

What is this method called? It's known as the BL-Trick.



Chapter 2: Overview of Re-Creating a Code

The BL-Trick is a great tool to use for transferring strings of data. It can be somewhat difficult to understand, so it's best if we recreate a code I have personally made before. That way you will know in the future when to apply the BL-Trick for your own codes.

We will create my "Friend Roster Plus Your Mii; Name Changer & Extender" code. It incorporates a simple BL-Trick.

Let's pretend on Mario Kart Wii that you have applied a Memory Read Breakpoint at your Mii Name in dynamic memory while switching into the Friend Roster while online. The BP was hit and you end up with the following instruction + address (PAL)...


Code:
PAL:
8075144C lwz r5, 0x0068 (r4)


After some manual edits directly within the Dolphin-memory-engine, you also come to the conclusion that the Mii Name can be extended to a max of 23 characters. Now that we have an instruction address, we can use Instruction BP's for further debugging of this address if needed.

If you want, feel free to boot your MKWii game if you have one available, connect to Wifi. Once you are at the Wifi Main Menu, place an Instruction BP at one of the addresses depending on the region of your game..

NTSC-U 8074BF0C
PAL 8075144C
NTSC-J 80750AB8
NTSC-K 8073F80C

Now select 'Friends' and the emulation should pause itself due to the BP hit. Let's take a look at Code View, Registers, and Memory all at once.

[Image: bl01.png]

r4 (source register of our instruction) is outlined in red. r4 + 0x0068 points to the start of the Mii Name. The Mii Name (day1test in the supplied picture) is outlined in magenta. Mii Names are always in 16-bit ASCII in every Wii game. 16-bit ASCII is just like standard (8-bit) ASCII, but each ASCII character is a halfword to accomodate for special characters such as Japanese letters, Picture-like symbols, etc.

Examples of 8 bit vs 16 bit ASCII:
  • 20 = space in ASCII
  • 0020 = space in 16-bit ASCII
  • 30 = zero in ASCII
  • 0030 = zero in 16 bit ASCII

Referring back to our code at hand, we need an efficient way to write out our new custom Mii Name and then replace it overwriting 'day1test'. We also want to extend the Mii name to the max of 23 characters (23 halfwords).



Chapter 3: Overview of a simple BL-Trick

The BL-Trick allows you to write a string of data in your source without using any PowerPC instructions. You may be wondering "How is this possible"? Let's look at a simple example of a BL Trick that will write out the word value of 0x12345678.

Code:
#Branch to the Label Name & Link
bl the_label
.long 0x12345678
the_label:
mflr r12

And here is that source in compiled form (C2 code with blank address)

Code:
C2000000 00000002
48000009 12345678
7D8802A6 00000000


48000009 = bl 0x8 (bl the_label)
12345678 = Our value written from scratch (.long 0x12345678)
7D8802A6 = mflr r12


As you can see the '.long' is not a PowerPC instruction. Before we go over this '.long', the bl and mflr instructions need to be explained first.

Branch & Link (bl)
It's similar to a standard branch instruction (b), but once the bl instruction has executed, the next address AFTER the instruction itself is placed into the Link Register.

Confused? Let's go over some of photos using the above example.

Here's a picture of right before the bl instruction gets executed~

[Image: bl02.png]

You will notice there's a 'ps_msub' instruction underneath the bl instruction. This is actually the '.long 0x12345678' part. Dolphin's Code View tries to decompile every word value present in Memory. So certain contents within a BL-Trick may appear as 'legit' instructions in Code View.

Here's a picture of once the bl instruction has executed (take notice the Link Register outlined in red)~

[Image: bl03.png]

The Link Register aka the LR has been modified and now contains the address that points to the start of the BL-Trick.

Here's a picture of once the 'mflr r12' instruction has executed. Blue arrow is indicating what exactly occurred in the instruction.

[Image: bl04.png]

The value in the LR was copied over to r12. r12 now points to the start of the BL-Trick. Since our BL-Trick is only one word value, r12's value is the address that points to 0x12345678.

The following two instructions are responsible for copying data to/from the LR~
  • mflr rD #Value in Link Register is copied to rD
  • mtlr rD #Value in rD is copied to the Link Register



Chapter 4: Pseudo-Ops

Code:
.long 0x12345678

What is this .long? It's called a Pseudo-Op. In non-coding terms, pseudo ops are 'keywords' for your ASM Code Assembler to add in numerical values to a code without requiring the use of a PowerPC instruction.

List of Pseudo-Ops:
  • .byte = byte (example: .byte 0xFF)
  • .short = halfword (example: .short 0x0102)
  • .long = word (example: .long 0x80456C04)
  • .llong = doubleword (example: .llong 0x8000150090323C7C)
  • .float = float value in it's 32-bit single precision form (example: .float 1 will use a value of 0x3F800000)
  • .string = ASCII write that auto appends a null byte at the end (example: .string "Hello!")
  • .ascii = ASCII write without the appended null byte
  • .string16 = 16-bit ASCII that auto appends a null halfword at the end. This Psuedo-Op only works in PyiiASMH!
  • .space X = X bytes of zero (example: .space 8)
  • .align 2 = Use this for alignment when needed because the BL trick 'amount' must be word divisible. Just place it at the very end of your BL Trick. The Assembler will auto calculate how many extra zero bytes to add to the end of your BL-Trick so the source can be word-aligned. If no alignment is necessary, you can still add this, as it will NOT add any extra unnecessary zero bytes.



Chapter 5: Making the code pt. 1/2

We will create a BL-Trick that contains our new extended 23-character Mii Name, and then we can use a basic Loop to copy the Mii Name from the space within our code to Dynamic Memory. With any code that involves the BL-Trick, you must be aware about the safety of the Link Register. You may have to backup up its value to a GPR (via mflr) and then move that value back to the Link Register at the end of your code (via mtlr). Let's find out if we can use the LR freely in this code. The obvious method to find out would be to look at the code's instruction address in Code View and scroll down til we find an instruction that modifies the LR.

At address 8075151C is this...

[Image: bl05.png]

The instruction at the address (highlighted in blue) is 'mtlr r0'. Okay at this point we need to know what is the the closest previous instruction that modifies r0. Well we can see just 4 instructions above at address 0x8075150C is a 'lwz r0, 0x0024 (sp)' instruction. It is highlighted in blue in the picture below.

[Image: bl06.png]

We see that a value is loaded into r0, and that value is then moved to the LR. In conclusion, we can freely write to the LR without backing it up since the CPU will write a new value to the LR anyway.

Referring back to the default instruction...

Code:
PAL:
8075144C lwz r5, 0x0068 (r4)

Since it's a load instruction, we want it as the last instruction of our source. That way we can freely use r5. r11 and r12 are safe to use 99% of the time. So that's 3 free registers. Alright, we should have enough free registers to use. So we won't need to use the 'Push/pop' the Stack Method.

We need an instruction that will set a register to point to start of the Mii Name that is currently in dynamic memory. However, we actually want to point 2 bytes BEFORE the start of the Mii Name. Why is this? Well recall back in the Creating Loops tutorial, load and store 'updating' instructions are used. They are usually stwu (store word & update), and lwzu (load word & update). These updating type of instructions constantly increment the loading and storing addresses after each loop iteration.

Since each Mii Name character is a halfword, it will make sense at some point later on in our Source to implement a loop that loads & stores a halfword for each iteration (lhzu & sthu). The loading offsets for the lhzu and instructions will be 0x2, so the loop can always continue its load+store for each individual halfword sized Mii Name character.

We want to have a register point to 2 bytes before the Mii Name so when this loop goes thru its first iteration, the first Mii Name character (the 'd' in 'day1test') will be exactly loaded.

With all of that being said here's the first instruction of our source. We will use r5.

Code:
#Need a register to point to 2 bytes before the original Mii Name
addi r5, r4, 0x66

Now we need to create our new 23-character Mii name using a BL-Trick. It will just a bunch of random numbers (01230123012301230123456789905). Here's the BL-Trick portion....

Code:
#Use BL-Trick to write out Mii Name 01230123012301230123456789905
bl mii_name

.short 0x0000
.llong 0x0030003100320033 #Start of Mii Name
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0034003500360037
.llong 0x0038003900390030
.short 0x0035 #Last Mii Name character
.short 0x0000
.short 0x0000

mii_name:
mflr r12

Okay so r12 now points to the start of the custom Mii Name. I used the .llong and .short Psuedo-Ops to give you a 'hex' view of the Mii Name.

Explaining all 4 .short's~
  • The first .short (0x0000) will be due to our creation of our loop that we will address soon. As you should already know, all loops use a form of store/load updating instructions. This first 0x0000 of space will allow use to load the Mii Data on the first iteration of the loop without any extra instructions needed.
  • The second .short (0x0035) is simply the final Mii Name character.
  • The third .short (0x0000) will be for a 'check' in the upcoming loop. We need to know when to stop the loop. There are no Mii Characters that are a 0x0000. So once we hit this null halfword, we know to end the loop.
  • The fourth .short (0x0000) is simply for alignment. The BL-Trick as a whole needs to be word-aligned.



Chapter 6: Making the code pt. 2/2

Now it's time to make that Loop that I covered about earlier~

Code:
the_loop:
lhzu r11, 0x2 (r12) #Load Mii Name Character from BL Trick
sthu r11, 0x2 (r5) #Store Mii Name Character to dynamic memory
cmpwi r11, 0 #Check for null halfword (is Mii Name transfer done?)
bne+ the_loop #If NOT null, keep loop going

This loop is a tiny bit different that the ones described in the Creating Loops tutorial. It's due to the fact that the custom Mii Name can vary in length, we need a way to know when any custom Mii Name has been completed transferred over to dynamic memory.

There are no 16-bit ASCII characters that are a null halfword (0x0000). So a basic check against the value of 0 will work. Once the loop has been completed, the custom Mii Name will be in dynamic memory. All we need now is the code's default instruction and we're done. Let's add that in and look at the entire source.

Code:
#Need a register to point to 2 bytes before the original Mii Name
addi r5, r4, 0x66

#Use BL-Trick to write out Mii Name 01230123012301230123456789905
bl mii_name

.short 0x0000
.llong 0x0030003100320033 #Start of Mii Name
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0034003500360037
.llong 0x0038003900390030
.short 0x0035 #Last Mii Name character
.short 0x0000
.short 0x0000

mii_name:
mflr r12

the_loop:
lhzu r11, 0x2 (r12) #Load Mii Name Character from BL Trick
sthu r11, 0x2 (r5) #Store Mii Name Character to dynamic memory
cmpwi r11, 0 #Check for null halfword (is Mii Name transfer done?)
bne+ the_loop #If NOT null, keep loop going

#Default Instruction
lwz r5, 0x0068 (r4)



Chapter 7: Conclusion

And that's the BL Trick! Key notes about BL Tricks to wrap up this tutorial...
  • Be sure of Link Register safety
  • Slap on a '.align 2' at the end of the BL-Trick to align it if necessary
  • And Happy Coding!