• 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!

How to Add Frame Speed Modifiers via ASM coding. (courtesy of Magus)

Ripple

ᗣᗣᗣᗣ ᗧ·····•·····
Joined
Sep 4, 2006
Messages
9,632
Magus said:
Animation Engine

This DOL injectable code I created will allow you to modify the animation speed for characters based on the character (or wildcard/character independent), the current animation frame, and current action or subaction. You could for example make Bowser's d-tilt play at 1.4x speed during frames 1-14, making it hit on frame 10 instead of 14.


Code:
SSBM v1.00

17A0        DOL - Injected Function (Animation Engine)
19D0        DOL - Frame Speed Mod (FSM) Entries
6FDA4       DOL - ASM Injection Point

800047A0    RAM - Injected Function (Animation Engine)
800049D0    RAM - Frame Speed Mod (FSM) Entries
800731C4    RAM - ASM Injection Point


@17A0 (1.00 DOL - Injected Function)
7F63DB78 8BE3006C
3FA08045 63BD10C4
1FFF0E90 7FFDFA14
809F0000 8BFF0008
2C040013 4182001C
2C040012 40A20020
2C1F0001 40A20018
38800013 48000010
2C1F0001 40A20008
38800012 C03E0894
FC20081E D8220000
80A20004 80C30070
80E30074 60E78000
3FE08000 63FF49C8
87BF0008 2C1D0000
41820060 57BC463E
2C1C00FF 41820014
7C1C2000 4182000C
41810048 4BFFFFDC
57BC863E 7C1C2800
41A1FFD0 57BC043E
7C1C3000 4182000C
7C1C3800 4082FFBC
839F0004 2C1CFFFF
41820018 C03F0004
3FE08006 63FFF034
7FE803A6 4E800021
BB610014 4806E94C

This is where the flow of code is modified to be redirected to at the end of an update animation frame and script timers function that runs each frame. It checks character ID, current animation frame, current action, and current subaction against a list of entries with these paired with floats that will modify animation speed when they match. With a match the code is then branched to a function that modifies animation speed for aerial/special landings (can be hijacked just fine for anything though) that is fed the float from the FSM entry, applied, then returns to the custom function before returning to after the original injection point.

It's written to a location in the dol that appears to be unused and unread by the game.


Code:
mr    r3,r27        [GET CHARACTER ID] moves an index address into r3 needed in function
lbz    r31,108(r3)    loads player number
lis    r29,0x8045
ori    r29,r29,0x10C4    804510C4. player 1 character ID
mulli    r31,r31,3728    players are 0xE90 apart
add    r31,r29,r31
lwz    r4,0(r31)    loads character ID
lbz    r31,8(r31)    loads secondary instance flag
cmpwi    r4,19        Sheik/Zelda ID
beq-    0x1C        go to "SHEIK/ZELDA"
cmpwi    r4,18        Zelda/Sheik ID
bne+    0x20        go to "GET ACTION, SUBACTION, & FRAME" if not Zelda or Sheik

cmpwi    r31,1        [DETERMINE ZELDA OR SHEIK][ZELDA/SHEIK] Zelda/Sheik & secondary instance = Sheik
bne+    0x18        go to "GET ACTION, SUBACTION, & FRAME" if not secondary instance
li    r4,19        Set Sheik as character ID
b    0x10        go to "GET ACTION, SUBACTION, & FRAME" [/ZELDA/SHEIK]

cmpwi    r31,1        [SHEIK/ZELDA] Sheik/Zelda & secondary instance = Zelda
bne+    0x8        go to "GET ACTION, SUBACTION, & FRAME" if not secondary instance
li    r4,18        Set Zelda as character ID [/SHEIK/ZELDA][/DETERMINE ZELDA OR SHEIK][/GET CHARACTER ID]

