Actions

SCHG How-to

Add Super Sonic to Sonic 1

From Sonic Retro

What you'll need

  • Hivebrain's 2005 Sonic 1 disassembly ASM68K
  • Xerowhirl's 2007 Sonic 2 disassembly
  • Any text editor

Step 1 Porting constants

You don't have to do this one but it's recommended that you add the constants to make this a lot easier.

So change this.

; /=========================================================================\
; º	This file is generated by The Interactive Disassembler (IDA)	    º
; º	Copyright (c) 2003 by DataRescue sa/nv,	<[email protected]>	    º
; \=========================================================================/
;
; Disassembly created by Hivebrain
; thanks to drx and Stealth

; Processor:	    68000
; Target Assembler: 680x0 Assembler in MRI compatible mode
; This file should be compiled with "as	-M"

; ===========================================================================
align macro
	cnop 0,\1
	endm
	
StartOfRom:

To this.

; /=========================================================================\
; º	This file is generated by The Interactive Disassembler (IDA)	    º
; º	Copyright (c) 2003 by DataRescue sa/nv,	<[email protected]>	    º
; \=========================================================================/
;
; Disassembly created by Hivebrain
; thanks to drx and Stealth

; Processor:	    68000
; Target Assembler: 680x0 Assembler in MRI compatible mode
; This file should be compiled with "as	-M"

; ===========================================================================
align macro
	cnop 0,\1
	endm
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equates section - Names for variables.
; ---------------------------------------------------------------------------
; size variables - you'll get an informational error if you need to change these...
; they are all in units of bytes
Size_of_DAC_samples =		$2F00
Size_of_SEGA_sound =		$6174
Size_of_Snd_driver_guess =	$F64 ; approximate post-compressed size of the Z80 sound driver

; ---------------------------------------------------------------------------
; Object Status Table offsets (for everything between Object_RAM and Primary_Collision)
; ---------------------------------------------------------------------------
; universally followed object conventions:
render_flags =		  1 ; bitfield ; bit 7 = onscreen flag, bit 0 = x mirror, bit 1 = y mirror, bit 2 = coordinate system
art_tile =		  2 ; and 3 ; start of sprite's art
mappings =		  4 ; and 5 and 6 and 7
x_pos =			  8 ; and 9 ... some objects use $A and $B as well when extra precision is required (see ObjectMove) ... for screen-space objects this is called x_pixel instead
y_pos =			 $C ; and $D ... some objects use $E and $F as well when extra precision is required ... screen-space objects use y_pixel instead
priority =		$18 ; 0 = front
width_pixels =		$19
mapping_frame =		$1A
; ---------------------------------------------------------------------------
; conventions followed by most objects:
x_vel =			$10 ; and $11 ; horizontal velocity
y_vel =			$12 ; and $13 ; vertical velocity
y_radius =		$16 ; collision width / 2
x_radius =		$17 ; collision height / 2
anim_frame =		$1B
anim =			$1C
next_anim =		$1D
anim_frame_duration =	$1E
status =		$22 ; note: exact meaning depends on the object... for sonic/tails: bit 0: leftfacing. bit 1: inair. bit 2: spinning. bit 3: onobject. bit 4: rolljumping. bit 5: pushing. bit 6: underwater.
routine =		$24
routine_secondary =	$25
angle =			$26 ; angle about the z=0 axis (360 degrees = 256)
; ---------------------------------------------------------------------------
; conventions followed by many objects but NOT sonic/tails:
collision_flags =	$20
collision_property =	$21
respawn_index =		$23
subtype =		$28
; ---------------------------------------------------------------------------
; conventions specific to sonic/tails (Obj01, Obj02, and ObjDB):
; note: $1F, $20, and $21 are unused and available
inertia =		$14 ; and $15 ; directionless representation of speed... not updated in the air
flip_angle =		$27 ; angle about the x=0 axis (360 degrees = 256) (twist/tumble)
air_left =		$28
flip_turned =		$29 ; 0 for normal, 1 to invert flipping (it's a 180 degree rotation about the axis of Sonic's spine, so he stays in the same position but looks turned around)
obj_control =		$2A ; 0 for normal, 1 for hanging or for resting on a flipper, $81 for going through CNZ/OOZ/MTZ tubes or stopped in CNZ cages or stoppers or flying if Tails
status_secondary =	$2B
flips_remaining =	$2C ; number of flip revolutions remaining
flip_speed =		$2D ; number of flip revolutions per frame / 256
move_lock =		$2E ; and $2F ; horizontal control lock, counts down to 0
invulnerable_time =	$30 ; and $31 ; time remaining until you stop blinking
invincibility_time =	$32 ; and $33 ; remaining
speedshoes_time =	$34 ; and $35 ; remaining
next_tilt =		$36 ; angle on ground in front of sprite
tilt =			$37 ; angle on ground
stick_to_convex =	$38 ; 0 for normal, 1 to make Sonic stick to convex surfaces like the rotating discs in Sonic 1 and 3 (unused in Sonic 2 but fully functional)
spindash_flag =		$39 ; 0 for normal, 1 for charging a spindash or forced rolling
spindash_counter =	$3A ; and $3B
jumping =		$3C
interact =		$3D ; RAM address of the last object Sonic stood on, minus $FFFFB000 and divided by $40
layer =			$3E ; collision plane, track switching...
layer_plus =		$3F ; always same as layer+1 ?? used for collision somehow
; ---------------------------------------------------------------------------
; conventions followed by several objects but NOT sonic/tails:
y_pixel =		2+x_pos ; and 3+x_pos ; y coordinate for objects using screen-space coordinate system
x_pixel =		x_pos ; and 1+x_pos ; x coordinate for objects using screen-space coordinate system
parent =		$3E ; and $3F ; address of object that owns or spawned this one, if applicable
; ---------------------------------------------------------------------------
; unknown or inconsistently used offsets that are not applicable to sonic/tails:
; (provided because rearrangement of the above values sometimes requires making space in here too)
objoff_A =		2+x_pos ; note: x_pos can be 4 bytes, but sometimes the last 2 bytes of x_pos are used for other unrelated things
objoff_B =		3+x_pos
objoff_E =		2+y_pos
objoff_F =		3+y_pos
objoff_14 =		$14
objoff_15 =		$15
objoff_1F =		$1F
objoff_27 =		$27
objoff_28 =		$28 ; overlaps subtype, but a few objects use it for other things anyway
objoff_29 =		$29
objoff_2A =		$2A
objoff_2B =		$2B
objoff_2C =		$2C
objoff_2D =		$2D
objoff_2E =		$2E
objoff_2F =		$2F
objoff_30 =		$30
objoff_31 =		$31
objoff_32 =		$32
objoff_33 =		$33
objoff_34 =		$34
objoff_35 =		$35
objoff_36 =		$36
objoff_37 =		$37
objoff_38 =		$38
objoff_39 =		$39
objoff_3A =		$3A
objoff_3B =		$3B
objoff_3C =		$3C
objoff_3D =		$3D
objoff_3E =		$3E
objoff_3F =		$3F
; ---------------------------------------------------------------------------
; property of all objects:
next_object =		$40 ; the size of an object

