Assembly Guides, Resources, & Q/A

Joined
Oct 10, 2011
Messages
1,126
Location
Boise, ID
NNID
dansalvato
#1
Guides/Resources
Intro to Wii Game Modding
A lengthy Youtube playlist of a livestream I did a couple years ago that details the basics of using Dolphin to edit memory, find addresses, read Assembly, and write Gecko codes. You'll probably want to start here.

WiiBrew Assembler Tutorial
A great human-readable explanation of many of the basic opcodes, plus some finer details of PPC ASM.

PowerPC Instruction Set
Incredibly useful documentation of the entire PPC instruction set by IBM themselves. Expand the left sidebar and find your instruction of interest. Note that not all of these instructions are usable on Gamecube.

Simplified PPC Instruction Set
Another PPC instruction set resource that may be useful. Easier to navigate, but less detailed.

Gecko Codetype Documentation
A complete documentation of all the capabilities of the Gecko codehandler. Again, extremely useful. Sometimes it's much more efficient to use some of these codetypes rather than use Assembly or 04 codes, so take a look at what it has to offer.

SSBM Data Sheet
Our bread and butter! Here we document our known memory addresses, functions, ID lists, tables, etc. There's still a lot to be added to this list, but it's publicly editable, so please feel free to contribute.

DOL Mod Tutorial (C2/ASM)
DOL Mod Tutorial (04 code/edit a single line in the DOL)


Utilities

ASMWiird
Absolutely necessary tool that converts your Assembly to/from C2 codes. Note that if your code contains comments, you'll need to enlarge the ASMWiird window to make sure your comments don't wrap lines; otherwise, your code won't render.

Online GCT Creator
Allows you to paste a list of codes into the text box and download them as a GCT file. Make sure to include the title of the codes you paste into it - the exact format we use on this board works just fine.

Floating-Point Converter
Multi-purpose float converter that converts decimals to/from 32- and 64-bit floats. Oftentimes it's smart enough to detect the format of the value you paste into it, which is extra convenient.


Q/A

I'll fill in this section with questions people ask, and links to the response posts.
 
Last edited:

CeLL

Smash Lord
Joined
Jan 26, 2014
Messages
1,025
Location
Washington
#4
How do you get a random integer in a certain range in a code? Specifically I want 1-9 inclusive. I see the random integer at 0x804D5F90, but I don't know what to do from there without modulo (which I couldn't find a command for and don't know how to do manually with basic operators).
 
Last edited:

Achilles1515

Smash Master
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH
#5
How do you get a random integer in a certain range in a code? Specifically I want 0-8 inclusive. I see the random integer at 0x804D5F90, but I don't know what to do from there without modulo (which I couldn't find a command for and don't know how to do manually with basic operators).
Set r3 to the number of possible values (9 in your case), branch into the RNG function, output (r3) will be your random integer of X possible values starting with 0x00. If you want to do a "percent chance", then compare the output of the RNG function to 0. There will be a one in X chance that the number will be zero.

Watch the default register values that get modified in the random function and make sure they will be safe to change. If not safe to change, you'll have to save them and then load back the defat values before branching back from custom code.
 

CeLL

Smash Lord
Joined
Jan 26, 2014
Messages
1,025
Location
Washington
#6
Set r3 to the number of possible values (9 in your case), branch into the RNG function, output (r3) will be your random integer of X possible values starting with 0x00. If you want to do a "percent chance", then compare the output of the RNG function to 0. There will be a one in X chance that the number will be zero.

Watch the default register values that get modified in the random function and make sure they will be safe to change. If not safe to change, you'll have to save them and then load back the default values before branching back from custom code.
When you say to branch into the RNG function, I know what you mean but I'm not sure how to do that.
 

CeLL

Smash Lord
Joined
Jan 26, 2014
Messages
1,025
Location
Washington
#8

Cyjorg

tiny.cc/19XXTE
Joined
Nov 18, 2013
Messages
686
Location
Purdue University
#9
Sorry so many questions, never done this before. So the RNG function you mention I assume is the function at 0x803804F8. But once I branch there, how does it get back to my code? There is a blr at the end of it so wouldn't it just branch to whatever is in the link register (which would skip the rest of my code and the rest of the function my code was in)?
branch and link is like running a subroutine. So if you bl to 0x803804F8, from 0x80002288 it will run the function and then return to 0x8000228C and finish running your function.

