WiiRd forum

Wii & Gamecube Hacking => Wii Game hacking help => Topic started by: goemon_guy on July 22, 2011, 07:50:59 PM

Title: ASM code help
Post by: goemon_guy on July 22, 2011, 07:50:59 PM
I am trying to write an ASM code to increase a value, and then STOP increasing it after it has increased once.

lis r14, 0x805B        # Load 1st half of address
ori r14,r14, 0x6BBA # Load 1st half of address
lwz r15,0(r14)         # Load the value @ 805B6BBA into r15
addi r15,r15,1         # Add 1 to r15, and store it to r15
stw r15,0(r14)         # Store r15's value back to r14
lha r8,18(r30)         # Original Instruction

But after I activate it, the value keeps on increasing and increasing... How can I stop it from doing that?
Title: Re: ASM code help
Post by: dcx2 on July 22, 2011, 08:41:07 PM
1) if using r14+, you should create a stack frame.  See the stwu/stmw/[ASM]/lmw/addi template here.  http://wiird.l0nk.org/forum/index.php/topic,6555.0.html

2) As it stands right now, addi will be executed every time the hook is executed.  You will need a branch, probably more, in order to have the flow of execution skip over addi.
Title: Re: ASM code help
Post by: Deathwolf on July 22, 2011, 08:44:59 PM
How do you want to deactivate it? With a button activator? A value?

stwu r1,-80(r1)         # make space for 18 registers
stmw r14,8(r1)         # push r14-r31 onto the stack
lis r14, 0x805B        # Load 1st half of address
ori r14,r14, 0x6BBA # Load 1st half of address
cmpwi rX,0x XXXX   # compare rX with value XXXX
bne- ORIGINAL        # If not equal, branch to ORIGINAL: instruction
lwz r15,0(r14)         # Load the value @ 805B6BBA into r15
addi r15,r15,1         # Add 1 to r15, and store it to r15
stw r15,0(r14)         # Store r15's value back to r14

ORIGINAL:             
lha r8,18(r30)         # Original Instruction
lmw r14,8(r1)         # pop r14-r31 off the stack
addi r1,r1,80         # release the space
Title: Re: ASM code help
Post by: goemon_guy on July 22, 2011, 09:11:43 PM
Ok, I took deathwolf's ASM and modified it a bit to correspond with the game, and it works, however the change isn't permanent. So, I hold the button to activate it, and then when I let go, it resets the value to 0.

Here's the ASM I used.

stwu r1,-80(r1)          # make space for 18 registers
stmw r14,8(r1)         # push r14-r31 onto the stack
lis r14,-32677            # Load 1st half of address
ori r14,r14,27576      # Load 2nd half of address
lis r16,-32724            # Load 1st half of button activator
ori r16,r16,44758        # Load 2nd half of button activator
lwz r17,0(r16)            # Load the value of the button activator to r17
cmpwi r17,2048         # Checks if Y is pressed
bne- 0x0C                 # If not, skip the next 3 instructions
lwz r15,0(r14)           # Load the value from the address to r15
addi r15,r15,1           # Add 1 to the value @ r15
cmpwi r15, 772          # If it tries to surpass 772...
bne- 0x08                 # If not, skip the next 2 instructions
li r15,0                      # Reset to 0
stw r15,0(r14)           # Write to the original address
lha r8,18(r30)            # ORIGINAL instruction
lmw r14,8(r1)             # pop r14-r31 off the stack
addi r1,r1,80              # release the space
Title: Re: ASM code help
Post by: Deathwolf on July 22, 2011, 09:17:13 PM
this should work too:

