ASM code help

Started by goemon_guy, July 22, 2011, 07:50:59 PM

Previous topic - Next topic

goemon_guy

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?
-Currently hacking the following game(s):
...
Request a code via PM, if you wish.

dcx2

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.

Deathwolf

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
lolz

goemon_guy

#3
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
-Currently hacking the following game(s):
...
Request a code via PM, if you wish.

Deathwolf

#4
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
lolz

Deathwolf

#5
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.
lolz

goemon_guy

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?
-Currently hacking the following game(s):
...
Request a code via PM, if you wish.

dcx2

#7
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

goemon_guy

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!
-Currently hacking the following game(s):
...
Request a code via PM, if you wish.

dcx2

#9
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?

goemon_guy

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...
-Currently hacking the following game(s):
...
Request a code via PM, if you wish.

dcx2

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.

Deathwolf

Please explain me why it works with this instruction: lwz r17,0(r16)            # Load the value of the button activator to r17
lolz

dcx2

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.

Deathwolf

Ah thanks. But lhz r16,0 (r16) would work too right?
lolz