• Welcome to Smashboards, the world's largest Super Smash Brothers community! Over 250,000 Smash Bros. fans from around the world have come to discuss these great games in over 19 million posts!

    You are currently viewing our boards as a visitor. Click here to sign up right now and start on your path in the Smash community!

Melee Gecko Codes + Guide and Discussion

Magus420

Smash Master
Joined
Dec 13, 2003
Messages
4,541
Location
Close to Trenton, NJ Posts: 4,071
"Smash Turn" being this mechanic: http://www.meleeitonme.com/back-dashes-smash-turns/

Flash Blue on Missed Smash Turn (v1.00) [Magus]
C20C9790 0000000F
A11E0448 2C084000
40820064 811E23A8
2C080000 41820058
811E23B0 2C080000
4182004C 3CE042C0
3D00437F 39200000
90FE0518 90FE051C
911E0520 913E0528
913E052C 913E0530
3CE0C200 3D00C280
39200091 3D406060
614AFFE0 90FE0524
911E0534 993E0564
915E0514 801F2358
60000000 00000000

Flash Blue on Missed Smash Turn (v1.02) [Magus]
C20C9B48 0000000F
A11E0448 2C084000
40820064 811E23A8
2C080000 41820058
811E23B0 2C080000
4182004C 3CE042C0
3D00437F 39200000
90FE0518 90FE051C
911E0520 913E0528
913E052C 913E0530
3CE0C200 3D00C280
39200091 3D406060
614AFFE0 90FE0524
911E0534 993E0564
915E0514 801F2358
60000000 00000000

Code:
CHECK_IF_SLOW:
lhz	r8,0x448(r30)	# animation frame
cmpwi	r8,0x4000	# frame 2 of Turn
bne-	END		# skip code if not frame 2 of Turn action

lwz	r8,0x23A8(r30)
cmpwi	r8,0		# 0 if not past 0.8 dash threshold on frame 2 of Turn
beq-	END		# skip if dash after slow turn will not activate if held (standing turn)

lwz	r8,0x23B0(r30)
cmpwi	r8,0		# 0 if no slow turn delay (smash turn, but didn't dash)
beq-	END		# skip if pivot

ENABLE_OVERLAY:
lis	r7,0x42C0	# 42C00000 (96)
lis	r8,0x437F	# 437F0000 (255)
li	r9,0		# 00000000 (0)
stw	r7,0x518(r30)	# Red = 96
stw	r7,0x51C(r30)	# Green = 96
stw	r8,0x520(r30)	# Blue = 255
stw	r9,0x528(r30)	# Red Transition = 0
stw	r9,0x52C(r30)	# Green Transition = 0
stw	r9,0x530(r30)	# Blue Transition = 0

lis	r7,-0x3E00	# C2000000 (-32)
lis	r8,-0x3D80	# C2800000 (-64)
li	r9,0x91		# flag to enable flash overlay
lis	r10,0x6060
ori	r10,r10,0xFFE0	# 6060FFE0. Initial RGBA
stw	r7,0x524(r30)	# Alpha = -32
stw	r8,0x534(r30)	# Alpha Transition = -64
stb	r9,0x564(r30)	# enable flash overlay
stw	r10,0x514(r30)	# Initial RGBA = 96/96/255/224

END:
lwz	r0,9048(r31)	# entry point (800C9B48)



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

The following makes the smash turn mechanic not dumb and match the input to dash forward:


Smash Turns Have a 2 Frame Input Window 2.0 (v1.00) [Magus]
C20C9794 00000008
A11F03E8 2C084000
4082002C 811F2348
2C080000 41820020
811F2340 2C080001
41820014 C01F002C
FC000050 D01F002C
38000001 2C000000
60000000 00000000

Smash Turns Have a 2 Frame Input Window 2.0 (v1.01) [Magus]
C20C98D8 00000008
A11F03E8 2C084000
4082002C 811F2348
2C080000 41820020
811F2340 2C080001
41820014 C01F002C
FC000050 D01F002C
38000001 2C000000
60000000 00000000

Smash Turns Have a 2 Frame Input Window 2.0 (v1.02) [Magus]
C20C9B4C 00000008
A11F03E8 2C084000
4082002C 811F2348
2C080000 41820020
811F2340 2C080001
41820014 C01F002C
FC000050 D01F002C
38000001 2C000000
60000000 00000000

Smash Turns Have a 2 Frame Input Window 2.0 (PAL) [Magus]
C20CA2F0 00000008
A11F03E8 2C084000
4082002C 811F2348
2C080000 41820020
811F2340 2C080001
41820014 C01F002C
FC000050 D01F002C
38000001 2C000000
60000000 00000000

Code:
CHECK_IF_SLOW:
lhz	r8,0x3E8(r31)	# animation frame
cmpwi	r8,0x4000	# frame 2 of Turn
bne-	END		# skip code if not frame 2 of Turn action

lwz	r8,0x2348(r31)
cmpwi	r8,0		# 0 if no 2 frame smash input beyond 0.8 dash threshold
beq-	END		# skip if no dash input by frame 2

lwz	r8,0x2340(r31)
cmpwi	r8,1		# 1 if change of direction has already completed (empty smash turn)
beq-	END		# skip if smash turn

lfs	f0,0x2C(r31)	# loads character direction
fneg	f0,f0
stfs	f0,0x2C(r31)	# changes character direction, completing the turn
li	r0,1		# 1 if able to dash out of turn on this frame to allow Dash change action

END:
cmpwi	r0,0		# entry point (800C9B4C). check flag for turn complete and can dash this frame
Old version of the code entered Dash on the frame after the smash input was detected, making it 1 frame slower than a normal smash turn. New version now enters Dash immediately, making them equal.



Smash Turns Have a 2 Frame Input Window (v1.00) [Magus]
C20C9794 00000005
A11E0448 2C084000
40820018 811E23A8
2C080000 4182000C
39000000 911E23B0
2C000000 00000000

Smash Turns Have a 2 Frame Input Window (v1.02) [Magus]
C20C9B4C 00000005
A11E0448 2C084000
40820018 811E23A8
2C080000 4182000C
39000000 911E23B0
2C000000 00000000

Code:
CHECK_IF_SLOW:
lhz	r8,0x448(r30)	# animation frame
cmpwi	r8,0x4000	# frame 2 of Turn
bne-	END		# skip code if not frame 2 of Turn action

lwz	r8,0x23A8(r30)
cmpwi	r8,0		# 0 if not past 0.8 dash threshold on frame 2 of Turn
beq-	END		# skip if no dash input by frame 2
li	r8,0
stw	r8,0x23B0(r30)	# clear slow turn delay timer if dash input by fr2

END:
cmpwi	r0,0		# entry point (800C9B4C)
 
Last edited:

seaghost

Smash Rookie
Joined
May 15, 2015
Messages
1
Hey everyone. I'm new to Melee (and GameCube) modding, but I have a good deal of background with Assembly (mostly ARM). I was looking for some detailed information on where various functions and key points in memory are located (i.e., main menu loop, CSS loop, game loop, etc.). Is there a well documented schematic of these locations in memory? I have seen this document, but it doesn't go super low level, it gives more of a broad overview. Is there anything more detailed?

If not, what sort of resources would you recommend to round out my understanding?

Also, what program should I be using to look at the Assembly commands on a Mac? I have Wine, so I can run exe's, but everything I've seen recommended only gives me hex, unless I'm doing something wrong.
 

SinsOfApathy

Smash Journeyman
Joined
Feb 24, 2015
Messages
474
NNID
Psion312
That document is about as concise as it goes, minus our personal notes. The game logic loop is always active and since we use Dolphin's debugger (which shows the function stack), you'll be able to figure out which one it is.

The Codes subsection has a guide with links to various resources.
 

flieskiller

Smash Journeyman
Joined
Jan 3, 2013
Messages
426
Disable Fox/Falco's shine (1.02) [flieskiller]
air shine
040e85ec 4e800020
ground shine
040e8560 4e800020

The spacie just stays still when pressing down-b. With this, you can test how Fox/Falco can do in a fight without shine (not much?). They both share the same function about their shine.
 

flieskiller

Smash Journeyman
Joined
Jan 3, 2013
Messages
426
Pictures added in spoiler:





Time mode = Handwarmer mode (1.02) [flieskiller]
04167c60 60000000
C21A4160 00000008
2C000001 40810034
3E208047 8A11B6A8
2C100007 41820024
3E208045 6231BF12
8A110000 2C100000
40820010 3A000001
9A110000 48000008
981F0003 00000000


