CT5 (unknown value comparisons) don't work AT AAAAAAAA nvm

Started by mugwhump, November 23, 2009, 01:57:29 AM

Previous topic - Next topic

mugwhump

OK, so whenever I load ANY code using unknown value comparisons, I get an exception error. I can't for the life of me figure out why.

The codetype doc says:
QuoteCST3 : 16bits (endif, then) If lower

A6______ NM00YYYY : 16bits If lower 16bits compares if ([grN] and not(YYYY))<([grM] and not(YYYY)). If yes, codes are executed (else code execution set to false).

A6_____1 NM00YYYY : Endif, then 16bits If lower Makes one endif, then 16bits compares if ([grN] and not(YYYY))<([grM] and not(YYYY)). If yes, codes are executed (else code execution set to false).

Note: For the Part1 codes, if N or M = 0xF, then [address+ba/po] will be used
instead of grF

For example:
80000002 00000009  //gr2=9
80000003 00000009  //gr3=9
A0000000 23000000  //if gr2==gr3
0249292C 00000007  //rupees=7
E0000000 80008000
Results in a crash. Why the heck would it do that? All it does it set gecko registers 2 and 3 to 9 then check if they're equal. wat

I also considered that maybe you're supposed to store an address in the gecko registers, and the value at that address would be compared...
8001000E 0049292A  //grE = health ADDRESS+ba
A649292A FE000000  //if (value at health address)<(value at grE)  (this will never be true, but whatever)
0249292C 00000005  //rupees=5
E0000000 80008000
But that got me an exception error too.

I looked through the code database but couldn't find any examples using this codetype. If I could just get a single working example of this codetype I might know what I was doing wrong.


Also, gecko register addition seems kinda funny. FFFFFFFF+00000002 should be 00000001, right? Cuz I dunno if it's working right.

My old OP, pre-edit:
[spoiler]I'm writing a code that tries to detect a decrease in health. To do this, I have the old health value stored in grN, which is compared to the current health value; grN is set to the health at the end of the code.

The problem is the beginning of the code, the first time it runs. I can't compare the health to grN when grN hasn't been given a value yet. I need some way to set grN to 00000000, but only ONCE, as I obviously can't set it to 0 every frame or that would overwrite the health value. I was thinking maybe I could use some kind of on/off switch maybe?

About gecko registers:
I'm referencing grN in ASM using the static addresses specified in the codetype doc (80001804,80001808...80001840), but I've heard these addresses have changed in different versions of gecko. Can I get some more info on that? If they have changed, should I try to find some unused register in the game I can use to store my health?

And about ASM registers:
I've just been using the registers r0, r1, r2, r3, r4, like in various asm guides. But apparently some of the registers are unsafe? Does that mean I can't use them at all?

Thanks for any replies.  O0[/spoiler]

LRFLEW

I don't know much about this sort of stuff, but could you do something to the degree of ...

if value is (something), set 00000000.

Just an Idea. 

mugwhump


Drenn

Well, maybe you could do something like this:

If (GR1 == 0)
Insert code here
GR1 = 1;
End If
Insert code here

I'm too lazy to convert that to Hex.

Edit: Oh wait, GR1 starts as null right? Maybe there's a way to check if it's null, I dunno...

Edit: would this work?

If (GR1 != 1)
Insert code here
GR1 = 1;
End If
Insert code here

Just a thought...

mugwhump

Nope, I'm pretty sure you're not allowed to do any kind of comparison with unassigned gecko registers, gives you an Exception error.

I was thinking I could reference the registers by their physical address (80001804 etc). What would that address be full of at the beginning? Zeroes?
I tried that way yesterday and got the same error, but I'm guessing that might've been a problem elsewhere in my code, because I don't know why I wouldn't be able to reference a static address...

Romaap

The Gecko registers should be assigned by default, their value is 0x00000000 by default. :-\

Drenn

Maybe it is something else then. Take a code you know works and try comparing grN to something.

mugwhump

Wow it'd suck if I'd been doing something else wrong the whole time lol. I'll do some tests then....

edit: I used this code to test
A449292A EF000000 if grE>HEALTH
80000001 00000000 gr1=0
E0000000 80008000

and it STILL gave me an error. I don't know what could be wrong, other than that the gecko register hasn't been initialized. :\

DOUBLE EDIT:
I think my use of the A4 code is just wrong somehow, because the code
8411000E 0049292A
works, and all that does is set health to grE (though for some reason that locked my hearts at 3 instead of killing me, huh).