lfs    f1,2196(r30)    [GET ACTION, SUBACTION, & FRAME] loads current animation frame
fctiwz    f1,f1        converts animation frame to int, rounded towards zero
stfd    f1,0(r2)    stores int animation frame
lwz    r5,4(r2)    loads current animation frame into normal register
lwz    r6,112(r3)    loads current action
lwz    r7,116(r3)    loads current subaction
ori    r7,r7,0x8000    changes it to 00008XXX [/GET ACTION, SUBACTION, & FRAME]

lis    r31,0x8000
ori    r31,r31,0x49C8    800049C8. 0x8 before 1st FSM entry

lwzu    r29,8(r31)    [FSM ENTRY CHECK LOOP] loads fsm entry (ex: 11078072)
cmpwi    r29,0        00000000 inidicates end of list
beq-    0x60        skip code if no matches in list

rlwinm    r28,r29,8,24,31    extracts leftmost byte (character id; ex: 11078072 -> 00000011)
cmpwi    r28,255        wild card (FF) character ID check
beq-    0x14        continue to animation frame check if wild card match
cmpw    r28,r4        compares char id to char id in fsm line
beq-    0xC        continue to animation frame check if character ID match
bgt-    0x48        skip code if entries for character have been passed
b    -0x24        loops to go on to next entry if character's entries haven't been reached yet

rlwinm    r28,r29,16,24,31    extracts 2nd from left byte (FSM timer; ex: 11078072 -> 00000007)
cmpw    r28,r5        compares to current frame
bgt-    -0x30        loops to go on to next entry if animation frame is before FSM entry's timer

rlwinm    r28,r29,0,16,31    extracts right 2 bytes (action/subaction; ex: 11078072 -> 00008072)
cmpw    r28,r6        compares action/subaction entry to current action
beq-    0xC        go to "CHECK IF FSM OF 1" if match
cmpw    r28,r7        compares action/subaction entry to current subaction
bne+    -0x44        loops to go on to next entry if no action/subaction match [/FSM ENTRY CHECK LOOP]

lwz    r28,4(r31)    [CHECK IF FSM END] loads FSM speed entry as word
cmpwi    r28,-1        FFFFFFFF
beq-    0x18        skip code if frame speed of 1 (so smash charges can work) [/CHECK IF FSM END]

lfs    f1,4(r31)    [GO TO FRAME SPEED FUNCTION] loads float from FSM to be applied
lis    r31,0x8006
ori    r31,r31,0xF034    8006F034. function used to change frame speed (on landing animations)
mtlr    r31
blrl            go to frame speed function [/GO TO FRAME SPEED FUNCTION]

lmw    r27,20(r1)    entry point (800731C4). restores r27-r31 from stack


@6FDA4 (1.00 DOL - ASM Injection Point)
4BF915DC

This redirects the code at the end of an update animation frame and script timers function to execute the custom function above (animation engine).



@19D0 (1.00 DOL - FSM Entries)
CCFFSAAA XXXXXXXX
...

This is where the entries for the animation engine are written to. Each entry contains a byte for the character ID, a byte for starting frame, a half word for action or subaction ID, and a float to be used for animation speed under those conditions. There is room at this location for 152 FSM entries (should be plenty), and it is the largest amount of open space in the DOL I could find.




Format
CCFFSAAA XXXXXXXX

C - Character ID
F - Timer for the FSM to begin on
S - Action/Subaction Tag (0 = Action; 8 = Subaction)
A - Action/Subaction ID
X - Float to set animation speed to

It's important to note that all entries for a character must be grouped together in the list, and when using multiple FSMs for the same character and action/subaction they must be in reverse timer order. Also, some animations begin on frame 0 not 1 and the 1st frame will always be animation frame 0.00.

Putting FF as the character ID will make it apply to all characters. If you wanted to make Bowser's d-tilt be at 1.4x speed from frames 1-14 you would use:


050E0039 3F800000
05000039 3FB33333

Notice the reverse timer ordering. It's like that because it takes the first entry that is satisfied (current frame is >= FSM entry). If it's an animation that begins on 0 instead of 1 (you can see in develop mode display), the 1st frame will always be 0 regardless of if a FSM is set to frame 0.

