WiiRd forum

Wii & Gamecube Hacking => Wii Game hacking help => Topic started by: Bully@Wiiplaza on August 04, 2011, 06:24:44 PM

Title: Codestype explanation
Post by: Bully@Wiiplaza on August 04, 2011, 06:24:44 PM
I found the following code:

Weapon Shrieker [Ozelot]
42000000 90000000
04F0BD1C 00000002
ACF0C35F FEF00000
04F0BD1C 00000001
E0000000 80008000

It let´s the player shoot any weapon with rapidfire.
But what´s the ACF0C35F FEF00000 line doing?
It seems like it´s setting a counter and continuously writes 02 and then 01 as value.
Very fast.

Can someone explain why this happens and also how to do it in ASM?
Thx ;D
Title: Re: Codestype explanation
Post by: dcx2 on August 04, 2011, 08:11:43 PM
According to http://www.geckocodes.org/index.php?arsenal=1#AC

ACF0C35F FEF00000

is non-sense.  The code handler would probably treat it like

AC00C359 FEF00000
Title: Re: Codestype explanation
Post by: Bully@Wiiplaza on August 04, 2011, 08:49:33 PM
Quote from: dcx2 on August 04, 2011, 08:11:43 PM
According to http://www.geckocodes.org/index.php?arsenal=1#AC

ACF0C35F FEF00000

is non-sense.  The code handler would probably treat it like

AC00C359 FEF00000
yeah but it actually works... :o
Idk what ozelot thought when he wrote that line...
Title: Re: Codestype explanation
Post by: Stuff on August 12, 2011, 09:47:18 PM
Is it alright if I post this here? I don't want to start a thread for every codetype, and this thread has such a perfect name.

A2______ KN00MMMM(gecko register if != )

8210000E 9014C0E4
42000000 90000000
A214CBFC EF000000
A8000008 0000005A
E0000000 80008000

After looking the the counter if in the code list, I thought it would be a good way to test any new conditional codetypes I come across.(Still need to understand it more, but whatever.) So I looked at A2(why I skipped A0 is beyond me). I read it, and it looks like a good way to compare 16bits in 2 addresses. Just store one value in a gr and compare it to F with the 2nd address in _______. I look at the addresses of the 1st 2 monsters in mh3 with this and if this worked, I should be able to see the counter going up in the codelist. But no. Instead, the game freezes as soon as I send the code. I tried instead putting the 2nd address in another gr and it still freezes. It freezes whether I expect the condition to be true or false. I just can't compare 2 grs. And it's that line. Any other if in it's place doesn't freeze the game. So I think the codetype might be documented wrong.
Title: Re: Codestype explanation
Post by: dcx2 on August 12, 2011, 10:03:50 PM
If ([grN] and not(MMMM))!=([grK] and not(MMMM))

The brackets mean "pointer goes here".  So instead of

8210000E 9014C0E4

You should use

8000000E 9014C0E4

Your original line was saying "take the 16-bit value out of 9014C0E4 and use it as a pointer".  Well, a 16-bit read of that address probably results in 0000XXXX, which is not a valid address, hence the crash.  You could probably press Step Into on the bp tab after the crash to see where and why it crashed.

Also, the Gecko Register ifs are 32-bit compares AFAIK.  lol the code type is specifically "16 bit if's" hahaha

EDIT:

might also want to review the second code in this post.  http://wiird.l0nk.org/forum/index.php/topic,8671.msg72146.html#msg72146

Using the 4E code and a 9421 code, you can have a gr over-write the operand of a code that doesn't normally use gr's.
Title: Re: Codestype explanation
Post by: Stuff on August 12, 2011, 11:32:06 PM
That didn't cause a freeze, but it never returned true. :/

42000000 90000000
A214CBFC EF000000

Does that also have to be a pointer? I think these gecko ifs suck then. I'm trying to compare 2 addresses without hogging up 2 gecko registers, and I have to add another 2 lines for that.

8210000E 9014C0E6
4E000016 00000000
9411000E 00000000
42000000 90000000
2A14CBFE 00000000
A8000008 0000005A
E0000000 80008000

So now the count up only works if the monsters have different hp as expected. And from the looks of it, if I put stuff after A8 it would delay the line after it by until 5A frames pass. but look at all them lines. XD