What this code does: When a player uses Time Mode, the shown time isn't minutes, but seconds (45:00 would be 45 seconds in-game).

After this, when the players do a time mode match and it ends, the game restarts the match but with Stock mode instead (and for future matches, so useable for game 1 of sets).

This shares the same inject point as the Salty Runback code, so be careful if injecting in your ISO.

ASM notes:
VS mode, time mode: minutes is seconds instead (remove multiplying by 60)
04167c60 60000000

C21a4160
cmpwi r0, 1 #check if we're in a game (not the SSS)
ble NOCHANGE
lis r17, 0x8047
lbz r16, -0x4958(r17) #loading at 8046B6A8
cmpwi r16, 7 #check if a player quit the game by doing LRAstart
beq NOCHANGE
lis r17, 0x8045
ori r17, r17, 0xBF12 #r17: game mode address
lbz r16, 0(r17) #r16: number of game mode (00 = time, 01 = stock)
cmpwi r16, 0 #if game mode is Time Mode, branch out if false
bne NOCHANGE
li r16, 1
stb r16, 0(r17) #set game mode as Stock mode at r17
b END #skip the store new scene line, so match restarts
NOCHANGE:
stb r0, 0x0003 (r31) #normal line
END:

player % percentage is hidden if time mode (1.02) [flieskiller]
C22F65C8 00000009
3E208046 8A11BF12
2C100000 40820024
8A11BF13 2C100000
41820018 3E20804D
8A116CF5 2C100004
40820008 48000014
3E20802F 62315EC0
7E2903A6 4E800421
60000000 00000000


What it does: If it's time mode in a VS match, the player's % are hidden to show that it's a handwarmer session. It's a neat visual thing only, so feel free to not include it if you don't want a pretty big C2 for what it does.

ASM notes:
C22f65c8
lis r17, 0x8046
lbz r16, -0x40EE(r17)#load 0x8045bf12
cmpwi r16, 0
bne NOSKIP #if not time mode, load as usual
lbz r16, -0x40ED(r17)#load 0x8045bf13
cmpwi r16, 0 #if timer is endless, load as usual
beq NOSKIP
lis r17, 0x804D
lbz r16, 0x6CF5(r17)
cmpwi r16, 4 #if not vs match, load as usual
bne NOSKIP
b SKIP #if vs mode + time mode, skip drawing %
NOSKIP:
lis r17, 0x802f
ori r17, r17, 0x5ec0
mtctr r17
bctrl#normal line (BL to drawing function)
SKIP:

current time mode timer (for setting after loading global constants, like a custom memory card load)
0045bf13 0000002D

for gecko code, set the global constant
003D4A4B 0000002D

2D = 45 seconds
 
Last edited:

flieskiller

Smash Journeyman
Joined
Jan 3, 2013
Messages
426
Part 2 of Handwarmer mode. If anything bugs, it will 99% be because of registers that are replaced (but was at 0 when I tested). These are not tested on console, I don't have a Wii. If you have any requests related to that, I'll be glad to answer.

Time Mode shows as seconds (1.02) [flieskiller]
C222FDB8 0000000C
7FA4EB78 3CE08000
60E72FFC 89470000
3D00804A 892804F4
2C090002 41800008
39200001 7D4848F8
550807FE 7D494838
7D094A79 41820028
99070000 80E40060
81040064 8124006C
81440070 90E4006C
91040070 91240060
91440064 00000000
C222F788 00000003
98030004 3E208000
62312FFC 3A000000
9A110000 00000000

A stored variable is needed for this part, the address is in red (1 byte). If it's time mode (only time mode), swaps the seconds and minutes.

ASM notes:
8022fdb8
mr r4, r29 #normal line
lis r7, 0x8000
ori r7, r7, 0x2ffc
lbz r10, 0(r7) #r10: custom switch
lis r8, 0x804A
lbz r9, 0x04F4(r8) #r9: loading mode
cmpwi r9, 2
blt NOTCOINBONUS
li r9, 1 #if it's bonus/coin, reduce it to 1 for checking
NOTCOINBONUS:
nor r8, r10, r9
rlwinm r8,r8,0,31,31
and r9, r10, r9
xor. r9, r8, r9 #These 4 commands above is similar to a XNOR
beq NOSWAP
stb r8, 0(r7) #store custom switch's new value
lwz r7, 0x60 (r4)
lwz r8, 0x64 (r4)
lwz r9, 0x6C (r4)
lwz r10, 0x70 (r4)
stw r7, 0x6C (r4)
stw r8, 0x70 (r4)
stw r9, 0x60 (r4)
stw r10, 0x64 (r4) #these 4 lines swap minutes and seconds
NOSWAP


small C2:
leaving settings menu reset custom switch to default
8022f788
stb r0, 0x0004 (r3) #normal line
lis r17, 0x8000
ori r17, r17, 0x2ffc
li r16, 0
stb r16, 0(r17)


load custom message in CSS instead of "-minute KO fest!" with different address
C23A662C 00000005
7C86002E 3E208046
8A11BF12 2C100000
40820014 2C050053
4082000C 3C808000
60842D00 00000000

0425BEE0 4800012C

04002D00 20FC2036
04002D04 20282026
04002D08 20322031
04002D0C 20272036
04002D10 1A203220
04002D14 291A203A
04002D18 20242035
04002D1C 2030202C
04002D20 2031202A
04002D24 1A203820
04002D28 3320EC00


The C2 checks if the String being created is made for Time mode, and is for a numbered Time set (not endless)

the 04 is the new text "-seconds of warming up!" instead of "minute of KO fest!". It doesn't replace if time is set at "none". The lonely 04 is the branch to skip the "KO fest!" addition to the String.

About the table and how it works, a letter/number is read by the game as "20XX", where XX is a number. "2030" = m, "2031" = n, etc. 1A is a space, EC is a !, FC is a -.

ASM notes:
803a662c
lwzx r4, r6, r0 #normal line
lis r17, 0x8046
lbz r16, -0x40EE(r17)#load 0x8045bf12
cmpwi r16, 0
bne NOCHANGE #if not time mode, load as usual
cmpwi r5, 0x53 #if it's String concatenate that will join the number
bne NOCHANGE
lis r4, 0x8000 # after the number, set the address of new message
ori r4, r4, 0x2D00
NOCHANGE:

20fc2036 (-s)
20282026 (ec)
20322031 (on)
20272036 (ds)
1a203220 ( o)
291a203a (f w)
20242035 (ar)
2030202c (mi)
2031202a (ng)
1a203820 ( u)
3320EC00 (p!)
 
Last edited:

Aerros11

Smash Journeyman
Joined
Sep 5, 2009
Messages
284
My newest code:

Stock Dependent Revival Platform Colors
(Gecko, 1.02)

The coloring of the revival platform changes based on how many stocks a player has remaining.