So what am I doing wrong with the A4 code :(

Almas

If you're experienced enough to use ASM, you should ditch the shackles of WiiRD codetypes as soon as possible. Not that they are necessarily bad but I find their naming system is nigh impossible to bother memorizing, and the simplicity of how ASM functions is enough. Although you seem to have some hiccups with ASM.

- Yes, some ASM registers are unsafe. An "unsafe" register is one which is read to before it is written to after your code executes. Clearly, if you write to a register and then the register is read from, the game is going to read something from it that it doesn't expect to read from it. More often than not, this will cause a crash. If a game is going to read the value stored at an address in a register and you write 42 into that register, it'll try to read from the address 42 (processors are dumb) and when it finds that the address is unreadable, it will crash. There are two ways around this: You can either find the set of registers that are written to before being read from by your code, and only change the value of those registers for whatever calculations or readings you want to perform. Or, you can start your code with a block of commands:

stw r1, <static address 1>
stw r2, <static address 2>
...

and end it with

lwz r1, <static address 1>
lwz r2, <static address 2>
...

By doing this you "save" the register values to values in RAM, mess around with them, then restore them to what they should be when you're done with your code. This has the advantage of requiring less effort but at times it may be a little unwieldy as it bulks up your code. It will also require one "safe" register to use to store the static address (note this address must be a location in RAM which is unused! But these are easier to find). For some games, such as Super Smash Brothers Brawl, certain registers are "fixed" at all times, and attempting to change them will cause bad juju to unfold.

If you choose the first option (finding safe registers), then a good place to start is registers which have nothing stored in them (i.e. take the value 0x00000000), but this is by far not a guarantee that they will work. This can be useful if the game's code branches off rapidly, making it hard to determine exactly which registers are safe. You can test this by writing a simple code that injects into the stream with a write to these registers, and seeing if it causes a crash or an observable change in gameplay.

- You say "If they have changed, should I try to find some unused register in the game I can use to store my health?". By this, I hope you mean "some unused RAM location". I highly doubt that any game will have a register which is completely unused - the notion is quite silly. Registers by function are designed to change on a very frequent basis, with a select few exceptions. Certain registers may be more prone to change than others, but in the period of a processor cycle it's almost certain that at some point all will get used.

I realize this is a wall of text. Assembly is much easier once you get into it! Honest.

mugwhump

Haha, walls of text are welcome, I've done tons of searching but it's hard to find good info. Thanks!
Still got some questions though:

1) Yeah, I meant "some unused RAM location." I don't have a usbgecko, however, so finding an unused RAM location and finding safe registers would both be tough. I'm writing a code for zelda, so perhaps I could dissect some other codes for it to find unused addresses/safe registers, like I did to get the health address?

2) What the heck am I doing wrong with Unknown value comparison (CT5) codes? Every time I use an A4 code I get an exception error, whether I'm comparing two gecko registers, a gecko register and a value at a location, whether I've assigned the registers values or not... all exceptions. :(

8000000E 0000000C grE=12
A449292A EF000000 if grE>HEALTH
80000001 00000000 gr1=0
E0000000 80008000
For example, this. I can't figure out why on earth this would give me an exception :/

3) I wouldn't even need ASM at all if I could figure out how to subtract a value at a location from a gecko register using the register operations!
0 : add (+)
1 : mul (*)
2 : or (|)
3 : and (&)
4 : xor (^)
5 : slw (<<)
6 : srw (>>)
7 : rol (rotate left)
8 : asr (arithmetic shift right)
A : fadds (single float add)
B : fmuls (single float mul)
If I could find some combination of these to do subtraction (if I could do a NOT operation that would work too).
I am offering a prize of 100,000,000 USD to any poster who can solve this problem.  :0

Almas

Depends how GeckoOS codetypes handle addition. Assembly code uses the idea that -X = NOT(X). You can simulate NOT(X) with XOR(X AND 0xFFFFFFFF).

mugwhump

YYYYYEEEEEEEEEEEEEEEESSSSSSSSSSSSSSSSSSSSSSSSSS
That will be perfect, won't need ASM any more!
Now just give me your bank number and PIN and I'll... deposit your prize >_>

edit: Alright CT5 is driving me crazy, exception errors for any code containing the A0, A2, A4, or A6 codetypes. The codetype doc and this thingy say the gecko registers are compared in 16 bits, does it mean I need to set them so they're 16 bit values instead of 32 or something? But... that doesn't make sense...  ._.

mugwhump

Can someone give me an example of how to use that codetype? Just one?


EDIT:
OK I got it working. Seems like it DOES use the addresses stored in the gecko registers. So I dunno why my example code up there got an error, but w/e, it's working now.

Though it seems like the A4/A6 codes are actually backwards