28 # button address
stwu r1,-80(r1)         # make space for 18 registers
stmw r14,8(r1)         # push r14-r31 onto the stack
lis r14, 0x805B        # Load 1st half of address
ori r14,r14, 0x6BBA # Load 1st half of address
lwz r15,0(r14)         # Load the value @ 805B6BBA into r15
addi r15,r15,1         # Add 1 to r15, and store it to r15
stw r15,0(r14)         # Store r15's value back to r14
lha r8,18(r30)         # Original Instruction
lmw r14,8(r1)         # pop r14-r31 off the stack
addi r1,r1,80         # release the space
CC # switch codetype
04 lha r8,18(r30)    # write lha value
E0000000 80008000 # Terminator line
Title: Re: ASM code help
Post by: Deathwolf on July 22, 2011, 09:25:21 PM
Quote from: goemon_guy on July 22, 2011, 09:11:43 PM
Ok, I took deathwolf's ASM and modified it a bit to correspond with the game, and it works, however the change isn't permanent. So, I hold the button to activate it, and then when I let go, it resets the value to 0.

Here's the ASM I used.

stwu r1,-80(r1)          # make space for 18 registers
stmw r14,8(r1)         # push r14-r31 onto the stack
lis r14,-32677            # Load 1st half of address
ori r14,r14,27576      # Load 2nd half of address
lis r16,-32724            # Load 1st half of button activator
ori r16,r16,44758        # Load 2nd half of button activator
lwz r17,0(r16)            # Load the value of the button activator to r17
cmpwi r17,2048         # Checks if Y is pressed
bne- 0x0C                 # If not, skip the next 3 instructions
lwz r15,0(r14)           # Load the value from the address to r15
addi r15,r15,1           # Add 1 to the value @ r15
cmpwi r15, 772          # If it tries to surpass 772...
bne- 0x08                 # If not, skip the next 2 instructions
li r15,0                      # Reset to 0
stw r15,0(r14)           # Write to the original address
lha r8,18(r30)            # ORIGINAL instruction
lmw r14,8(r1)             # pop r14-r31 off the stack
addi r1,r1,80              # release the space


lwz r17,0(r16)            # Load the value of the button activator to r17

should be :

lis r14,-32677            # Load 1st half of address
ori r14,r14,27576      # Load 2nd half of address
lis r16,-32724            # Load 1st half of button activator
ori r16,r16,44758        # Load 2nd half of button activator
lhz r16, 0 (r16)          # Load the value of the button activator to 16
cmpwi r16,2048         # Checks if Y is pressed
bne- 0x0C                 # If not, skip the next 3 instructions

or not?

because actually you are loading nothing in r17, you are loading into r16.
Title: Re: ASM code help
Post by: goemon_guy on July 22, 2011, 09:32:08 PM
Quote from: Deathwolf on July 22, 2011, 09:25:21 PM
Quote from: goemon_guy on July 22, 2011, 09:11:43 PM
Ok, I took deathwolf's ASM and modified it a bit to correspond with the game, and it works, however the change isn't permanent. So, I hold the button to activate it, and then when I let go, it resets the value to 0.

Here's the ASM I used.

stwu r1,-80(r1)          # make space for 18 registers
stmw r14,8(r1)         # push r14-r31 onto the stack
lis r14,-32677            # Load 1st half of address
ori r14,r14,27576      # Load 2nd half of address
lis r16,-32724            # Load 1st half of button activator
ori r16,r16,44758        # Load 2nd half of button activator
lwz r17,0(r16)            # Load the value of the button activator to r17
cmpwi r17,2048         # Checks if Y is pressed
bne- 0x0C                 # If not, skip the next 3 instructions
lwz r15,0(r14)           # Load the value from the address to r15
addi r15,r15,1           # Add 1 to the value @ r15
cmpwi r15, 772          # If it tries to surpass 772...
bne- 0x08                 # If not, skip the next 2 instructions
li r15,0                      # Reset to 0
stw r15,0(r14)           # Write to the original address
lha r8,18(r30)            # ORIGINAL instruction
lmw r14,8(r1)             # pop r14-r31 off the stack
addi r1,r1,80              # release the space


lwz r17,0(r16)            # Load the value of the button activator to r17

should be :

