WiiRd forum

Wii & Gamecube Hacking => Wii Game hacking help => Topic started by: Nutmeg on January 23, 2011, 02:06:18 AM

Title: ASM Code Example (Part I)
Post by: Nutmeg on January 23, 2011, 02:06:18 AM
ASM Code Example (Part I)
Home Team Has 999 Goals [Mario Strikers Charged]
Game ID: R4QE01
By Nutmeg on 1/17/11

Overview

We are going to make a basic assembly language (ASM) code.  This tutorial is not for a beginner coder.  If you have never made a code using Gecko dotNET [Credits: Link and dcx2] or WiiRd [Credits: kenobi and Link], then I suggest that you read dexter0’s basic RAM write tutorial that can be found here: http://members.cox.net/dexter0/WiiHacking/example1.shtml (http://members.cox.net/dexter0/WiiHacking/example1.shtml)

What We Will Accomplish

I have found a code that will set the home team’s goals to 999:  

Home Team Always Has 999 Goals [Nutmeg] [NTSC-USA]
05060578 000003E7


[spoiler](http://img707.imageshack.us/img707/3319/r4qe01005.png)[/spoiler]

The home team will always have 999 goals, no more, no less.  It comes with a catch however, this code will only work on the first stadium.  (For those of you who actually own Mario Strikers Charged, it is “The Vice”.)  The easy way to solve this problem is to make a pointer… but I don’t like pointers.  (They take too long to search for, and they are not always found.)  So, we are going to write a code in ASM that writes 999 goals to the home team, for all stadiums (levels).

Before We Begin


•What you will need
•Your wii
•A USB Gecko [Credits: Nuke]
•The Homebrew Channel [Credits: Team Twiizers]
•Gecko OS (app for the Homebrew Channel) [Credits: brkirch]
•WiiRd GUI or Gecko dotNET (I will be using Gecko dotNET)
•Know how to make a RAM write code.  You cannot make an ASM code without knowing how to make a RAM write code.  If you cannot make a RAM write code, go to dexter0’s tutorial: http://members.cox.net/dexter0/WiiHacking/example1.shtml (http://members.cox.net/dexter0/WiiHacking/example1.shtml)
•Make sure you can access the “disassembly” tab on either WiiRd or Gecko dotNET.  If you cannot access this tab, go to wiird.l0nk.org to ask for help.  I’m sure they will help you if you ask nicely.



Background about ASM

Assembly language coding is completely different than RAM write coding.  RAM write codes are almost always found in the later sections of memory.  Here is how the Wii’s memory is formatted.  (For this tutorials purpose, it will only involve the 80 memory range):

[spoiler](http://img266.imageshack.us/img266/3497/wiimem.jpg)[/spoiler]

Vocabulary Terms

ASM: This is an abbreviation for “Assembly Language.”
ASM Read: The ASM “reads” the values in the “value” section of the memory, and moves it to the ASM section of memory.
ASM Write: Once the ASM has “read” the value, it can “write” an entirely new value to the “value” section of memory.
ASM Instruction: These are held in the ASM section of memory.  They manipulate the “registers,” which we will deal with later in this tutorial.
Destination Register: Is the register where a value to be stored.  (In our example, it is r0.)
Source Register: Is the register whose value is stored somewhere in the “value” section of memory.  (In our example, it is also r0.)
Additional Note: The destination register is always insignificant because the value it holds will be overwritten by the next ASM “instruction.”  Because it is insignificant, we can always use it in ASM codes.

Here is the basic format on how Assembly Language works:

Step 1: The ASM reads a value out of the value section of memory.
Step 2: The ASM performs some “instructions” on the value.
Step 3: The ASM writes the new value back to the value section of memory.


ASM Reading

The chart above is very simplified and does not always hold to be true however; it should give you a good idea about how a Wii game works.  Here is how a Wii game works when you apply a direct RAM write code (e.x. a 04 code, like in dexter0’s tutorial):  You write a value to an address.  For this example we will use my code for Mario Strikers Charged (NTSC-USA version).  The value 0x3E7 (999) is written to 0x81060578.  The Assembly language part of the memory “reads” the value, 999, and the game thinks that you have 999 goals.  Additional Note: An address is usually “read” more than it is “written to.”

ASM Writing


The assembly language does not only take in the value from 0x81060578, it can also write a new value into that address.  Here’s an example:  First, assume that we have no codes applied.  The game is not hacked.  When we score a goal there is an “instruction” in the assembly language part of the memory that writes a new value to the address.  In our case, it’s 0x81060578.

Let’s Get Started!

First, we will take our address that holds the value of our home team goals, 0x81060578.  Now copy the address into the “break-points tab on WiiRd or on Gecko dotNET and select “read” as the break-point type.  This is what your “break-points tab should look like:

[spoiler](http://img405.imageshack.us/img405/1174/breakpointstab.png)[/spoiler]   


The Break Point Results Screen

Then click "set."

[spoiler](http://img203.imageshack.us/img203/6892/breakpointresults.png)[/spoiler]

Zoom in on your screen if you cannot see the above image clearly enough.  Please note that I maximized the Gecko dotNET window to show all of the information.  Your window might not be this big after you click “set.”

The screen is divided into two boxes.  The lower box holds assembly language instructions.  The instructions have two uses.  They are used to manipulate, or change the values in the upper box, and they are used to take a value out of the upper box and send it to an address in the “values” section of memory.  The upper box holds something called the “registers.”  The ASM “instructions” are what controls these “registers.”   Together, the “instructions” and the “registers” are what runs the game.  But, how do we hack them so that they do what we want?


Back to Our Example


The “instruction” that is at the top of the lower box is the instruction we want to manipulate.  The instruction is:

801AEB5C:   801E0008   lwz   r0,8(r30)

-801AEB5C is our “ASM Address.”
-lwz is our ASM “instruction.”
-r0 is the “destination register.”
-(r30) is our “base” of the ASM “instruction.”
-8 is our “displacement” of our ASM “instruction.”

Here is what that means.  The 801AEB5C is the address that our code will use.  In the code that only works for the first level, the address is 81060578.  The code written in assembly language will use a completely different address!  The second part is 801E0008.  Don’t worry about that part, you have no use for it.  Now, we come to the important part about the ASM.


Lwz r0,8(r30)
The value in r30 is 81060570.  You can find the value in r30, by locating r30 in the upper box.
The value in r0 is insignificant.  We don’t care what is in it.


Lwz is an assembly language “instruction.”  Lwz is short of “Load Word and Zero.”  What it does, is it loads a value from an address in the “value” section of memory and puts it into a given register.  The “instruction” that we are dealing with is lwz r0,8(r30).  We know what lwz does, but what does the r0,8(r30) do?  First, go to the value in r30, 81060570, and add 8.  Our address is 81060578.  Look at the address from our original code.  It is also 81060578.  This means that we are dealing with the correct ASM “instruction.”  lwz r0,8(r30) takes the value from our address, 81060578, and puts it into r0.  That is why the original value in r0 is insignificant.  It is over-written by the number of goals we have.  Right now, we have not changed anything in the “Assembly Language” section of memory.  We need to figure out how to turn our information into a code.  More specifically, we need to make the game think that we have 999 goals.



Creating the Code’s Structure


How should we make the game think that we have 999 goals?  In this case, it is just like any other code.  We have to “write” 999 to the original code that only works on the first stadium.  The address for that is 81060578.  But how do we do that?  We will use another ASM “instruction.”  It is called “stw.”  Stw is an abbreviation of “store word.”  It does exactly the opposite of lwz.  Stw takes a value from a register (the values in the upper box) and writes it to an address in the “value” section of memory.  Our instruction will look like this:

Stw   r0,8(r30)

Does that look familiar to the lwz “instruction?”  The r0,8(r30) is exactly the same as in the lwz “instruction.”  The “instructions” are exactly the same, except stw puts the value from r0 into r30 + 8, while lwz takes the value from r30 + 8 and puts it into r0.

Our next problem is, is that we have to change r0 to be 999 before we store it to our address, 81060578.  Right now, it is far from 999.  We will use another ASM “instruction” to put 999 goals into r0.  This “instruction” is called “li.”  â€œLi” is an abbreviation for “load immediate.”  What it does, is it puts a value into a “register.”  In our case, we want to put 999 into r0.  This is what our instruction will look like:

Li   r0,999

This ASM “instruction is much simpler than the lwz and stw “instructions.”  This instructions puts 999 into r0.  That was easy, wasn’t it?


Now we have the skeleton of our code.  We will put 999 into r0.  Then we will put r0 into r30 + 8 (That is 81060578, our original address).  The overall effect of this code, is that the game will think we have 999 goals, just like the original code, however it should work on every stadium.  (I will not tell you why.  It’s just built into the “Assembly Language” part of memory.)


Our code will look like this.  We start with the address we found in the “Assembly Language” portion of memory.  That is 801AEB5C.  So here, is the basic format of our code:
Address: 801AEB5C
Li   r0,999
Stw   r0,8(30)
Nop

“Nop” is an abbreviation of “no operation.”  Every code in ASM needs an odd number of lines.  Without the “nop” we only have 2 lines, which is even.  We use the ASM instruction, “nop,” to fill up the last line.  â€œNop” does absolutely nothing.  It’s just “there” to make the code have an odd number of “instructions.”



Turning that Nonsense into a Code

   
Open up ASMWiiRd.  In The “address” box at the top, put our address that is in the “Assembly Language” area of memory.  Then, in the box that is called “Assembler Code,” put our ASM “instructions.”  Click the arrow that is pointing to the “Code” box, and it should give us a code.  Here is what it should look like before we click the arrow:

[spoiler](http://img593.imageshack.us/img593/3188/asmwiird.jpg)[/spoiler]

Now, we will click the top arrow, which is between the “Assembler code” box and the “Code” box.  After it is clicked, it should look like this:


[spoiler](http://img808.imageshack.us/img808/2866/asmwiirdresults.jpg)[/spoiler]

Now, We have our code!  The final code is exactly what you see in the “Code” box.

Home Team Always Has 999 Goals [Nutmeg] [NTSC-USA]
C21AEB5C 00000002
380003E7 901E0008
60000000 00000000


[spoiler](http://img600.imageshack.us/img600/8255/r4qe01006.png)[/spoiler]
The code works perfectly.  Instead of working specifically on the first stadium, it works on all stadiums!

Conclusion

   You should now be able to figure out how to make your own basic codes using assembly language!  Here are some simplified steps to conclude this tutorial:

•   Make the basic code.  (One that looks like this: 05060578 000003E7)
•   Copy the address into the “breakpoints” tab and select the type as “read.”  Set the breakpoint.
•   Use ASMWiiRd to change the given “instruction” to store your own value (999) to your basic address (81060578).
•   Remember to use the address in the “Assembly Language” section of memory (801AEB5C)!

This concludes Part I of the tutorial.  Thanks for reading, and I hope you’ve learned how to make codes using assembly language!



Addition Help

If there is anything about this tutorial you don’t understand, go to the WiiRd forums, and to “Wii Game Hacking Help.”  http://wiird.l0nk.org/forum/index.php/board,7.0.html  If you have a good question to ask, and you ask nicely, I’m sure that myself, or another member will be happy to help you.

What’s up Next

In part II, I will be covering the same code, except we will change it so that it is possible to add/subtract goals from the score, just by pressing a button!  Stay tuned!


Written by,

Nutmeg

Places you can find me:
WiiRd Forums: http://wiird.l0nk.org/forum/ (http://wiird.l0nk.org/forum/)
Volderbeek’s Forums: http://volderbeek.freeforums.org/ (http://volderbeek.freeforums.org/)
Mdmwii’s Forums: http://mdmwii.altervista.org/ (http://mdmwii.altervista.org/)






Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 23, 2011, 02:36:40 PM
THANK YOU!!! My prayers have been anwsered. Please make many more. And if possible vid tutorials.
Title: Re: ASM Code Example (Part I)
Post by: Nutmeg on January 23, 2011, 06:56:48 PM
If you have any questions feel free to ask.  :D

-Glad you like it!  :D
Title: Re: ASM Code Example (Part I)
Post by: Bully@Wiiplaza on January 23, 2011, 08:13:09 PM
Quote from: Nutmeg on January 23, 2011, 06:56:48 PM
If you have any questions feel free to ask.  :D

-Glad you like it!  :D
did the posts get deleted? :confused:
Title: Re: ASM Code Example (Part I)
Post by: Romaap on January 23, 2011, 11:13:01 PM
Really nice, I added it to the Game Hacking Guides (http://wiird.l0nk.org/forum/index.php/topic,101.0.html) post.
Title: Re: ASM Code Example (Part I)
Post by: Nutmeg on January 23, 2011, 11:26:13 PM
Quote from: Bully@Wiiplaza on January 23, 2011, 08:13:09 PM
Quote from: Nutmeg on January 23, 2011, 06:56:48 PM
If you have any questions feel free to ask.  :D

-Glad you like it!  :D
did the posts get deleted? :confused:

Nope, I had in the "secret section" only.  Most everybody in there already knows ASM, so now it's available to everybody.

Quote from: Romaap on January 23, 2011, 11:13:01 PM
Really nice, I added it to the Game Hacking Guides (http://wiird.l0nk.org/forum/index.php/topic,101.0.html) post.

Thanks! :D
Title: Re: ASM Code Example (Part I)
Post by: floppytripod on January 24, 2011, 05:04:00 AM
I really understand this now, because of this tutorial. I am amazed how detailed it is. You cleared up so many questions that I had. Thank you so much for taking the time to make this tut.
:D
Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 24, 2011, 03:38:31 PM
Ok I have a little noob trouble. I think a final smash value is 806289BC 0000000E
So I did a write break point  and checked if the value was right, it was.
The lower box said 800028C8: 90030008    stw r0,8(r3)
What I'm trying to do is make everyone always have a final smash. So this looked like the correct ASM instruction So inASM<>WiiRd converter I put
Address: 800028C8
stw r0,8(r3)
and got
C20028C8 00000001
90030008 00000000
I put it in and the game froze.
Can you help me. If you need more info I can provide it.
Title: Re: ASM Code Example (Part I)
Post by: Jackal on January 24, 2011, 05:34:08 PM
What you did should not make the game freeze
It's just branching and do the same instruction
Did you try disabling everything else?
Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 24, 2011, 05:42:53 PM
branching??
Title: Re: ASM Code Example (Part I)
Post by: Deathwolf on January 24, 2011, 05:50:43 PM
Quote from: toonlink444 on January 24, 2011, 03:38:31 PM
Ok I have a little noob trouble. I think a final smash value is 806289BC 0000000E
So I did a write break point  and checked if the value was right, it was.
The lower box said 800028C8: 90030008    stw r0,8(r3)
What I'm trying to do is make everyone always have a final smash. So this looked like the correct ASM instruction So inASM<>WiiRd converter I put
Address: 800028C8
stw r0,8(r3)
and got
C20028C8 00000001
90030008 00000000
I put it in and the game froze.
Can you help me. If you need more info I can provide it.

C20028C8 00000001
90030008 00000000

and

040028C8 90030008
is the same
if you always want a final smash, use another register for the final smash value.

lis r12,0x0000
ori r12,r12,0x000E
stw r12,8(r3)

now it stores the 0E value from r12 into your RAM address [806289BC]
Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 24, 2011, 06:13:11 PM
Ummm, Can you explain the lis, and ori. And why use a different register
Edit:
Didn't work. I'll keep searching for the final smash value because I found more addresses that act the same
Title: Re: ASM Code Example (Part I)
Post by: Romaap on January 24, 2011, 06:23:02 PM
lis - load immediate shifted (loads a value in the register at the first 16 bits instead of the last 16 bits)
lis r12, 0x1234 - this puts 0x12340000 in r12

ori - OR immediate (in Deathwolf's example it is used to set the last 16 bits of a register)
ori r12, 0x5678 - assuming that r12 is 0x1234000, this will make r12: 0x12345678
Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 24, 2011, 06:35:25 PM
hopefully one day I will understand this better. But why change registers
Title: Re: ASM Code Example (Part I)
Post by: Deathwolf on January 24, 2011, 06:40:41 PM
example on your last address:

800028C8: 90030008    stw r0,8(r3)

stw r0,8(r3) <-- r0 = 0000000E <-- value
stw r0,8(r3) <-- r3 = 806289BC <-- address

if you lose your final smash, the 0E value changes back to 00.
so you another register. 0E on r12. so you have always the 0E value.

Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 24, 2011, 06:50:55 PM
But why r12 why not r13?
Title: Re: ASM Code Example (Part I)
Post by: Deathwolf on January 24, 2011, 07:40:34 PM
r12 is always free
Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 24, 2011, 07:49:00 PM
So if I understand correctly you can move values to a different register. Why would you do that?
Title: Re: ASM Code Example (Part I)
Post by: Deathwolf on January 24, 2011, 08:00:12 PM
you can WRITE your own value to a free register

example you write 99999999 to r12 and then store value from r12 into address 80123456 (r31)

lis r12,0x9999
ori r12,r12,0x9999
stw r12,0(r31)

r12 = value 99999999
r31 = address 80123456
Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 24, 2011, 09:06:10 PM
What does sth do?
Title: Re: ASM Code Example (Part I)
Post by: Deathwolf on January 24, 2011, 09:07:15 PM
stw = 32 bit = XXXXXXXX
sth = 16 bit = XXXX
stb = 8 bit = XX
Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 24, 2011, 09:08:17 PM
Ok I'll try again with this info.
Title: Re: ASM Code Example (Part I)
Post by: dcx2 on January 24, 2011, 09:09:57 PM
Don't use r13.  It's a special register that holds a very special pointer that you do not want to mess with, ever.

Ditto for r1 and r2.

r12 is usually the safest register.  Then, in decreasing order of safety, it goes from r11 to r3, and then r0.

The non-volatile registers, r14-r31, are safe to use if you back them up with a stack frame.

---

As far as toonlink's C2 code, look at the address.  800028C8  That looks like it belongs to the code handler.

I think you found the wrong write breakpoint.  Set your write breakpoint again, then copy and paste the registers into a spoiler.  If you use Gecko.NET you will probably have to switch the view mode to "Text View" from "Edit View" so you can copy and paste.  Then we'll know if your breakpoint was right.

---

Nutmeg, if you want, I can split this discussion into a separate thread if it's too off-topic for your thread.
Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 24, 2011, 09:24:01 PM
r13 was an example. And sure I can do that. I've been trying different values but I saved the first address. I'll also show the address I'm looking at now.
Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 24, 2011, 11:13:37 PM
Here's the first one. The origanal breakpoint. Bully@Wiiplaza said the smash value is 00000001. I've been looking for that but I can't find it, so I'm left in the dark. [spoiler]CR:42000088  XER:00000000  CTR:8082CBE4 DSIS:02400000
DAR:806289BC SRR0:80044964 SRR1:0000B032   LR:8084FC14
  r0:0000000E   r1:805B4E70   r2:805A9320   r3:806289B4
  r4:80627EA0   r5:0000000D   r6:00000000   r7:0000000D
  r8:000000FF   r9:00000008  r10:000000FF  r11:805B4E70
r12:80817150  r13:805A4420  r14:00000000  r15:00000000
r16:00000000  r17:00000000  r18:00000000  r19:00000000
__________________________________________________
80044964:  90030008   stw   r0,8(r3)
80044968:  4E800020   blr   
8004496C:  80A40000   lwz   r5,0(r4)
80044970:  80C40004   lwz   r6,4(r4)
80044974:  2C050000   cmpwi   r5,0
80044978:  4182000C   beq-   0x80044984[/spoiler]
Title: Re: ASM Code Example (Part I)
Post by: dcx2 on January 24, 2011, 11:24:43 PM
80044964:  90030008   stw   r0,8(r3)

That's not what you said before.

800028C8: 90030008    stw r0,8(r3)

Did you happen to have an 04 code type writing to the address the first time?  That would explain why you hit that breakpoint.  That write you hit was probably the code handler executing your 04 code.

The 80044964 looks like a bad breakpoint to try to use.  It's not destroying a stack frame (you would see mtlr and addi right before the blr).  So that means it's probably a short function that's meant to copy data between pointers in r4 and r3...you'll hit these with write breakpoints sometimes.

When you hit that breakpoint, press step two times.  After the second step, you'll see the ASM change to address 8084FC14 (because it will execute the blr, which will branch to the LR, which is 8084FC14).  Looking around that function might help you.

EDIT: or, you can use Gecko.NET, and hit "Step Out".  This will take you to the function that called the one your breakpoint was in
Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 24, 2011, 11:50:48 PM
I used the step out button and I got, 801E797C:  800DC388  lwz  r0,-15480(r13)
What do you do with the negitive? Just leave it?
Title: Re: ASM Code Example (Part I)
Post by: dcx2 on January 25, 2011, 12:05:34 AM
I think you found a different breakpoint again.

We should move this discussion to your "finding the final smash value" thread.  I can help you in greater detail there tomorrow.
Title: Re: ASM Code Example (Part I)
Post by: toonlink444 on January 25, 2011, 12:41:26 AM
Ok.
Title: Re: ASM Code Example (Part I)
Post by: Nutmeg on January 25, 2011, 02:55:37 AM
Quote from: dcx2 on January 24, 2011, 09:09:57 PM
Nutmeg, if you want, I can split this discussion into a separate thread if it's too off-topic for your thread.

Do what you like.  If you feel that it is cluttering the topic, then go ahead and delete it.

If it really gets out of hand, I'll shoot you a pm.  As for now, do what you like.   It makes me feel helpful when so many people post under my thread. xD