3 stocks left = green platform
2 stocks left = orange platform
1 stock left = red platform (as in, danger....you're about to lose)

  • This only gets applied in a 4 stock vs. match. The revival platform is normal colored in any other game mode.
  • If two players die at roughly the same time, the same color will be used for both reviving players regardless as to whether or not their stock count differs. The color applied will be based on stock count of whoever technically died last. There can be multiple different colored revival platforms out at once, just as long as those characters don't die within a few frames of each other. I don't think I can fix this.
Video Demonstration

Gecko Code:
(sorry about the length - it's doing quite a few things at once)
284530C8 FF000000
0046B6AF 00000000
E2000001 00000000
2A45BF14 00FF0400
0046B6AF 00000000
E2000001 00000000
2846B6AE FF000003
48000000 804D64FC
12000AC4 000000FF
12000AC6 000000FF
12000AF0 00000059
12000AF2 000000FF
12000B90 000000FF
12000B92 000000FF
12000CE0 000000FF
12000CE2 000000FF
12000D18 000000FF
12000D1A 000000FF
E2000001 80008000
2846B6AF FF000002
48000000 804D64FC
12000AC4 0000FF99
12000AC6 000000FF
12000AF0 00009F5F
12000AF2 000000FF
12000B90 0000FF99
12000B92 000000FF
12000CE0 0000FF99
12000CE2 000000FF
12000D18 0000FF99
12000D1A 000000FF
E2000001 80008000
2846B6AF FF000001
48000000 804D64FC
12000AC4 0000FF00
12000AC6 000000FF
12000AF0 00009000
12000AF2 000000FF
12000B90 0000FF00
12000B92 000000FF
12000CE0 0000FF00
12000CE2 000000FF
12000D18 0000FF00
12000D1A 000000FF
E2000001 80008000
2846B6AD FF000000
2845310E 00FF0300
0046B6AF 00000003
2845310F 00FF0200
0046B6AF 00000002
2845310F 00FF0100
0046B6AF 00000001
E2000002 80008000
2846B6AD FF000001
28453F9E 00FF0300
0046B6AF 00000003
28453F9F 00FF0200
0046B6AF 00000002
28453F9F 00FF0100
0046B6AF 00000001
E2000002 80008000
2846B6AD FF000002
28454E2E 00FF0300
0046B6AF 00000003
28454E2F 00FF0200
0046B6AF 00000002
28454E2F 00FF0100
0046B6AF 00000001
E2000002 80008000
2846B6AD FF000003
28455CBE 00FF0300
0046B6AF 00000003
28455CBF 00FF0200
0046B6AF 00000002
28455CBF 00FF0100
0046B6AF 00000001
E0000000 80008000

Let me know if you have any questions. I think I might write a guide about using 'if' statements with Gecko code. It took me awhile to figure out the right way to nest a bunch.
A bit late to the party, I am, but is it possible to know which section of the code controls the colors?

Blue -> Green -> Red is my preference >__<'|l

____

I was trying to google this myself with green as 00ff00 and red as ff0000...but there's so many fs and 0s that I'm not sure if that's even the right start
 
Last edited:

Achilles1515

Smash Master
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH

Achilles1515

Smash Master
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH
Part 2 of Handwarmer mode. If anything bugs, it will 99% be because of registers that are replaced (but was at 0 when I tested). These are not tested on console, I don't have a Wii. If you have any requests related to that, I'll be glad to answer.

Time Mode shows as seconds (1.02) [flieskiller]
C222FDB8 0000000C
7FA4EB78 3CE08000
60E72FFC 89470000
3D00804A 892804F4
2C090002 41800008
39200001 7D4848F8
550807FE 7D494838
7D094A79 41820028
99070000 80E40060
81040064 8124006C
81440070 90E4006C
91040070 91240060
91440064 00000000
C222F788 00000003
98030004 3E208000
62312FFC 3A000000
9A110000 00000000

A stored variable is needed for this part, the address is in red (1 byte). If it's time mode (only time mode), swaps the seconds and minutes.

ASM notes:
8022fdb8
mr r4, r29 #normal line
lis r7, 0x8000
ori r7, r7, 0x2ffc
lbz r10, 0(r7) #r10: custom switch
lis r8, 0x804A
lbz r9, 0x04F4(r8) #r9: loading mode
cmpwi r9, 2
blt NOTCOINBONUS
li r9, 1 #if it's bonus/coin, reduce it to 1 for checking
NOTCOINBONUS:
nor r8, r10, r9
rlwinm r8,r8,0,31,31
and r9, r10, r9
xor. r9, r8, r9 #These 4 commands above is similar to a XNOR
beq NOSWAP
stb r8, 0(r7) #store custom switch's new value
lwz r7, 0x60 (r4)
lwz r8, 0x64 (r4)
lwz r9, 0x6C (r4)
lwz r10, 0x70 (r4)
stw r7, 0x6C (r4)
stw r8, 0x70 (r4)
stw r9, 0x60 (r4)
stw r10, 0x64 (r4) #these 4 lines swap minutes and seconds
NOSWAP


small C2:
leaving settings menu reset custom switch to default
8022f788
stb r0, 0x0004 (r3) #normal line
lis r17, 0x8000
ori r17, r17, 0x2ffc
li r16, 0
stb r16, 0(r17)


load custom message in CSS instead of "-minute KO fest!" with different address
C23A662C 00000005
7C86002E 3E208046
8A11BF12 2C100000
40820014 2C050053
4082000C 3C808000
60842D00 00000000

0425BEE0 4800012C

04002D00 20FC2036
04002D04 20282026
04002D08 20322031
04002D0C 20272036
04002D10 1A203220
04002D14 291A203A
04002D18 20242035
04002D1C 2030202C
04002D20 2031202A
04002D24 1A203820
04002D28 3320EC00


The C2 checks if the String being created is made for Time mode, and is for a numbered Time set (not endless)

the 04 is the new text "-seconds of warming up!" instead of "minute of KO fest!". It doesn't replace if time is set at "none". The lonely 04 is the branch to skip the "KO fest!" addition to the String.

About the table and how it works, a letter/number is read by the game as "20XX", where XX is a number. "2030" = m, "2031" = n, etc. 1A is a space, EC is a !, FC is a -.

ASM notes:
803a662c
lwzx r4, r6, r0 #normal line
lis r17, 0x8046
lbz r16, -0x40EE(r17)#load 0x8045bf12
cmpwi r16, 0
bne NOCHANGE #if not time mode, load as usual
cmpwi r5, 0x53 #if it's String concatenate that will join the number
bne NOCHANGE
lis r4, 0x8000 # after the number, set the address of new message
ori r4, r4, 0x2D00
NOCHANGE:

20fc2036 (-s)
20282026 (ec)
20322031 (on)
20272036 (ds)
1a203220 ( o)
291a203a (f w)
20242035 (ar)
2030202c (mi)
2031202a (ng)
1a203820 ( u)
3320EC00 (p!)
This is really neat, Flieskiller. I like these creative codes you are making.
 

Savestate

Smash Cadet
Joined
Apr 14, 2015
Messages
38
Location
Greensboro, NC
P1 Peach can pull any item [Savestate]
C206AD28 0000001C
7C7E1B78 3821FFF0
91410000 91610004
91810008 91A1000C
89430067 280A0009
408200A4 8943006C
280A0000 40820098
3D4080BD 614A5D60
3D60000B 616B203B
916A0000 39600B20
B16A0004 3960000B
996A0007 39600020
996A0008 39600F0D
B16A000A 39600000
818306BC 718C0001
280C0000 4182000C
60000000 396BFFFF
818306BC 718C0002
280C0000 4182000C
60000000 396B0001
898A0006 89AA0009
558C2036 7D8C6B78
7DAC5A14 71AD00FF
71AC00F0 71AD000F
558CE13E 998A0006
99AA0009 81410000
81610004 81810008
81A1000C 38210010
60000000 00000000
C211D0A4 0000000B
7FE6FB78 3821FFF0
91410000 91610004
91810008 895D006C
280A0000 40820024
60000000 3D4080BD
614A5D60 896A0006
898A0009 556B2036
7D6B6214 7D665B78
81410000 81610004
81810008 38210010
60000000 00000000

Hey guys, I have been messing around with Melee ASM a bit recently, and this was sort of a warmup to get more acquainted with it that I didn't want to keep to myself. It's probably a bit rough around the edges, so it's provided with no promises or guarantees haha.

It's made for version 1.2 btw

What this code does is allow P1 peach to pull any item 0x00 - 0xFF ( given it wont crash the game (: ). First enable your tag, then use dpad left / right to select the item ID. Pull a turnip and boom, item. The embedded video shows it in action.

It's not very useful, just a little toy I thought someone might find interesting.

 

Savestate

Smash Cadet
Joined
Apr 14, 2015
Messages
38
Location
Greensboro, NC
So, I don't know if anyone's tried this before, but I built a cross compiler for PowerPC targeted towards the Gamecube to see if I could write gecko codes for Melee in C. The assembly generated is pretty inefficient, but it might make developing prototypes for larger scale projects easier.

I first wrote this little C function to get the number of action states a player has made.

Code:
#define SSBM_func_CHARACTER_POINTER 0x80034110
#define SSBM_char_ACTION_STATES 0x20CC/sizeof(int)

int action_states(int player) {
    // 0x80034110 is the offset for the "get character data pointer"
    // pass into it the number of the player you want.
    // it returns a pointer to it.
    // 0-5
    unsigned int * (*get_character)(int) = SSBM_func_CHARACTER_POINTER;
    unsigned int *player_one = get_character(player);
    unsigned int total = player_one[SSBM_char_ACTION_STATES];
    // eg 80C6B900 -> 80C6D9CC
    // it's a half word, so shift it over
    total = total >> 16;
    return total;
}
I then compiled it with
Code:
powerpc-gamecube-elf-gcc -g -c test.c
to get an object file test.o

Afterwards, I ran it through objdump with some regex I made to produce some legible assembly
Code:
powerpc-gamecube-elf-objdump -d -M ppc -S test.o | sed -r 's/r1([^0-9])/sp\1/g' | sed -r 's/r1$/sp/g' | sed -r 's/^\s+[0-9|a-f]+:\s+[0-9|a-f]+\s+[0-9|a-f]+\s+[0-9|a-f]+\s+[0-9|a-f]+\s+//g'
the above produced this :
Code:
test.o:     file format elf32-powerpc


Disassembly of section .text:

00000000 <action_states>:
#define SSBM_func_CHARACTER_POINTER 0x80034110
#define SSBM_char_ACTION_STATES 0x20CC/sizeof(int)

int action_states(int player) {
stwu    sp,-48(sp)
mflr    r0
stw     r0,52(sp)
stw     r31,44(sp)
mr      r31,sp
stw     r3,24(r31)
    // 0x80034110 is the offset for the "get character data pointer"
    // pass into it the number of the player you want.
    // it returns a pointer to it.
    // 0-5
    unsigned int * (*get_character)(int) = SSBM_func_CHARACTER_POINTER;
lis     r9,-32765
ori     r9,r9,16656
stw     r9,8(r31)
    unsigned int *player_one = get_character(player);
lwz     r9,8(r31)
lwz     r3,24(r31)
mtctr   r9
bctrl
stw     r3,12(r31)
    unsigned int total = player_one[SSBM_char_ACTION_STATES];
lwz     r9,12(r31)
lwz     r9,8396(r9)
stw     r9,16(r31)
    // eg 80C6B900 -> 80C6D9CC
    // it's a half word, so shift it over
    total = total >> 16;
lwz     r9,16(r31)
rlwinm  r9,r9,16,16,31
stw     r9,16(r31)
    return total;
lwz     r9,16(r31)
}
mr      r3,r9
addi    r11,r31,48
lwz     r0,4(r11)
mtlr    r0
lwz     r31,-4(r11)
mr      sp,r11
blr
you can run it without -S to remove the insertion of the original C code (makes copy/pasting easier)

0x802F3B04 is the line of code that says what goes into the milliseconds slot in the timer (purely visual, doesn't affect actual internal milliseconds)
Code:
# code originally at 0x802F3B04
addi r24, r5, 0
# r24 is what will be displayed on the clock's milliseconds slot
I'm going to replace r24 with the number of action states player 1 has made.

I took the generated assembly, added a little extra to it to come up with this code, and injected it at 0x802F3B04
Code:
enter:
subi sp, sp, 4
stw r3, 0(sp)

li r3, 0
bl action_states

addi r24, r3, 0

exit:
lwz r3, 0(sp)
addi sp, sp, 4
b leave

action_states:
stwu    sp,-48(sp)
mflr    r0
stw     r0,52(sp)
stw     r31,44(sp)
mr      r31,sp
stw     r3,24(r31)
lis     r9,-32765
ori     r9,r9,16656
stw     r9,8(r31)
lwz     r9,8(r31)
lwz     r3,24(r31)
mtctr   r9
bctrl
stw     r3,12(r31)
lwz     r9,12(r31)
lwz     r9,8396(r9)
stw     r9,16(r31)
lwz     r9,16(r31)
rlwinm  r9,r9,16,16,31
stw     r9,16(r31)
lwz     r9,16(r31)
mr      r3,r9
addi    r11,r31,48
lwz     r0,4(r11)
mtlr    r0
lwz     r31,-4(r11)
mr      sp,r11
blr

leave:
nop
The following assembly generated this gecko code:
Code:
C22F3B04 00000013
3821FFFC 90610000
38600000 48000015
3B030000 80610000
38210004 48000074
9421FFD0 7C0802A6
90010034 93E1002C
7C3F0B78 907F0018
3D208003 61294110
913F0008 813F0008
807F0018 7D2903A6
4E800421 907F000C
813F000C 812920CC
913F0010 813F0010
5529843E 913F0010
813F0010 7D234B78
397F0030 800B0004
7C0803A6 83EBFFFC
7D615B78 4E800020
60000000 00000000
Which produced this result...

Like I said, I don't know if anyone's compiled C into assembly for Melee before.
If not, just a little something I thought I'd share with y'all.
 

Savestate

Smash Cadet
Joined
Apr 14, 2015
Messages
38
Location
Greensboro, NC
Alright, just a heads up. Don't use objdump for your ASM
I just realized that it doesn't work properly a lot of the time
Just compile your code with -S in GCC and deal with it being unreadable.
Even being unreadable though, it is very powerful (although, really verbose... I wish it compiled things a bit more efficiently haha)

I just compiled the following C code with powerpc-gamecube-elf-gcc -S

This C code loads the index number of the write-to-next position in the stale moves table for each character's stale moves table and puts them into the tag for player 1. I got the location of these through some research a buddy of mine was doing (they're now in the 1.2 datasheet)

Code:
// Specific stuff
#define SSBM_Staleness_Index_Location 0x8045313C
#define SSBM_Staleness_Index_Distance 0x0E90
#define SSBM_P1_Tag 0x80BD5D60
// Known Functions
#define SSBM_Count_Players_In_Match 0x8016B558
void set_tag_p1(char *tag, int length)
{
    if (length > 4) length = 4;
    if (length < 1) length = 1;
    int i;
    unsigned char *ram_tag = SSBM_P1_Tag;
    for (i=0; i<length; i++)
    {
        ram_tag[0] = tag[i];
        if (i != length-1)
        {
            ram_tag[1] = 0x0B;
            ram_tag[2] = 0x20;
        }
        else
        {
            ram_tag[1] = 0x0F;
            ram_tag[2] = 0x0D;
        }
        ram_tag = ram_tag + sizeof(char)*3;
    }
}
int stale_move_index(int player)
{
    unsigned int *location = SSBM_Staleness_Index_Location;
    unsigned int distance = (SSBM_Staleness_Index_Distance * player)/sizeof(int);
    return location[distance];
}
int set_p1_tag_to_staleness_slot_values()
{
    int * (*character_count)() = SSBM_Count_Players_In_Match;
    int total_characters = character_count();
    unsigned char tag[4];
    int i;
    for (i=0; i<total_characters; i++)
    {
        int index = stale_move_index(i);
        unsigned char index_char = (unsigned char)index;
        tag[i] = index_char;
    }
    set_tag_p1(tag, total_characters);
    return 0;
}
it outputted the following assembly file:

Code:
    .file    "slot_index_nametag.c"
    .section    ".text"
    .align 2
    .globl set_tag_p1
    .type    set_tag_p1, @function
set_tag_p1:
    stwu 1,-48(1)
    stw 31,44(1)
    mr 31,1
    stw 3,24(31)
    stw 4,28(31)
    lwz 9,28(31)
    cmpwi 7,9,4
    ble 7,.L2
    li 9,4
    stw 9,28(31)
.L2:
    lwz 9,28(31)
    cmpwi 7,9,0
    bgt 7,.L3
    li 9,1
    stw 9,28(31)
.L3:
    lis 9,0x80bd
    ori 9,9,23904
    stw 9,12(31)
    li 9,0
    stw 9,8(31)
    b .L4
.L7:
    lwz 9,8(31)
    lwz 10,24(31)
    add 9,10,9
    lbz 9,0(9)
    rlwinm 10,9,0,0xff
    lwz 9,12(31)
    stb 10,0(9)
    lwz 9,28(31)
    addi 10,9,-1
    lwz 9,8(31)
    cmpw 7,10,9
    beq 7,.L5
    lwz 9,12(31)
    addi 9,9,1
    li 10,11
    stb 10,0(9)
    lwz 9,12(31)
    addi 9,9,2
    li 10,32
    stb 10,0(9)
    b .L6
.L5:
    lwz 9,12(31)
    addi 9,9,1
    li 10,15
    stb 10,0(9)
    lwz 9,12(31)
    addi 9,9,2
    li 10,13
    stb 10,0(9)
.L6:
    lwz 9,12(31)
    addi 9,9,3
    stw 9,12(31)
    lwz 9,8(31)
    addi 9,9,1
    stw 9,8(31)
.L4:
    lwz 10,8(31)
    lwz 9,28(31)
    cmpw 7,10,9
    blt 7,.L7
    addi 11,31,48
    lwz 31,-4(11)
    mr 1,11
    blr
    .size    set_tag_p1, .-set_tag_p1
    .align 2
    .globl stale_move_index
    .type    stale_move_index, @function
stale_move_index:
    stwu 1,-48(1)
    stw 31,44(1)
    mr 31,1
    stw 3,24(31)
    lis 9,0x8045
    ori 9,9,12604
    stw 9,8(31)
    lwz 9,24(31)
    mulli 9,9,3728
    srwi 9,9,2
    stw 9,12(31)
    lwz 9,12(31)
    slwi 9,9,2
    lwz 10,8(31)
    add 9,10,9
    lwz 9,0(9)
    mr 3,9
    addi 11,31,48
    lwz 31,-4(11)
    mr 1,11
    blr
    .size    stale_move_index, .-stale_move_index
    .align 2
    .globl set_p1_tag_to_staleness_slot_values
    .type    set_p1_tag_to_staleness_slot_values, @function
set_p1_tag_to_staleness_slot_values:
    stwu 1,-48(1)
    mflr 0
    stw 0,52(1)
    stw 31,44(1)
    mr 31,1
    lis 9,0x8016
    ori 9,9,46424
    stw 9,12(31)
    lwz 9,12(31)
    mtctr 9
    bctrl
    mr 9,3
    stw 9,16(31)
    li 9,0
    stw 9,8(31)
    b .L11
.L12:
    lwz 3,8(31)
    bl stale_move_index
    stw 3,20(31)
    lwz 9,20(31)
    stb 9,24(31)
    addi 10,31,28
    lwz 9,8(31)
    add 9,10,9
    lbz 10,24(31)
    stb 10,0(9)
    lwz 9,8(31)
    addi 9,9,1
    stw 9,8(31)
.L11:
    lwz 10,8(31)
    lwz 9,16(31)
    cmpw 7,10,9
    blt 7,.L12
    addi 9,31,28
    mr 3,9
    lwz 4,16(31)
    bl set_tag_p1
    li 9,0
    mr 3,9
    addi 11,31,48
    lwz 0,4(11)
    mtlr 0
    lwz 31,-4(11)
    mr 1,11
    blr
    .size    set_p1_tag_to_staleness_slot_values, .-set_p1_tag_to_staleness_slot_values
    .ident    "GCC: (GNU) 4.8.4"
I then renamed my main function main and cut out the fluff that isn't used in asm <> wiird to get the following formatted asm

Code:
Inject into 0x8006AD28
(yes it gets run multiple times, but that's not the point here)

start:
subi r1,r1,4
stw r3,0(r1)

goto_main:
bl main

cleanup:
lwz r3,0(r1)
addi r1,r1,4

b exit

set_tag_p1:
    stwu 1,-48(1)
    stw 31,44(1)
    mr 31,1
    stw 3,24(31)
    stw 4,28(31)
    lwz 9,28(31)
    cmpwi 7,9,4
    ble 7,.L2
    li 9,4
    stw 9,28(31)
.L2:
    lwz 9,28(31)
    cmpwi 7,9,0
    bgt 7,.L3
    li 9,1
    stw 9,28(31)
.L3:
    lis 9,0x80bd
    ori 9,9,23904
    stw 9,12(31)
    li 9,0
    stw 9,8(31)
    b .L4
.L7:
    lwz 9,8(31)
    lwz 10,24(31)
    add 9,10,9
    lbz 9,0(9)
    rlwinm 10,9,0,0xff
    lwz 9,12(31)
    stb 10,0(9)
    lwz 9,28(31)
    addi 10,9,-1
    lwz 9,8(31)
    cmpw 7,10,9
    beq 7,.L5
    lwz 9,12(31)
    addi 9,9,1
    li 10,11
    stb 10,0(9)
    lwz 9,12(31)
    addi 9,9,2
    li 10,32
    stb 10,0(9)
    b .L6
.L5:
    lwz 9,12(31)
    addi 9,9,1
    li 10,15
    stb 10,0(9)
    lwz 9,12(31)
    addi 9,9,2
    li 10,13
    stb 10,0(9)
.L6:
    lwz 9,12(31)
    addi 9,9,3
    stw 9,12(31)
    lwz 9,8(31)
    addi 9,9,1
    stw 9,8(31)
.L4:
    lwz 10,8(31)
    lwz 9,28(31)
    cmpw 7,10,9
    blt 7,.L7
    addi 11,31,48
    lwz 31,-4(11)
    mr 1,11
    blr

stale_move_index:
    stwu 1,-48(1)
    stw 31,44(1)
    mr 31,1
    stw 3,24(31)
    lis 9,0x8045
    ori 9,9,12604
    stw 9,8(31)
    lwz 9,24(31)
    mulli 9,9,3728
    srwi 9,9,2
    stw 9,12(31)
    lwz 9,12(31)
    slwi 9,9,2
    lwz 10,8(31)
    add 9,10,9
    lwz 9,0(9)
    mr 3,9
    addi 11,31,48
    lwz 31,-4(11)
    mr 1,11
    blr

main:
    stwu 1,-48(1)
    mflr 0
    stw 0,52(1)
    stw 31,44(1)
    mr 31,1
    lis 9,0x8016
    ori 9,9,46424
    stw 9,12(31)
    lwz 9,12(31)
    mtctr 9
    bctrl
    mr 9,3
    stw 9,16(31)
    li 9,0
    stw 9,8(31)
    b .L11
.L12:
    lwz 3,8(31)
    bl stale_move_index
    stw 3,20(31)
    lwz 9,20(31)
    stb 9,24(31)
    addi 10,31,28
    lwz 9,8(31)
    add 9,10,9
    lbz 10,24(31)
    stb 10,0(9)
    lwz 9,8(31)
    addi 9,9,1
    stw 9,8(31)
.L11:
    lwz 10,8(31)
    lwz 9,16(31)
    cmpw 7,10,9
    blt 7,.L12
    addi 9,31,28
    mr 3,9
    lwz 4,16(31)
    bl set_tag_p1
    li 9,0
    mr 3,9
    addi 11,31,48
    lwz 0,4(11)
    mtlr 0
    lwz 31,-4(11)
    mr 1,11
    blr

exit:

replaced:
    mr r30, r3
The code above outputs the gecko code...
Code:
C206AD28 00000045
3821FFFC 90610000
48000165 80610000
38210004 4800020C
9421FFD0 93E1002C
7C3F0B78 907F0018
909F001C 813F001C
2F890004 409D000C
39200004 913F001C
813F001C 2F890000
419D000C 39200001
913F001C 3D2080BD
61295D60 913F000C
39200000 913F0008
48000090 813F0008
815F0018 7D2A4A14
89290000 552A063E
813F000C 99490000
813F001C 3949FFFF
813F0008 7F8A4800
419E0028 813F000C
39290001 3940000B
99490000 813F000C
39290002 39400020
99490000 48000024
813F000C 39290001
3940000F 99490000
813F000C 39290002
3940000D 99490000
813F000C 39290003
913F000C 813F0008
39290001 913F0008
815F0008 813F001C
7F8A4800 419CFF68
397F0030 83EBFFFC
7D615B78 4E800020
9421FFD0 93E1002C
7C3F0B78 907F0018
3D208045 6129313C
913F0008 813F0018
1D290E90 5529F0BE
913F000C 813F000C
5529103A 815F0008
7D2A4A14 81290000
7D234B78 397F0030
83EBFFFC 7D615B78
4E800020 9421FFD0
7C0802A6 90010034
93E1002C 7C3F0B78
3D208016 6129B558
913F000C 813F000C
7D2903A6 4E800421
7C691B78 913F0010
39200000 913F0008
48000038 807F0008
4BFFFF69 907F0014
813F0014 993F0018
395F001C 813F0008
7D2A4A14 895F0018
99490000 813F0008
39290001 913F0008
815F0008 813F0010
7F8A4800 419CFFC0
393F001C 7D234B78
809F0010 4BFFFE1D
39200000 7D234B78
397F0030 800B0004
7C0803A6 83EBFFFC
7D615B78 4E800020
7C7E1B78 00000000
View it in action:


This is pretty useless, but I am kinda demoing using C to hack melee.
 
Joined
Oct 10, 2011
Messages
1,126
Location
Boise, ID
NNID
dansalvato
Alright, just a heads up. Don't use objdump for your ASM
I just realized that it doesn't work properly a lot of the time
Just compile your code with -S in GCC and deal with it being unreadable.
Even being unreadable though, it is very powerful (although, really verbose... I wish it compiled things a bit more efficiently haha)

I just compiled the following C code with powerpc-gamecube-elf-gcc -S

This C code loads the index number of the write-to-next position in the stale moves table for each character's stale moves table and puts them into the tag for player 1. I got the location of these through some research a buddy of mine was doing (they're now in the 1.2 datasheet)

Code:
// Specific stuff
#define SSBM_Staleness_Index_Location 0x8045313C
#define SSBM_Staleness_Index_Distance 0x0E90
#define SSBM_P1_Tag 0x80BD5D60
// Known Functions
#define SSBM_Count_Players_In_Match 0x8016B558
void set_tag_p1(char *tag, int length)
{
    if (length > 4) length = 4;
    if (length < 1) length = 1;
    int i;
    unsigned char *ram_tag = SSBM_P1_Tag;
    for (i=0; i<length; i++)
    {
        ram_tag[0] = tag[i];
        if (i != length-1)
        {
            ram_tag[1] = 0x0B;
            ram_tag[2] = 0x20;
        }
        else
        {
            ram_tag[1] = 0x0F;
            ram_tag[2] = 0x0D;
        }
        ram_tag = ram_tag + sizeof(char)*3;
    }
}
int stale_move_index(int player)
{
    unsigned int *location = SSBM_Staleness_Index_Location;
    unsigned int distance = (SSBM_Staleness_Index_Distance * player)/sizeof(int);
    return location[distance];
}
int set_p1_tag_to_staleness_slot_values()
{
    int * (*character_count)() = SSBM_Count_Players_In_Match;
    int total_characters = character_count();
    unsigned char tag[4];
    int i;
    for (i=0; i<total_characters; i++)
    {
        int index = stale_move_index(i);
        unsigned char index_char = (unsigned char)index;
        tag[i] = index_char;
    }
    set_tag_p1(tag, total_characters);
    return 0;
}
it outputted the following assembly file:

Code:
    .file    "slot_index_nametag.c"
    .section    ".text"
    .align 2
    .globl set_tag_p1
    .type    set_tag_p1, @function
set_tag_p1:
    stwu 1,-48(1)
    stw 31,44(1)
    mr 31,1
    stw 3,24(31)
    stw 4,28(31)
    lwz 9,28(31)
    cmpwi 7,9,4
    ble 7,.L2
    li 9,4
    stw 9,28(31)
.L2:
    lwz 9,28(31)
    cmpwi 7,9,0
    bgt 7,.L3
    li 9,1
    stw 9,28(31)
.L3:
    lis 9,0x80bd
    ori 9,9,23904
    stw 9,12(31)
    li 9,0
    stw 9,8(31)
    b .L4
.L7:
    lwz 9,8(31)
    lwz 10,24(31)
    add 9,10,9
    lbz 9,0(9)
    rlwinm 10,9,0,0xff
    lwz 9,12(31)
    stb 10,0(9)
    lwz 9,28(31)
    addi 10,9,-1
    lwz 9,8(31)
    cmpw 7,10,9
    beq 7,.L5
    lwz 9,12(31)
    addi 9,9,1
    li 10,11
    stb 10,0(9)
    lwz 9,12(31)
    addi 9,9,2
    li 10,32
    stb 10,0(9)
    b .L6
.L5:
    lwz 9,12(31)
    addi 9,9,1
    li 10,15
    stb 10,0(9)
    lwz 9,12(31)
    addi 9,9,2
    li 10,13
    stb 10,0(9)
.L6:
    lwz 9,12(31)
    addi 9,9,3
    stw 9,12(31)
    lwz 9,8(31)
    addi 9,9,1
    stw 9,8(31)
.L4:
    lwz 10,8(31)
    lwz 9,28(31)
    cmpw 7,10,9
    blt 7,.L7
    addi 11,31,48
    lwz 31,-4(11)
    mr 1,11
    blr
    .size    set_tag_p1, .-set_tag_p1
    .align 2
    .globl stale_move_index
    .type    stale_move_index, @function
stale_move_index:
    stwu 1,-48(1)
    stw 31,44(1)
    mr 31,1
    stw 3,24(31)
    lis 9,0x8045
    ori 9,9,12604
    stw 9,8(31)
    lwz 9,24(31)
    mulli 9,9,3728
    srwi 9,9,2
    stw 9,12(31)
    lwz 9,12(31)
    slwi 9,9,2
    lwz 10,8(31)
    add 9,10,9
    lwz 9,0(9)
    mr 3,9
    addi 11,31,48
    lwz 31,-4(11)
    mr 1,11
    blr
    .size    stale_move_index, .-stale_move_index
    .align 2
    .globl set_p1_tag_to_staleness_slot_values
    .type    set_p1_tag_to_staleness_slot_values, @function
set_p1_tag_to_staleness_slot_values:
    stwu 1,-48(1)
    mflr 0
    stw 0,52(1)
    stw 31,44(1)
    mr 31,1
    lis 9,0x8016
    ori 9,9,46424
    stw 9,12(31)
    lwz 9,12(31)
    mtctr 9
    bctrl
    mr 9,3
    stw 9,16(31)
    li 9,0
    stw 9,8(31)
    b .L11
.L12:
    lwz 3,8(31)
    bl stale_move_index
    stw 3,20(31)
    lwz 9,20(31)
    stb 9,24(31)
    addi 10,31,28
    lwz 9,8(31)
    add 9,10,9
    lbz 10,24(31)
    stb 10,0(9)
    lwz 9,8(31)
    addi 9,9,1
    stw 9,8(31)
.L11:
    lwz 10,8(31)
    lwz 9,16(31)
    cmpw 7,10,9
    blt 7,.L12
    addi 9,31,28
    mr 3,9
    lwz 4,16(31)
    bl set_tag_p1
    li 9,0
    mr 3,9
    addi 11,31,48
    lwz 0,4(11)
    mtlr 0
    lwz 31,-4(11)
    mr 1,11
    blr
    .size    set_p1_tag_to_staleness_slot_values, .-set_p1_tag_to_staleness_slot_values
    .ident    "GCC: (GNU) 4.8.4"
I then renamed my main function main and cut out the fluff that isn't used in asm <> wiird to get the following formatted asm

Code:
Inject into 0x8006AD28
(yes it gets run multiple times, but that's not the point here)

start:
subi r1,r1,4
stw r3,0(r1)

goto_main:
bl main

cleanup:
lwz r3,0(r1)
addi r1,r1,4

b exit

set_tag_p1:
    stwu 1,-48(1)
    stw 31,44(1)
    mr 31,1
    stw 3,24(31)
    stw 4,28(31)
    lwz 9,28(31)
    cmpwi 7,9,4
    ble 7,.L2
    li 9,4
    stw 9,28(31)
.L2:
    lwz 9,28(31)
    cmpwi 7,9,0
    bgt 7,.L3
    li 9,1
    stw 9,28(31)
.L3:
    lis 9,0x80bd
    ori 9,9,23904
    stw 9,12(31)
    li 9,0
    stw 9,8(31)
    b .L4
.L7:
    lwz 9,8(31)
    lwz 10,24(31)
    add 9,10,9
    lbz 9,0(9)
    rlwinm 10,9,0,0xff
    lwz 9,12(31)
    stb 10,0(9)
    lwz 9,28(31)
    addi 10,9,-1
    lwz 9,8(31)
    cmpw 7,10,9
    beq 7,.L5
    lwz 9,12(31)
    addi 9,9,1
    li 10,11
    stb 10,0(9)
    lwz 9,12(31)
    addi 9,9,2
    li 10,32
    stb 10,0(9)
    b .L6
.L5:
    lwz 9,12(31)
    addi 9,9,1
    li 10,15
    stb 10,0(9)
    lwz 9,12(31)
    addi 9,9,2
    li 10,13
    stb 10,0(9)
.L6:
    lwz 9,12(31)
    addi 9,9,3
    stw 9,12(31)
    lwz 9,8(31)
    addi 9,9,1
    stw 9,8(31)
.L4:
    lwz 10,8(31)
    lwz 9,28(31)
    cmpw 7,10,9
    blt 7,.L7
    addi 11,31,48
    lwz 31,-4(11)
    mr 1,11
    blr

stale_move_index:
    stwu 1,-48(1)
    stw 31,44(1)
    mr 31,1
    stw 3,24(31)
    lis 9,0x8045
    ori 9,9,12604
    stw 9,8(31)
    lwz 9,24(31)
    mulli 9,9,3728
    srwi 9,9,2
    stw 9,12(31)
    lwz 9,12(31)
    slwi 9,9,2
    lwz 10,8(31)
    add 9,10,9
    lwz 9,0(9)
    mr 3,9
    addi 11,31,48
    lwz 31,-4(11)
    mr 1,11
    blr

main:
    stwu 1,-48(1)
    mflr 0
    stw 0,52(1)
    stw 31,44(1)
    mr 31,1
    lis 9,0x8016
    ori 9,9,46424
    stw 9,12(31)
    lwz 9,12(31)
    mtctr 9
    bctrl
    mr 9,3
    stw 9,16(31)
    li 9,0
    stw 9,8(31)
    b .L11
.L12:
    lwz 3,8(31)
    bl stale_move_index
    stw 3,20(31)
    lwz 9,20(31)
    stb 9,24(31)
    addi 10,31,28
    lwz 9,8(31)
    add 9,10,9
    lbz 10,24(31)
    stb 10,0(9)
    lwz 9,8(31)
    addi 9,9,1
    stw 9,8(31)
.L11:
    lwz 10,8(31)
    lwz 9,16(31)
    cmpw 7,10,9
    blt 7,.L12
    addi 9,31,28
    mr 3,9
    lwz 4,16(31)
    bl set_tag_p1
    li 9,0
    mr 3,9
    addi 11,31,48
    lwz 0,4(11)
    mtlr 0
    lwz 31,-4(11)
    mr 1,11
    blr

exit:

replaced:
    mr r30, r3
The code above outputs the gecko code...
Code:
C206AD28 00000045
3821FFFC 90610000
48000165 80610000
38210004 4800020C
9421FFD0 93E1002C
7C3F0B78 907F0018
909F001C 813F001C
2F890004 409D000C
39200004 913F001C
813F001C 2F890000
419D000C 39200001
913F001C 3D2080BD
61295D60 913F000C
39200000 913F0008
48000090 813F0008
815F0018 7D2A4A14
89290000 552A063E
813F000C 99490000
813F001C 3949FFFF
813F0008 7F8A4800
419E0028 813F000C
39290001 3940000B
99490000 813F000C
39290002 39400020
99490000 48000024
813F000C 39290001
3940000F 99490000
813F000C 39290002
3940000D 99490000
813F000C 39290003
913F000C 813F0008
39290001 913F0008
815F0008 813F001C
7F8A4800 419CFF68
397F0030 83EBFFFC
7D615B78 4E800020
9421FFD0 93E1002C
7C3F0B78 907F0018
3D208045 6129313C
913F0008 813F0018
1D290E90 5529F0BE
913F000C 813F000C
5529103A 815F0008
7D2A4A14 81290000
7D234B78 397F0030
83EBFFFC 7D615B78
4E800020 9421FFD0
7C0802A6 90010034
93E1002C 7C3F0B78
3D208016 6129B558
913F000C 813F000C
7D2903A6 4E800421
7C691B78 913F0010
39200000 913F0008
48000038 807F0008
4BFFFF69 907F0014
813F0014 993F0018
395F001C 813F0008
7D2A4A14 895F0018
99490000 813F0008
39290001 913F0008
815F0008 813F0010
7F8A4800 419CFFC0
393F001C 7D234B78
809F0010 4BFFFE1D
39200000 7D234B78
397F0030 800B0004
7C0803A6 83EBFFFC
7D615B78 4E800020
7C7E1B78 00000000
View it in action:


This is pretty useless, but I am kinda demoing using C to hack melee.
You should definitely make a new thread for this. I think a ton of people will be interested in supporting this project of yours.
 

Savestate

Smash Cadet
Joined
Apr 14, 2015
Messages
38
Location
Greensboro, NC
You should definitely make a new thread for this. I think a ton of people will be interested in supporting this project of yours.
I'm planning on it! But before I do, I want to get a port of the powerpc-gamecube-elf toolchain I built working running on Windows due to that being the OS of the masses. I wish I could count how many hours of sleep I've lost trying to get it to work... but it's just about done I believe; I have just a little more to do.
Once I get that finished and working, I'll make a write up for people to get started on writing Melee codes with C (and C++ technically since I'm building the toolchain with support for it, but it will be XTRA verbose no doubt haha).
 
Last edited:
Joined
Oct 10, 2011
Messages
1,126
Location
Boise, ID
NNID
dansalvato
I'm planning on it! But before I do, I want to get a port of the powerpc-gamecube-elf toolchain I built working running on Windows due to that being the OS of the masses. I wish I could count how many hours of sleep I've lost trying to get it to work... but it's just about done I believe; I have just a little more to do.
Once I get that finished and working, I'll make a write up for people to get started on writing Melee codes with C (and C++ technically since I'm building the toolchain with support for it, but it will be XTRA verbose no doubt haha).
Are you using the tools provided with devkitpro? http://devkitpro.org/
I haven't looked at it in a while but I believe it provides everything needed for Windows.
 

Savestate

Smash Cadet
Joined
Apr 14, 2015
Messages
38
Location
Greensboro, NC
Are you using the tools provided with devkitpro? http://devkitpro.org/
I haven't looked at it in a while but I believe it provides everything needed for Windows.
No, I built it with MinGW.
I didn't realize that site existed actually! (I'm still a n00b at a lot of this stuff)
I'm currently installing it to see how much time I actually wasted doing it myself haha.
 

SinsOfApathy

Smash Journeyman
Joined
Feb 24, 2015
Messages
474
NNID
Psion312
No, I built it with MinGW.
I didn't realize that site existed actually! (I'm still a n00b at a lot of this stuff)
I'm currently installing it to see how much time I actually wasted doing it myself haha.
Oh christ, dude. I saw your post and thought you were using devkitPro, since I've made the suggestion to use C a number of times lol
 