; ---------------------------------------------------------------------------
; RAM variables
RAM_Start =			$FFFF0000
Metablock_Table =		$FFFF0000
Level_Layout =			$FFFF8000
Block_Table =			$FFFF9000
Decomp_Buffer =			$FFFFAA00
Sprite_Table_Input = 		$FFFFAC00 ; in custom format before being converted and stored in Sprite_Table/Sprite_Table_2
Object_RAM =			$FFFFB000 ; through $FFFFD5FF
MainCharacter =			$FFFFB000 ; first object (usually Sonic except in a Tails Alone game)
Sidekick =			$FFFFB040 ; second object (Tails in a Sonic and Tails game)
Tails_Tails =			$FFFFD000 ; address of the Tail's Tails object
Sonic_Dust =			$FFFFD100
Tails_Dust =			$FFFFD140

PNT_Buffer =			$FFFFD000 ; in special stage
Primary_Collision =		$FFFFD600
Horiz_Scroll_Buf_2 =		$FFFFD700 ; in special stage
Secondary_Collision =		$FFFFD900
VDP_Command_Buffer =		$FFFFDC00 ; stores VDP commands to issue the next time ProcessDMAQueue is called
VDP_Command_Buffer_Slot =	$FFFFDCFC ; stores the address of the next open slot for a queued VDP command
Sprite_Table_2 =		$FFFFDD00 ; Sprite attribute table buffer for the bottom split screen in 2-player mode
Horiz_Scroll_Buf =		$FFFFE000
Sonic_Stat_Record_Buf =		$FFFFE400
Sonic_Pos_Record_Buf =		$FFFFE500
Tails_Pos_Record_Buf =		$FFFFE600
Ring_Positions =		$FFFFE800
Camera_RAM =			$FFFFEE00
Camera_X_pos =			$FFFFEE00
Camera_Y_pos =			$FFFFEE04
Camera_Max_Y_pos =		$FFFFEEC6
Camera_Min_X_pos =		$FFFFEEC8
Camera_Max_X_pos =		$FFFFEECA
Camera_Min_Y_pos =		$FFFFEECC
Camera_Max_Y_pos_now =		$FFFFEECE ; was "Camera_max_scroll_spd"...
Sonic_Pos_Record_Index =	$FFFFEED2 ; into Sonic_Pos_Record_Buf and Sonic_Stat_Record_Buf
Tails_Pos_Record_Index =	$FFFFEED6 ; into Tails_Pos_Record_Buf
Camera_Y_pos_bias =		$FFFFEED8 ; added to y position for lookup/lookdown, $60 is center
Camera_Y_pos_bias_2P =		$FFFFEEDA ; for Tails
Dynamic_Resize_Routine =	$FFFFEEDF
Tails_Min_X_pos =		$FFFFEEF8
Tails_Max_X_pos =		$FFFFEEFA
Tails_Max_Y_pos =		$FFFFEEFE

Underwater_palette_2 = 		$FFFFF000 ; not sure what it's used for but it's only used when there's water
Underwater_palette = 		$FFFFF080 ; main palette for underwater parts of the screen
Underwater_palette_line4 = 	$FFFFF0E0

Game_Mode =			$FFFFF600 ; 1 byte ; see GameModesArray (master level trigger, Mstr_Lvl_Trigger)
Ctrl_1_Logical =		$FFFFF602 ; 2 bytes
Ctrl_1_Held_Logical =		$FFFFF602 ; 1 byte
Ctrl_1_Press_Logical =		$FFFFF603 ; 1 byte
Ctrl_1 =			$FFFFF604 ; 2 bytes
Ctrl_1_Held =			$FFFFF604 ; 1 byte ; (pressed and held were switched around before)
Ctrl_1_Press =			$FFFFF605 ; 1 byte
Ctrl_2 =			$FFFFF606 ; 2 bytes
Ctrl_2_Held =			$FFFFF606 ; 1 byte
Ctrl_2_Press =			$FFFFF607 ; 1 byte
Demo_Time_left =		$FFFFF614 ; 2 bytes

Vscroll_Factor =		$FFFFF616
Hint_counter_reserve =		$FFFFF624 ; Must contain a VDP command word, preferably a write to register $0A. Executed every V-INT.
Delay_Time =			$FFFFF62A ; number of frames to delay the game
RNG_seed =			$FFFFF636 ; used for random number generation
Game_paused =			$FFFFF63A
DMA_data_thunk =		$FFFFF640 ; Used as a RAM holder for the final DMA command word. Data will NOT be preserved across V-INTs, so consider this space reserved.

Water_Level_1 =			$FFFFF646
Water_Level_2 =			$FFFFF648
Water_Level_3 =			$FFFFF64A
Water_routine =			$FFFFF64D
Water_move =			$FFFFF64E
Water_on =			$FFFFF64C ; is set based on Water_flag
New_Water_Level =		$FFFFF650
Water_change_speed =		$FFFFF652
Palette_frame_count =		$FFFFF65E
Super_Sonic_palette =		$FFFFF65F
Ctrl_2_Logical =		$FFFFF66A ; 2 bytes
Ctrl_2_Held_Logical =		$FFFFF66A ; 1 byte
Ctrl_2_Press_Logical =		$FFFFF66B ; 1 byte
Sonic_Look_delay_counter = 	$FFFFF66C ; 2 bytes
Tails_Look_delay_counter = 	$FFFFF66E ; 2 bytes
Super_Sonic_frame_count =	$FFFFF670
Plc_Buffer =			$FFFFF680 ; Pattern load queue

Misc_Variables =		$FFFFF700

; extra variables for the second player (CPU) in 1-player mode
Tails_control_counter =		$FFFFF702 ; how long until the CPU takes control
Tails_respawn_counter =		$FFFFF704
Tails_CPU_routine =		$FFFFF708
Tails_CPU_target_x =		$FFFFF70A
Tails_CPU_target_y =		$FFFFF70C
Tails_interact_ID =		$FFFFF70E ; object ID of last object stood on