lis r14,-32677            # Load 1st half of address
ori r14,r14,27576      # Load 2nd half of address
lis r16,-32724            # Load 1st half of button activator
ori r16,r16,44758        # Load 2nd half of button activator
lhz r16, 0 (r16)          # Load the value of the button activator to 16
cmpwi r16,2048         # Checks if Y is pressed
bne- 0x0C                 # If not, skip the next 3 instructions

or not?

because actually you are loading nothing in r17, you are loading into r16.

I tried replacing my lwz and cmpwi with your lhz and cmpwi, and when I press Y, nothing happens.
Wouldn't it be because, cmpwi would be comparing 2048 (0x800) to 802CAED8?
Title: Re: ASM code help
Post by: dcx2 on July 22, 2011, 09:32:30 PM
Deathwolf's ASM/Code-type hybrid would probably work for you.  However, I want to address a few things to help make your ASM codes more readable.

First, you should insert line breaks between "parts" of the code.  Think of them like paragraphs.  They improve readability.

Second, instead of using decimal for lis/ori, you should use hex.  Deathwolf's example uses hex.

Third, in Deathwolf's example he used branch labels (in his first example, the label was "ORIGINAL:").  Branch labels spare you the painful process of counting instructions.

Finally, when creating codes like this, you should carefully evaluate every path that the code can take.  In your example, assume that no buttons are pressed.  The first bne- will be taken, and it will skip over the lwz r15.  The second bne- is probably taken, and it lands on the stw r15.  Notably, since lwz r15 was branched over, whatever random value existed in r15 at the time of the hook will be stw'd.  In this case you should move your lwz r15 before the first bne-, so that r15 is loaded with a known value every time the hook runs.

Oh, one last thing.  Be careful with button activators.  Button activators are typically half-words (16-bits), which means you use lhz instead of lwz.  Although you can use lwz if you adjust the address.

EDIT:

Noticed another thing.  The data address of interest is 805B6BBA.  This is almost certainly not a 32-bit word, because it's on a 16-bit boundary (address ends in 2/6/A/E).

EDIT2:

...Y?  Is this a GameCube game?  I think it is.  In which case, if you go from an unaligned lwz to an aligned lhz, your new button activator address would be 802CAED8, not 802CAED6.

Quote from: goemon_guy on July 22, 2011, 09:11:43 PM
stwu r1,-80(r1)          # make space for 18 registers
stmw r14,8(r1)         # push r14-r31 onto the stack
lis r14,-32677            # Load 1st half of address
ori r14,r14,27576      # Load 2nd half of address
lis r16,-32724            # Load 1st half of button activator
ori r16,r16,44758        # Load 2nd half of button activator
lwz r17,0(r16)            # Load the value of the button activator to r17
cmpwi r17,2048         # Checks if Y is pressed
bne- 0x0C                 # If not, skip the next 3 instructions
lwz r15,0(r14)           # Load the value from the address to r15
addi r15,r15,1           # Add 1 to the value @ r15
cmpwi r15, 772          # If it tries to surpass 772...
bne- 0x08                 # If not, skip the next 2 instructions
li r15,0                      # Reset to 0
stw r15,0(r14)           # Write to the original address
lha r8,18(r30)            # ORIGINAL instruction
lmw r14,8(r1)             # pop r14-r31 off the stack
addi r1,r1,80              # release the space
Title: Re: ASM code help
Post by: goemon_guy on July 22, 2011, 09:43:21 PM
Sigh, dcx2, what would I do without you? Thanks to the both of you! I learned alot from this code. And it works now! :D

And as to breaking the line in between sections, I understand what you mean. I'll keep that in mind next time ;).

I normally use hex when I make them, but when I throw the commands into ASMWiird, it converts them :S. It's a real pain.