Savestate

Smash Cadet
Joined
Apr 14, 2015
Messages
38
Location
Greensboro, NC
Oh christ, dude. I saw your post and thought you were using devkitPro, since I've made the suggestion to use C a number of times lol
Haha nah,
I built it originally on Linux (which is generally much better for building cross compilers) and it didn't take but one try, building it on Windows though took nearly 12 hours. You can imagine how I felt when Dan told me it was already done haha. (emphasis on how much of a n00b i am) I made the thread in the melee workshop board for building codes in C last night and listed devkitpro as the compiler of choice since he pointed it out.

I haven't been around these forums too much, so I haven't seen your posts about it yet, but I'm working on a gameplay mod for peach that I'm building in C. In short, it's monado arts for peach, except instead of character buff changes, it's item type changes. I'm also implementing a timer feature for it similar to how shulk can only use it for so long before going back to neutral (and can't use it for a while after)
 

undergroundmonorail

Smash Cadet
Joined
Oct 20, 2014
Messages
28
Location
Hamilton, Ontario
Something like this has probably been done before, but I didn't feel like looking and it seemed easy to do myself.

Code:
Loop time above 8:00 [monorail]
2046B6C8 000001E1
0446B6C8 0000021D
It's very simple. Any time there are 8 minutes and 1 second left in the game, the remaining time is set to 9:01 instead. Setting the match time to anything above 8 minutes means time will never run out, but you can still see Randall timings :)
 

