Mario Kart Wii Gecko Codes, Cheats, & Hacks
Basic GVR Usage in ASM Codes - 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: Power PC Assembly (https://mariokartwii.com/forumdisplay.php?fid=50)
+--- Thread: Basic GVR Usage in ASM Codes (/showthread.php?tid=1962)



Basic GVR Usage in ASM Codes - Vega - 05-21-2022

Basic GVR Usage in ASM Codes

For Beginner ASM Coders.



Chapter 1: Intro; Explaining more about C2 Codes

C2 'Insert ASM' Codes are executed by the Code Handler when its Hook Address is executed by Broadway. For a full refresher regarding this, reread Chapter 3 of this thread -> https://mariokartwii.com/showthread.php?tid=1383

A C2 ASM Code can be executed for game specific list/cycle of circumstances. What do I mean by that?

Well for Mario Kart Wii, many addresses that are used by C2 Codes will be executed in a cycle for each player/CPU. An address will be executed for Player 1. Then next time that the game executes said address, it will be for Player 2. Then Player 3, 4, 5, etc etc.

For a game like Dragon Ball Z Budokai Tenkaichi 3 (where a match is typically Player 1 vs Player 2/COM), an address can be executed first for Player 1, then next time it will be for Player 2/COM.

Understanding this is crucial to reaching to that 'next level' of ASM Coding. This may not seem important at first, but this will open up a variety of possibilities for your future Codes.



Chapter 2: What is a GVR? Why do values in the GVRs matter?

GVR = Global Variable Register

It is any General Purpose Register that is r14 thru r31. GVRs will contain values such as...
  • Player Number/Slot
  • CPU Number/Slot
  • Course Number/Slot
  • Menu/Mode Type Number/Slot
  • etc

Therefore during the time when your ASM Code is executing, the GVRs may contain data that is relevant to improving your Code. By the way, the term "slot" is preferred by most Coders over the term "number". Regarding Player Slots, for the majority of cases, Slot value of 0 represents Player 1 (1st non-CPU Player).

By figuring out which GVR contains a specific slot value, you can modify your ASM Codes to only execute when said GVR has a certain value. A big issue for new Coders is creating a code and running into an issue where it applies to both the Human Player and the CPU (when the Coder only wants their Code to execute for the Human Player). At this point, if said Coder isn't familiar with GVR data, he/she will have literally zero idea on how to fix their code.



Chapter 3: Let's Make a Code using GVR Data; Part 1

We will use the old historical version of the Mario Kart Wii Shared Item Code (PAL) for demonstrating GVR fundamentals

Code:
C27BA164 00000002
386000WW 90770020
60000000 00000000

This code simply changes what item you receive from the item box when you pick it up. WW = Item to Receive, we will set this to 00 (Green Shell) for this GVR tutorial.

Code:
C27BA164 00000002
38600000 90770020
60000000 00000000

Now let's inspect the source...

Code:
li r3, 0 #Set Item (green shell)
stw r3, 0x0020 (r23) #Default/Original Instruction of Insertion/Hook Address. This stores the Item to Dynamic Memory.

At this moment we have no idea what data is represented in any of the GVRs. If you have MKWii, launch it on Dolphin. If not, be sure to examine the following screenshots closely to follow along. In MKWii, do a normal Offline Race. Simply pick Luigi Circuit (as that is the track I did for the exercise, and this plays an important role to the explanation of the final screenshot in this chapter). Character+Vehicle combo doesn't matter. Sometime before the Race begins, pause the emulation & set an Instruction BP on Address 807BA164 (do NOT have the Shared Item Code equipped!)

[Image: gvr01.png]

Once you have the Breakpoint set go ahead and start the race, but wait at the start line. When the first CPU hits the item box, the BP will break/hit. Note down the r14 thru r31 data that you see.

[Image: gvr02.png]

Once you have that all noted down, while keeping the Breakpoint ON, resume the emulation. It will pause again once another CPU hits an item box. Take a look at r14 thru r31. If any values changed from the previous Instruction BP hit, they will be in Red font. Note down the Red font GVR values.

[Image: gvr03.png]

While still keeping the Breakpoint ON, resume the emulation again. It will pause again after another Item Box hit. Take a look at the previous BP-hit Red font GVR values. How do they differ from the previous BP-hit? Note this all down (including their new current values).

[Image: gvr04.png]

In the above screen shot, there is something that sort of has a pattern to it. It's r25. We see that it has been incrementing (1 to 2 to 4). Fyi this WILL differ slightly on your own test. But you will see that r25 is indeed incrementing.

Go ahead and repeat the process until all CPUs have passed the first row of item boxes. Once they have pass that first row, go ahead and manually pause the emulation to prevent any further item box hits.

When I did this (for providing pics for this tutorial), here were the rest of the screenshots.

[Image: gvr05.png]

[Image: gvr06.png]

You can see that r25 is definitely incrementing. What could it be? Take a moment to think about it. It CANNOT be slot value, because the odds of it incrementing that many times in a row is extremely low.

Well we know the first CPU to hit the box is VERY likely to be in first place. In fact, said CPU WILL be 1st place unless said CPU somehow missed picking up the very first box in the race.

Thus, we can conclude that r25 represents the Player's/CPU's Position in the Race (at the time when they picked up a box).

To further prove this point, here is the next screenshot (when I did this exercise). All CPUs have already went past the first set of boxes (on Luigi Circuit), and now we can see from the screenshot that 1st Place CPU has picked up the first box on the next item box row on the track.

[Image: gvr07.png]

And the screenshot proves to us that r25 is 1, as expected. So now we know for 100% certainty that r25 = Position. 1 = 1st Place, 2 = 2nd Place, etc etc til C = 12th (last) Place.



Chapter 4: Let's Make a Code using GVR Data; Part 2

Awesome, we have some GVR data in which we can make a code with. Let's say you only wanted the Shared Item Code to execute when the Player/CPU is in last (12th place). Before we have anything at all execute in this new code we are writing, the 'check' for r25's value needs to be first.

We will use a simply Compare Word Immediate instruction. Now, since we only want the Code to execute when CPU is in 12th place, we will obviously check r25's value against the value of 0xC (12).

Code:
cmpwi r25, 0xC #12

We have a comparison instruction written out, now for the Branch instruction. Well, we know that we do NOT want the code to execute if r25 isnt' 12, so we will be using a Branch-If-Not-Equal instruction.

Code:
cmpwi r25, 0xC
bne

Since there are 12 different total positions, the odds of r25 NOT being 12 is high, thus we can supply a + symbol to the branch instruction to give a small hint to Broadway that the Branch Instruction/Jump will most likely occur.

Code:
cmpwi r25, 0xC
bne+

Now we need a label name. We will simply call it jump_code.

Code:
cmpwi r25, 0xC
bne+ jump_code

Underneath the branch instruction, we will put the instructions from the original Shared Item Code. Therefore if r25 is equal to 0xC (12), it will NOT take the branch jump and execute the instructions directly below.

Code:
cmpwi r25, 0xC #Check if in Last Place
bne+ jump_code #If not, don't execute code

li r3, 0 #Set Green Shell
stw r3, 0x0020 (r23) #Default/original instruction

At this point, you may be thinking to place the branch's jump 'landing spot' label at the very end, and the code is complete. However that would be wrong, we will write it out below and I will explain why that is incorrect to do.

Code:
cmpwi r25, 0xC #Check if in Last Place
bne+ jump_code #If not, don't execute code

li r3, 0 #Set Green Shell
stw r3, 0x0020 (r23) #Default/original instruction

jump_code:

Why is this wrong? Well, what happens if r25 isn't 12 and the branch is taken? You will completely skip over the Default Instruction. We need that instruction, so the r3 value (Item value from Box) will always get stored to Dynamic Memory. With that in mine, we need the 'jump_code:' label right before the Default instruction. Like this...

Code:
cmpwi r25, 0xC #Check if in Last Place
bne+ jump_code #If not, don't execute code

li r3, 0 #Set Green Shell

jump_code:
stw r3, 0x0020 (r23) #Default/original instruction

Now compile that code using Insertion Address (PAL) 0x807BA164

Code:
C27AB704 00000003
2C19000C 40A20008
38600000 90770020
60000000 00000000

We know from earlier that the '38600000' line is the 'li r3, 0' instruction. We can change that back to 38600WW to allow the end user to set a custom Item Value for the Code.

The first instruction of our new code is the cmpwi r25, 0xC. We can also configure that compiled line of code to end-user fill-able, we will use a P value for that.

PAL Positional Shared Item Code
P = Position Required
WW = Item to Receive

C27AB704 00000003
2C19000P 40A20008
386000WW 90770020
60000000 00000000


Congrats, you've just remade Star's Positional Shared Item Code! Link - https://mariokartwii.com/showthread.php?tid=536