# Transform at will in Sonic 2

Discussion in 'Engineering & Reverse Engineering' started by Machenstein, May 28, 2012.

1. ### Machenstein

Member
830
0
0
With the help of vladikcomper, we figured out how to implement the Sonic 3 method of Super Sonic transformation into Sonic 2. In the original Sonic 2, you had no control over when Sonic transformed once you collected 50 or more rings. Your only recourse was to try not to jump which automatically triggered the Super Sonic transformation. With this tutorial, your Sonic 2 hack will give you more control over when Sonic transforms.

The first thing you do is locate the label Sonic_JumpHeight. You should see something like this:

Code (ASM):
1. ; loc_1AAF0:
2. Sonic_JumpHeight:
3.     tst.b   jumping(a0) ; is Sonic jumping?
4.     beq.s   Sonic_UpVelCap  ; if not, branch
5.
6.     move.w  #-\$400,d1
7.     btst    #6,status(a0)   ; is Sonic underwater?
8.     beq.s   +       ; if not, branch
9.     move.w  #-\$200,d1
10. +
11.     cmp.w   y_vel(a0),d1    ; is Sonic going up faster than d1?
12.     ble.s   +       ; if not, branch
13.     move.b  (Ctrl_1_Held_Logical).w,d0
15.     bne.s   +       ; if yes, branch
16.     move.w  d1,y_vel(a0)    ; immediately reduce Sonic's upward speed to d1
17. +
18.     tst.b   y_vel(a0)       ; is Sonic exactly at the height of his jump?
19.     beq.s   Sonic_CheckGoSuper  ; if yes, test for turning into Super Sonic
20.     rts
Replace this:

Code (ASM):
1.     tst.b   y_vel(a0)       ; is Sonic exactly at the height of his jump?
2.     beq.s   Sonic_CheckGoSuper  ; if yes, test for turning into Super Sonic
3.     rts
with this:

Code (ASM):
1.     move.b  (Ctrl_1_Press_Logical).w,d0
3.     bne.s   Sonic_CheckGoSuper  ; if yes, test for turning into Super Sonic
4.     rts
That's it! Now you can make Sonic transform at will just like in Sonic 3. At those times when you are low on rings though, what if you want to cancel out Super Sonic? There is also a fix for that. First, find the label Obj01_MdJump. It should look like this:

Code (ASM):
1. Obj01_MdJump:
2.     bsr.w   Sonic_JumpHeight
3.     bsr.w   Sonic_ChgJumpDir
4.     bsr.w   Sonic_LevelBound
5.     jsr (ObjectMoveAndFall).l
6.     btst    #6,status(a0)   ; is Sonic underwater?
7.     beq.s   +       ; if not, branch
8.     subi.w  #\$28,y_vel(a0)  ; reduce gravity by \$28 (\$38-\$28=\$10)
9. +
10.     bsr.w   Sonic_JumpAngle
11.     bsr.w   Sonic_DoLevelCollision
12.     rts
13. ; End of subroutine Obj01_MdJump
Insert this under Obj01_MdJump:

Code (ASM):
1.     bsr.w   Sonic_CancelSuper
It should now look like this:

Code (ASM):
1. Obj01_MdJump:
2.     bsr.w   Sonic_CancelSuper
3.     bsr.w   Sonic_JumpHeight
4.     bsr.w   Sonic_ChgJumpDir
5.     bsr.w   Sonic_LevelBound
6.     jsr (ObjectMoveAndFall).l
7.     btst    #6,status(a0)   ; is Sonic underwater?
8.     beq.s   +       ; if not, branch
9.     subi.w  #\$28,y_vel(a0)  ; reduce gravity by \$28 (\$38-\$28=\$10)
10. +
11.     bsr.w   Sonic_JumpAngle
12.     bsr.w   Sonic_DoLevelCollision
13.     rts
14. ; End of subroutine Obj01_MdJump
Finally, create the subroutine. Right under "; End of subroutine Obj01_MdJump" insert this:

Code (ASM):
1. ; ---------------------------------------------------------------------------
2. ; Subroutine to cancel Super Sonic
3. ; ---------------------------------------------------------------------------
4.
5. Sonic_CancelSuper:
6.         tst.b   (Super_Sonic_Flag).w
7.         beq.s   +
8.         move.b  (Ctrl_1_Press_Logical).w,d0
10.         beq.s   +
12.         jmp     Sonic_RevertToNormal
13. +       rts
Now you can cancel out Super Sonic at any time without having to wait for your rings to run out. You can also use just one button to make Sonic transform and cancel out by replacing this in each step:

Code (ASM):
With one of these:

Code (ASM):
Now you have complete control over when Sonic transforms in Sonic 2!

2. ### Knucklez

I love 2B 'n' ass. Member
683
17
18
Wow, this is beyond useful. I'm glad you guys finally got this issue addressed. Could you also provide the ROM with this implementation? :v:

Member
830
0
0
Yup.

4. ### Aerosol

Not here. Moderator
11,078
479
63
Not where I want to be.
Sonic (?): Coming summer of 2055...?
Forgive me but...isn't this actually really basic? I pulled this off while I was trying to code my own homing attack for Sonic 2, and I'm pretty retarded when it comes to asm. Not trying to shit on your parade or anything. I'm just not sure a whole topic was necessary for this.

5. ### Knucklez

I love 2B 'n' ass. Member
683
17
18
So much for me knowing anything about asm if this is basic. As far as I'm concerned, I haven't seen this in any hacks of Sonic 2.

6. ### MainMemory

Kate the Wolf Tech Member
4,670
231
43
SonLVL
Just because you have not seen it does not mean it is complex.

7. ### Aerosol

Not here. Moderator
11,078
479
63
Not where I want to be.
Sonic (?): Coming summer of 2055...?
This. And just to clarify, I'm only talking about checking for a button press to activate Super Sonic, not the deactivation code. This modification also fixes the "transform after signpost" glitch, I think. That's what happened to me.

8. ### TheInvisibleSun

OVER THE TOP TECHNO-BLAST Member
1,626
193
43
Buffalo, NY, USA
The Water
Should this be put in the guide then?

9. ### Tets

one rude dude Oldbie
878
46
28
This was one of the first things I did when I hacked Sonic 2. Depending on how you code it, it either completely or partially fixes the "transform after signpost" glitch. My implementation still allowed you to transform if you hit the button exactly as you pass the signpost, leaving you stuck walking in the air as in the original glitch. I was never quite able to pin down a fix for that before I lost interest.

10. ### Knucklez

I love 2B 'n' ass. Member
683
17
18
Yes, but the glitch that still remains is when you jump past the signpost as regular Sonic and activate the Super transformation, which leaves you stuck walking/running in the air with the results screen not appearing.

Tech Member
203
125
43
Sonic Warped
Lol, I didn't expect that me helping you with that manual transformation thingie yesterday will do a guide.
Anyways, this is quite helpful one, because the way transformation was done in the original Sonic 2 is really annoying. I hope in future we'll see more Sonic 2 hacks with better way of transformation.

But frankly, solution this guide suggests is not perfect, I would say, 'hack-ish'. I mean that Sonic_CancelSuper subroutine I wrote for you. I knew this wasn't all good from the beginning, but hell, for some reason I couldn't think properly yesterday. Silly me. Because the good solution was so simple.

Let me fix my stupid mistake and introduce this good solution as an alternative to your guide:

* * *

Go to Sonic_JumpHeight and replace this:

Code (Text):
1.         tst.b   y_vel(a0)               ; is Sonic exactly at the height of his jump?
2.         beq.s   Sonic_CheckGoSuper      ; if yes, test for turning into Super Sonic
3.         rts
with this:

Code (Text):
1.         move.b  (Ctrl_1_Press_Logical).w,d0
3.         bne.s   Sonic_CheckGoSuper      ; if yes, test for turning into Super Sonic
4.         rts
Goto Sonic_CheckGoSuper and replace:

Code (Text):
1.     bne.s   return_1ABA4
at the very beginning with

Code (Text):
1.     bne.w   Sonic_RevertToNormal
That's it.

* * *

Now, there are few bugs that original game has:
1) Sonic's transformation palette bug
2) Sonic freezing in air after revert to normal bug
They are much easier to fix.

* * *

1) Sonic's transformation palette bug

A palette bug occurs when you transform for the second time and on: Sonic colors look wrong during transformation animation. It happens due to program error in Super palette cycling code. The code resets palette position incorrectly when revert to normal cycle is over.

For HG disassembly.
Goto PalCycle_SuperSonic_revert and find these lines:

Code (Text):
1.     subq.w  #8,(Palette_frame).w    ; previous frame
2.     bcc.s   +           ; branch, if it isn't the first frame
3.     move.b  #0,(Palette_frame).w
The last instruction uses 'byte' type, while the variable used as 'word' in the rest of the code (see SUBQ line for example). Therefore, the variable is not cleared properly, which causes wrong colors to load in the next transformation.
Replace '.b' with '.w' and the bug is gone.

For Xenowhirl's 2007 Disassembly.
The label you're looking for is loc_2188 and those 3 lines look like this:

Code (Text):
1.     subq.w  #8,(\$FFFFF65C).w
2.     bcc.s   loc_21B0
3.     move.b  #0,(\$FFFFF65C).w
* * *

2) Sonic freezing in air after revert to normal bug

It happens when Sonic has to revert from transformation instantly. The controls are looked when the transformation starts until a certain moment (controlled by PalCycle_SuperSonic routine), and routine that reverts Sonic to normal doesn't bother to unlock the controls.

In the beginning of Sonic_RevertToNormal add:
Code (Text):
1.     move.b  #0,(MainCharacter+obj_control).w    ; restore Sonic's movement
Applies to both disassemblies.

12. ### Tets

one rude dude Oldbie
878
46
28
I totally forgot about the transformation palcycle bug, it's something the average player would never encounter in vanilla Sonic 2. I remember posting a quick fix for it years ago, it took me the longest time to track that one down due to its utter simplicity, but I don't know that it ever found its way into any guides.

As for the "stuck in the air" bug, I had never even thought of simply restoring player control in the RevertToNormal routine. It seems like there should be a better way to do it, but I think that more or less cuts it.

13. ### Machenstein

Member
830
0
0
That's much better. Thanks again, vladikcomper. There is one last thing I want to point out though.

These garbled tiles appear on Sonic when he transforms. Is this a side effect of fixing the palette bug or could it be something else?

Tech Member
203
125
43
Sonic Warped
It's nothing to do with palettes. This is DMA transfer bug, it happens when transferred Sonic's art crosses 128 KB ROM bank.
Check out this post for fixing it: http://forums.sonicretro.org/index.php?showtopic=10880&st=3915&p=626425&#entry626425
This is for Sonic 1. In Sonic 2 it's exactly the same, except for the label you'll be looking for is 'ArtUnc_Sonic'.

15. ### redhotsonic

Also known as RHS Tech Member
1,587
9
18
United Kingdom
I use to have that problem years ago, but "align \$20000" takes up quite a bit of space. I use "align \$10000" (any lower and the glitch still happens) and I haven't had any glitches since. So I've applied this for all my characters. Seeming as I've had no problems since, I guess this is fine?

16. ### Sik

Sik is pronounced as "seek", not as "sick". Tech Member
6,719
0
0
being an asshole =P
Align \$10000 aligns to 64KB, the issue can still happen if the artwork crosses a 128KB boundary. Didn't check how big are Sonic's sprites though, if they're under 64KB then it's never going to cross a 128KB boundary anyways (since they won't cross a 64KB one, and 128KB boundaries are also 64KB boundaries - similar rules apply to other powers of two).

The best way to avoid wasting space is moving stuff around though =P

17. ### redhotsonic

Also known as RHS Tech Member
1,587
9
18
United Kingdom
Mine's at 81KB, but still no problems =P

Anyway, that's useful to know, thanks for the tip.

Tech Member
203
125
43
Sonic Warped
Yes, sure. If your art is smaller than \$10000 bytes (64 KB), you can align it like that without worrying that your art may cross 128 KB boundary.
But notice, that bug only happens when transferred tiles cross the boundary, not the whole art. So you may even place one bunch of tiles in before the boundary, and another after it, for example. But such alignment would be a real pain in ass though =P

But like Sik said, to avoid wasting space, it's good to organize your data order. Use listing file to see what offsets your data takes and how much 'align' directives take. If they take too much, you can always move some data from end of ROM to wasted space.

19. ### Sik

Sik is pronounced as "seek", not as "sick". Tech Member
6,719
0
0
being an asshole =P
I generally tend to do that, actually, but I can afford to do it because each sprite is its own file in the source code, so at worst alignment would affect only one sprite and nothing else.

20. ### Machenstein

Member
830
0
0
I found a small quirk with vladikcomper's alternative to the guide. If you push the transform button when don't have all 7 Chaos Emeralds and 50 rings, Sonic simply flashes yellow for a second. I would suggest going with the subroutine in the first guide until this issue is fixed with the alternative one.