Ripple
ᗣᗣᗣᗣ ᗧ·····•·····
- Joined
- Sep 4, 2006
- Messages
- 9,633
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 dayMagus 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
Action IDsCode: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
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)