Level_started_flag =		$FFFFF711
CNZ_Bumper_routine =		$FFFFF71A
Dirty_flag =			$FFFFF72C ; if whole screen needs to redraw
Water_flag =			$FFFFF730 ; if the level has water or oil

Sonic_top_speed =		$FFFFF760
Sonic_acceleration =		$FFFFF762
Sonic_deceleration =		$FFFFF764
Obj_placement_routine =		$FFFFF76C
Obj_load_addr_0 =		$FFFFF770
Obj_load_addr_1 =		$FFFFF774
Obj_load_addr_2 =		$FFFFF778
Obj_load_addr_3 =		$FFFFF77C
Demo_button_index =		$FFFFF790 ; index into button press demo data, for player 1
Demo_press_counter =		$FFFFF792 ; frames remaining until next button press, for player 1
Demo_button_index_2P =		$FFFFF732 ; index into button press demo data, for player 2
Demo_press_counter_2P =		$FFFFF734 ; frames remaining until next button press, for player 2
Collision_addr =		$FFFFF796
Current_Boss_ID =		$FFFFF7AA
Control_Locked =		$FFFFF7CC
Chain_Bonus_counter =		$FFFFF7D0 ; counts up when you destroy things that give points, resets when you touch the ground
Bonus_Countdown_1 =		$FFFFF7D2 ; level results time bonus or special stage sonic ring bonus
Bonus_Countdown_2 =		$FFFFF7D4 ; level results ring bonus or special stage tails ring bonus
Update_Bonus_score =		$FFFFF7D6
Camera_X_pos_coarse =		$FFFFF7DA ; (Camera_X_pos - 128) / 256

Sprite_Table =			$FFFFF800 ; Sprite attribute table buffer

Normal_palette =		$FFFFFB00
Normal_palette_line2 =		$FFFFFB20
Normal_palette_line3 =		$FFFFFB40
Normal_palette_line4 =		$FFFFFB60
Second_palette =		$FFFFFB80
Second_palette_line2 =		$FFFFFBA0
Second_palette_line3 =		$FFFFFBC0
Second_palette_line4 =		$FFFFFBE0

Object_Respawn_Table =		$FFFFFC00
System_Stack =			$FFFFFE00
Level_Inactive_flag = 		$FFFFFE02 ; (2 bytes)
Timer_frames =			$FFFFFE04 ; (2 bytes)
Debug_object =			$FFFFFE06
Debug_placement_mode =		$FFFFFE08
Current_ZoneAndAct =		$FFFFFE10 ; 2 bytes
Current_Zone =			$FFFFFE10 ; 1 byte
Current_Act =			$FFFFFE11 ; 1 byte
Life_count =			$FFFFFE12
Current_Special_Stage =		$FFFFFE16
Continue_count =		$FFFFFE18
Super_Sonic_flag =		$FFFFFE19
Time_Over_flag =		$FFFFFE1A
Extra_life_flags =		$FFFFFE1B

; If set, the respective HUD element will be updated.
Update_HUD_lives =		$FFFFFE1C
Update_HUD_rings =		$FFFFFE1D
Update_HUD_timer =		$FFFFFE1E
Update_HUD_score =		$FFFFFE1F

Ring_count =			$FFFFFE20 ; 2 bytes
Timer =				$FFFFFE22 ; 4 bytes
Timer_minute_word =		$FFFFFE22 ; 2 bytes
Timer_minute =			$FFFFFE23 ; 1 byte
Timer_second =			$FFFFFE24 ; 1 byte
Timer_centisecond =		$FFFFFE25 ; 1 byte
Score =				$FFFFFE26 ; 4 bytes
Last_star_pole_hit =		$FFFFFE30 ; 1 byte -- max activated starpole ID in this act

Saved_Last_star_pole_hit =	$FFFFFE31
Saved_x_pos =			$FFFFFE32
Saved_y_pos =			$FFFFFE34
Saved_Ring_count =		$FFFFFE36
Saved_Timer =			$FFFFFE38
Saved_art_tile =		$FFFFFE3C
Saved_layer =			$FFFFFE3E
Saved_Camera_X_pos =		$FFFFFE40
Saved_Camera_Y_pos =		$FFFFFE42
Saved_Water_Level =		$FFFFFE50
Saved_Water_routine =		$FFFFFE52
Saved_Water_move =		$FFFFFE53
Saved_Extra_life_flags =	$FFFFFE54
Saved_Extra_life_flags_2P =	$FFFFFE55
Saved_Camera_Max_Y_pos =	$FFFFFE56
Saved_Dynamic_Resize_Routine =	$FFFFFE58

Logspike_anim_counter =		$FFFFFEA0
Logspike_anim_frame =		$FFFFFEA1
Rings_anim_counter =		$FFFFFEA2
Rings_anim_frame =		$FFFFFEA3
Unknown_anim_counter =		$FFFFFEA4 ; I think this was $FFFFFEC4 in the alpha
Unknown_anim_frame =		$FFFFFEA5
Ring_spill_anim_counter =	$FFFFFEA6 ; scattered rings
Ring_spill_anim_frame =		$FFFFFEA7
Ring_spill_anim_accum =		$FFFFFEA8

; values for the second player (some of these only apply to 2-player games)
Tails_top_speed =		$FFFFFEC0 ; Tails_max_vel
Tails_acceleration =		$FFFFFEC2
Tails_deceleration =		$FFFFFEC4
Life_count_2P =			$FFFFFEC6
Extra_life_flags_2P =		$FFFFFEC7
Update_HUD_lives_2P =		$FFFFFEC8
Update_HUD_rings_2P =		$FFFFFEC9
Update_HUD_timer_2P =		$FFFFFECA
Update_HUD_score_2P =		$FFFFFECB ; mostly unused
Time_Over_flag_2P =		$FFFFFECC
Ring_count_2P =			$FFFFFED0
Timer_2P =			$FFFFFED2 ; 4 bytes
Timer_minute_word_2P =		$FFFFFED2 ; 2 bytes
Timer_minute_2P =		$FFFFFED3 ; 1 byte
Timer_second_2P =		$FFFFFED4 ; 1 byte
Timer_centisecond_2P =		$FFFFFED5 ; 1 byte
Score_2P =			$FFFFFED6
Last_star_pole_hit_2P =		$FFFFFEE0

Saved_Last_star_pole_hit_2P =	$FFFFFEE1
Saved_x_pos_2P =		$FFFFFEE2
Saved_y_pos_2P =		$FFFFFEE4
Saved_Ring_count_2P =		$FFFFFEE6
Saved_Timer_2P =		$FFFFFEE8
Saved_art_tile_2P =		$FFFFFEEC
Saved_layer_2P =		$FFFFFEEE