SinsOfApathy

Smash Journeyman
Joined
Feb 24, 2015
Messages
474
NNID
Psion312
I think he's referring to the one that isn't even done yet.
Ah, that explains it.

I've made some modifications to the Char Data Offsets portion of the spreadsheet, since some things were outright incorrect (0x0C isn't next player, and none of them point to last player), among other things like incorrect notes. In addition, I added information on the linked list structs and various other missing things like item duration.
 
Last edited:

god_cyndaquil

Smash Rookie
Joined
Aug 18, 2015
Messages
16
Ah, that explains it.

I've made some modifications to the Char Data Offsets portion of the spreadsheet, since some things were outright incorrect (0x0C isn't next player, and none of them point to last player), among other things like incorrect notes. In addition, I added information on the linked list structs and various other missing things like item duration.
than can i get the closest thing to it
 

SinsOfApathy

Smash Journeyman
Joined
Feb 24, 2015
Messages
474
NNID
Psion312
than can i get the closest thing to it
It was literally linked in DoctorKirby's post.

In other news, I've added the Entity Data Offsets page to the spreadsheet. This has the generic entity struct, item spawn struct, player spawn struct, and the camera struct.

The camera struct is available on the first page of the spreadsheet, but after making sure everything is moved over, I'll be removing it from the first portion (Except maybe the start address). I feel that it's better that we move to this type of layout used by the Char Data page, instead of the current dropping arbitrary addresses everywhere.

