How would someone write the assembly to toggle through the written values, each time the same button is pressed?
Like this WiiRd codestype code:
[spoiler]Super Wetter Modifier (Change Weather with Z Button) [Bully@Wiiplaza]
043B4530 38000005
285356D2 DFFF2000 -> BA
C23BFB40 00000003
3D800000 618C0000
91830180 80030180
60000000 00000000
02478554 00000000
02478630 00000000
CC000000 00000000 -> Switch
C23BFB40 00000003
3D800000 618C0002
91830180 80030180
60000000 00000000
02478554 00000002
02478630 00000002
CC000000 00000000 -> Switch
C23BFB40 00000003
3D800000 618C0004
91830180 80030180
60000000 00000000
02478554 00000004
02478630 00000004
CC000000 00000000 -> Switch
C23BFB40 00000003
3D800000 618C0010
91830180 80030180
60000000 00000000
02478554 0000000A
02478630 0000000A
CC000000 00000000 -> Switch
C23BFB40 00000003
3D800000 618C0040
91830180 80030180
60000000 00000000
02478554 00000028
02478630 00000028
CC000000 00000000 -> Switch
C23BFB40 00000003
3D800000 618C5000
91830180 80030180
60000000 00000000
02478554 00001388
02478630 00001388
CC000000 00000000 -> Switch
C23BFB40 00000003
3D800000 618C8000
91830180 80030180
60000000 00000000
02478554 00001F40
02478630 00001F40
CC000000 00000000 -> Switch
C23BFB40 00000003
3D800005 618C0000
91830180 80030180
60000000 00000000
02478554 0000C350
02478630 0000C350
E0000000 80008000[/spoiler]
Default assembly code:
[spoiler]Transformation V.6 [Thomas83Lin]
C2140F58 00000013
899F0007 2C0C0000
41820020 2C0C0001
4182002C 2C0C0002
41820038 2C0C0003
41820044 4082006C
3D80803A A18C1ACE
2C0C1000 41820040
40820058 3D80803A
A18C2046 2C0C1000
4182002C 40820044
3D80803A A18C25BE
2C0C1000 41820018
40820030 3D80803A
A18C2B36 2C0C1000
40820020 39800000
7D8C0214 398C0001
2C0C0006 40810008
39800000 919F14E0
808314E0 00000000
lbz r12,7(r31)
cmpwi r12,0
beq- 0x0020
cmpwi r12,1
beq- 0x0020
cmpwi r12,2
beq- 0x0020
cmpwi r12,3
beq- 0x0020
bne- 0x0020
lis r12,-32710
lhz r12,6862(r12)
cmpwi r12,4096
beq- 0x0020
bne- 0x0020
lis r12,-32710
lhz r12,8262(r12)
cmpwi r12,4096
beq- 0x0020
bne- 0x0020
lis r12,-32710
lhz r12,9662(r12)
cmpwi r12,4096
beq- 0x0020
bne- 0x0020
lis r12,-32710
lhz r12,11062(r12)
cmpwi r12,4096
bne- 0x0020
li r12,0
add r12,r12,r0
addi r12,r12,1
cmpwi r12,6
ble- 0x0020
li r12,0
stw r12,5344(r31)
lwz r4,5344(r3)[/spoiler]
I´ll provide a random example for which it should be made:
lis r12, 0x803f
ori r12, r12, 0x12e2
lhz r12, 0 (r12) # load button value into r12
cmpwi r12, 0x8000 # if home is pressed...
bne- _END
li r0, 0xYY # load value into r0
... # how do I toggle the li according to how many times my cmpwi was true, like the CC codestype? (= button pressed)
_END:
stw r0, 0 (r3) # store it
thx!
Thomas83lin's code didn't disassemble right. The branches are all wrong. Which app did you use to generate that?
---
I think you mean "how do you make a roller". The feature of the CC code that you want is that it only does something once each time the combination is pressed, instead of doing it for the duration of the combination being held down.
Assuming 805356D2 is your button activator address, then 805356D6 probably holds a "delta activator". delta is a science term for "changed". You can use that for a button activator that only happens once per button press. It's usually used to "roll" something from one value to the next.
Quote from: dcx2 on June 19, 2011, 06:59:50 PM
Thomas83lin's code didn't disassemble right. The branches are all wrong. Which app did you use to generate that?
I used PyiiASMH.
ASMWiiRd is probably not that error prone.
Yet I also noticed that PyiiASMH calculated some braches wrong, so that my game froze.... (while ASMWiiRd did it right with the offsets) :rolleyes:
Quote from: dcx2 on June 19, 2011, 06:59:50 PM
I think you mean "how do you make a roller".
Yes, that´s what I mean.
Quote from: dcx2 on June 19, 2011, 06:59:50 PM
You can use that for a button activator that only happens once per button press.
Which address do I need to pick, if I search for the button values to get the "one shot" button activator (if I calculate +4 then)?
There are always like 20 results left that act like this. Finding one legit button activator is an ease for me, however...
Pick the first address, go to Memory Viewer, hit Pause, then hold a button in, then press Next Frame a couple times. You should see the delta activator appear for one frame. If you don't see it, try the next address.
Quote from: dcx2 on June 19, 2011, 08:35:27 PM
Pick the first address, go to Memory Viewer, hit Pause, then hold a button in, then press Next Frame a couple times. You should see the delta activator appear for one frame. If you don't see it, try the next address.
thx, and how would you build a roller then? :-[
Default code:
[spoiler]
Party Roller [dcx2]
C205C88C 0000000C
3D80804D 618C755A
A14C0004 714A000C
41820048 A1431B62
2C0A000B 4181003C
A18C0000 2C0C2008
40820010 2C0A000B
40800008 394A0001
2C0C2004 40820010
2C0A0001 40810008
394AFFFF B1431B62
394AFFFF B1431B60
A0631B62 00000000
Hold Z. Press down and up to change the character (non-monsters only).[/spoiler]
It seems like you´re adding/subing a value if the button is pressed...
Very cool rollers you made, I couldn´t even find a simple one that only uses one button to roll :o
Just one button to roll is bad. You could roll accidentally.
First, pick a good hook. There are usually a lot of read breakpoints; pick one that looks like it only executes at a specific place in the game, usually which can provide feedback. For instance, the Party Roller hooks a read which only executes during the Status menu. When you roll the value, you see the character change immediately to another party member. But if you aren't in the Status menu, the hook won't work, so you can't accidentally change who you are.
The next step is to pick a good "roll enable" button. Some button that doesn't do anything in the area of interest. At the Status menu, the Z button does nothing, so there is no reason for you to press it normally. It acts as another level of protection against accidentally activating the roller. Holding this button down enables the roller, so this step checks the "regular" button address.
The next step is to pick increment and/or decrement buttons. This does the act of rolling. These will check the delta activators and make sure that we inc or dec only once.
Then, you must protect against roll-over and roll-under. Usually if you roll too far the game will crash. A good idea to do for roll-over is to jump to the first value, and for roll-under jump to the last value. This way it wraps around.
Finally, if there are a lot of values to roll through, it helps to make "scrollers". These are "regular" button activators so that it keeps rolling while the button is held down. You can use the scroll to get close to the value you want quickly, and then roll the rest of the way with the one-shot delta activators.
---
A good example is the Skit Roller, which does all of these things. In this game, Skits were short cut-scenes. There were 304 of them. The hook I chose was 8006F5B4: 836373A8 lwz r27,29608(r3) and it would check for skits on the world map (so it wouldn't activate during a battle, or on the menu, etc). The skit number was put into r27. The min value was -1, which meant "no skit", and the last skit was 303. The enable button was Z, which made you stand still on the world map. This was convenient, because otherwise the arrow keys would cause you to move, heh. Left or right would roll one value, up or down would scroll. Everything within the spoiler can be copied and pasted into PyiiASMH or ASMWiiRD (you may have to resize the window with ASMWiiRD for it to work)
[spoiler]
.set BTN_ADDR,0x804D755A
.set BTN_Z,0x2000
.set BTN_UP,0x0008
.set BTN_DOWN,0x0004
.set BTN_RIGHT,0x0002
.set BTN_LEFT,0x0001
.set BTN_ENABLE,BTN_Z
lwz r27,29608(r3) # original instruction
lis r12,BTN_ADDR@h
ori r12,r12,BTN_ADDR@l
lhz r9,0(r12) # get buttons
lhz r10,4(r12) # get button deltas hword
andi. r0,r9,BTN_DOWN|BTN_UP # if up or down held, skip the delta check
bne- _DO_CODE
andi. r0,r10,BTN_LEFT|BTN_RIGHT
beq- _END
_DO_CODE:
cmpwi r9,BTN_ENABLE|BTN_UP # if z up
beq- _ROLL_INC
cmpwi r9,BTN_ENABLE|BTN_RIGHT # or z right, inc skit
bne- _TEST_ROLL_DEC
_ROLL_INC:
addi r27,r27,1
_TEST_ROLL_DEC:
cmpwi r9,BTN_ENABLE|BTN_DOWN # if z down
beq- _ROLL_DEC
cmpwi r9,BTN_ENABLE|BTN_LEFT # or z left, dec skit
bne- _WRAP_TEST
_ROLL_DEC:
subi r27,r27,1
_WRAP_TEST:
cmpwi r27,303 # 303 is the last skit
ble- 0f
li r27,-1
0:
cmpwi r27,-1 # -1 is no skit
bge- 0f
li r27,303
0:
_END:
stw r27,29608(r3) # update skit value
[/spoiler]
Normal Button Activator: 803A1AC8
One Shot Button Activator: 803A1ACC
Best Hook: 80140F58 lwz r4,5344(r3)
Button for the roller: Minus (Value 1000)
Possible distance: 00 - 06 (other values freeze the game)
Function:
[spoiler]80140F40: 9421FFF0 stwu r1,-16(r1)
80140F44: 7C0802A6 mflr r0
80140F48: 90010014 stw r0,20(r1)
80140F4C: 93E1000C stw r31,12(r1)
80140F50: 7C7F1B78 mr r31,r3
80140F54: 80031090 lwz r0,4240(r3)
80140F58: 808314E0 lwz r4,5344(r3)
80140F5C: 7C002000 cmpw r0,r4
80140F60: 4082000C bne- 0x80140f6c
80140F64: 38600000 li r3,0
80140F68: 4800006C b 0x80140fd4
80140F6C: 81830060 lwz r12,96(r3)
80140F70: 38A00000 li r5,0
80140F74: 818C00E4 lwz r12,228(r12)
80140F78: 7D8903A6 mtctr r12
80140F7C: 4E800421 bctrl
80140F80: 7FE3FB78 mr r3,r31
80140F84: 4BF0D0CD bl 0x8004e050
80140F88: 887F038D lbz r3,909(r31)
80140F8C: 7C630774 extsb r3,r3
80140F90: 4BF29841 bl 0x8006a7d0
80140F94: 7FE3FB78 mr r3,r31
80140F98: 38800001 li r4,1
80140F9C: 480004C5 bl 0x80141460
80140FA0: 801F1090 lwz r0,4240(r31)
80140FA4: 2C000003 cmpwi r0,3
80140FA8: 40820024 bne- 0x80140fcc
80140FAC: 7FE3FB78 mr r3,r31
80140FB0: 4BFE64C1 bl 0x80127470
80140FB4: C01F00EC lfs f0,236(r31)
80140FB8: FC000840 fcmpo cr0,f0,f1
80140FBC: 40810008 ble- 0x80140fc4
80140FC0: D03F00EC stfs f1,236(r31)
80140FC4: 7FE3FB78 mr r3,r31
80140FC8: 4BFED5D9 bl 0x8012e5a0
80140FCC: 7FE3FB78 mr r3,r31
80140FD0: 4BF0D071 bl 0x8004e040
80140FD4: 80010014 lwz r0,20(r1)
80140FD8: 83E1000C lwz r31,12(r1)
80140FDC: 7C0803A6 mtlr r0
80140FE0: 38210010 addi r1,r1,16
80140FE4: 4E800020 blr
[/spoiler]
Disassembly:
[spoiler] CR:88000488 XER:00000000 CTR:80140F40 DSIS:00400000
DAR:8154CCE4 SRR0:80140F58 SRR1:0000B032 LR:80141528
r0:00000000 r1:8043FAB8 r2:80433080 r3:8154B804
r4:80325248 r5:00000001 r6:00000000 r7:00000003
r8:00000000 r9:40C00000 r10:41F80000 r11:FFFFFFFF
r12:80140F40 r13:8042F680 r14:00000000 r15:00000000
r16:00000000 r17:00000000 r18:00000000 r19:00000000
r20:00000000 r21:00000000 r22:00000000 r23:00000000
r24:00000000 r25:00000000 r26:00000000 r27:00000000
r28:8154B804 r29:8043FB88 r30:8043FB70 r31:8154B804[/spoiler]
It should roll from 01 to 06 continuing with 01 again if 06 was reached. I still need some help there... :(
If you want help, ask specific questions. if you don't know what to ask, re-read the previous post. Try to make something - anything at all - and then when you don't know what something means, or why one instruction was chosen instead of another, ask that question. I'm not going to write the code for you.
is it something like mdmwii's stalking hack?
Quote from: Deathwolf on June 21, 2011, 06:30:23 PM
is it something like mdmwii's stalking hack?
it should change character suit.
Quote from: dcx2 on June 21, 2011, 01:27:04 AM
If you want help, ask specific questions.
good, I´ll provide my attempts but don´t think that they will be fine.
Hook: 80140F58
[spoiler]
lwz r4,5344(r3) # load value of interest into r4
lis r12, 0x803A
ori r12, r12, 0x1ACC # load one shot BA
lhz r12, 0 (r12) # load value into r12
andi. r12, r12, 0x1000 # do we press minus?
beq- _NOTPRESSED # if we don´t press minus, branch (I´m not quite sure why you need to use beq- with an andi.)
addi r4, r4, 1 # add 1 to the value
stw r4,5344(r3) # update new value
_NOTPRESSED:
lwz r4,5344(r3) # original instruction
[/spoiler]
Question:
How do I roll the value from 01 to 06, continuing at 01 again, when it reached 06? (to avoid crashes + to only use one button)
Possibly like this?
[spoiler]
lwz r4,5344(r3) # load value of interest into r4
lis r12, 0x803A
ori r12, r12, 0x1ACC # load one shot BA
lhz r12, 0 (r12) # load value into r12
andi. r12, r12, 0x1000 # do we press minus?
beq- _NOTPRESSED # if we don´t press minus, branch (I´m not quite sure why you need to use beq- with an andi.)
addi r4, r4, 1 # add 1 to the value
cmpwi r4, 0x7 # did we reach 7?
bne- _NORESET # branch, if value is not 7
li r4, 0x1 # back to 01
_NORESET:
stw r4,5344(r3) # update new value
_NOTPRESSED:
lwz r4,5344(r3) # original instruction[/spoiler]
That's a good start. Here's a tip - do you see all the extra blank lines in my ASM template above? They are there to help "group" instructions together. They are like paragraphs. Imagine reading a book which had no paragraphs - it would be terribly hard to read!
---
lis r12, 0x803A
ori r12, r12, 0x1ACC # load one shot BA
lhz r12, 0 (r12) # load value into r12
lhz = Load Half-word and Zero. You'll load the half-word at address 803A1ACC. This will probably be zero. I think you want 803A1ACE instead.
---
andi. r12, r12, 0x1000 # do we press minus?
beq- _NOTPRESSED # if we don´t press minus, branch (I´m not quite sure why you need to use beq- with an andi.)
Recall that the . at the end of an instruction means you get a free cmpwi rD, 0. In this case, if we andi. the button we want and it is NOT pressed, the result will be 0, which is equal to 0 so the branch will be taken. If we andi. with minus and IT IS pressed, the result will be 0x1000, which is not equal to 0, so the branch is not taken.
---
cmpwi r4, 0x6 # did we reach 6?
bgt- _END # if greater than 6, branch ("avoid crash")
You shouldn't just branch to the end (although it seems like you figured this out already, good job). Instead, you need to roll-over. This is the "_WRAP_TEST:" in my code above, it helps you "wrap around" to 1 again. Instead, you should do this.
cmpwi r4,6
ble- 0f
li r4,1
0:
would it look like this then?
lwz r4,5344(r3)
lis r12, 0x803A
ori r12, r12, 0x1ACE
lhz r12, 0 (r12)
andi. r12, r12, 0x1000
beq- _NOTPRESSED
addi r4, r4, 1
cmpwi r4,6
ble- 0f
li r4,1
0:
stw r4,5344(r3)
_NOTPRESSED:
C2140F58 00000007
808314E0 3D80803A
618C1ACE A18C0000
718C1000 41820018
38840001 2C040006
40810008 38800001
908314E0 808314E0
60000000 00000000
Thanks for your help :smileyface:
You forgot to lwz r4 at the beginning.
You also forgot the addi r4, r4, 1 in the middle.
I highly suggest having an "enable button" in your final code. If someone has to press minus for any reason when your hook is executed, it will accidentally roll.
Quote from: dcx2 on June 22, 2011, 03:50:15 PM
You forgot to lwz r4 at the beginning.
You also forgot the addi r4, r4, 1 in the middle.
I highly suggest having an "enable button" in your final code. If someone has to press minus for any reason when your hook is executed, it will accidentally roll.
it´s not needed for this code since the player does never need the minus button.
If it was pressed accidentally, one can reverse it with a few more presses.
Thanks for the tip, though.
You can't say you know that for sure. What if someone else wants to use - as part of a button activator? It will conflict with your code.
After reviewing your edit, I have two questions for you.
1) Why is the lwz r4 at the end unnecessary?
2) What is the meaning of 0: and 0f?
Once you confirm the code works, I'll help you optimize it. This code could be two lines shorter than it is now.
EDIT:
btw can you change your first post title to "how to make a roller in ASM?" instead?
Quote from: dcx2 on June 22, 2011, 04:53:04 PM
1) Why is the lwz r4 at the end unnecessary?
2) What is the meaning of 0: and 0f?
btw can you change your first post title to "how to make a roller in ASM?" instead?
1) Because we already have the value from r3 + 5344 in r4 due to the lwz at the beginning
2) ble- 0f = if less or equal branch to 0: (0f = false condition)
0: = true condition
3.) I edited the title to "How to make a roller in ASM?"
4.) I tried the code and it worked fine!
1) Yes, r4 has the value in it from the beginning. If the activator is false, it still has that value in it. If the activator is true, it gets rolled, and the rolled value is still in the right register, so there's still no need to lwz again.
2) No, 0f means "branch to the label 0 that is forward". 0b would mean "branch to the label 0 that is backward"
A label represented by a single digit, 0-9, can be re-used multiple times. It is nice if you don't want to keep coming up with label names for simple branches. Review the ASM roller source that I posted earlier and you'll see 0: is used twice.
EDIT: optimized.
lwz r4,5344(r3) # original instruction
lis r12, 0x803A # load r12 with half of button activator address
lhz r12, 0x1ACE(r12) # load r12 with the delta buttons
andi. r12, r12, 0x1000 # was - pressed?
beq- _NOTPRESSED # if not, skip roll
subic. r4, r4, 1 # dec and compare against 0
bgt- 0f # if greater than 0, skip wrap
li r4,6 # wrap around to 6
0:
stw r4,5344(r3) # store rolled value
_NOTPRESSED:
perfectly done, man. I guess I understood how to do it now.
Also created a level roller. :)
http://www.geckocodes.org/?c=SMNE01