Loser_Time_Left =		$FFFFFEF8
Results_Screen_2P =		$FFFFFF10 ; 0 = act, 1 = zone, 2 = game, 3 = SS, 4 = SS all
Results_Data_2P =		$FFFFFF20 ; $18 bytes
EHZ_Results_2P =		$FFFFFF20 ; 6 bytes
MCZ_Results_2P =		$FFFFFF26 ; 6 bytes
CNZ_Results_2P =		$FFFFFF2C ; 6 bytes
SS_Results_2P =			$FFFFFF32 ; 6 bytes
SS_Total_Won =			$FFFFFF38 ; 2 bytes (player 1 then player 2)
Perfect_rings_left =		$FFFFFF40
Player_mode =			$FFFFFF70 ; 0 = Sonic and Tails, 1 = Sonic, 2 = Tails
Player_option =			$FFFFFF72 ; 0 = Sonic and Tails, 1 = Sonic, 2 = Tails

Two_player_items =		$FFFFFF74
Level_select_zone =		$FFFFFF82
Sound_test_sound =		$FFFFFF84
Title_screen_option =		$FFFFFF86
Current_Zone_2P =		$FFFFFF88
Current_Act_2P =		$FFFFFF89
Two_player_mode_copy =		$FFFFFF8A
Options_menu_box =		$FFFFFF8C
Level_Music =			$FFFFFF90
Game_Over_2P =			$FFFFFF98
Got_Emerald =			$FFFFFFB0
Emerald_count =			$FFFFFFB1
Got_Emeralds_array =		$FFFFFFB2 ; 7 bytes
Next_Extra_life_score =		$FFFFFFC0
Next_Extra_life_score_2P =	$FFFFFFC4
Level_Has_Signpost =		$FFFFFFC8 ; 1 byte ; 1 = signpost, 0 = boss or nothing
Level_select_flag =		$FFFFFFD0
Slow_motion_flag =		$FFFFFFD1
Correct_cheat_entries =		$FFFFFFD4
Correct_cheat_entries_2 =	$FFFFFFD6 ; for 14 continues or 7 emeralds codes
Two_player_mode =		$FFFFFFD8 ; flag (0 for main game)

; Values in these variables are passed to the sound driver during V-INT.
; They use a playlist index, not a sound test index.
Music_to_play =			$FFFFFFE0
SFX_to_play =			$FFFFFFE1 ; normal
SFX_to_play_2 =			$FFFFFFE2 ; alternating stereo
Music_to_play_2 =		$FFFFFFE4 ; alternate (higher priority?) slot

Demo_mode_flag =		$FFFFFFF0 ; 1 if a demo is playing (2 bytes)
Demo_number =			$FFFFFFF2 ; which demo will play next (2 bytes)
Graphics_Flags =		$FFFFFFF8 ; misc. bitfield
Debug_mode_flag =		$FFFFFFFA ; (2 bytes)
Checksum_fourcc =		$FFFFFFFC ; (4 bytes)

; ---------------------------------------------------------------------------
; VDP addressses
VDP_data_port =			$C00000 ; (8=r/w, 16=r/w)
VDP_control_port =		$C00004 ; (8=r/w, 16=r/w)

; ---------------------------------------------------------------------------
; Z80 addresses
Z80_RAM =			$A00000 ; start of Z80 RAM
Z80_RAM_End =			$A02000 ; end of non-reserved Z80 RAM
Z80_Version =			$A10001
Z80_Port_1_Data =		$A10002
Z80_Port_1_Control =		$A10008
Z80_Port_2_Control =		$A1000A
Z80_Expansion_Control =		$A1000C
Z80_Bus_Request =		$A11100
Z80_Reset =			$A11200

Security_Addr =			$A14000	
StartOfRom:

Step 2 Porting Sonic's art from Sonic 2

Next we actually need to port Sonic's art from Sonic 2 so go into sonmapED and Replace the Art file Mapping file and the PLC file and don't forget to change the format to sonic 1.

Step 3 Porting DMA Queue and Fixing animations

First replace everything from Sonic_Animate to Sonic's original animation file with.

; ---------------------------------------------------------------------------
; Subroutine to animate Sonic's sprites
; See also: AnimateSprite
; ---------------------------------------------------------------------------

; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||

; loc_1B350:
Sonic_Animate:
	lea	(SonicAniData).l,a1
	tst.b	(Super_Sonic_flag).w
	beq.s	loc1
	lea	(SuperSonicAniData).l,a1
loc1
	moveq	#0,d0
	move.b	anim(a0),d0
	cmp.b	next_anim(a0),d0	; has animation changed?
	beq.s	SAnim_Do		; if not, branch
	move.b	d0,next_anim(a0)	; set to next animation
	move.b	#0,anim_frame(a0)	; reset animation frame
	move.b	#0,anim_frame_duration(a0)	; reset frame duration
	bclr	#5,status(a0)
; loc_1B384:
SAnim_Do:
	add.w	d0,d0
	adda.w	(a1,d0.w),a1	; calculate address of appropriate animation script
	move.b	(a1),d0
	bmi.s	SAnim_WalkRun	; if animation is walk/run/roll/jump, branch
	move.b	status(a0),d1
	andi.b	#1,d1
	andi.b	#$FC,render_flags(a0)
	or.b	d1,render_flags(a0)
	subq.b	#1,anim_frame_duration(a0)	; subtract 1 from frame duration
	bpl.s	SAnim_Delay			; if time remains, branch
	move.b	d0,anim_frame_duration(a0)	; load frame duration
; loc_1B3AA:
SAnim_Do2:
	moveq	#0,d1
	move.b	anim_frame(a0),d1	; load current frame number
	move.b	1(a1,d1.w),d0		; read sprite number from script
	cmpi.b	#$F0,d0
	bcc.s	SAnim_End_FF		; if animation is complete, branch
; loc_1B3BA:
SAnim_Next:
	move.b	d0,mapping_frame(a0)	; load sprite number
	addq.b	#1,anim_frame(a0)	; go to next frame
; return_1B3C2:
SAnim_Delay:
	rts
; ===========================================================================
; loc_1B3C4:
SAnim_End_FF:
	addq.b	#1,d0		; is the end flag = $FF ?
	bne.s	SAnim_End_FE	; if not, branch
	move.b	#0,anim_frame(a0)	; restart the animation
	move.b	1(a1),d0	; read sprite number
	bra.s	SAnim_Next
