Beginning MIPS R4300i Assembly

The Stupid Arrow to Rupee Ratio Code


November 7th 2010 6:12 PM EST

It has been a very long time since I last released a tutorial, sorry for the hiatus, I just needed to take some time for myself and leave the hacking scene for abit. I hope you guys learn something for those who don't know asm, and for those that do, please help me correct this tutorial because its very basic lol.

The point of this is to test asm, and learn how to make simple codes. The code is to add one rupee with every arrow that is fired.

This is kind of a semi tutorial at the same time, because I am learning this, so those who don't understand asm as well can learn this at the same time with me.

Basically the way the code needs to work is that, when an arrow is fire, obviously the counter for the number of arrows you have needs to deplenish. Everytime the number of arrows is changed, a piece of code writes the new number to the ram. The same goes for rupees.

So the first part of this I am going to explain how to use a Code searching tool correctly, to find values in the ram. This is a pretty basic technique, that isn't console specific, this can be applied to anything.

So first open up your game trainer tool, which I use Renegade. It is a really solid tool and allows you to not only do memory searchs, but disassemble MIPS 4300i. This will be useful to us when we make our code.

Your going to attach the tool to your running emulator, I use NEMU because of the memory tools, and assembly tools.

Now go to do a memory search. Now any good Game Trainer utility is going to have an advanced set of search options. Like "Equal To", "Less Than" and "Greater Than". This is instrumental in finding values quickly and efficiently. Thankfully because arrows are qauntifable and display their qauntity, we aren't doing an unknown value search.

So start with 30 Arrows. 30 is Decimal, so therefore we need to convert it to a hex number. The best and easiest way is with the calculator tool on Windows and selecting Scientific (Programmer for Windows 7 guys).

30 converted = 1E hex

So lets do an Equals search for 1E. I got 7646 results... Thats way to many to start picking out by hand. So lets use an arrow and reduce the number by 1. Go back to your search and now hit the less than ( < ) button. It is searching for a value less then 1E.

We came back with 118 results... Thats pretty good, but lets do it one more time. Now we are talking, we have 6 results. The nice thing about Renegade as well is that it shows you the previous values. What is not about this, is that anything that is not linear in its depletion is obviously not the arrows, because arrows run out in sequential order. Wouldn't make sense if you had 15 arrows then suddenly had 2.

As shown right in the top of the picture. You get 1E - 1D - 1C. Perfect, if you translate 1C to decimal, you have exactly 28, the number of arrows we have. If you still aren't sure it is the arrow qauntity, poke it, but just trust me on this one.

So now we need to get the rupees. Do the same process abouve for the rupees and find them on your own.

Now we want to set a breakpoint on when the arrow quantity depleets. There are two different types of breaks we can point on our address. A read, and a write. This is selected by going to that address and write clicking it. When its a read, it will be yellow, when a write break is set it will be purple. You can do both, but I never do.

Now fire an arrow. The game will freeze up and the "Commands" window will open in Nemu. This will show you the operation being carried out at that specific time. Record what you see, right click on the break you set and hit GO in the command window. This will allow you to resume the game.

Here are the commands and the locations of the arrow and rupee qauntity.

800874F8 SB T8,0x008C (V0) <--- Writes New amount of arrows
Arrow quantity is located at 8015E6EF

8008DCC4 SH T4,0X0034(T0) <--- Writes New amount of rupees
Rupees are located at 8015E695

Now this is the tricky part. You have to actually write the code. There is a plethora of documentation on the MIPS 4300i, its programming documentation, hardware specs. Its great. But unless you are really good at figuring things out it can really get confusing. So I am going to go through each line of this code below and explain it as best as I can.

First of all, we want it so that when you fire your arrow, it jumps to our line of code. So what we will do first of all, is go to that command for the arrow quantity being written to the ram. That is 800874F8.

We will use this code.

800874F8 0C0579DF JAL 0015E77C <--- This line of code simple says we are going to JUMP AND LINK to 0015E77C. 0015E77C is where our new code is going to start. Easy enough.

8015E77C A058008C SB $T8,008C($V0) <-- This is the original line of code that was located at 800874F8. We need this to still be here, because we want the arrow qauntity to still deminish when we shoot an arrow.

8015E780 3C1B8016 LUI $K1,8016 <-- This is the insertion of my own code now. I found an area of unused ram underneath the arrow qauntity offset. This leave plent of room to put my code. This code means to LOAD UPPER IMMEDIATE. LOAD UPPER simply means we are going to load 8016 into the upper half of the register $K1. IMMEDIATE means that we can load just any 4 digit value into the upper half of K1. It doesn't need to be 8016 it could be FFFF. But we want 8016 because we want to use this to load something from and address.

8015E784 8368E695 LB $T0,E695($K1) <-- This means we are going to LOAD a BYTE to the lower half of K1. So our result will be 8015E695. Now this is the part that I don't understand but I will find out. I put 8016, and you would think that by adding E695 it would become 8016E695. This isn't what it does though. It will turn it to 8015E695. Keep this in mind when your doing this. What we are doing here, it loading the byte store at 8015E695 into register $T0.This is infact our quantity of rupees. So if you have 145 rupees it will be 91 hex loaded to $T0.

8015E788 25080001 ADDIU $T0,$T0,0001 <-- This is an easy part of the code. The number that we loaded (91) which is the number of rupees. We are simply adding 1 to the value stored in $T0 which is 91 and storing the sum again in $T0.

8015E78C A368E695 SB $T0,E695($K1) <-- Here we are going to STORE the BYTE of data that is located in $T0 at address 8015E695. 92 has been stored to 8015E695.

8015E790 8D6B71B0 LW $T3,71B0($T3) <-- This is the command that followed the original SB $T8,008C($V0) used to write the quantity of arrows. We still want it to execute so we have to pop it back in to our new code.

8015E794 03E00008 JR $RA <-- This comes back to the return address, which is the address right after the one we jaled out of.

Essentially what we did with this code, is jumped out of the regular routine, start with the code we just removed. Then sandwiched our code in between it, and the original code that came after it, then jumped back into the regular routine. We
basically continued the code, outside of where it normally is. This happens all the time in the games routines and it nothing new.

I hope that you guys learned a little bit today. I definately did and I will continue to keep learning and sharing what I

learn with you guys so you can do your own stuff!

Here is the code un explained:

800874F8 0C0579DF JAL 0015E77C
8015E77C A058008C SB $T8,008C($V0)
8015E780 3C1B8016 LUI $K1,8016
8015E784 8368E695 LB $T0,E695($K1)
8015E788 25080001 ADDIU $T0,$T0,0001
8015E78C A368E695 SB $T0,E695($K1)
8015E790 8D6B71B0 LW $T3,71B0($T3)
8015E794 03E00008 JR $RA

Translated into a gameshark code:

810874F8 0C05
810874FA 79DF
8115E77C A058
8115E77E 008C
8115E780 3C1B
8115E782 8016
8115E784 8368
8115E786 E695
8115E788 2508
8115E78A 0001
8115E78C A368
8115E78E E695
8115E790 8D6B
8115E792 71B0
8115E794 03E0
8115E796 0008