Likewise, I've adjusted a few things on the Char Data portion and added a missing attribute.
 

flieskiller

Smash Journeyman
Joined
Jan 3, 2013
Messages
426
I didn't check in 20XX training pack if it was in it, but I'm planning to do in a few days: Replace rumble on/off from name tags to tap jump on/off (combined with Rumble settings at CSS from 20XX TE)
 

Absolome

Smash Cadet
Joined
Jan 3, 2014
Messages
68
Location
Asheville, NC
I've been working on making a symbol map for melee (dolphin) that gives names to as many functions as I can figure out, I have around 150 newly named functions right now. The more that get named the easier it is to figure out what a function is doing, for example seeing a branch to something like "RemoveInstantItem" immediately gives you a much easier time figuring out what that function is there for.

Has anyone done something similar to this? And would anyone be interested in a copy of the (still very much in development) current map?
 
Joined
Oct 10, 2011
Messages
1,126
Location
Boise, ID
NNID
dansalvato
I've been working on making a symbol map for melee (dolphin) that gives names to as many functions as I can figure out, I have around 150 newly named functions right now. The more that get named the easier it is to figure out what a function is doing, for example seeing a branch to something like "RemoveInstantItem" immediately gives you a much easier time figuring out what that function is there for.

Has anyone done something similar to this? And would anyone be interested in a copy of the (still very much in development) current map?
We should talk more about this. I think the community would benefit hugely from a shared symbol map with some naming scheme guidelines, etc. We should figure something out that makes pushing/pulling symbol map updates very easy so that people are encouraged to do it often.
 