; ===========================================================================
; loc_1B3D4:
SAnim_End_FE:
	addq.b	#1,d0		; is the end flag = $FE ?
	bne.s	SAnim_End_FD	; if not, branch
	move.b	2(a1,d1.w),d0	; read the next byte in the script
	sub.b	d0,anim_frame(a0)	; jump back d0 bytes in the script
	sub.b	d0,d1
	move.b	1(a1,d1.w),d0	; read sprite number
	bra.s	SAnim_Next
; ===========================================================================
; loc_1B3E8:
SAnim_End_FD:
	addq.b	#1,d0			; is the end flag = $FD ?
	bne.s	SAnim_End		; if not, branch
	move.b	2(a1,d1.w),anim(a0)	; read next byte, run that animation
; return_1B3F2:
SAnim_End:
	rts
; ===========================================================================
; loc_1B3F4:
SAnim_WalkRun:
	addq.b	#1,d0		; is the start flag = $FF ?
	bne.w	SAnim_Roll	; if not, branch
	moveq	#0,d0		; is animation walking/running?
	move.b	flip_angle(a0),d0	; if not, branch
	bne.w	SAnim_Tumble
	moveq	#0,d1
	move.b	angle(a0),d0	; get Sonic's angle
	bmi.s	loc2
	beq.s	loc2
	subq.b	#1,d0
loc2
	move.b	status(a0),d2
	andi.b	#1,d2		; is Sonic mirrored horizontally?
	bne.s	loc3		; if yes, branch
	not.b	d0		; reverse angle
loc3
	addi.b	#$10,d0		; add $10 to angle
	bpl.s	loc4		; if angle is $0-$7F, branch
	moveq	#3,d1
loc4
	andi.b	#$FC,render_flags(a0)
	eor.b	d1,d2
	or.b	d2,render_flags(a0)
	btst	#5,status(a0)
	bne.w	SAnim_Push
	lsr.b	#4,d0		; divide angle by 16
	andi.b	#6,d0		; angle must be 0, 2, 4 or 6
	move.w	inertia(a0),d2	; get Sonic's "speed" for animation purposes
	bpl.s	loc5
	neg.w	d2
loc5
	tst.b	status_secondary(a0)
	bpl.w	loc6
	add.w	d2,d2
loc6
	tst.b	(Super_Sonic_flag).w
	bne.s	SAnim_Super
	lea	(SonAni_Run).l,a1	; use running animation
	cmpi.w	#$600,d2		; is Sonic at running speed?
	bcc.s	loc7			; use running animation
	lea	(SonAni_Walk).l,a1	; if yes, branch
	add.b	d0,d0
loc7
	add.b	d0,d0
	move.b	d0,d3
	moveq	#0,d1
	move.b	anim_frame(a0),d1
	move.b	1(a1,d1.w),d0
	cmpi.b	#-1,d0
	bne.s	loc8
	move.b	#0,anim_frame(a0)
	move.b	1(a1),d0
loc8
	move.b	d0,mapping_frame(a0)
	add.b	d3,mapping_frame(a0)
	subq.b	#1,anim_frame_duration(a0)
	bpl.s	return_1B4AC
	neg.w	d2
	addi.w	#$800,d2
	bpl.s	loc81
	moveq	#0,d2
loc81
	lsr.w	#8,d2
	move.b	d2,anim_frame_duration(a0)	; modify frame duration
	addq.b	#1,anim_frame(a0)		; modify frame number

return_1B4AC:
	rts
; ===========================================================================
; loc_1B4AE:
SAnim_Super:
	lea	(SupSonAni_Run).l,a1	; use fast animation
	cmpi.w	#$800,d2		; is Sonic moving fast?
	bcc.s	SAnim_SuperRun		; if yes, branch
	lea	(SupSonAni_Walk).l,a1	; use slower animation
	add.b	d0,d0
	add.b	d0,d0
	bra.s	SAnim_SuperWalk
; ---------------------------------------------------------------------------
; loc_1B4C6:
SAnim_SuperRun:
	lsr.b	#1,d0
; loc_1B4C8:
SAnim_SuperWalk:
	move.b	d0,d3
	moveq	#0,d1
	move.b	anim_frame(a0),d1
	move.b	1(a1,d1.w),d0
	cmpi.b	#-1,d0
	bne.s	loc9
	move.b	#0,anim_frame(a0)
	move.b	1(a1),d0
loc9
	move.b	d0,mapping_frame(a0)
	add.b	d3,mapping_frame(a0)
	move.b	($FFFFFE05).w,d1
	andi.b	#3,d1
	bne.s	loc10
	cmpi.b	#-$4B,mapping_frame(a0)
	bcc.s	loc10
	addi.b	#$20,mapping_frame(a0)
loc10
	subq.b	#1,anim_frame_duration(a0)
	bpl.s	return_1B51E
	neg.w	d2
	addi.w	#$800,d2
	bpl.s	loc11
	moveq	#0,d2
loc11
	lsr.w	#8,d2
	move.b	d2,anim_frame_duration(a0)
	addq.b	#1,anim_frame(a0)

return_1B51E:
	rts
; ===========================================================================
; loc_1B520:
SAnim_Tumble:
	move.b	flip_angle(a0),d0
	moveq	#0,d1
	move.b	status(a0),d2
	andi.b	#1,d2
	bne.s	SAnim_Tumble_Left

	andi.b	#$FC,render_flags(a0)
	addi.b	#$B,d0
	divu.w	#$16,d0
	addi.b	#$5F,d0
	move.b	d0,mapping_frame(a0)
	move.b	#0,anim_frame_duration(a0)
	rts
; ===========================================================================
; loc_1B54E:
SAnim_Tumble_Left:
	andi.b	#$FC,render_flags(a0)
	tst.b	flip_turned(a0)
	beq.s	loc_1B566
	ori.b	#1,render_flags(a0)
	addi.b	#$B,d0
	bra.s	loc_1B572
; ===========================================================================

loc_1B566:
	ori.b	#3,render_flags(a0)
	neg.b	d0
	addi.b	#$8F,d0

loc_1B572:
	divu.w	#$16,d0
	addi.b	#$5F,d0
	move.b	d0,mapping_frame(a0)
	move.b	#0,anim_frame_duration(a0)
	rts
; ===========================================================================
; loc_1B586:
SAnim_Roll:
	subq.b	#1,anim_frame_duration(a0)	; subtract 1 from frame duration
	bpl.w	SAnim_Delay			; if time remains, branch
	addq.b	#1,d0		; is the start flag = $FE ?
	bne.s	SAnim_Push	; if not, branch
	move.w	inertia(a0),d2
	bpl.s	loc12
	neg.w	d2