If you used a bl to get to your function (why?) then you could just use a mflr rX to store whatever was in the link register before.

Does this answer your question?
 

CeLL

Smash Lord
Joined
Jan 26, 2014
Messages
1,025
Location
Washington
#10
branch and link is like running a subroutine. So if you bl to 0x803804F8, from 0x80002288 it will run the function and then return to 0x8000228C and finish running your function.

If you used a bl to get to your function (why?) then you could just use a mflr rX to store whatever was in the link register before.

Does this answer your question?
Oh I see now. My function is injected like 6 lines before a blr so I was thinking that when I branched to the RNG function that the blr at the end of that would return to the address that the blr after my function was supposed to but now I see what to do.
 

Achilles1515

Smash Master
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH
#11
Oh I see now. My function is injected like 6 lines before a blr so I was thinking that when I branched to the RNG function that the blr at the end of that would return to the address that the blr after my function was supposed to but now I see what to do.
You are correct, with your thought about it skipping the rest of your code. That is what the "bctrl" is for. Specifically, the "l" at the end which basically tells it to branch link. Depending on how you structure/inject your code, you may need to save your link register as well before branching into the random function, because it does not do that for you.

Something like:

mflr r14
- branch to RNG stuff-
mtlr r14


r14 is arbitrary, but it is a register not used within the RNG function so it is safe to save/load a value from there.

The RNG function I am talking about is 80380580.
 

Cyjorg

tiny.cc/19XXTE
Joined
Nov 18, 2013
Messages
686
Location
Purdue University
#12
Oh I see now. My function is injected like 6 lines before a blr so I was thinking that when I branched to the RNG function that the blr at the end of that would return to the address that the blr after my function was supposed to but now I see what to do.
yeah so just use a mflr rX and a mtlr rX to save your link register.
 

Achilles1515

Smash Master
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH
#13
***FYI***
After spending an hour thinking I'm an idiot, I have come to a bad conclusion.

Dolphin displays the hex instruction "FC402050" as "fneg f2,f1". If you use the ASM<>WiiRD program to get the instruction from that hex value, it gives you "fneg f2,f4" which is what accurately happens in game.

For proof, go to code line 8007d1fc.

....Dolphin....y u do dis?
 
Joined
Oct 10, 2011
Messages
1,126
Location
Boise, ID
NNID
dansalvato
#14
yeah so just use a mflr rX and a mtlr rX to save your link register.
Usually, when you bl to another function, you don't need to save your link register, because the function does it for you. Almost every function begins by allocating stack space and then saving the link register to the stack.
 
Joined
Oct 10, 2011
Messages
1,126
Location
Boise, ID
NNID
dansalvato
#15
***FYI***
After spending an hour thinking I'm an idiot, I have come to a bad conclusion.

Dolphin displays the hex instruction "FC402050" as "fneg f2,f1". If you use the ASM<>WiiRD program to get the instruction from that hex value, it gives you "fneg f2,f4" which is what accurately happens in game.

For proof, go to code line 8007d1fc.

....Dolphin....y u do dis?
I brought this up with some Dolphin devs and they're likely going to push a fix. They've already found the cause.
 

Achilles1515

Smash Master
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH
#18
Code:
Modulus Function in ASM
- example using arbitrary registers to hold integers

A mod B = C

    Where C is the remainder of A divided by B.
-------------------------------------------
# r6 holds A
# r7 holds B


divw r8, r6, r7
mullw r9, r8, r7
sub r6,r6,r9

#r6 now holds C

-------------------------------------------

If wanting to check that B is a multiple of A (so C=0):

divw r8, r6, r7
mullw r9, r8, r7
cmpw r9, r6
bne-  NOT_MULTIPLE_OF

YES_MULTIPLE_OF:
# do whatever
 
Last edited:

Fizzi

Smash Ace
Joined
Feb 14, 2008
Messages
800
Location
San Francisco, CA
#19
Are there available memory locations that are not used by the game?

Basically I'm looking for absolute memory addresses that are safe to write to and come back and read later.