On smash attacks with a FSM before the charge frame, disable the FSM from being further reapplied by putting an entry with a float of FFFFFFFF on or before the charge frame. This is very important for pre-charge FSMs as they will be unable to charge without it (overrides the 0.00x modifier).

If you wanted to make Yoshi's f-smash (charge frame on 6) 1.5x speed from 1-12 you would use:


110C003C 3F800000
1101003C FFFFFFFF
1100003C 3FC00000

The 1.5x FSM will still carry through the smash charge until frame 12. The FFFFFFFF is needed during the charge frame to prevent the 1.5x to being reapplied during it so the charge freeze can work.



Character IDs
Code:
Captain Falcon . 00
Donkey Kong .... 01
Fox ............ 02
Game & Watch ... 03
Kirby .......... 04
Bowser ......... 05
Link ........... 06
Luigi .......... 07
Mario .......... 08
Marth .......... 09
Mewtwo ......... 0A
Ness ........... 0B
Peach .......... 0C
Pikachu ........ 0D
Ice Climbers ... 0E
Jigglypuff ..... 0F
Samus .......... 10
Yoshi .......... 11
Zelda .......... 12
Sheik .......... 13
Falco .......... 14
Young Link ..... 15
Dr Mario ....... 16
Roy ............ 17
Pichu .......... 18
Ganondorf ...... 19
Master Hand .... 1A
M Wireframe .... 1B
F Wireframe .... 1C
Giga Bowser .... 1D
Crazy Hand ..... 1E
Sandbag ........ 1F
ALL ............ FF
Action IDs
Code:
000 - DeadDown
001 - DeadLeft
002 - DeadRight
003 - DeadUp
004 - DeadUpStar
005 - DeadUpStarIce
006 - DeadUpFall
007 - DeadUpFallHitCamera
008 - DeadUpFallHitCameraFlat
009 - DeadUpFallIce
00A - DeadUpFallHitCameraIce
00B - Sleep
00C - Rebirth
00D - RebirthWait
00E - Wait
00F - WalkSlow
010 - WalkMiddle
011 - WalkFast
012 - Turn
013 - TurnRun
014 - Dash
015 - Run
016 - RunDirect
017 - RunBrake
018 - KneeBend
019 - JumpF
01A - JumpB
01B - JumpAerialF
01C - JumpAerialB
01D - Fall
01E - FallF
01F - FallB
020 - FallAerial
021 - FallAerialF
022 - FallAerialB
023 - FallSpecial
024 - FallSpecialF
025 - FallSpecialB
026 - DamageFall
027 - Squat
028 - SquatWait
029 - SquatRv
02A - Landing
02B - LandingFallSpecial
02C - Attack11
02D - Attack12
02E - Attack13
02F - Attack100Start
030 - Attack100Loop
031 - Attack100End
032 - AttackDash
033 - AttackS3Hi
034 - AttackS3HiS
035 - AttackS3S
036 - AttackS3LwS
037 - AttackS3Lw
038 - AttackHi3
039 - AttackLw3
03A - AttackS4Hi
03B - AttackS4HiS
03C - AttackS4S
03D - AttackS4LwS
03E - AttackS4Lw
03F - AttackHi4
040 - AttackLw4
041 - AttackAirN
042 - AttackAirF
043 - AttackAirB
044 - AttackAirHi
045 - AttackAirLw
046 - LandingAirN
047 - LandingAirF
048 - LandingAirB
049 - LandingAirHi
04A - LandingAirLw
04B - DamageHi1
04C - DamageHi2
04D - DamageHi3
04E - DamageN1
04F - DamageN2
050 - DamageN3
051 - DamageLw1
052 - DamageLw2
053 - DamageLw3
054 - DamageAir1
055 - DamageAir2
056 - DamageAir3
057 - DamageFlyHi
058 - DamageFlyN
059 - DamageFlyLw
05A - DamageFlyTop
05B - DamageFlyRoll
05C - LightGet
05D - HeavyGet
05E - LightThrowF
05F - LightThrowB
060 - LightThrowHi
061 - LightThrowLw
062 - LightThrowDash
063 - LightThrowDrop
064 - LightThrowAirF
065 - LightThrowAirB
066 - LightThrowAirHi
067 - LightThrowAirLw
068 - HeavyThrowF
069 - HeavyThrowB
06A - HeavyThrowHi
06B - HeavyThrowLw
06C - LightThrowF4
06D - LightThrowB4
06E - LightThrowHi4
06F - LightThrowLw4
070 - LightThrowAirF4
071 - LightThrowAirB4
072 - LightThrowAirHi4
073 - LightThrowAirLw4
074 - HeavyThrowF4
075 - HeavyThrowB4
076 - HeavyThrowHi4
077 - HeavyThrowLw4
078 - SwordSwing1
079 - SwordSwing3
07A - SwordSwing4
07B - SwordSwingDash
07C - BatSwing1
07D - BatSwing3
07E - BatSwing4
07F - BatSwingDash
080 - ParasolSwing1
081 - ParasolSwing3
082 - ParasolSwing4
083 - ParasolSwingDash
084 - HarisenSwing1
085 - HarisenSwing3
086 - HarisenSwing4
087 - HarisenSwingDash
088 - StarRodSwing1
089 - StarRodSwing3
08A - StarRodSwing4
08B - StarRodSwingDash
08C - LipStickSwing1
08D - LipStickSwing3
08E - LipStickSwing4
08F - LipStickSwingDash
090 - ItemParasolOpen
091 - ItemParasolFall
092 - ItemParasolFallSpecial
093 - ItemParasolDamageFall
094 - LGunShoot
095 - LGunShootAir
096 - LGunShootEmpty
097 - LGunShootAirEmpty
098 - FireFlowerShoot
099 - FireFlowerShootAir
09A - ItemScrew
09B - ItemScrewAir
09C - DamageScrew
09D - DamageScrewAir
09E - ItemScopeStart
09F - ItemScopeRapid
0A0 - ItemScopeFire
0A1 - ItemScopeEnd
0A2 - ItemScopeAirStart
0A3 - ItemScopeAirRapid
0A4 - ItemScopeAirFire
0A5 - ItemScopeAirEnd
0A6 - ItemScopeStartEmpty
0A7 - ItemScopeRapidEmpty
0A8 - ItemScopeFireEmpty
0A9 - ItemScopeEndEmpty
0AA - ItemScopeAirStartEmpty
0AB - ItemScopeAirRapidEmpty
0AC - ItemScopeAirFireEmpty
0AD - ItemScopeAirEndEmpty
0AE - LiftWait
0AF - LiftWalk1
0B0 - LiftWalk2
0B1 - LiftTurn
0B2 - GuardOn
0B3 - Guard
0B4 - GuardOff
0B5 - GuardDamage
0B6 - GuardReflect
0B7 - DownBoundU
0B8 - DownWaitU
0B9 - DownDamageU
0BA - DownStandU
0BB - DownAttackU
0BC - DownFowardU
0BD - DownBackU
0BE - DownSpotU
0BF - DownBoundD
0C0 - DownWaitD
0C1 - DownDamageD
0C2 - DownStandD
0C3 - DownAttackD
0C4 - DownFowardD
0C5 - DownBackD
0C6 - DownSpotD
0C7 - Passive
0C8 - PassiveStandF
0C9 - PassiveStandB
0CA - PassiveWall
0CB - PassiveWallJump
0CC - PassiveCeil
0CD - ShieldBreakFly
0CE - ShieldBreakFall
0CF - ShieldBreakDownU
0D0 - ShieldBreakDownD
0D1 - ShieldBreakStandU
0D2 - ShieldBreakStandD
0D3 - FuraFura
0D4 - Catch
0D5 - CatchPull
0D6 - CatchDash
0D7 - CatchDashPull
0D8 - CatchWait
0D9 - CatchAttack
0DA - CatchCut
0DB - ThrowF
0DC - ThrowB
0DD - ThrowHi
0DE - ThrowLw
0DF - CapturePulledHi
0E0 - CaptureWaitHi
0E1 - CaptureDamageHi
0E2 - CapturePulledLw
0E3 - CaptureWaitLw
0E4 - CaptureDamageLw
0E5 - CaptureCut
0E6 - CaptureJump
0E7 - CaptureNeck
0E8 - CaptureFoot
0E9 - EscapeF
0EA - EscapeB
0EB - Escape
0EC - EscapeAir
0ED - ReboundStop
0EE - Rebound
0EF - ThrownF
0F0 - ThrownB
0F1 - ThrownHi
0F2 - ThrownLw
0F3 - ThrownLwWomen
0F4 - Pass
0F5 - Ottotto
0F6 - OttottoWait
0F7 - FlyReflectWall
0F8 - FlyReflectCeil
0F9 - StopWall
0FA - StopCeil
0FB - MissFoot
0FC - CliffCatch
0FD - CliffWait
0FE - CliffClimbSlow
0FF - CliffClimbQuick
100 - CliffAttackSlow
101 - CliffAttackQuick
102 - CliffEscapeSlow
103 - CliffEscapeQuick
104 - CliffJumpSlow1
105 - CliffJumpSlow2
106 - CliffJumpQuick1
107 - CliffJumpQuick2
108 - AppealR
109 - AppealL
10A - ShoulderedWait
10B - ShoulderedWalkSlow
10C - ShoulderedWalkMiddle
10D - ShoulderedWalkFast
10E - ShoulderedTurn
10F - ThrownFF
110 - ThrownFB
111 - ThrownFHi
112 - ThrownFLw
113 - CaptureCaptain
114 - CaptureYoshi
115 - YoshiEgg
116 - CaptureKoopa
117 - CaptureDamageKoopa
118 - CaptureWaitKoopa
119 - ThrownKoopaF
11A - ThrownKoopaB
11B - CaptureKoopaAir
11C - CaptureDamageKoopaAir
11D - CaptureWaitKoopaAir
11E - ThrownKoopaAirF
11F - ThrownKoopaAirB
120 - CaptureKirby
121 - CaptureWaitKirby
122 - ThrownKirbyStar
123 - ThrownCopyStar
124 - ThrownKirby
125 - BarrelWait
126 - Bury
127 - BuryWait
128 - BuryJump
129 - DamageSong
12A - DamageSongWait
12B - DamageSongRv
12C - DamageBind
12D - CaptureMewtwo
12E - CaptureMewtwoAir
12F - ThrownMewtwo
130 - ThrownMewtwoAir
131 - WarpStarJump
132 - WarpStarFall
133 - HammerWait
134 - HammerWalk
135 - HammerTurn
136 - HammerKneeBend
137 - HammerFall
138 - HammerJump
139 - HammerLanding
13A - KinokoGiantStart
13B - KinokoGiantStartAir
13C - KinokoGiantEnd
13D - KinokoGiantEndAir
13E - KinokoSmallStart
13F - KinokoSmallStartAir
140 - KinokoSmallEnd
141 - KinokoSmallEndAir
142 - Entry
143 - EntryStart
144 - EntryEnd
145 - DamageIce
146 - DamageIceJump
147 - CaptureMasterhand
148 - CapturedamageMasterhand
149 - CapturewaitMasterhand
14A - ThrownMasterhand
14B - CaptureKirbyYoshi
14C - KirbyYoshiEgg
14D - CaptureLeadead
14E - CaptureLikelike
14F - DownReflect
150 - CaptureCrazyhand
151 - CapturedamageCrazyhand
152 - CapturewaitCrazyhand
153 - ThrownCrazyhand
154 - BarrelCannonWait
155 - (Specials & Character Specific)
I know this has been posted before but since Search is odd now, I thought I'd turn it into a thread. and who know, maybe someone with ASM knowledge can expand on this one day
 
Top Bottom