loc12
	lea	(SonAni_Roll2).l,a1
	cmpi.w	#$600,d2
	bcc.s	loc14
	lea	(SonAni_Roll).l,a1
loc14
	neg.w	d2
	addi.w	#$400,d2
	bpl.s	loc15
	moveq	#0,d2
loc15
	lsr.w	#8,d2
	move.b	d2,anim_frame_duration(a0)
	move.b	status(a0),d1
	andi.b	#1,d1
	andi.b	#$FC,render_flags(a0)
	or.b	d1,render_flags(a0)
	bra.w	SAnim_Do2
; ===========================================================================

SAnim_Push:
	subq.b	#1,anim_frame_duration(a0)	; subtract 1 from frame duration
	bpl.w	SAnim_Delay			; if time remains, branch
	move.w	inertia(a0),d2
	bmi.s	loc16
	neg.w	d2
loc16
	addi.w	#$800,d2
	bpl.s	loc17
	moveq	#0,d2
loc17
	lsr.w	#6,d2
	move.b	d2,anim_frame_duration(a0)
	lea	(SonAni_Push).l,a1
	tst.b	(Super_Sonic_flag).w
	beq.s	loc18
	lea	(SupSonAni_Push).l,a1
loc18
	move.b	status(a0),d1
	andi.b	#1,d1
	andi.b	#$FC,render_flags(a0)
	or.b	d1,render_flags(a0)
	bra.w	SAnim_Do2
; ===========================================================================

; ---------------------------------------------------------------------------
; Animation script - Sonic
; ---------------------------------------------------------------------------
; off_1B618:
SonicAniData:
	dc.w SonAni_Walk-SonicAniData		; 0
	dc.w SonAni_Run-SonicAniData		; 1
	dc.w SonAni_Roll-SonicAniData		; 2
	dc.w SonAni_Roll2-SonicAniData	; 3
	dc.w SonAni_Push-SonicAniData		; 4
	dc.w SonAni_Wait-SonicAniData		; 5
	dc.w SonAni_Balance-SonicAniData	; 6
	dc.w SonAni_LookUp-SonicAniData	; 7
	dc.w SonAni_Duck-SonicAniData		; 8
	dc.w SonAni_Spindash-SonicAniData	; 9
	dc.w SonAni_Blink-SonicAniData	; 10 ; $A
	dc.w SonAni_GetUp-SonicAniData	; 11 ; $B
	dc.w SonAni_Balance2-SonicAniData	; 12 ; $C
	dc.w SonAni_Stop-SonicAniData		; 13 ; $D
	dc.w SonAni_Float-SonicAniData	; 14 ; $E
	dc.w SonAni_Float2-SonicAniData	; 15 ; $F
	dc.w SonAni_Spring-SonicAniData	; 16 ; $10
	dc.w SonAni_Hang-SonicAniData		; 17 ; $11
	dc.w SonAni_Dash2-SonicAniData	; 18 ; $12
	dc.w SonAni_Dash3-SonicAniData	; 19 ; $13
	dc.w SonAni_Hang2-SonicAniData	; 20 ; $14
	dc.w SonAni_Bubble-SonicAniData	; 21 ; $15
	dc.w SonAni_DeathBW-SonicAniData	; 22 ; $16
	dc.w SonAni_Drown-SonicAniData	; 23 ; $17
	dc.w SonAni_Death-SonicAniData	; 24 ; $18
	dc.w SonAni_Hurt-SonicAniData		; 25 ; $19
	dc.w SonAni_Hurt-SonicAniData		; 26 ; $1A
	dc.w SonAni_Slide-SonicAniData	; 27 ; $1B
	dc.w SonAni_Blank-SonicAniData	; 28 ; $1C
	dc.w SonAni_Balance3-SonicAniData	; 29 ; $1D
	dc.w SonAni_Balance4-SonicAniData	; 30 ; $1E
	dc.w SupSonAni_Transform-SonicAniData	; 31 ; $1F
	dc.w SonAni_Lying-SonicAniData	; 32 ; $20
	dc.w SonAni_LieDown-SonicAniData	; 33 ; $21
SonAni_Walk:	dc.b $FF, $F,$10,$11,$12,$13,$14, $D, $E,$FF
SonAni_Run:	dc.b $FF,$2D,$2E,$2F,$30,$FF,$FF,$FF,$FF,$FF
SonAni_Roll:	dc.b $FE,$3D,$41,$3E,$41,$3F,$41,$40,$41,$FF
SonAni_Roll2:	dc.b $FE,$3D,$41,$3E,$41,$3F,$41,$40,$41,$FF
SonAni_Push:	dc.b $FD,$48,$49,$4A,$4B,$FF,$FF,$FF,$FF,$FF
SonAni_Wait:
	dc.b   5,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
	dc.b   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  2
	dc.b   3,  3,  3,  3,  3,  4,  4,  4,  5,  5,  5,  4,  4,  4,  5,  5
	dc.b   5,  4,  4,  4,  5,  5,  5,  4,  4,  4,  5,  5,  5,  6,  6,  6
	dc.b   6,  6,  6,  6,  6,  6,  6,  4,  4,  4,  5,  5,  5,  4,  4,  4
	dc.b   5,  5,  5,  4,  4,  4,  5,  5,  5,  4,  4,  4,  5,  5,  5,  6
	dc.b   6,  6,  6,  6,  6,  6,  6,  6,  6,  4,  4,  4,  5,  5,  5,  4
	dc.b   4,  4,  5,  5,  5,  4,  4,  4,  5,  5,  5,  4,  4,  4,  5,  5
	dc.b   5,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  4,  4,  4,  5,  5
	dc.b   5,  4,  4,  4,  5,  5,  5,  4,  4,  4,  5,  5,  5,  4,  4,  4
	dc.b   5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  7,  8,  8
	dc.b   8,  9,  9,  9,$FE,  6