Thanks again!
Title: Re: ASM code help
Post by: dcx2 on July 22, 2011, 09:49:06 PM
Yeah, if you disassemble the code in ASMWiiRD or PyiiASMH, it gives you decimal offsets.  And it gets rid of white space and branch labels. =(

That's why I keep my pre-compiled ASM in a separate text file.  And then I copy and paste the final version into the assembler.

If you're hooking GameCube, you might want to make sure that your hook is constant.  GameCube had limited memory and so most games would swap ASM in and out of RAM.  I suggest cold-booting the game, and then at the menu screen, verify that the ASM you're hooking is there.  If it's not there when you start the game, then it's hot-swapped ASM and you'll need an F2 code.

EDIT:

Also, if you review the "On the Safety of Registers" post, you'll see that you can often get away without using a stack frame.  In fact, if you go to the disassembler and right-click your hook and select "Copy Function", I can probably point out what registers are safe to use.

Also, do you really need to load 805B6BBA into r14?  I imagine you found this hook by using a read breakpoint.  Is 18(r30) == 805B6BBA?
Title: Re: ASM code help
Post by: goemon_guy on July 22, 2011, 10:12:38 PM
Actually, 805B6BBA is the address for a value in the game, so in order to go through and add to its value, I had to load it into the ASM in order to increase it.

I think I might have misinterpreted the question, though...
Title: Re: ASM code help
Post by: dcx2 on July 22, 2011, 10:16:30 PM
I think you did, too.

I imagine you used a RBP to find this hook address, right?  Did you set the RBP on 805B6BBA?

The point is that if the code is already putting the value you want into r8 with the instruction lha r8,18(r30), then you won't need to load 805B6BBA yourself, because the game is already doing it for you.
Title: Re: ASM code help
Post by: Deathwolf on July 22, 2011, 10:17:27 PM
Please explain me why it works with this instruction: lwz r17,0(r16)            # Load the value of the button activator to r17
Title: Re: ASM code help
Post by: dcx2 on July 22, 2011, 10:20:55 PM
Contrary to my first opinion, the PPC can do unaligned reads, although it's not recommended.  So it will work.

Also, note that he uses only one button activator.  The second bne- is a test to make sure that he doesn't roll-over the max value 772, it's not actually a button activator.
Title: Re: ASM code help
Post by: Deathwolf on July 22, 2011, 10:24:38 PM
Ah thanks. But lhz r16,0 (r16) would work too right?
Title: Re: ASM code help
Post by: dcx2 on July 22, 2011, 10:26:31 PM
Yes, but you would lose the pointer that you put into r16.

Remember the basic format.  lhz rD,d(rA)  rD is the destination register; it will hold the value that is read from memory.  rA is a pointer register; it will hold the base address to the value.  d is the displacement operand, it will say how far forward or backward the value is from rA's address.

EDIT:

review this post.  http://wiird.l0nk.org/forum/index.php/topic,5249.0.html
Title: Re: ASM code help
Post by: Deathwolf on July 22, 2011, 10:28:30 PM
Yes, then we need to write the pointer again to another register. Everything is clear now. Thanks
Title: Re: ASM code help
Post by: goemon_guy on July 22, 2011, 10:29:04 PM
Say I wanted to add a subtraction after the addi, using a different button activator, then. How would I do that. The question is basically where to put the subi, because I can't seem to figure out where it should go. o.o

I tried this;

stwu r1,-80(r1)
stmw r14,8(r1)

lis r14,-32677
ori r14,r14,27576

lis r16,-32724
ori r16,r16,44758

lwz r16,0(r16)
lwz r15,0(r14)

cmpwi r16,2064
bne- 0x0C
addi r15,r15,1

cmpwi r16, 0x410
bne- 0x0C
subi r15,r15,1


cmpwi r15,772
bne- 0x08
li r15,0

stw r15,0(r14)
lha r8,18(r30)
lmw r14,8(r1)
addi r1,r1,80
subi r1,r1,80

But it doesn't seem to allow the value to decrease.
Title: Re: ASM code help
Post by: Deathwolf on July 22, 2011, 10:34:48 PM
the last subi is outside of the stack frame which doesn't work anymore.

stwu r1,-80(r1)
stmw r14,8(r1)
lis r14,-32677
ori r14,r14,27576
lis r16,-32724
ori r16,r16,44758
lwz r16,0(r16)
lwz r15,0(r14)
cmpwi r16,2064
bne- 0x0C
addi r15,r15,1
cmpwi r16, 0x410
bne- 0x0C
subi r15,r15,1
cmpwi r15,772
bne- 0x08
li r15,0
stw r15,0(r14)
lha r8,18(r30)
subi r1,r1,80 <-- inside the stack frame
lmw r14,8(r1)
addi r1,r1,80
Title: Re: ASM code help
Post by: goemon_guy on July 22, 2011, 10:39:41 PM
I moved the subi r1,r1,80 and it froze the game :S. I then moved it under the lmw, and it froze upon entering the status screen.
Title: Re: ASM code help
Post by: Deathwolf on July 22, 2011, 10:41:26 PM
Oh, ok then sorry for this. dcx2 could help you with this.

btw why are you going to subtract 80 from r1? r1 is for the stack frame!
Title: Re: ASM code help
Post by: goemon_guy on July 22, 2011, 10:46:56 PM
Haha, I dunno what I was trying to do there!

Either way, I removed it and the code worked just fine.

Thanks again!
Title: Re: ASM code help
Post by: dcx2 on July 22, 2011, 11:24:47 PM
Yeah, r1 is the stack pointer, don't touch it unless you know what you're doing.  Removing the subi r1 should make your code work as expected.

BTW, when making your roller roll backwards, make sure you don't roll-under.  That is, assuming 0 is the "first" legit value, then when your subi result is less than 0, you will want to replace it with 771.

EDIT:

btw, you can prefix lines with # to make them a comment.  i.e.

lis r16,-32724      # load r16 with button activator address
ori r16,r16,44758

Note that when you paste the assembly into ASMWiiRD, you should maximize the window.  ASMWiiRD uses word-wrap for its textbox, and so a comment that is long will wrap to a new line, and the assembler will try to treat the new line as a command instead of a comment.
Title: Re: ASM code help
Post by: goemon_guy on July 22, 2011, 11:27:38 PM
That's actually useful to know, as I forgot to add that into the code.

And it seems like I'm going to have to use the F6 codetype for the code, as the address for the ASM does in fact change upon switching discs.

And it also seems like I changed something in the code, and my subi no longer subtracts from it. XD
Title: Re: ASM code help
Post by: dcx2 on July 22, 2011, 11:28:43 PM
Do you mean the F2 code type?

F6 searches for a unique pattern of Z values and if it finds it, puts the address of those Z values into the po.  If the ASM actually moves to a completely different address, this is what you'll need.  You will also need to make sure that the F6 code runs after the ASM is loaded, and you may need a way to re-trigger the F6 code.

F2 uses an XOR checksum to make sure that a C2 patch is being applied to the correct ASM.  If the ASM is just sometimes there, sometimes not, but always at the same address, then this is what you want.

EDIT:

This is why your subi doesn't work.  It's a prime example of why you should use branch labels!!

cmpwi r16,2064
bne- 0x0C           # this should be bne- 0x08
addi r15,r15,1

cmpwi r16, 0x410
bne- 0x0C           # this should ALSO be bne- 0x08
subi r15,r15,1
Title: Re: ASM code help
Post by: goemon_guy on July 22, 2011, 11:34:39 PM
Quote from: dcx2 on July 22, 2011, 11:28:43 PM
This is why your subi doesn't work.  It's a prime example of why you should use branch labels!!

Alright, alright, I'll use them from now on :P

The ASM completely changes its location when you change the disc to the 2nd.

Fortunately, it's always in the same place, (Disc 1 is always in the same spot, and Disc 2 is in a different spot, but, it too is constant.)