Absolome

Smash Cadet
Joined
Jan 3, 2014
Messages
68
Location
Asheville, NC
We should talk more about this. I think the community would benefit hugely from a shared symbol map with some naming scheme guidelines, etc. We should figure something out that makes pushing/pulling symbol map updates very easy so that people are encouraged to do it often.
I would be extremely interested in this, it's basically already the project I'm working on now! That's why I was pestering your Ask.fm recently about releasing functions you found while making TE.

Soon I'm going to try to clean up the unknown/sloppy function names I have in my map and I'll publish it in its current (very unfinished) form. It'd be fairly easy to publish as a simple smashboards post that I update since the map file is just text
 

flieskiller

Smash Journeyman
Joined
Jan 3, 2013
Messages
426
Absolome Absolome I have some:
8026d324 = if current item is at ON (r3 = item ID)
80224fdc = item spawning point? (choose a coordinate in the map)

Are you looking for generic functions that can be called from anywhere or all functions?

Also, wParam's searches surely has a bunch of them, if you want to navigate through that:
http://wparam.com/ssbm/SSBMScratchpad.txt
 

Absolome

Smash Cadet
Joined
Jan 3, 2014
Messages
68
Location
Asheville, NC
Absolome Absolome I have some:
8026d324 = if current item is at ON (r3 = item ID)
80224fdc = item spawning point? (choose a coordinate in the map)