SonAni_Balance:	dc.b   9,$CC,$CD,$CE,$CD,$FF
SonAni_LookUp:	dc.b   5, $B, $C,$FE,  1
SonAni_Duck:	dc.b   5,$4C,$4D,$FE,  1
SonAni_Spindash:dc.b   0,$42,$43,$42,$44,$42,$45,$42,$46,$42,$47,$FF
SonAni_Blink:	dc.b   1,  2,$FD,  0
SonAni_GetUp:	dc.b   3, $A,$FD,  0
SonAni_Balance2:dc.b   3,$C8,$C9,$CA,$CB,$FF
SonAni_Stop:	dc.b   5,$D2,$D3,$D4,$D5,$FD,  0 ; halt/skidding animation
SonAni_Float:	dc.b   7,$54,$59,$FF
SonAni_Float2:	dc.b   7,$54,$55,$56,$57,$58,$FF
SonAni_Spring:	dc.b $2F,$5B,$FD,  0
SonAni_Hang:	dc.b   1,$50,$51,$FF
SonAni_Dash2:	dc.b  $F,$43,$43,$43,$FE,  1
SonAni_Dash3:	dc.b  $F,$43,$44,$FE,  1
SonAni_Hang2:	dc.b $13,$6B,$6C,$FF
SonAni_Bubble:	dc.b  $B,$5A,$5A,$11,$12,$FD,  0 ; breathe
SonAni_DeathBW:	dc.b $20,$5E,$FF
SonAni_Drown:	dc.b $20,$5D,$FF
SonAni_Death:	dc.b $20,$5C,$FF
SonAni_Hurt:	dc.b $40,$4E,$FF
SonAni_Slide:	dc.b   9,$4E,$4F,$FF
SonAni_Blank:	dc.b $77,  0,$FD,  0
SonAni_Balance3:dc.b $13,$D0,$D1,$FF
SonAni_Balance4:dc.b   3,$CF,$C8,$C9,$CA,$CB,$FE,  4
SonAni_Lying:	dc.b   9,  8,  9,$FF
SonAni_LieDown:	dc.b   3,  7,$FD,  0
	even

; ---------------------------------------------------------------------------
; Animation script - Super Sonic
; (many of these point to the data above this)
; ---------------------------------------------------------------------------
SuperSonicAniData:
	dc.w SupSonAni_Walk-SuperSonicAniData		; 0
	dc.w SupSonAni_Run-SuperSonicAniData          ; 1
	dc.w SonAni_Roll-SuperSonicAniData            ; 2
	dc.w SonAni_Roll2-SuperSonicAniData           ; 3
	dc.w SupSonAni_Push-SuperSonicAniData         ; 4
	dc.w SupSonAni_Stand-SuperSonicAniData        ; 5
	dc.w SupSonAni_Balance-SuperSonicAniData      ; 6
	dc.w SonAni_LookUp-SuperSonicAniData          ; 7
	dc.w SupSonAni_Duck-SuperSonicAniData         ; 8
	dc.w SonAni_Spindash-SuperSonicAniData        ; 9
	dc.w SonAni_Blink-SuperSonicAniData           ; 10 ; $A
	dc.w SonAni_GetUp-SuperSonicAniData           ; 11 ; $B
	dc.w SonAni_Balance2-SuperSonicAniData        ; 12 ; $C
	dc.w SonAni_Stop-SuperSonicAniData            ; 13 ; $D
	dc.w SonAni_Float-SuperSonicAniData           ; 14 ; $E
	dc.w SonAni_Float2-SuperSonicAniData          ; 15 ; $F
	dc.w SonAni_Spring-SuperSonicAniData          ; 16 ; $10
	dc.w SonAni_Hang-SuperSonicAniData            ; 17 ; $11
	dc.w SonAni_Dash2-SuperSonicAniData           ; 18 ; $12
	dc.w SonAni_Dash3-SuperSonicAniData           ; 19 ; $13
	dc.w SonAni_Hang2-SuperSonicAniData           ; 20 ; $14
	dc.w SonAni_Bubble-SuperSonicAniData          ; 21 ; $15
	dc.w SonAni_DeathBW-SuperSonicAniData         ; 22 ; $16
	dc.w SonAni_Drown-SuperSonicAniData           ; 23 ; $17
	dc.w SonAni_Death-SuperSonicAniData           ; 24 ; $18
	dc.w SonAni_Hurt-SuperSonicAniData            ; 25 ; $19
	dc.w SonAni_Hurt-SuperSonicAniData            ; 26 ; $1A
	dc.w SonAni_Slide-SuperSonicAniData           ; 27 ; $1B
	dc.w SonAni_Blank-SuperSonicAniData           ; 28 ; $1C
	dc.w SonAni_Balance3-SuperSonicAniData        ; 29 ; $1D
	dc.w SonAni_Balance4-SuperSonicAniData        ; 30 ; $1E
	dc.w SupSonAni_Transform-SuperSonicAniData    ; 31 ; $1F

SupSonAni_Walk:		dc.b $FF,$77,$78,$79,$7A,$7B,$7C,$75,$76,$FF
SupSonAni_Run:		dc.b $FF,$B5,$B9,$FF,$FF,$FF,$FF,$FF,$FF,$FF
SupSonAni_Push:		dc.b $FD,$BD,$BE,$BF,$C0,$FF,$FF,$FF,$FF,$FF
SupSonAni_Stand:	dc.b   7,$72,$73,$74,$73,$FF
SupSonAni_Balance:	dc.b   9,$C2,$C3,$C4,$C3,$C5,$C6,$C7,$C6,$FF
SupSonAni_Duck:		dc.b   5,$C1,$FF
SupSonAni_Transform:	dc.b   2,$6D,$6D,$6E,$6E,$6F,$70,$71,$70,$71,$70,$71,$70,$71,$FD,  0
	even

Now if you do this you'll get two out of range errors.

To fix it go to this label

Boundary_Bottom:
		cmpi.w	#$501,($FFFFFE10).w ; is level SBZ2 ?
		bne.w	KillSonic	; if not, kill Sonic
		cmpi.w	#$2000,($FFFFD008).w
		bcs.w	KillSonic
		clr.b	($FFFFFE30).w	; clear	lamppost counter
		move.w	#1,($FFFFFE02).w ; restart the level
		move.w	#$103,($FFFFFE10).w ; set level	to SBZ3	(LZ4)
		rts

Change Both killSonic routines to Jmp_KillSonic.

And add this routine.

Jmp_KillSonic:
	       jmp    KillSonic

That should fix the problem.

Now you might notice the art has overwritten other art and some animations are broken!

To fix it you'll have to port QueueDMATransfer and extend the map and animation limit.

Here's both guides.

Step 4 Actually porting Super Sonic

Now it's time to actually port Super Sonic so goto Sonic_jumpheight and at label locret_134C2 add this.

	tst.b	y_vel(a0)		; is Sonic exactly at the height of his jump?
	beq.s	Sonic_CheckGoSuper	; if yes, test for turning into Super Sonic

Then after ; End of function Sonic_JumpHeight Add this.

; ---------------------------------------------------------------------------
; Subroutine called at the peak of a jump that transforms Sonic into Super Sonic
; if he has enough rings and emeralds
; ---------------------------------------------------------------------------

; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||

; loc_1AB38: test_set_SS:
Sonic_CheckGoSuper:
	tst.b	(Super_Sonic_flag).w	; is Sonic already Super?
	bne.s	return_1ABA4		; if yes, branch
