Coding Questions and other Quandaries
Nice code. It appears you should be able to actually combine the 2nd, 3rd, and 4th sources into one C0. Also don't forget about that sign-extension trick I mentioned before about working with offsets greater than 0x7FFF for stores and loads.

Here's a rough draft of those 3 sources combined into one.

#Load Controller Halfword Input Value
lis r12, 0x8033
lhz r11, 0xFFFFFF1A (r12)

#Check if Z and + are at least pressed, if so, reset Weapon Value to 0
andi. r0, r11, 0x2010

#Setup EVA before branch
lis r10, 0x8000

#Preset weapon value to 0 if branch gets taken
li r9, 0

#Skip over Minus check if Z+ was pressed
beq- update_weapon_value

#Check if Minus button was at least pressed.
#We need to custom status check for this button as we don't want to weapon value to increase while we hold the button down, only when we press it.
andi. r0, r11, 0x0010
beq- button_has_been_pressed

#Minus button not Pressed, Reset Button Status
li r0, 0
stb r0, 0x3FF (r10)
b check_c_button

#Minus button Pressed, Adjust Button Status
#If Status is already 1, then button is being held down. If held down, skip the weapon incrementation
lbz r0, 0x3FF (r10)
cmpwi r0, 1
beq- check_c_button

#Minus button newly pressed. Update button status
li r0, 1
stb r0, 0x3FF (r10)

#Increment weapon value
lbz r9, 0x03FE (r10)
addi r9, r9, 1

#Check if it exceeded max weapon value allowed. Allowed range of 1 thru 33 only.
cmplwi r9, 34
blt+ update_weapon_value

#Exceeded 33. Reset weapon value to 1
li r9, 1

#Update weapon
stb r9, 0x03FE (r10)

#Weapon is fully updated, lets now check if C button was pressed to use said new weapon
andi. r0, r11, 0x0040
beqlr+ #Not pressed, end C0

#Activate weapon! Weapon is in r9
#Setup addresses
lis r12, 0x8033
lis r11, 0x8035
lis r10, 0x917E
lis r5, 0x92BE

#Do all the memory writes
stb r9, 0x7F30 (r12)
stb r9, 0x7EF0 (r12)
stb r9, 0xFFFFD8E1 (r11)
stb r9, 0xFFFFEBD3 (r10)
stb r9, 0xFFFFEBD3 (r5)

#End C0
blr #Comment this if compiling with pyiiasmh. Pyiiasmh auto adds the blr.

99% chance I typo'd or forgot something. Step/debug first before live attempt.

Here's whole code in compiled form.

007542D7 0000000A
C0000000 00000011
3D808033 A16CFF1A
71602010 3D408000
39200000 41820040
71600010 41820010
38000000 980A03FF
48000030 880A03FF
2C000001 41820024
38000001 980A03FF
892A03FE 39290001
28090022 41A00008
39200001 992A03FE
71600040 4DA20020
3D808033 3D608035
3D40917E 3CA092BE
992C7F30 992C7EF0
992BD8E1 992AEBD3
9925EBD3 4E800020
So I do a read bp on the text string I found: 0x802C77F0 ss/cmd/save_e.dat.jeegfsie

It breaks at instruction address: 0x80182E80 when stating the game save process and the next screen is about to load.

The call stack has the following displayed:

LR = 80182e64 b ->0x801A7750
address = 80093ef8 bl ->0x80182E54
address = 8002209c bl ->0x80093EC4
address = 80021b30 bl ->0x80022034
address = 800226c8 bl ->0x80021A78
address = 80022834 bl ->0x8002264C
address = 80151fd8 bctrl
address = 8017ed9c blr

I can see how it made its way from the bottom (more parent).

The code that immediately follows the: 8017ed9c blr
stwu sp, -0x0020 (sp)
mflr r0,
stw r0, 0x24 (sp)
stw r31, 0x24 (sp)
stw r30, 0x24 (sp)
stw r29, 0x24 (sp)
stw r28, 0x24 (sp)
mr r28, r3
bl -> 0x8017B124