4E is a beast and you be OD'in with it, dcx2. lol
Still wish I could just compare the 2 addresses with a gr if.
Title: Re: Codestype explanation
Post by: dcx2 on August 15, 2011, 02:11:43 AM
This should have worked, except that you won't see the effect until after 5A frames.  I am surprised if it doesn't work...maybe try swapping E and F?

8000000E 9014C0E4
42000000 90000000
A214CBFC EF000000
A8000008 0000005A
E0000000 80008000
Title: Re: Codestype explanation
Post by: Stuff on August 15, 2011, 03:15:14 AM
Now that I look at it, I think it might've been a typo. should be 9014C0E6 and A214CBFE like in my last post. At some point I noticed the hp is in the 2nd 16 bits. I'll try this again.

Quote from: dcx2 on August 15, 2011, 02:11:43 AMI am surprised if it doesn't work...maybe try swapping E and F?
That's like saying if 3=5 makes more sense than if 5=3. XD I'll try it though.

It worked. Thanks. Not the  E and F swapping XD.
9014C0E4 and 9014CBFC are both 0000(unless something has 65536+hp >.>), so it was checking if there weren't equal and returned false. That's why it didn't work before.
Title: Re: Codestype explanation
Post by: dcx2 on August 15, 2011, 03:22:05 AM
"corner cases" as these are called, where the gr = F, are quite often handled by custom code.  Sometimes it might work for one corner case and not the other.  Though the alignment problem may actually have been what caused it to fail.
Title: Re: Codestype explanation
Post by: Stuff on August 15, 2011, 03:42:45 AM
hmm. Interesting. Well I was editing my post when you posted. It was the alignment/\, but I guess I'll keep an eye out for corner cases.
Title: Re: Codestype explanation
Post by: Stuff on August 16, 2011, 07:25:09 AM
Some more codetypes. This time I'm tackling flow control and address range check and stuff. I already thought about how these could be used. But I gotta make sure I understand. First CE.

CE00000T XXXXYYYY

if XXXX<=ba<YYYY
else false
apply Endif if T=1.

Looks like an if to me. So I guess it needs a endif as well? And does it apply 1 endif or end all ifs?
I guess this would go well with F6 or maybe something that changes the pointer(DE) to something unknown.

64000000 0000000P

So I think it can't come back to the next line after it's done. I was messing with the code list and I think it didn't run the next code after 64000000 0000000P. I want to know if I'm right in believing that.
I can imagine using this to make a while loop by going back to a previous line while something is true. I could do a for loop with set and execute repeat. You could get real funky with this and gecko registers.

F0000000 00000000
Tells the code handler that there are no more codes in the code list. The code handler exits.

>.> for what? Does 'code handler exits' mean that it'll stop executing codes completely when it reaches this? Does it end ifs?

Going back to the masking thing, lets say I want to do 'if <MMMMXXXX', but I want to keep 0 out of the possible trues. I'll use 2331 for X. I really don't want to do do if>0 after, because that's another line. So I put a bit of thought into this. If I make M=DCCE it would do Z%2331=2331? But then I got lost. This is definitely not gonna take me anywhere. It looks like it might be true unless Z is 0 or 2331 because there's no remainder for those 2. This would turn out to be a better if in quest than the one I had using the timer.
Title: Re: Codestype explanation
Post by: dcx2 on August 17, 2011, 03:09:19 AM
CE code type - Yes, it is an if and requires its own end-if or a terminator.  T = 1 will apply exactly one end-if.  Adding 1 to if codes in general will apply one end-if.

CE is fairly useless because you will never load the ba with a random pointer due to the ba addressing restriction (i.e. it masks off the lower 25 bits and only uses the upper 7 when calculating addresses)  For much the same reason, 46 is pretty useless too (it will always create ba = 80000000).

In contrast its cousins, DE and 4E, are extremely powerful.  Every time you load a pointer into the po from the game (i.e. 48 code type, or any code type which does po = [xxxxxxxx]), you should do a DE check.  If you load the po explicitly (i.e. 4A code, or po = xxxxxxxx), then you know the address would be valid so you don't need to DE check.