Are you looking for generic functions that can be called from anywhere or all functions?

Also, wParam's searches surely has a bunch of them, if you want to navigate through that:
http://wparam.com/ssbm/SSBMScratchpad.txt
Thanks!

I'm looking for all functions, anything that can be given a name to help speed up the process of identifying what's going on in the code.

I've scubbed through all of wParam's notes available and I've pulled any useful info on functions into the map, that's actually where I started! A lot of the functions listed in those notes are almost correct, but a little bit off, so I've had to do a lot of editing and checking
 

flieskiller

Smash Journeyman
Joined
Jan 3, 2013
Messages
426
Disable Float Jump (1.02) [flieskiller]
040cba34 48000060

This function is the air animation every frame, but goes through all of it when a character jumps and check the character internal ID if it has a float jump (Peach, Ness, Mewtwo, Yoshi). This branch skips all of these conditions and make all characters go through the normal jump.

Yoshi loses his double jump armor (means it's related to a function; hard-coded directly to Yoshi in the DOL instead of inside his character file?), but Peach keeps her levitation.
 

flieskiller

Smash Journeyman
Joined
Jan 3, 2013
Messages
426
name tag toggle = tap jump toggle (1.02) [flieskiller, Achilles1515]
0423c128 38600001
04167810 60000000
C20CBA30 0000000B
3DC08048 61CE082A
8A180678 1E100024
7E0E80AE 2C100078
40800038 3DC08045
61CED859 1E1001A4
7E0E80AE 2C100000
40820020 89FD06BE
2C0F0004 40800014
3DC0800C 61CEBA9C
7DC903A6 4E800420
801E0004 00000000
C20CB4E0 00000009
3DC08048 61CE082A
8A180678 1E100024
7E0E80AE 2C100078
40800028 3DC08045
61CED859 1E1001A4
7E0E80AE 2C100000
40820010 2C040001
40820008 4E800020
7C0802A6 00000000

Based on Achilles' stuff on Tap Jump from 20XX, I've improved it so that the name tag toggle (from Rumble menu) acts as a Tap Jump toggle instead of a Rumble toggle. Maybe it could be added for next version of 20XX? (not 20XXTE, to anyone curious: it's written that tap jump toggle wouldn't be toggleable)

The code works for all jumps, except Jigglypuff and Kirby's aerial jumps (they're balloons, so it's not a dramatic thing).

edit: modified a condition that checks the flag. Now rumble must be set at 0 for tap jump to work, with ON being the default behavior if the player has more than 8 letters tag (thus replacing the rumble flag)

UNTESTED: Rumble is only active if the player's port is set at ON (the controllers on the left side of the Rumble menu).

Theorically, it should be working with 20XXTE rumble toggle within the CSS:
taken from this page: http://www.20xx.me/blog/toggling-rumble-the-te-way

20XXTE rumble toggle (1.02) [Dan Salvato]
C22608D8 00000019
887F0007 2C030000
40820070 7C972378
57800739 40820010
5780077B 40820034
4800009C 7EE3BB78
38800000 38A0000E
38C00000 38ED9950
3D808037 618C8430
7D8903A6 4E800421
38800001 48000008
38800000 7EE3BB78
3D808015 618CED4C
7D8903A6 4E800421
38800001 989F0007
3C80C040 909F0014
C03F0014 C0428E0C
C01F000C EC01002A
D01F000C FC600850
FC030840 41810008
EC6300B2 D07F0014
4180001C C0828258
FC032040 41810010
38800000 909F0014
989F0007 889F0004
60000000 00000000

ASM notes:
new name has always rumble ON (1.02) [flieskiller]
0423c128 38600001

This is based normally on the controller's port (port OFF = name rumble OFF). Always ON = ON per default for Tap Jump

player port is always used for rumble
04167810 60000000

This skip the branch that checks if the player has a tag, and always go in the part that the name is at OFF, always using the controller port's rumble setting.

#part 1, aerial jump
800cba30

lis r14, 0x8048
ori r14, r14, 0x082A #name ID of player 1
lbz r16, 0x0678 (r24) #r16 = player ID
mulli r16, r16, 0x24 #number of the jumping player
lbzx r16, r14, r16 #r16 = name ID
cmpwi r16, 120 # if character has no ID, tap jump on
bge TAPJUMPON
lis r14, 0x8045
ori r14, r14, 0xD859 #start of name table
mulli r16, r16, 0x1a4
lbzx r16, r14, r16 #r16 = rumble of name ID
cmpwi r16, 1
beq TAPJUMPON
lbz r15, 0x06BE (r29)
cmpwi r15, 4 #check if the jump is from control stick or X/Y
bge TAPJUMPON
lis r14, 0x800c
ori r14, r14, 0xba9c
mtctr r14
bctr #skip the jump action
TAPJUMPON:
lwz r0, 0x0004 (r30) #normal line

#part 2, ground jump
800CB4E0

lis r14, 0x8048
ori r14, r14, 0x082A #name ID of player 1
lbz r16, 0x0678 (r24) #r16 = player ID
mulli r16, r16, 0x24 #number of the jumping player
lbzx r16, r14, r16 #r16 = name ID
cmpwi r16, 120 # if character has no ID, tap jump on
bge TAPJUMPON
lis r14, 0x8045
ori r14, r14, 0xD859 #start of name table
mulli r16, r16, 0x1a4
lbzx r16, r14, r16 #r16 = rumble of name ID
cmpwi r16, 1
beq TAPJUMPON
cmpwi r4,1 #check if the jump is from control stick or X/Y
bne TAPJUMPON
blr #don't execute the function
TAPJUMPON:
mflr 0 #normal line
 
Last edited:

flieskiller

Smash Journeyman
Joined
Jan 3, 2013
Messages
426
exported from the Crazy Mod. Just paste anywhere and bl to it with these registers
r3 = player number
r4 = single-point float (will be converted from r4 to float register for adding as float)

function: self-damage to player (wParam)
7C0802A6 90010004
9421FFF0 90810008
3DE08003 61EF4110
7DE803A6 4E800021
2C030000 4182001C
8063002C C0210008
3DE08006 61EFCC7C
7DE803A6 4E800021
80010014 38210010
7C0803A6 4E800020
 

flieskiller

Smash Journeyman
Joined
Jan 3, 2013
Messages
426
Dan Salvato Dan Salvato What is the code to make that the reset button goes to the debug menu instead of the start screen?

edit: forgot about the function in SSBM document

reset button goes to debug menu
041a4258 38600006

edit2: ^ This doesn't work on a Gamecube, searching later.
 
Last edited:
Top Bottom