Hey again guys and gals.
I'm not sure waht would be the correct IF codetype to use for this...
I've found an address and I want to build a code that checks this address and then writes a value to it, dependant on the current value. I'm aiming to make it only work when I press a button combination. I think it's the Regular IF Codes that I'll need to use, 32bit.
Example:
80104920 00000000
I want to first check if this value is less than 15. If it is, then set to 14.
I then want to check if it is between 15 and 30. If it is, then set to 29.
I then want to check if it is between 30 and 45. If it is, then set to 44.
All in the one button press.
The purpose is to make it that I can press a button combination and have it check the value at the address and write to it accordingly. The value naturally increases on it's own depending on what I do in the game, but want to speed it up by making it 1 value less than is required to get to the next level. This will ensure that it triggers the unlockable when it reaches 15/30/45, etc.
I've thought of the logic and think this should work. It should write the value without jumping straight to writing 44 to the address until I've gotten the unlockable. I just don't know how to do it lol Being able to do this for two or more addresses (using different values) from the one button combo would be perfect.
Anyone help please?
Are you sure you need a 32-bit if? Your values are small enough that it might be 16-bit or even 8-bit. Anyway, here's pseudo-code for what you're trying to do.
if (val < 15) {
val = 14;
}
else if (val < 30) {
val = 29;
}
else if (val < 45) {
val = 44;
}
You need to use else-if's. Then, if you make it to the second else-if, you know for sure that you're at least 15.
Thanks for the reply, dcx2.
The way you structured that is more simplified than the way I was initially trying to do it, but might result in writing the final 44 value into the address. It will check if it's less than 25, then write 24, but then move onto the next line and check if it's less than 30, then write 29, etc. I don't think that there is a "else if" in the code types to end the branch.
You're probably correct about the 32bit if though. I've just been using the entire 32bits out of laziness lol
My only problem now is how I turn this into codes for use in Geckos using these Code Types:
CST4 : 16bits (endif, then) If equal
28______ ZZZZYYYY : 16bits If equal (ba) 16bits compares if ([ba+address] and not(ZZZZ))==YYYY.
If yes, codes are executed (else code execution set to false).
38______ ZZZZYYYY : 16bits If equal (po) 16bits compares if ([po+address] and not(ZZZZ))==YYYY.
If yes, codes are executed (else code execution set to false).
28_____1 ZZZZYYYY : Endif, then 16bits If equal (ba) Makes one endif, then 16bits compares if ([ba+address] and not(ZZZZ))==YYYY. If yes, codes are executed (else code execution set to false).
38_____1 ZZZZYYYY : Endif, then 16bits If equal (po) Makes one endif, then 16bits compares if ([po+address] and not(ZZZZ))==YYYY. If yes, codes are executed (else code execution set to false).
CST5 : 16bits (endif, then) If not equal
2A______ ZZZZYYYY : 16bits If not equal (ba) 16bits compares if ([ba+address] and not(ZZZZ))!=YYYY. If yes, codes are executed (else code execution set to false).
3A______ ZZZZYYYY : 16bits If not equal (po) 16bits compares if ([po+address] and not(ZZZZ))!=YYYY. If yes, codes are executed (else code execution set to false).
2A_____1 ZZZZYYYY : Endif, then 16bits If not equal (ba) Makes one endif, then 16bits compares if ([ba+address] and not(ZZZZ))!=YYYY. If yes, codes are executed (else code execution set to false).
3A_____1 ZZZZYYYY : Endif, then 16bits If not equal (po) Makes one endif, then 16bits compares if ([po+address] and not(ZZZZ))!=YYYY. If yes, codes are executed (else code execution set to false).
CST6 : 16bits (endif, then) If greater
2C______ ZZZZYYYY : 16bits If greater (ba) 16bits compares if ([ba+address] and not(ZZZZ))>YYYY. If yes, codes are executed (else code execution set to false).
3C______ ZZZZYYYY : 16bits If greater (po) 16bits compares if ([po+address] and not(ZZZZ))>YYYY. If yes, codes are executed (else code execution set to false).
2C_____1 ZZZZYYYY : Endif, then 16bits If greater (ba) Makes one endif, then 16bits compares if ([ba+address] and not(ZZZZ))>YYYY. If yes, codes are executed (else code execution set to false).
3C_____1 ZZZZYYYY : Endif, then 16bits If greater (po) Makes one endif, then 16bits compares if ([po+address] and not(ZZZZ))>YYYY. If yes, codes are executed (else code execution set to false).
CST7 : 16bits (endif, then) If lower
2E______ ZZZZYYYY : 16bits If lower (ba) 16bits compares if ([ba+address] and not(ZZZZ))<YYYY.
If yes, codes are executed (else code execution set to false).
3E______ ZZZZYYYY : 16bits If lower (po) 16bits compares if ([po+address] and not(ZZZZ))<YYYY.
If yes, codes are executed (else code execution set to false).
2E_____1 ZZZZYYYY : Endif, then 16bits If lower (ba) Makes one endif, then 16bits compares if ([ba+address] and not(ZZZZ))<YYYY. If yes, codes are executed (else code execution set to false).
3E_____1 ZZZZYYYY : Endif, then 16bits If lower (po) Makes one endif, then 16bits compares if ([po+address] and not(ZZZZ))<YYYY. If yes, codes are executed (else code execution set to false).
I've never used these and am not entirely sure how they work...
EDIT: I found that there IS "End IF" and "Else" in with the terminators
CST0 : Full Terminator
E0000000 XXXXYYYY : full terminator
It clears the code execution status.
If XXXX<>0, ba = 0xXXXX0000
If YYYY<>0, po = 0xYYYY0000
CST1 : Endif (+else)
E20000VV XXXXYYYY = endifs
Applies VV endifs.
If XXXX<>0, ba = 0xXXXX0000
If YYYY<>0, po = 0xYYYY0000
E21000VV XXXXYYYY = endifs + else
Applies VV endifs, and inverse the code execution status (="else").
If XXXX<>0, ba = 0xXXXX0000
If YYYY<>0, po = 0xYYYY0000
CST7 : End of Code
F0000000 00000000 = end of code handler It tells the code handler that there are no more codes in the code list. The code handler exits.
But I am absolutely clueless how to assemble this all together with a button activator :(
Look at the bottom of the codetypes doc, Code Type 7, Code Sub-Type 1
CST1 : Endif (+else)
E20000VV XXXXYYYY = endifs
Applies VV endifs.
If XXXX<>0, ba = 0xXXXX0000
If YYYY<>0, po = 0xYYYY0000
E21000VV XXXXYYYY = endifs + else
Applies VV endifs, and inverse the code execution status (="else").
If XXXX<>0, ba = 0xXXXX0000
If YYYY<>0, po = 0xYYYY0000
...hm, now that I look at this, I'm not sure cascading else's will work properly. Try this instead
tmp = 14;
if (val > 14) tmp = 29;
if (val > 29) tmp = 44;
if (val > 44) tmp = 45;
val = tmp;
For tmp, you can use a gecko register.
Have you considered asm, like a C2 code-type? The code might end up being shorter.
EDIT: to add a button activator, change the last line to
if (button_pressed) val = tmp;
Every frame you will calculate tmp, but you actually only move tmp into val if your button is activated
I did consider using assembly, but I have ZERO knowledge of it and don't even know where to start :p
I do have more of an understanding of conditionals and feel I should try to find some compromise using this method first...
If it's ok, would it be possible for you to post a few examples of using the 16bit if code type? E.G. Using 80123456 00000000 as the test address and checking if it's less than 15 and writing in 14. Also, perhaps using the End If + Else type?
Thank you so much for your help so far. If I can use a few examples as a base then I might be able to figure out and even test adding in button activators and possibly stacking...
80000007 0000000E # pre-load gr7 with 14
2C123456 0000000E # 16-bit if > 14
80000007 0000001D # load gr7 with 29
2C123457 0000001D # end if (note 7 instead of 6!), if > 29
80000007 0000002C # load gr7 with 44
2C123457 0000002C # end if, if > 44
80000007 0000002D # load gr7 with 45
28_____1 0000wxyz # end if, if buttons equal, ___ is address, wxyz are buttons
84100007 80123456 # 16-bit write gr7 into val if buttons were activated
E0000000 80008000 # end if
use 8420 instead of 8410 to write a 32-bit value from the gr into your memory cell. Use 24 instead of 2C for 32-bit if >. When doing 16-bit reads/writes, make sure you're reading/writing the correct half-word.
You are an absolute star, dcx2!
This is a more complete example than I expected. It's so much clearer now seeing it laid out, but there are a few things that I'm not entirely sure about...
you used the If Greater Than 2C______ ZZZZYYYY. I'm not sure if this is right for what I need, so I'll try the If Less Than 2E______ ZZZZYYYY for the example and alter it to how I HOPE it would work.
The register (gr7) is part of the actual Geckos code and not part of Wiis memory? Or is it using the Wiis memory register to store the value? It's just that I've done similar kind of things using CheatEngine and think that you need to "backup" what was previously in the register and then "restore" it after the code has completed. Does this apply to here? And/Or is this particular register safe for general usage? I.E. it's universal to every game.
I also have multiple addresses that I'd like to do this operation on, with altered values to pop into the register. Is it possible to use the single button activator to manipulate multiple addresses?
2E123456 0000000E # 16-bit if < 14
80000007 0000000E # load gr7 with 14
2E123457 0000001D # end if (note 7 instead of 6!), if < 29
80000007 0000001D # load gr7 with 29
2E123457 0000002C # end if, if < 44
80000007 0000002C # load gr7 with 44
28_____1 0000wxyz # end if, if buttons equal, ___ is address, wxyz are buttons
84100007 80123456 # 16-bit write gr7 into val if buttons were activated
2E234567 00000004 # 16-bit if < 4
80000007 00000004 # load gr7 with 4
2E234568 00000009 # end if (note 7 instead of 6!), if < 9
80000007 00000009 # load gr7 with 9
2E234568 0000000E # end if, if < 14
80000007 0000000E # load gr7 with 14
28_____1 0000wxyz # end if, if buttons equal, ___ is address, wxyz are buttons (Use the same button activator)
84100007 80234567 # 16-bit write gr7 into val if buttons were activated
E0000000 80008000 # end if
Would this example work?
Quote from: Dude on March 03, 2010, 05:44:03 PM
You are an absolute star, dcx2!
*points to "Thank You" button* ;D
Quoteyou used the If Greater Than 2C______ ZZZZYYYY. I'm not sure if this is right for what I need, so I'll try the If Less Than 2E______ ZZZZYYYY for the example and alter it to how I HOPE it would work.
If you do less than, make sure you test the largest value first. If you test the smaller values first, then your larger values will always be true.
For example, assume the value you're reading was 22. Is 22 < 14? No, turn off code execution until we hit an end if. Next, is 22 < 29? Yes, set gr7 to 29. Next, is 22 < 44? Yes, set gr7 to 44.
You would need to rearrange them. Is 22 < 44? Yes, set gr7 to 44. Is 22 < 29? Yes, set gr7 to 29. Is gr7 < 14? No.
That's why I purposely wrote mine with >'s. Is 22 > 14? Yes, set gr7 to 29. Is 22 > 29? No. Is gr7 > 44? No. Two ways to skin a cat.
QuoteThe register (gr7) is part of the actual Geckos code and not part of Wiis memory?
It's not a register in the classical sense, like r0 (or eax, if you used x86 asm). Gecko OS reserves a chunk of memory low in the 80000000 range. The Gecko Registers are just chunks of memory (80001808 is where they start, I believe).
QuoteI've done similar kind of things using CheatEngine and think that you need to "backup" what was previously in the register and then "restore" it after the code has completed.
If you were writing an asm code, then you would have to watch out for that (or use a register that doesn't have any dependencies at that point in the program). Gecko Registers are only used by Gecko OS, so you would only need to push/pop the value in a gecko register if some other code was using the same register.
QuoteI also have multiple addresses that I'd like to do this operation on, with altered values to pop into the register. Is it possible to use the single button activator to manipulate multiple addresses?
Your button activator can be multiple execution lines between it and the end if, but you'll need one gecko register for each value, unless you're writing the same value to multiple places.
EDIT:
Okay, since this gecko register is only holding a temporary value, you could re-use it. If you needed the value to be remembered between frames, you would need to use a different gecko register.
However, besides for your example testing numbers in the wrong order, your second set of if's are totally wrong. The last bit of the address CANNOT be a 1, for two reasons.
1) The last bit of an if code-type's address is used to signify an end-if.
2) You would be doing an un-aligned read. If you want to read a 16-bit half-word, your address MUST be a multiple of 2. This requirement is why the least significant bit (LSbit) can be used for an end-if.
I've clicked your applaud button and intend to click it again - I didn't have a good enough idea about how to use the IF conditionals until now ;D
Hmm, I walked into the same trap that I mentioned that I wanted to avoid in my earlier post about the logical order of the value tests lol I should consider getting some sleep soon :p
I had assumed that the registers operated in the same style as I had encountered on the PC. It was a bit of a headache jumping through hoops to manage them and that is why I avoided them until I understood the inner workings for the Wii better. I have a lot of plans for these Gecko registers now...
Ok, about the endif, it's not possible to start a new if conditional while the current one is still active? (would a terminator for this resolve it if it is?) Or it's because the example address just wouldn't work?
I'm sorry to keep bombarding you with questions :p Everything else I now understand and can figure out. It's just the ability of inserting a second set of new if statements that I'm fuzzy on. Other than this, I'm all set to go ;D
Gecko "register" is a bit of a misnomer. It's not a register in the sense of single-cycle memory inside the CPU. For that matter, "if" is a bit of a misnomer, too.
The code handler reads every code during each frame. If codes work by telling the code handler to turn off execution of codes for a little bit.
When the code handler encounters an if that resolves to true, it sets code execution status to true. Any code the code handler reads will then be executed.
When it encounters an if that resolves to false, it sets code execution status to false. Any codes that the code handler reads will NOT be executed.
End-ifs and full terminators reset code execution status to true.
So if you have a series of ifs separated by endifs, each one will always be tested every frame no matter what. No if will have any effect on any other ifs.
If you have a series of ifs that are NOT separated by endifs, then it will be much like a logical AND. If all of the ifs resolve true, then the code execution status will be true. If ANY of the ifs resolve false, code execution status will be false, and the rest of the ifs and the associated codes will be skipped, until the code handler encounters an endif or terminator.
EDIT:
Examples: if-code-endif,if-code-terminator
2E123456 0000000E # 16-bit if < 14
80000007 0000000E # load gr7 with 14
2E123457 0000001D # end if (note 7 instead of 6!), if < 29
80000007 0000001D # load gr7 with 29
E0000000 80008000 # terminator
If value < 14, then store 14 to gr7.
If value < 29, then store 29 to gr7.
if-if-code-terminator
2C123456 0000000E # 16-bit if > 14
2E123456 0000001D # (note 6! NOT AN ENDIF), if < 29
80000007 0000001D # load gr7 with 29
E0000000 80008000 # terminator
if (value > 14)
if (value < 29)
then store 29 into gr7
If value <= 14, the first if sets code execution status to false, the second if and code are not executed, and the terminator sets code execution status back to true.
If value >= 29, the second if sets code execution status to false, the code is not executed, and the terminator sets code execution status back to true.
If 14 < value < 29, both ifs will set code execution status to true, the code IS executed, and the terminator still sets code execution status to true, even though it's already true.
btw, your example two posts ago has another error. You should have two terminators, not one. Each if must always be matched with an endif or a terminator.
Ohhhhhhhhh.
I was treating it like general code from programming. It doesn't JUMP to the end of the if statement, it just tells Geckos to not execute the the following codes in the list while the execution status is set to false.
Ok. I just have to make sure I place my logic in the correct order and ensure that I use the read address correctly (Im sure I'll be able to iron out any kinks related to this now) and I'm all set ;D ;D
I really can't thank you enough! I'm gonna click your applaud button twice. I had been pondering about creating codes like this for a game I'm currently working through for a while now but then couldn't get my head around how it all came together when I decided to look into it.
Thanks again, dcx2 :D
Edit: Can't applaud you more than once in 15 hours. Thought I could do it another two times lol Whoops XD I'll be checking back to this thread for reference tomorrow when I start to throw my codes together for testing, so I'll be sure to give you your second applaud then. You more than deserve.
Quote from: Dude on March 03, 2010, 02:17:30 PMExample:
80104920 00000000
I want to first check if this value is less than 15. If it is, then set to 14.
I then want to check if it is between 15 and 30. If it is, then set to 29.
I then want to check if it is between 30 and 45. If it is, then set to 44.
All in the one button press.
This is an interessing question (and interessing answers).
The problem being to check a value against different ranges, and update that value accordingly.
There are of course many ways to achieve the effect you want.
As dc2x stated, using ifs/endifs/elseifs, along with storing the value in a gecko register (or copying it somewhere in RAM), is one way.
Another would be to code a small ASM routine (that solution could be used each time you wanna do something "complicated"). But in the end using ASM is "too easy" (once you know ASM, nothing can stop you, but you might stop understanding all the possibilities of the codes type and only rely on ASM).
So, as I liked your question, I tried to think of other ways to do it :
1) My first approach would be to mix if/endif and GOTO codes types.
Like that :
IF<45
IF<30
IF<15
write 14
goto terminator
endif
write 29
goto terminator
endif
write 44
terminator
In term of code types, it should be something like this (of course, the button check code should be added at the very start of the code) :
2E104920 0000002D
2E104920 0000001E
2E104920 0000000F
02104920 0000000E
66000005 00000000
E2000001 00000000
02104920 0000001D
66000002 00000000
E2000001 00000000
02104920 0000002C
E0000000 80008000
2) One other 'interessing' way to do it would be to load the value in the Pointer, then use the offset 'if in range' codes. This will only work for direct RAM accesses (ie. not using pointers), and for values of 16bits (or less). To achieve this we first need to load the 16bits data in a gecko register(gr7 for exemple), then left shift it so it'll be placed in the upper 16bits, put it in the Pointer, and then do the Pointer range comparison (because the range comparison only looks for the upper 16 bits, as it was meant for memory range comparison). (here again, the button check code should be added at the very start of the code) :
82100007 80104920 <- load into gr7 the 16 bits at 0x80104920
86500007 00000010 <- left shifts gr7 by 16
4A001007 00000000 <- Pointer = gr7
DE000000 0000000F <- If PO>=0 and PO<15
02104920 0000000E <- writes 14 to 0x80104920
DE000001 000F001E <- Endif, If PO>=15 and PO<30
02104920 0000001D <- writes 29 to 0x80104920
DE000001 001E002D <- Endif, If PO>=30 and PO<45
02104920 0000002C <- writes 44 to 0x80104920
E0000000 80008000 <- Terminator
As you can see, this second method needs 3 lines to load the desired value into the Pointer, but it woud create smaller codes if you do a lot of comparisons as it uses 2 lines per new comparison, instead of 4 for the other method.
Of course all of this is only theorical (untested), so forgive me if anything I said is wrong (I haven't touched my wii or wiird since a good year...).
And the point of this post is not to confuse you, but to put in the light some "advanced" (=rarely used) codes type (that can be useful sometimes).
Thanks obi-wan!
I had not considered using pointer bounds checks to make sure code is in a certain range. That's definitely a clever idea, but will only work for 16 bit values.
I had also never seen goto in action. Thank you for that, too.
QuoteBut in the end using ASM is "too easy" (once you know ASM, nothing can stop you
Quoted For Truth. I develop ASM hacks almost exclusively...I find it much easier than pointer hacks because ASM doesn't move around (not quite the whole truth...in Resident Evil 4, the code that handles guns is "paged out" so that only the code for the gun you're currently using will be loaded into memory). You can also do pretty much anything, especially once you learn to use C2 codes. I've done some really, really cool stuff with C2 codes, like preventing the player's A button from working if they would miss an enemy.
You know, I think every possibly solution at pretty much every skill level has been covered for this problem! :D
I also don't think that there are any tutorials and examples for creating codes using the "if" codetype (I know I couldn't find any). I would definatley nominate both of you guys for this, though I think the content of this thread should suffice ;D
I think I'll start with just using the "if" code type first and see if I can succeed, then try to work my way up to the ASM methods.
I agree that using ASM is the ultimate way to go since it's effectively just like writing raw code. It has almost no barriers and opens up so many amazing possiblities...I just don't know enough about it yet lol The closest I've gotten to this is using "code injection" in CheatEngine and using it's debugger to alter the way a game works. Not able to create ASM gecko codes just yet :p
But thank you both so so much. Lots more info and examples than I expected and I'm sure others are gonna benefit from it all too. both applauded!
If you need more tutorials, you could just check the Game Hacking Guides (http://wiird.l0nk.org/forum/index.php/topic,101.0.html) topic. ;)
Sorry, there is just one more things that I'm curios about.
There only seems to be an option for 32bit or 16bit "if" code types. What if I was wanting to use an 8bit value (with values occupying 8bits on either side) to read from, or even write to?
Is it possible to perform this function on an 8bit value?
Many thanks in advance ;D
There are 8-bit writes. There are no 8-bit ifs. The reason is that the least significant bit of the first code-word is used to specify end-if, and so is not available to use for resolving 8-bit addresses.
28543210 0000wxyz
Would read address 80543210 and compare equal to wxyz
28543211 0000wxyz
Would end-if, then read address 80543210 and compare equal to wxyz
---
Note how they both read the same address. That last bit can't be used for the address, so no 8-bit ifs.
...however...
Those 0's before wxyz can otherwise be used to mask off the 8 bits you don't care about. For address 80543210, I think* an 8-bit if would look like
28543210 00FFxy00
The bits set to 1 are bits we don't care about (i.e. we don't care about byte 80543211 if we want to know what byte 80543210 is)
And for address 80543211, you would use
28543210 FF0000xy
We don't care about byte 80543210, so we mask it by using 1s.
You can also use this with button activators, too. When moon jumping, for instance, you want to keep moon jumping even if the player presses other buttons like Z or C or B, so you mask off those buttons when doing your test.
* I haven't tried this so I might have the FF's backwards
once again, THANK YOU :D
I was hoping that there would be a method to it but I just couldn't figure it out lol
I'll test this to see what order the bit mask needs to be and to test if this would work for my needs :) I'll report back what order the bit mask needs to be.
EDIT: Ok, I've checked.
For an 8bit "if equal" at address 80543211 it should be 28543211 FF00wxyz.
I have built a "multi-if" code using 8bit "if" and it works. Example using a 16bit to check an 8bit value:
28XXXXX 00008008 IF Home + DPad-UP buttons pressed THEN
28543212 FF000001 IF 8bit value at 80543211 = 01 (note 2 instead of 1) THEN
00AABBCC 0000000A 8bit write to address 80AABBCC with value of 10
28543211 FF000002 IF 8bit value at 80543211 = 02 (note 1) THEN
00AABBCC 00000014 8bit write to address 80AABBCC with value of 20
28543211 FF000003 IF 8bit value at 80543211 = 03 (note 1) THEN
00AABBCC 0000001E 8bit write to address 80AABBCC with value of 30
E0000000 80008000 Terminator
I have found that all "if" statements after the initial "endif" don't require the last significant bit increased for the logic to work. It will write all correct values based on the "if" comparison without just writing the final value.
Thanks again to everyone that has helped me (and everyone else that checks how these IF code-types work) ;D
Quote28543211 FF00wxyz
That is an end-if;if on address 80543210, actually.
28543210 FF0000yz # if 80543211 is yz
We are not
adding one to the address. Remember, 16-bit if must always be hword-aligned, so any address we use the if on must be a multiple of 2, and so we can never if on an odd address directly. We are
setting the least significant bit - when the address *looks* odd, it's actually an end-if on the even address.
28XXXXX 00008008 IF Home + DPad-UP buttons pressed THEN
2854321
0 FF000001 IF 8bit value at 80543211 = 01 (note 0 instead of 1 - this is
not an end-if) THEN
00AABBCC 0000000A 8bit write to address 80AABBCC with value of 10
2854321
1 FF000002 END-IF; IF 8bit value at 80543211 = 02 (note 1 - this is an end-if) THEN
00AABBCC 00000014 8bit write to address 80AABBCC with value of 20
2854321
1 FF000003 IF 8bit value at 80543211 = 03 (note 1 - this is an end-if) THEN
00AABBCC 0000001E 8bit write to address 80AABBCC with value of 30
E0000000 80008000 Terminator (this ends
two ifs; the first line, and the sixth line)
This is just odd ???
I'm not sure if it's just the addresses that I'm using but it doesn't seem to be working in the way that it's supposed to be, based on the ways that have been mentioned.
I used this as an example:
28XXXXX 00008008 IF Home + DPad-UP buttons pressed THEN
28543212 FF000001 IF 8bit value at 80543211 = 01 (note 2 instead of 1) THEN
00AABBCC 0000000A 8bit write to address 80AABBCC with value of 10
28543211 FF000002 IF 8bit value at 80543211 = 02 (note 1) THEN
00AABBCC 00000014 8bit write to address 80AABBCC with value of 20
28543211 FF000003 IF 8bit value at 80543211 = 03 (note 1) THEN
00AABBCC 0000001E 8bit write to address 80AABBCC with value of 30
E0000000 80008000 Terminator
Because this code is identical to how I did it, only with example addresses...
The ifs and endifs are in all the same places. It have confirmed that it works in THIS way, but not the if, endif, endif way.
Also, I tried to make another code this way but with the IF addresses on the next byte, one address up, and NOTHING is getting it to work. It will do the first write after the if, but none of the rest.
I am using Geckos v1.9.3, a USB Gecko and the final codes tested independent of each other :'(
I've tried turning ifs into endifs, etc, etc, etc but it just won't work how it SHOULD work. could it be the addresses I am using?
You're going to need to copy and paste your code and the appropriate addresses.
This is the code that works perfectly:
2817D6E0 00008008 Check if Home + DPad-UP is pressed
28907B72 FF000003 Check if value is 3 (endif)
00908923 0000000A Write 10
28907B71 FF000006 Check if value is 6 (not endif)
00908923 00000014 Write 20
28907B71 FF000009 Check if value is 9 (not endif)
00908923 0000001E Write 30
E0000000 80008000 Terminator
It writes all the correct values to address 80908923 based on the value at address 80907B71.
This is the code that just refuses to work as it should (note, the read address is just 1 byte away and the write address is just 4 bytes from the code above):
2817D6E0 00008008 Check if Home and DPad-UP is pressed
28907B72 FF000002 Check if value is 2 (Not endif)
00908927 00000018 Write 24
28907B73 FF000004 Check if value is 4 (endif)
00908927 00000031 Write 49
28907B73 FF000006 Check if value is 6 (endif)
00908927 00000063 Write 99
E0000000 80008000 Terminator
I've tried turning ifs to endifs, without button activator, etc, but at best all that it does is the first write ???
I have tested both codes independently so that they don't interfere. I did the top code first and tested that it works perfectly. I altered the read address to test and it always wrote the correct values. But it doesn't work if the if/endifs are the same as the bottom code (if, if, endif, endif, terminator) I then copied it and modified it to the new addresses, editing the read address again during testing, but it doesn't work correctly.
Quote from: Dude on March 08, 2010, 08:33:11 PM
This is the code that works perfectly:
2817D6E0 00008008 Check if Home + DPad-UP is pressed
28907B72 FF000003 Check if value is 3 (endif)
00908923 0000000A Write 10
28907B71 FF000006 Check if value is 6 (not endif)
00908923 00000014 Write 20
28907B71 FF000009 Check if value is 9 (not endif)
00908923 0000001E Write 30
E0000000 80008000 Terminator
It writes all the correct values to address 80908923 based on the value at address 80907B71.
This is the code that just refuses to work as it should (note, the read address is just 1 byte away and the write address is just 4 bytes from the code above):
2817D6E0 00008008 Check if Home and DPad-UP is pressed
28907B72 FF000002 Check if value is 2 (Not endif)
00908927 00000018 Write 24
28907B73 FF000004 Check if value is 4 (endif)
00908927 00000031 Write 49
28907B73 FF000006 Check if value is 6 (endif)
00908927 00000063 Write 99
E0000000 80008000 Terminator
I've tried turning ifs to endifs, without button activator, etc, but at best all that it does is the first write ???
I have tested both codes independently so that they don't interfere. I did the top code first and tested that it works perfectly. I altered the read address to test and it always wrote the correct values. But it doesn't work if the if/endifs are the same as the bottom code (if, if, endif, endif, terminator) I then copied it and modified it to the new addresses, editing the read address again during testing, but it doesn't work correctly.
Um.. without criticising you: both codes have the same endif/if structure just the addresses differ. Let me point out:
2817D6E0 00008008 Perform a 16 bit comparison on 8017D6E0 - read the value - and AND it with FFFF ( FFFF = NOT 0000 ) and check whether the result of that logic calculation is 8008
28907B72 FF000003 Perform a 16 bit comparison on 80907B72 - read the value - and AND it with 00FF ( 00FF = NOT FF00 ) (basically make the first byte 00) ands check whether the result if 0003
28907B71 FF000006 Endif first - then perform a 16 bit comparison on 80907B70 - read the value - and AND it with 00FF ( 00FF = NOT FF00 ) (basically make the first byte 00) ands check whether the result if 0003
28907B71 FF000009 Endif first - then perform a 16 bit comparison on 80907B70 - read the value - and AND it with 00FF ( 00FF = NOT FF00 ) (basically make the first byte 00) ands check whether the result if 0003
Um.. so you say it would write everything correctly based on the value at address 80907B71 - hm.. hard to beleve.. you only check 80907B71 in the second and third line.. the first line should be 28907B70
You're not getting your alignment correctly. Remember, these are 16-bit ifs, and we need to mask the upper or lower byte off.
28907B72 FF000003 Check if 80907B73 is 3 (not endif)
28907B72 00FF0300 Check if 80907B72 is 3 (not endif)
28907B71 FF000006 Check if 80907B71 is 6 (endif)
28907B71 00FF0600 Check if 80907B70 is 6 (endif)
I'm surprised your first code would ever write 10. I believe these are the codes you actually want.
2817D6E0 00008008 Check if Home + DPad-UP is pressed
28907B70 FF000003 Check if 80907B71 is 3 (not endif)
00908923 0000000A Write 10
28907B71 FF000006 Check if 80907B71 is 6 (endif)
00908923 00000014 Write 20
28907B71 FF000009 Check if 80907B71 is 9 (endif)
00908923 0000001E Write 30
E0000000 80008000 Terminator
2817D6E0 00008008 Check if Home and DPad-UP is pressed
28907B72 00FF0200 Check if 80907B72 is 2 (Not endif)
00908927 00000018 Write 24
28907B73 00FF0400 Check if 80907B72 is 4 (endif)
00908927 00000031 Write 49
28907B73 00FF0600 Check if 80907B72 is 6 (endif)
00908927 00000063 Write 99
E0000000 80008000 Terminator
I welcome all criticism. As long as it's relevant to the topic, constructive and/or funny, then it's cool lol :p No worries.
@Link:
that is exactly why I'm confused...
The top code, as it is, works without a problem :confused: I tested it using various values, poking the read address with each target value to make sure that it reads and executes correctly...and it DOES. It's reading from address 80907B71 and only has one endif (on the second line) and the terminator at the end. It wouldn't work initially when I used the If, endif, endif, terminator format so I played around with the logic and found that this is what worked - if, endif, if, if, terminator.
I swear I'm not making this up and honestly cannot understand how or why this works, since it seems to go against the logic :( Typical that I end up with an illogical code that actually works.
@dcx2:
I didn't think to check the alignment :p I literally just copied the first code but modified the addresses. I'll check with moving the mask and see how it goes. I'm a little concerned with the fact that the first code works when I feel sure (and had it confirmed by two other people) that it shouldn't...
If I get the second code to work and have double-checked the first one that it also works then I will copy and paste them directly from the codes tab in Wiird - it's possible that I posted the "scratch" version that I made by accident. I'm pretty tired and still learning :( *fingers crossed*
It is within the realm of possibility that the adjacent byte that you were reading just happens to be the right values at the right time. These sorts of strange blue-moon phenomenon are quite common with technology, believe it or not.
If you know how to use breakpoints, you could set a breakpoint on your code or one of the destination addresses. It will pause the game (hopefully when the code handler is running your code) and then you can step through line-by-line and see what addresses it's reading and writing to and what codes it is executing or not executing.
With exact checked, set a Write breakpoint on the address 80908923 or a Read breakpoint on the address 80907B70. When you hit "Set Breakpoint", your game should pause instantly. If you're staring at an instruction very low in memory (around 0x80001xxx), you're in the code handler, and if you aren't just keep hitting Set Breakpoint until you get there. r3 and r4 should have the current line of the code being executed.
You can also use Memory Viewer to find your code and break when the code handler reads it, which is probably the most reliable since 1) only the code handler is reading the portion of memory where your code is, and 2) codes aren't always reading or writing to game memory if execution status is off.
To find your code in Memory Viewer, search for a unique-ish line of your code that will hopefully not be in many places in the game, like 2817D6E0 (C2 codes are usually pretty good too!). Start searching from 80000000, result should be 80001xxxish, very low in memory again. Right-click it -> breakpoint, change it to "Read", then Step away!
Hm...maybe I should do a tutorial on stepping through the code handler and watching it process your codes.
Ok, I've really been looking at this...
Your modifications of the second code, dcx2, worked when everything I tried had failed (my attempt would only work up to a certain point).
I read the documentation closer to make sure I was understanding it correctly. I understand the logic of how my code should go and the logic of how the code-type works...
I tried my first code again and found that it DID still work, so I checked in memory viewer to see what the adjacent values were. All 8bit values in this memory area are similar. I set ALL values, 2bytes on either side, to ZERO except for the address I wanted to read (28907B71). I tried the code again and it still worked...
Also, I re-read through this thread to make sure I wasn't missing something before continuing with testing and found dcx2 saying:
QuoteThe last bit of the address CANNOT be a 1, for two reasons.
1) The last bit of an if code-type's address is used to signify an end-if.
2) You would be doing an un-aligned read. If you want to read a 16-bit half-word, your address MUST be a multiple of 2. This requirement is why the least significant bit (LSbit) can be used for an end-if.
For my first code the address I WANTED to read as an 8bit IF was 80907B71. My first 8bit IF was 28907B72 FF000003. The one dcx2 posted had 28907B70 FF000003. I had all adjacent memory addresses set to ZERO and my version of the code STILL worked. Was it because the address 80907B71 wasn't aligned and increasing (instead of decreasing) the last bit fixed this? This would explain why I was getting so confused and messing up my second attempt using different addresses...
EDIT:
It must be the alignment. Here are some examples of codes that I have just created. They are all based from codes that I just made. the codes work as expected...so these should be correct :p
When reading an 8bit value at address 80907B71
28907B70 FF000001 if = 01
00123456 000000xy 8bit write xy to address 80123456
28907B71 FF000002 endif = 02
00123456 000000xy 8bit write xy to address 80123456
28907B71 FF000003 endif = 03
00123456 000000xy 8bit write xy to address 80123456
E0000000 80008000 terminator
When reading an 8bit value at address 80907B72
28907B72 00FF0100 if = 01
00123456 000000xy 8bit write xy to address 80123456
28907B73 00FF0200 endif = 02
00123456 000000xy 8bit write xy to address 80123456
28907B73 00FF0300 endif = 03
00123456 000000xy 8bit write xy to address 80123456
E0000000 80008000 terminator
When reading an 8bit value at address 80907B73
28907B72 FF000001 if = 01
00123456 000000xy 8bit write xy to address 80123456
28907B73 FF000002 endif = 02
00123456 000000xy 8bit write xy to address 80123456
28907B73 FF000003 endif = 03
00123456 000000xy 8bit write xy to address 80123456
E0000000 80008000 terminator
When reading an 8bit value at address 80907B74
28907B74 00FF0100 if = 01
00123456 000000xy 8bit write xy to address 80123456
28907B75 00FF0200 endif = 02
00123456 000000xy 8bit write xy to address 80123456
28907B75 00FF0300 endif = 03
00123456 000000xy 8bit write xy to address 80123456
E0000000 80008000 terminator
Congrats! Your edit looks good to me. You got the alignment correct, you got the end-ifs correct, and you got the read addresses correct. (Alignment's a bitch, huh?)
I really don't understand how
28907B72 FF000003
worked for you. It was reading 80907B73 and comparing it to 3.
When did you look in Memory Viewer? There's a chance that when you paused the game, the values in Memory Viewer were changing. You also said you set the values to 0, but when the code handler was reading your code, the game might have fixed your pokes.
If you were using that code, you could set an Exact Read Breakpoint on 80907B73 and it would probably pause in the code handler while it is executing your code (you might have to set the breakpoint a few times, because there's probably more people than just the code handler reading it). That would be the best time to cruise the Memory Viewer.
Other than that...good job!
Thanks ;D
I gotta agree, alignments are are right up there with the dentist. But I've found that it's just the same as finding the alignment for a binary digit in CheatEngine. Once I understood and got the ruling for it nailed down it is actually pretty simple :p
I can't understand why it worked either. I had the memory viewer auto-refreshing to see if anything was modifying the address it should, in theory, have been pointing to and that nothing was modifying the address that the code said it SHOULD be reading from... Every address near the byte was set to zero and there was nothing altering them. I poked the address with the values needed to trigger the code with and it worked every time (I had a progress bar and decimal value in the game to confirm it worked).
I also tried the "correct" code and it gave the exact same results. I also haven't tried investigating using breakpoints. I've used them on many an occasion before but never with any depth. That breakpoint tutorial you mentioned earlier would be fantastic though :D
I might just go ahead and investigate this later :) Many, many thanks to all that helped!