F6 codes sortof DE check themselves, because they either find the address they're looking for, or they fail and do not execute; the po never has a chance to be an illegal address.

---

64 is used to "jump" execution of the code list from one address to another.  What you're trying to accomplish might be better with a 66 Goto instead of a 64 Return.  You probably intend to jump over code  lines instead of addresses.  But you could probably use Gosub to set up the pointer for a Return.

---

All of the cheat codes are executed sequentially every frame, almost like a sort of program.  F0/FE/FF code type indicates the end of the code list.  It tells the code handler that it can stop executing cheats for this frame and return to the game.  The next time the code handler's hook is executed, it will run through all the cheats again.  It doesn't *technically* apply any end-ifs, but since the code handler will be done executing any un-ended ifs are moot.

Imagine it goes something like this.

while (codetype != 0xF0) { executeNextCode(); }

---

You're misunderstanding how masking works.  The "remainder" shortcut is misleading and only works for remainders that are powers of 2.

In order to understand masking, you have to know how hex maps to binary.  When I say 0xFC, you need to see 0b1111 1100.  Each hex digit has a corresponding binary pattern.  0xF = 0b1111, which is why "all 1s" is 0xFFFFFFFF.  Alternating 1s and 0s, i.e. 0b0101 0101, would be 0x55.

For code types, the mask bits M will "ignore" any bits that are 1.  So let's say your mask was 0x0002.  It would count up from 0, to 1, and when it got to 2 it would look like 0 again because that bit is masked.  3 -> 1.  4 -> 4.  5 -> 5.  6 -> 4.  7 ->5.  8 -> 8.  Do you see now why the remainder shortcut is misleading?

Code type masks are the exact opposite of ASM masks.  0's are masked instead of 1's.  Hence the "& not(MMMM)" part of the code type mask; this is what makes 1's mask.
Title: Re: Codestype explanation
Post by: Stuff on August 18, 2011, 03:24:47 AM
Thanks for the DE suggestion. I probably would've never thought about that. I would've always assumed if the pointer was there, it would always be there. I'll try to keep that in mind.

---

Oh I see. Didn't think binary would come in handy ever >.>. I'll have to find a binary<->hex converter. Seeing this, I don't think I can keep 0 from returning true in a if less than :/ . It just needed to be 0. Yeah. The remainder thing is quite misleading. lol.
Title: Re: Codestype explanation
Post by: dcx2 on August 18, 2011, 03:46:49 AM
For binary <-> hex, use Windows Calculator in Scientific mode.  F5 switches to Hex, F6 decimal, F7 octal, and F8 binary.  Windows Calculator can also do binary operations like AND, OR, NOT, and XOR.  After a while, though, you just kinda know.
Title: Re: Codestype explanation
Post by: Stuff on August 26, 2011, 12:45:46 AM
4A100 : po += XXXXXXXX

5A010 : po = po+XXXXXXXX

I looked at this many times. To me, they mean the same thing. So for what?
Title: Re: Codestype explanation
Post by: dcx2 on September 04, 2011, 01:06:48 AM
Yeah, they're functionally equivalent.

---

So I was looking at the source code for the C6 code in the code handler.  And I saw this interesting line.

   rlwimi   r5,r3,0,31,31      #restore lr bit

r3 has the first code word.  So if the LSB of the first code word is set, the branch created will be a bl instead of a b.

So I believe C6012344 800018A8 will create a b 0x800018A8, while C6012345 800018A8 will create a bl 0x800018A8.

We might want to update http://www.geckocodes.org/index.php?arsenal=1#C6 to note this.

Unfortunately, the C2 code type does not have such a feature.

---

Another important detail about sending codes.   The 00000000 at the end is where the back-branch will go.  The back-branch is only written when the C2/D2/F2 code is actually executed.

This means that if you send a code more than once, without undo, and your hook was run conditionally (either an F2 code, or a C2 after an if), then executing codes after sending them will not cause the back-branch to be written, and therefore a dangling hook can still cause the code to executed with the 00000000, causing a crash.
Title: Re: Codestype explanation
Post by: Stuff on September 07, 2011, 03:41:52 PM
Gecko Register / Direct Value Operations. And the other one too. Is XXXXXXXX signed or is it impossible to -1?
Title: Re: Codestype explanation
Post by: dcx2 on September 07, 2011, 04:27:32 PM
Technically it doesn't matter if X is signed or not because it's a whole word.  There is no "extsw" instruction because a 32-bit word is already full-size so there's nothing to extend.  Therefore, if you add 0xFFFFFFFF to an unsigned number, it still goes down by 1.  The overflow bit would be lost.