;	cmpi.b	#7,(Emerald_count).w	; does Sonic have exactly 7 emeralds?
;	bne.s	return_1ABA4		; if not, branch
	cmpi.w	#50,(Ring_count).w	; does Sonic have at least 50 rings?
	bcs.s	return_1ABA4		; if not, branch

	move.b	#1,(Super_Sonic_palette).w
	move.b	#$F,(Palette_frame_count).w
	move.b	#1,(Super_Sonic_flag).w
	move.b	#$81,obj_control(a0)
	move.b	#$1F,anim(a0)			; use transformation animation
;	move.b	#$7E,(Object_RAM+$2040).w	; Obj7E is the ending sonic which is why it's commented out
	move.w	#$A00,(Sonic_top_speed).w
	move.w	#$30,(Sonic_acceleration).w
	move.w	#$100,(Sonic_deceleration).w
	move.w	#0,invincibility_time(a0)
	bset	#1,status_secondary(a0)	; make Sonic invincible
	move.w	#$C3,d0         ; 
	jsr	(PlaySound).l	; Play special ring sound effect.
	move.w	#$87,d0         
	jmp	(PlaySound_Special).l	; load the invincibility song and return also playmusic doesn't exist

; ---------------------------------------------------------------------------
return_1ABA4:
	rts
; End of subroutine Sonic_CheckGoSuper


; ---------------------------------------------------------------------------
; Subroutine doing the extra logic for Super Sonic
; ---------------------------------------------------------------------------

; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||

; loc_1ABA6:
Sonic_Super:
	tst.b	(Super_Sonic_flag).w	; Ignore all this code if not Super Sonic
	beq.w	return_1AC3C
	tst.b	(Update_HUD_timer).w
	beq.s	Sonic_RevertToNormal ; ?
	subq.w	#1,(Super_Sonic_frame_count).w
	bpl.w	return_1AC3C
	move.w	#60,(Super_Sonic_frame_count).w	; Reset frame counter to 60
	tst.w	(Ring_count).w
	beq.s	Sonic_RevertToNormal
	ori.b	#1,(Update_HUD_rings).w
	cmpi.w	#1,(Ring_count).w
	beq.s	@update
	cmpi.w	#10,(Ring_count).w
	beq.s	@update
	cmpi.w	#100,(Ring_count).w
	bne.s	@update2
@update
	ori.b	#$80,(Update_HUD_rings).w
@update2
	subq.w	#1,(Ring_count).w
	bne.s	return_1AC3C
; loc_1ABF2:
Sonic_RevertToNormal:
	move.b	#2,(Super_Sonic_palette).w	; Remove rotating palette
	move.w	#$28,($FFFFF65C).w	; Unknown
	move.b	#0,(Super_Sonic_flag).w
	move.b	#1,next_anim(a0)	; Change animation back to normal ?
	move.w	#1,invincibility_time(a0)	; Remove invincibility
	move.w	#$600,(Sonic_top_speed).w
	move.w	#$C,(Sonic_acceleration).w
	move.w	#$80,(Sonic_deceleration).w
	btst	#6,status(a0)	; Check if underwater, return if not
	beq.s	return_1AC3C
	move.w	#$300,(Sonic_top_speed).w
	move.w	#6,(Sonic_acceleration).w
	move.w	#$40,(Sonic_deceleration).w

return_1AC3C:
	rts
; End of subroutine Sonic_Super

Step 5 Fixing bugs and issues

Sonic isn't invincible

Change this.

bset #1,status_secondary(a0) ; make Sonic invincible

To this

move.b #1,($FFFFFE2D).w ; make Sonic invincible

Ring count wont drain

Go to Obj01_Control and at label loc_12C7E add a branch to sonic_super.

		bsr.s	Sonic_Display
	        bsr.w	Sonic_Super       ;<--- add this!
		bsr.w	Sonic_RecordPos
		bsr.w	Sonic_Water

Water related bugs

Goto Obj01_InWater and after this.

		move.w	#$300,($FFFFF760).w ; change Sonic's top speed
		move.w	#6,($FFFFF762).w ; change Sonic's acceleration
		move.w	#$40,($FFFFF764).w ; change Sonic's deceleration

Add this

	tst.b	(Super_Sonic_flag).w	; Is Sonic Super?
	beq.s	@Skip			; If not branch
	move.w	#$500,(Sonic_top_speed).w
	move.w	#$18,(Sonic_acceleration).w
	move.w	#$80,(Sonic_deceleration).w
@Skip

Then goto Obj01_OutWater and after this.

		move.w	#$600,($FFFFF760).w ; restore Sonic's speed
		move.w	#$C,($FFFFF762).w ; restore Sonic's acceleration
		move.w	#$80,($FFFFF764).w ; restore Sonic's deceleration

Add this

	tst.b	(Super_Sonic_flag).w	; Is Sonic Super?
	beq.s	@Skip			; If not branch
	move.w	#$A00,(Sonic_top_speed).w
	move.w	#$30,(Sonic_acceleration).w
	move.w	#$100,(Sonic_deceleration).w
@Skip

Sonic doesn't go back to normal when he passes the signpost and dies

Go to Obj0D_Spin and KillSonic & add

		clr.b (Super_Sonic_Flag).w ; Revert Sonic to Normal
		move.w #$600,(Sonic_top_speed).w ; Revert speeds
		move.w #$C,(Sonic_acceleration).w ; ^^^
		move.w #$80,(Sonic_deceleration).w ; ^^^

Super Sonic loses invincibility when the invincibility power up run out

Go to Obj2E_ChkInvinc & below Obj2E_ChkRings add.

		cmpi.b #1,(Super_Sonic_Flag).w ; Prevent Sonic from getting (invincibility, shoes) if Super
                beq Obj2E_NoMusic

Super Sonic loses speed when speedshoes power up run out

Go to Obj2E_ChkShoes & below Obj2E_ChkShield add.

		cmpi.b #1,(Super_Sonic_Flag).w ; Prevent Sonic from getting (invincibility, shoes) if Super
                beq Obj2E_NoMusic

Sonic Still looks super when exiting a level via debug

Goto Obj01_Main and at the end add this

		move.b	#0,(Super_Sonic_flag).w

Bugs I don't know how to fix

  • Some Level palates bug out
  • Grabbing speed shoes before transforming bugs the speed
  • 10 Points and 100 Points text gets overwritten
  • Super Sonic's palate doesn't display underwater

If you have these solutions you can add them here.

There are more bugs click here to fix them.

Porting Super Sonic's pallete

(Coming Soon)