Edit: Nvm, just found the Free Memory tab in the SSBM Data Sheet linked in the OP. You guys are awesome :D
 
Last edited:

zankyou

Smash Lord
Joined
Sep 12, 2014
Messages
1,055
#20
Ive been trying to write a code that will play the menu back sound if player 1 hits down on the d pad.

@802f4290

lis r14,0x8046
ori r14,r14,0xb108
lbz r15,0x01(r14)
cmpwi r15,0x04
bne Exit
lis r14,0x8017
ori r14,r14,0x435c
mtctr r14
bctrl
Exit:
lis r4, 0x8040

The code plays the sound but the game crashes immediately afterwards. Any guidance would be appreciated.
 
Joined
Oct 10, 2011
Messages
1,126
Location
Boise, ID
NNID
dansalvato
#21
Ive been trying to write a code that will play the menu back sound if player 1 hits down on the d pad.

@802f4290

lis r14,0x8046
ori r14,r14,0xb108
lbz r15,0x01(r14)
cmpwi r15,0x04
bne Exit
lis r14,0x8017
ori r14,r14,0x435c
mtctr r14
bctrl
Exit:
lis r4, 0x8040

The code plays the sound but the game crashes immediately afterwards. Any guidance would be appreciated.
It's because you're hooking right in the middle of the current function trying to save the link register to the stack. The link register "lr" tells execution where to return to once the current function is finished (which is why functions end in "blr"). You're hooking right after "mflr r0", which means the link register is in r0. Two lines down you see "stw r0,0x0004(sp)", which safely stores r0 to the stack.

When you hook right after "mflr r0", well, the function that you manually execute also begins with "mflr r0", so the link register for the original function gets completely overwritten. So when it's time to end the function, it branches back to the wrong spot.

Solution: Wait for the stack operations to finish before you hook. Hook into 802f42a0 (subi r28,r4,27416). Even though r4 got overwritten in your custom function, just repeat both lines at the end of your function:
lis r4,0x8040
subi r28,r4,27416

Extra note: Don't bother using r14 and r15. if you look at the function you're hooking into, you can see that r3, r4, r5, etc. are safe. They are immediately overwritten right at the beginning of the function, meaning they're not storing any important values and you can use them instead of r14, etc. It's good practice to use local-scope registers whenever possible (r12 and below).
 
Last edited:

zankyou

Smash Lord
Joined
Sep 12, 2014
Messages
1,055
#22
Ah I found the problem. I had to inject at 802f42a8 because at 802f42a4 the line is
lwz r30, 0x0028 (r3)
So the code looks like this and works.

@802f42a8
lis r3,0x8046
ori r3,r3,0xb108
lbz r5,0x01(r3)
cmpwi r5,0x04
bne Exit
lis r5,0x8017
ori r5,r5,0x435c
mtctr r5
bctrl
Exit:
lis r3, 0x804A

I really appreciate the help. I generally avoided registers that werent empty but Ill take your advice and look more closely at the functions from now on.
 
Last edited:

Dab980

Smash Rookie
Joined
Feb 18, 2015
Messages
5
Location
VA
3DS FC
2621-2802-2852
NNID
slowflute401
#24
is there a way to add giga bowser to the select menu
 

Achilles1515

Smash Master
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH
#26
Need some help. I am not too familiar with using stack traces to debug problems, and am not sure what I am doing wrong or misunderstanding.

So something happens in the game and it freezes and gets put in an infinite loop.
Capture1.PNG

Now let's go back to line 80345a58.

Capture1.PNG

Okay, it calls InfiniteLoop as expected. Looking back at the stack trace from pic 1, lets go to the branch link from before this @ 8037079c.

Capture1.PNG

This does not branch link to 80345870 and instead goes to 8036ec10. And nowhere in function 8036ec10 does it directly branch to 80345870. I'm confused as to what is going on.

SinsOfApathy SinsOfApathy
 
Last edited:
Joined
Oct 10, 2011
Messages
1,126
Location
Boise, ID
NNID
dansalvato
#27
Need some help. I am not too familiar with using stack traces to debug problems, and am not sure what I am doing wrong or misunderstanding.

So something happens in the game and it freezes and gets put in an infinite loop.
View attachment 84036

Now let's go back to line 80345a58.