This gets trickier with 16- and 8-bit adds, on account of sign extension.  (extsh and extsb instructions, which copy the sign bit over all of the bits to the left, thus making 0x7F into 0x0000007F, and 0x80 into 0xFFFFFF80).
Title: Re: Codestype explanation
Post by: Stuff on September 07, 2011, 05:36:33 PM
ah. Well for now it was for 32-bits. I did FFFFFFFF and it minused. I was making a C2 change the addi amount by +/-1 on the fly. It works. So I'll know I can do that later...I'll have to find something 16/8-bit to -1 so I can see what your saying. I think the player hp would work.

So with the C6, that's just used if you want it to branch to some other asm? I was trying to think of how it could be useful...but C2 kind of just works.

And what about C0. I don't understand that one at all.

"Executes the NNNNNNNN lines of instruction placed under the code.
The instructions MUST end with a blr (0x4E800020)"

But what's gonna be in the LR? From the description, I'm assuming that the asm runs every time the code handler executes, like every other codetype. But then if it must end with a blr, then that's probably not the case.
Title: Re: Codestype explanation
Post by: dcx2 on September 07, 2011, 05:48:21 PM
extsh and extsb are only for ASM.  If you're doing Gecko Register ops you should just use 16-bit and 8-bit loads.  Although a 16-bit Gecko Reg load isn't going to sign-extend.  You could fake it by left-shifting (T=5) 16 bits and then arithmetic-shift-right (T=8) by 16 bits.  8-bit loads would need a 24-bit left-shift followed by a 24-bit arithmetic-shift-right.  Once sign-extended you still use 0xFFFFFFFF = -1.  Sign extension isn't necessary if you know your value will never be negative.  Sign extension is bad if the original 8- or 16-bit value was supposed to be unsigned!

---

C6 can be used to create branches from one address to another.  It is one-line.

C2 is used to create branches to and from a patch of ASM that lives in the code handler.  It is multi-line.

The reason you need a code type to create branches is that a relative branch requires you to know the address of the branch instruction and how many bytes away the destination is (i.e. how far away it is relative to the branch instruction).  This isn't so useful for the ba on account of being able to calculate the branch ahead of time, but it's extremely useful for the po.

Assume you F6 to find some code and you just want to turn one instruction into a branch.  You don't know where your branch will be, but you know the destination; this means you can't calculate the branch offset without copying the po into a Gecko Reg and doing some Gecko ops on it.

EDIT: here's an example code that used an F6 and a D6 to add the OSSleepThread hook, courtesy of Y.S.

OSSleepThread hook
F6000002 80008180
90A402E0 806502E4
908502E4 2C030000
D600005C 800018A8
E0000000 80008000

This is especially important because you can't use a branch in a C2 code, because the address of the branch inside the C2 is determined by the order codes were sent in (AND what version of the code handler you're using!), so again you don't know enough information to calculate the branch offset.

---

When the code handler executes a C2 code, all it does is write some branches.  The code handler does not execute the ASM inside the C2.  Later on, the game actually executes the ASM inside the C2.

C0 codes run in the context of the code handler.  So when the code handler runs, the ASM inside the C0 runs.  When the code handler "calls" a C0 code, it places the next instruction of the code handler into the LR.  This means a C0 code needs to end with a blr so that execution returns to the code handler after the ASM is done.  This allows the code handler to continue reading the code list and executing codes.
Title: Re: Codestype explanation
Post by: Stuff on September 11, 2011, 08:26:06 PM
So I did a XBP on this:
C0000000 00000001
4E800020 00000000

From there, I can see that r3 is safe. The next thing that happens is lwz r3,0(r15) and no conditional branches. But that's about it. I'll assume r12 is safe.. r9 looks safe too. andi. r9,r8,1 is the first time it gets used after the C0. Is there any more that would be definitely safe? Since it's probably always predictable, I wanted to know if there were some exceptions with C0, but that doesn't seem to be the case. It's probably always the same, so it'd be nice to know that there's a set of registers that don't need restoring. r10, r5, and r11 also look nice. This is the first time they're used after C0:

80001FB8:  546A1F7E   rlwinm   r10,r3,3,29,31
80001FBC:  54653F7E   rlwinm   r5,r3,7,29,31
80001FC0:  746B1000   andis.    r11,r3,4096

So from this I can say r3, r5, r9, r10, r11, and r12 are safe to use in C0 codes without having to restore them. That's a lot of flex. but is there more...:p. I was too scared to go further. Conditional branches that I wasn't gonna try to understand yet comes next.
Title: Re: Codestype explanation
Post by: dcx2 on September 11, 2011, 08:28:56 PM
You pretty much have it figured out.

http://wiird.l0nk.org/forum/index.php/topic,5622.msg55892.html#msg55892
Title: Re: Codestype explanation
Post by: Stuff on September 12, 2011, 07:28:22 PM
Interesting. I don't really want to stack frame anything since that would be 2 extra lines of code, so I'll just start with r12 and work my way down, skipping those reserved registers. I haven't needed more than 3 registers so far, so I'll hope with future codehandlers, if there are future ones, nothing changes with r12-r9. After reading "On the safety of registers" a few times, I can see why r0 would be considered safe in this situation. I didn't see it being used yet, so I considered it to be unknown.

I was thinking about messing with C0 in a real code, but C2 is superior for most ideas. For example, if monster id wasn't constantly being read, C0 would've almost been an option, but then I have no way to make it work for all monsters with out unnecessary effort.
Title: Re: Codestype explanation
Post by: dcx2 on September 12, 2011, 07:40:57 PM
C0 codes are for when normal WiiRD code types would take too much effort to use.  For instance, in this thread, I posted two ways to do a "Gecko Register Slider".  http://wiird.l0nk.org/forum/index.php/topic,8671.msg72146.html#msg72146  And then I posted a C0 conversion, which is one line shorter.  http://wiird.l0nk.org/forum/index.php/topic,8671.msg72154.html#msg72154

C2 codes have the benefit of access to game pointers.

And the code handler does not strictly follow the PowerPC EABI, so most of "On the Safety of Registers" does not apply to the code handler.

One very useful feature of the C0 is that you have access to the po via r16, the Gecko Registers and the Blocks via r7, and the address of the current code line via r15 ("current code line" in this case should be a pointer to the C0000000 00000001)
Title: Re: Codestype explanation
Post by: Stuff on October 10, 2011, 03:39:36 AM
Here's a stupid question. Wasn't there a way to store the next code's address in a gecko register or block? Not jump to it. Just store it. Don't want to change the pointer in the process.60 doesn't need a terminator, right? I'll just work with that. But I do wish it would do next code's address +XXXX. :/

And a much better question. If I do that/\, followed by a C2 code, can I expect that grN/bP to be that when my asm executes, even if there's a line that modifies that grN/bP in the next or previous code.

load into gr3
C2
lwz r12, d(r12) ##EA == gr3
load into gr3

Has the grN and bP location ever moved in previous code handlers?
Title: Re: Codestype explanation
Post by: dcx2 on October 10, 2011, 05:13:25 AM
Try 4E/4C.  Use 80001808 with 4C to write the pointer to gr0.

C2 codes execute in the context of the game, not the code handler.  Anything you write to a gr will probably still be there, although you should double-check to make sure it's a legit pointer first. (EDIT: The last code in the code list which writes to a gr will "win" when the C2 tries to read the gr)  The code handler usually runs first, but when sending codes that might not be true.

Old versions of the code handler used 8000180C as gr0 instead of 80001808.
Title: Re: Codestype explanation
Post by: Stuff on October 10, 2011, 07:48:37 PM
:/ that almost sucks that grNs were different in older code handlers. I used 60. It works just fine. I was trying to avoid using using a terminator. And it worked out. I needed 1 more instruction to not have to end with a nop. And that 1 instruction was addi rA, rA, 0x10.  ;D

----
Wow. I could've just bl->mflr for the same result. It's already safe to modify the link register and the code started with a branch.