I believe this is the prologue (correct me if I'm wrong).

After reading the calling functions guide, there were some posts afterwards that say to hook to the code at the address directly after the blr, which would be: 0x8017EDA0 stwu sp, -0x0020 (sp)

So I wrote this C0 code:

lis r12, 0x8017
ori r12, r12, 0xEDA0
mtlr r12

Obviously I don't want it to constantly run the the save function call. so I tried a C0 based button activator (at the beginning of the code, along with a Gecko button activator. In both cases, the game froze as soon as I tried to activate it.
I also tried activating the code by checking and unchecking the box next to the code in dolphin code manager without any button activators in the code.
Same thing. the game just froze.

Am I way off base?

Thanks in advance!!!!!!!
The call stack starts at the top and works its way down. You should be looking for functions starting at the top first.

Your code fails for 3 reasons
- You're effecting the main parent function (bottom of call stack) which is responsible for a crap ton of things, guaranteed to crash
- You are calling a function without a re-link (will eventually crash or end up in a infinite loop somewhere).
- You've provided no args and odds are that the function does requires arg(s)


Regarding your game, afaik save data for Wii games are stored in the /title directory of the NAND. The string you have provided does not include the title directory, which is odd. Be sure you are actually looking at the true save data file path.

If it is, I would start looking at what is at 0x80182E54. Should be a prologue there.

To get an idea of what register args are used for a function, observe the prologue.

If it does something like this in its prologue...

stwu sp, -0x0010 (sp)
mflr r0
stw r0, 0x14 (sp)
stmw r30, 0x8 (sp) #Backup old r30 and r31 values
mr r31, r3 #Place r3 into r31 for later processing
mr r30, r4 #Place r4 into r30 for later processing

Then it appears only process r3 and r4 as args. The game will usually place the args starting at r31 and working down from there. This is because r14 thru r31 are global variable registers and are preserved thru function calls. The game will use the new r30 and r31 values as elements for other/new child functions that it calls. I suggest re-reading the Guide to Function Calls in Codes guide again.

Anyway, check the address that called the 0x80182E54 function. See if there are instructions after the bl instruction. Something like this...

cmpwi r3, 0
beq- XXXX

Look for any instructions that deal with verifying r3. This would be the CPU doing a r3 return value check of the function that was just called.

Args (non floats; stuff in r3 thru r10) will be pointers (memory addresses) or integers. It can be very difficult to figure out what exactly the args represent.

This kind of PPC coding is quite the jump from beginner stuff. It may be best for you to take existing known functions from other games (like the ISFS functions on Brawl or mkwii) and port them using RAM Dumps to your game. Then twiddle with ISFS to get a hang of function calls and also working with files on the NAND.
Medal Of Honor Vanguard Wii (USA)

In-game Button Cheat Code Decoder

There were only 3 codes posted online for this game. I wanted to find the other 5.

I started tracing the cheat code routine, learned some stuff from it, but thought, "there's got to be an easier way."

The James Bond Way Smile

With a couple of C0 codes and one C2 code, I made a decoder that returned the button values of all the button cheat codes. Total runtime of the decoder around 6 hours.

One of the thing I needed was to simulate the buttons being pressed and released constantly. I used a trick I found that works in pretty much every Wii game; Auto Fire.
When searching for the games button activators addresses you'll usually come up with about 20 - 30 something returns. If you go through these one at a time, writing a 0x0, then press the fire/action button. See if you have auto fire, if not, uncheck that addresses box and move on to the next one. Sometimes 2 addresses may have to be held to 0x0 for the auto fire effect.

In this game, those addresses are:

808C9F80 00000000
808C9F20 00000000

I found the byte that keeps the "Enter Cheat Code" dialog box open. This is normally opened in the game by pressing Up Down Up Down in the pause menu. However, when you enter a invalid code it tells you so and waits for you to do the U D U D thing again to enter another code. With the byte held to 0x1, if a bad button combo was entered, the game immediately waits for another code to be entered. "Cheat Code Bad" is only displayed for a blink of an eye. If a valid code is entered, the game automatically drops you out of the pause menu back into game play.

All the existing codes used the D-pad exclusively, with 6 button presses needed for a code entry, so the only values I needed to randomly write to the button cheat code entry addresses was 1 - 2 - 4 - 8.

Here is the code to do that:

c0000000 00000004
3d608000 898b03b1
398c0001 2c0c0008
41a00008 39800001
998b03b1 4e800020


C0 Insert:
lis r11, 0x8000 #Upper half word of EVA
lbz r12, 0x3B1 (r11) #Load byte from EVA 0x800003B1
addi r12, r12, 0x1 #Add 1 to it
cmpwi r12, 0x8 #The value here will set up the speed of the 1 - 2 - 4 - 8 "rotation"; for this game 0x8 worked.
blt+ loc_0x18 #If the value is = to or > than
li r12, 0x1 #Reset EVA byte to 0x1

stb r12, 0x3B1 (r11) #Store updated byte to EVA

Now for the 1 - 2 - 4 - 8 portion:

c0000000 00000006
3d608000 898b03b1
88ab03b0 2c0c0008
4ca20020 1ca50002
2c050009 41a00008
38a00001 98ab03b0
4e800020 00000000

C0 Insert:
lis r11, 0x8000 #Upper half word of EVA
lbz r12, 0x3B1 (r11) #Load r12 with byte from above code
lbz r5, 0x3B0(r11) #Load our current 1 - 2 - 4 - 8 byte value to r5
cmpwi r12, 0x8 #Compare value in EVA code above with 0x8
bnelr+ #If not equal end C0
mulli r5, r5, 0x2 #Multiply current value in 1 - 2 - 4 - 8 byte EVA
cmpwi r5, 0x9 #See if that value is greater than 0x8
blt+ store_it #If less than, store new multiplied value
li r5, 0x1 #If it's greater than 0x8, reset the byte to 0x1

stb r5, 0x3B0 (r11)

Notice that I have not loaded a 0x1 or any value in EVA 0x800003B0
That's because I'm lazy, and knew I could prime the pump by poking any value in that byte.
In hindsight, it's a good thing. Randomly poking this value while the code was running, changed the algorithm of the values being entered into the button cheat, and quickly fleshed out some new button codes.

Here is the portion where we store the 1 - 2 - 4 - 8:

The 6 Button presses are entered in half words sequentially 0x8077E540 -> 0x8077E54A

The original store command:

8035f638 sth r27, 0xC (r3)

The insert to write the value from EVA instead:

lis r11, 0x8000 #Upper half of EVA
lbz r27, 0x3B0 (r11) #Load current 1 - 2 - 4 - 8 value into r27
sth r27, 12 (r3) #Original store command


Autofire code and C2 codes disabled until in the pause menu. Game freezes with ram writes and C2 running on boot up.
C0 codes doing their thing. At this point, EVA 0x800003B1 is cycling 1 -> 8

Once in the pause menu, I held the Enter Cheat Code always enabled address to 0x1

I knew the addresses of all the cheat enable bytes that get set to 0x1 when a valid code is entered.
I set write bp's on the 5 that there were no button codes for.

I enabled the C2 and auto fire codes.

Poked the byte at 0x800003B0 to get the 1 - 2 - 4 - 8 rotation going.

Finally, I taped down the A button and let it rip.

As hoped, the button press addresses auto filled again and again with random 1 - 2 - 4 - 8

After about 4 minutes, the breakpoint tripped, and I found one of the 5 unknown button codes: InvisiMOH Mode

Copied down the 6 button values that tripped it and deciphered into the correct D-pad values to be pressed.

I kept this up, and when it seemed it was only finding already know button combos, I would poke 0x800003B0 to change the algorithm.

It would usually pop out a new code not long after doing that.

Happy Hacking!!!
Link's Crossbow Training - Wii (USA)

Fully automatic exploding grenades:

(Goal) Write 0x0 to button press/release address. The exploding arrows are only fired when you release the button. For this code I'm using 0x80322010 as an example.
Don't have the exact address handy right now.

lis r11, 0x8000 #ASM this is setting up a 0x0 -> 0xF rotation at 0x800003C0
lhz r12, 0x3c0 (r11)
addi r12, r12, 0x1
cmpwi r12, 0xf #ASM this value will set up the speed of the 0x0 writes to 0x80322010 in the next C0 code; lower the value, the faster the writes
bne+ update_it
li r12, 0x0
sth r12, 0x3c0 (r11)

Here is the button compare and write portion:

lis r11, 0x802e #ASM setting up the button conditional
ori r11, r11, 0xe000
lhz r12, 0x43e (r11)
andi. r12, r12, 0x4400 #ASM checks to see if B and C buttons are being pressed
beqlr #ASM if not end C0
lis r11, 8000 #ASM load EVA rotation value for compare
lhz r12, 0x3c0 (r11)
cmpwi r12, 0xf
bnelr+ #ASM end C0 if EVA rotation value not 0xF
li r3, 0x0 #ASM load 0x0 to write to button press/release address 0x80322010
lis r4, 0x8032
sth r3, 0x201a (r4) #ASM store 0x0 to button press/release address 0x80322010, signaling the game that button has been released
blr #ASM let's blow this joint
New & Newer Super Mario Brothers Wii

Instant Transformations Press (-)

Code Created by: Thomas83Lin

lbz r12, 7(r31)
cmpwi r12, 0x0
beq- loc_0x28
cmpwi r12, 0x1
beq- loc_0x3C
cmpwi r12, 0x2
beq- loc_0x50
cmpwi r12, 0x3
beq- loc_0x64
bne- loc_0x90

lis r12, 0x803A
lhz r12, 6862(r12)
cmpwi r12, 0x1000
beq- loc_0x74
bne- loc_0x90

lis r12, 0x803A
lhz r12, 8262(r12)
cmpwi r12, 0x1000
beq- loc_0x74
bne- loc_0x90

lis r12, 0x803A
lhz r12, 9662(r12)
cmpwi r12, 0x1000
beq- loc_0x74
bne- loc_0x90

lis r12, 0x803A
lhz r12, 11062(r12)
cmpwi r12, 0x1000
bne- loc_0x90

li r12, 0x0
add r12, r12, r0
addi r12, r12, 0x1
cmpwi r12, 0x7
ble- loc_0x8C
li r12, 0x0

stw r12, 5344(r31)

lwz r4, 5344(r3)
At first glance, you can chop down the source to something like this. Btw I have no idea what any of the checks are for. I don't own the game and have never made codes for it.

lbz r4, 0x7 (r31)
lis r12, 0x803A

cmpwi r4, 0
lhz r11, 6862 (r12)
beq- check_bit_19
cmpwi r4, 1
lhz r11, 8262 (r12)
beq- check_bit_19
cmpwi r4, 2
lhz r11, 9662 (r12)
beq- check_bit_19
cmpwi r4, 3
lhz r11, 11062 (r12)
bne- original_instruction

cmpwi r11, 0x1000 #Considering this appear to be a bit check, I would try to use andi. instead
bne- original_instruction #If using andi. switch this to beq-

mr r4, r0
addi r4, r4, 1 #Instead of doing addi, there may be a way to implement subic. with a free check against 0 due to record bit usage. Retweak rest of code for check against 0 instead of seven.
cmplwi r4, 7
ble- store_it

li r4, 0

stw r4, 5344 (r31)

lwz r4, 5344 (r31)

NOTE: On the discord screenshot you gave me, the source doesn't use the actual original instruction. The original instruction uses r3 as the source register, not r31.
#2nd attempt at shortening the code

#Assumes r10 is safe for use
#Assumes cr5 thru cr7 are safe for use

lbz r4, 0x7 (r31) #Load ??? byte

subi r10, r4, 1 #Copy r4's value to r10 but subtract 1 from it as well

li r12, 4 #Set loop amount
mtctr r12

lis r12, 0x803A #Set upper half of ??? address
ori r12, r12, 5462 #Too lazy to convert this hex. It 6862 - 1400. Since in the original source that you posted, each check done on 803Axxxx was incremented by 1400 every time

addi r10, r10, 1 #Increment r10 by 1
cmpw cr7, r10, r4 #Check if r4 is equal to 0, 1, 2, or 3, place result in cr7
lwzu r11, 1400 (r12) #Load 1400 offset of r12, increment r12 to next load address
cmpwi cr6, r11, 0x1000 #Check that only bit 19 is high, all other bits must be low. Place result in cr6.
crand 4*cr7+eq,  4*cr6+eq, 4*cr7+eq #Logically AND's cr6 EQ bit with cr7 EQ bit, result placed back in cr7 EQ bit. If cr7 EQ bit results as high, then both earlier comparisons were true.
beq- cr7, do_final_check #If both earlier two checks passed, we're onto final check
bdnz+ loop #Decerment Loop

b original_instruction

#NOTE I can probably do more "condition register/field" trickery to where we don't need the follow segment of code separated from the loop, thus shortening the code even more

mr r4, r0
addi r4, r4, 1
cmplwi r4, 7
ble- store_it

li r4, 0

stw r4, 5344 (r31)

lwz r4, 5344 (r31)
I worked on and made good working C0 codes for 1 or 2 players.
Ummm, compared to what you wrote above, 'tis utter rubbish.


So, to fill in a blank,

lbz r4, 0x7 (r31) #Load ??? byte; [This is the byte that holds the number of players 1 - 4 = 0x0 -> 0x3]

I'm going to work on your second version. I'll let you know how it goes.

I'm thankful you like sharing your knowledge with others. Thanks!!!
Your second code with tweaked address values.
Works fine with 1 player, but in two player game pressing (-) on controller 1 changes both characters simultaneously.

lbz r4, 7(r31)
subi r10, r4, 0x1
li r12, 0x4
mtctr r12
lis r12, 0x803A
ori r12, r12, 0x1ACA
addi r10, r10, 0x1
cmpw cr7, r10, r4
lhzu r11, 0(r12)
cmpwi cr6, r11, 0x1000
crand 30, 26, 30
beq- cr7, loc_0x38

bdnz+ loc_0x30
b loc_0x50

mr r4, r0
addi r4, r4, 0x1
cmplwi r4, 7
ble- loc_0x4C
li r4, 0x0

stw r4, 5344(r31)

lwz r4, 5344(r31)

Forum Jump:

Users browsing this thread: 2 Guest(s)