Turning on/off C2 code?

Started by Sharkbyte, October 08, 2010, 04:31:26 AM

Previous topic - Next topic

Sharkbyte

Is there a way to turn on/off a C2 code free at will without freezing the game? if so, how?

dcx2

The problem you experience is the result of how a C2 hook works.  The hook address you specify is actually replaced with a branch to where your code is stored.  If you remove the C2 code, but don't replace the branch, then the CPU will jump to garbage and you will crash.

To disable a C2 code, you must replace the C2 hook's branch with the original instruction; we sometimes call this original instruction the anti-code.  For instance, when you get hit, there's a subi that decreases your health, right?  You replace it with a 60000000.  Well, whatever you replaced with 60000000 is the anti-code.

Writing the anti-code to the hook address is the equivalent of turning off the C2 code.  In the following example, wiiztec is using a CC switch with the anti-code to make his C2-code toggle-able.

cerebral palsy afflicted mario/luigi/yoshi toggle Z++ [wiiztec, SMG2]
28750A02 00002010  # button activator
0406ACAC D003000C  # anti-code, replaces the C2 hook branch with the original instruction
CC000000 00000000  # switch
C206ACAC 00000002  # C2 hook
3E203F00 9223000C  # ASM instructions.  The CPU actually branches here
60000000 00000000  # ASM instructions.  The 0 is replaced with a branch back to the C2 hook address
E0000000 80008000  # terminator

Dude

I'm still messing around with ASM codes when I get the chance and this is something I could really make use of!

I've done "nop" codes, simple enough, and knew that to revert it back (switch off) you'd have insert the original instruction.

The code you used as the example, is this the code in it's entirety?
And you could use either a CC switch or two seperate codes to enable/disable? - One to set the C2 code and the other to rewrite the original instruction?

A few more examples of this sort would be greatly appreciated!

dcx2

Yeah, that's the whole code.  Here's another way that ZiT did it, with two if's.

---

Moon Jump (Z Button) [ZiT, Mad World]
28698FFA 00002000  # button activator
C22C7BE4 00000002  # C2 hook
3E003F00 92031180  # asm
60000000 00000000  # asm
E0000000 80008000  # terminator
28698FFA 00000000 # "inverse button activator"
042C7BE4 D0031180  # anti-code
E0000000 80008000  # terminator

When the first button activator is true, the code handler will execute the C2 code (i.e. 1: go to hook address, 2: make a branch from there to the asm, 3: replace the 0 at the end of the asm with a branch back to hook address).

When the "inverse button activator" is true, it replaces the branch written by the code handler in step 2 above with the anti-code.

---

Here's a super-epic code by ZiT/wiiztec, annotated by yours truly.  I suggest reading the whole post to understand the code, but I'll copy/paste and bold the code/anti-code template.

http://wiird.l0nk.org/forum/index.php/topic,5808.msg53284.html#msg53284

28750A02 FFFB0004   # if down arrow is pressed
C23AEC9C 00000003   # hook the following routine, which loads momentum from 80002FFC
3D808000 818C2FFC   # lis r12,-32768; lwz r12,12284(r12)
9181FFFC C001FFFC   # stw r12,-4(r1); lfs f0,-4(r1)
D01D0278 00000000   # stfs f0,632(r29)
26002FFC 3F800000   # if [80002FFC] < 3F800000 = 1
80000002 3F800000   # set GR2 = 3F800000
26002FFD 40000000   # else if [80002FFC] < 40000000 = 2
86900002 3A83126F   # fp add 0.001 to the value in gr2
84200002 80002FFC   # store gr2 to the address 80002FFC
E2000002 00000000   # 2 end-ifs (goes back to the "if down arrow is pressed")
2A750A02 FFFB0004   # if down arrow is not pressed
043AEC9C D01D0278   # write anti-code
80000002 3F800000   # load 3F800000 = 1 into gr2
84200002 80002FFC   # store gr2 to 80002FFC
E0000000 80008000   # terminator

dcx2

Okay, I'm a bit confused...that first code (the long one) is the speed code?  The last code is the moon jump?  They both hook the same address?

dcx2

Yeah, you can't do two hooks on the same address.  You can only have one branch there.

It almost kinda makes sense, though, because a moon jump is just vertical speed, right?

dcx2

This might be what you're looking for.

80583C24:  D3A30134   stfs   f29,308(r3)

It looks like you were supposed to set an Exact breakpoint.  If you don't have Exact checked, the Breakpoint will be hit if any of the 8 bytes that are double-word aligned with your address are touched.

So, if you set a breakpoint on 80000004 that is not exact, and the game writes to any address from 80000000 to 80000007, the BP will be hit.  If you set the BP at 80000008, then anything writing to the addresses 80000008 to 8000000F will be hit.

If you use exact, then the address must match exactly.  i.e. 80000007 will only trigger when 80000007 is written to.  If 80000004 is written to with four bytes, it will NOT hit, even though 80000007 is affected by a 32-bit write to 80000004.