View attachment 84037

Okay, it calls InfiniteLoop as expected. Looking back at the stack trace from pic 1, lets go to the branch link from before this @ 8037079c.

View attachment 84038

This does not branch link to 80345870 and instead goes to 8036ec10. And nowhere in function 8036ec10 does it directly branch to 80345870. I'm confused as to what is going on.

SinsOfApathy SinsOfApathy
Dolphin's log might give you a better stack trace than the one you're looking at. Click View > Show Log and see if it gives you a stack trace after the crash.
 

SinsOfApathy

Smash Journeyman
Joined
Feb 24, 2015
Messages
459
NNID
Psion312
#29
This does not branch link to 80345870 and instead goes to 8036ec10. And nowhere in function 8036ec10 does it directly branch to 80345870. I'm confused as to what is going on.
Might be some kind of exception handler from the kernel due to values in the CR, since C doesn't have a built-in exception handler.

I'd probably have better luck looking at it in IDA. I'll try to get to it later.
 
Last edited:

Zeus_Da_master

Smash Journeyman
Joined
Jan 22, 2007
Messages
298
Location
Atlanta Ga
#31
can someone help me with writing a code? i've never done it before and have no clue how to do it or input it into the coding of the game... i'd like to have it be a counter that counts how many times you hit someone without getting hit (n when you get hit it resets) but once it reaches the value of X, maybe 15, it plays an audio clip... also how do i put the audio clip into the game?..... and another code with the same thing but it counts how many times you attack and miss, n when u miss 10 times in a row, it plays a different audio clip
 
Last edited:

dandeto

Smash Apprentice
Joined
Feb 19, 2015
Messages
108
Location
Medieval castle
#32
Hey, I went through your tutorials, Dan - they are ridiculously amazing and entertaining - so I understand how codes work. I had previously looked through tons of tutorials on how to write codes, but they were all very vague and confusing. Now that I finally started to get back into it and found your tutorial awhile ago, I have been doing great!

One question on the data sheet's organization. I have looked through for fun stuff to modify, and have found a few things. I was going to find the address in Dolphin, however, only the offset was listed. I am having trouble finding the addresses the offsets start at. Am I just missing something simple?

Note: PPC Instruction reference by IBM link is broken.
 
Last edited:

SinsOfApathy

Smash Journeyman
Joined
Feb 24, 2015
Messages
459
NNID
Psion312
#33
One question on the data sheet's organization. I have looked through for fun stuff to modify, and have found a few things. I was going to find the address in Dolphin, however, only the offset was listed. I am having trouble finding the addresses the offsets start at. Am I just missing something simple?
That's because what you're looking at likely doesn't have a static address. If it's character data, you follow the pointer in the static block, which the addresses are listed for at the top or on the Global Functions page.
 
Last edited:

SinsOfApathy

Smash Journeyman
Joined
Feb 24, 2015
Messages
459
NNID
Psion312
#35
Thanks! what are the IDs? I am looking at the action state reference.
Action States define how a move transitions. The ID is just from a table in memory, I think.

The struct at the top of that part of the spreadsheet is related to the move tables, which are fairly character specific. I think it's the animation ID, but it varied per character and crashed on certain characters when testing if I modified it. So, I haven't really gotten around to looking into it.
 

DRGN

Technowizard
Moderator
Premium
Joined
Aug 20, 2005
Messages
2,042
Location
Sacramento, CA
#38
MCM supports them as well.

upload_2017-3-3_12-25-29.png


Also, this probably isn't widely realized, but in the latest versions of MCM, code can be saved in ASM form (including with comments) for easy amending/tweaking. When you save your codes to your game, the assembly is automatically compiled into hex and added to the DOL. So you don't need to repeatedly convert the code yourself after you make changes while you're writing or tweaking a mod.

This does take a few extra moments during the saving process though, so I only recommend it while you're working with that particular mod. If you leave many mods in ASM form, the saving time could begin to add up. So once you're finished with the mod, I'd just convert it and save the code in the library as hex. Of course, since comments can be saved with the mod, you can keep your source code and other notes in there too, but commented out. So then if you go back to work on it again later, you could just delete the hex portion, and uncomment your source code.
 
Last edited:
Top