banner



How To Add Spin Dash To Sonic 1

(Original guide by Lightning)
updated by kram1024 to remove dependency on super sonic flag

This tutorial was made possible thanks to the references, guides, and information plant at Hacking CulT, The Sonic 2 Beta Page, Sonic Retro, and Sonicology. It was inspired by the guide at The Glowing Bridge that details porting the simpler Spin Dash from the Sonic 2 early on beta.

This document is property of Lightning. Sonic and all related characters and graphics that appear on this page are property of Sega and are used without permission for no profit.

Contents

  • 1 What you demand
  • 2 Hivebrain's 2005 disassembly
    • 2.one Directly copying the object code
    • ii.2 Changing the animations and sounds
    • 2.3 Fixing bugs
    • 2.iv Adding new tiles
    • ii.5 Making PLCs for the tiles
    • 2.half dozen Mappings
    • 2.7 Animation sequence
    • 2.8 Changing the animation over again
    • 2.nine Some other ready
    • 2.10 Appendix
  • 3 GitHub disassembly
    • 3.ane Previous preparation
    • 3.ii Direct copying the object lawmaking
    • 3.3 Changing the animations and sounds
    • 3.4 Fixing bugs
    • iii.5 Adding new tiles
    • 3.six Making PLCs for the tiles
    • 3.7 Mappings
    • three.8 Animation sequence
    • three.nine Changing the animation once again
    • 3.ten Another fix
    • 3.eleven Appendix
  • 4 Pu7o's continuation

What you lot demand

  • Sonic 1 carve up disassembly
  • Sonic ii split disassembly
  • A evidently text editor of your choice
  • A tile editor capable of editing Genesis format tiles
  • A Sega Genesis emulator (or hardware with a copier)

In making this tutorial, I used:

  • Hivebrain's 2005 Sonic 1 split disassembly (updated to ASM68K - andlabs)
  • Aurochs' 2006 Sonic 2 divide disassembly
  • Leafpad 0.viii.10le - GTK+ based uncomplicated text editor
  • Tile Molester 0.16 - Java tile editor (writer's site no longer exists)
  • Generator/gtk 0.35 - Cross-platform Genesis emulator

Hivebrain'south 2005 disassembly

Directly copying the object code

Open up sonic1.asm from the Sonic 1 disassembly in your text editor, and search for the phrase Obj01: (line 23466 in Hivebrain's disassembly). This should bring you to the Sonic object's code, which is what yous're interested in editing right at present. Now, open s2.asm from the Sonic two disassembly in your text editor, and search for Object_Sonic: (line 35720 in Aurochs' disassembly). This will bring you again to Sonic'southward object code. Having been based on the aforementioned code from Sonic i, it shows many similarities that y'all should be able to spot. Thanks to the like lawmaking, our task in porting the Spin Dash should exist pretty easy!

Find or ringlet to the location Obj01_MdNormal: in Sonic ane's source, and loc_1A2B8: in Sonic 2'due south source. Below this characterization in each is a series of branches and jumps to subroutines that handle Sonic'south actions in dissimilar situations. If you await carefully, y'all'll observe that there are 9 of these branches in Sonic 2, only merely eight in Sonic 1. That's because Sonic 2 has another co-operative to the code that handles the Spin Dash. You're going to add together Spin Nuance to Sonic 1, so the first thing to do is add a call to the Spin Dash office that you're going to re-create. Don't worry about the label names from Sonic 2, since yous're going to name the subroutine Sonic_SpinDash when we copy information technology over.

In Sonic one'south code, make a copy of the line bsr.west Sonic_Jump and change information technology to branch to Sonic_SpinDash, every bit shown:

; --------------------------------------------------------------------------- ; Modes	for decision-making	Sonic ; ---------------------------------------------------------------------------  Obj01_MdNormal:				; XREF: Obj01_Modes 		bsr.w	Sonic_SpinDash	; add this line! 		bsr.w	Sonic_Jump 		bsr.west	Sonic_SlopeResist 		bsr.w	Sonic_Move 		bsr.westward	Sonic_Roll 		bsr.westward	Sonic_LevelBound 		jsr	SpeedToPos 		bsr.due west	Sonic_AnglePos 		bsr.west	Sonic_SlopeRepel 		rts	 ; ===========================================================================

Now, to actually copy the Spin Dash subroutine. In Sonic 2, observe the characterization loc_1AC3E:. This is the subroutine that we are going to copy, so select from that line all the style down to where you see ; End of subroutine loc_1AC3E, and copy the code. In Sonic 1, discover ; End of function Sonic_JumpHeight and paste the block of code from Sonic ii below it.

There are a few changes that we demand to make and so this code will cooperate with the rest of the Sonic ane lawmaking, since some of the labels in each disassembly differ from each other (the same functions take different names). The following replacements should exist made (apply your text editor's find and supersede function, if applicable):

  • loc_1AC3E with Sonic_SpinDash
  • loc_1A974 with Sonic_LevelBound
  • loc_1E234 with Sonic_AnglePos
  • play_SFX with PlaySound_Special
  • word_1AD0C with Dash_Speeds
  • remove all this lawmaking since it is a leftover artifact of super sonic:
            tst.b	(Super_Sonic_flag).w 		beq.s	loc_1ACD0 		move.west	word_1AD1E(pc,d0.west),$xiv(a0)  loc_1ACD0:
  • remove this besides since it is super sonic'southward dash speeds:
word_1AD1E:	dc.westward  $B00		; 0 		dc.w  $B80		; 1 		dc.w  $C00		; 2 		dc.w  $C80		; 3 		dc.due west  $D00		; 4 		dc.w  $D80		; v 		dc.due west  $E00		; six 		dc.w  $E80		; seven 		dc.westward  $F00		; 8

Done! You should now accept a block of code that looks like the post-obit in between where it says ; Terminate of role Sonic_JumpHeight and ; Subroutine to slow Sonic walking up a slope in Sonic 1.

; --------------------------------------------------------------------------- ; Subroutine to brand Sonic perform a spindash ; ---------------------------------------------------------------------------  ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||   Sonic_SpinDash: 		tst.b	$39(a0) 		bne.s	loc_1AC8E 		cmpi.b	#8,$1C(a0) 		bne.s	locret_1AC8C 		movement.b	($FFFFF603).w,d0 		andi.b	#$seventy,d0 		beq.westward	locret_1AC8C 		move.b	#nine,$1C(a0) 		move.w	#$E0,d0 		jsr	(PlaySound_Special).l 		addq.l	#4,sp 		move.b	#1,$39(a0) 		move.w	#0,$3A(a0) 		cmpi.b	#$C,$28(a0) 		bcs.south	loc_1AC84 		move.b	#ii,($FFFFD11C).west  loc_1AC84: 		bsr.w	Sonic_LevelBound 		bsr.w	Sonic_AnglePos  locret_1AC8C: 		rts	 ; ---------------------------------------------------------------------------  loc_1AC8E: 		move.b	($FFFFF602).w,d0 		btst	#1,d0 		bne.west	loc_1AD30 		move.b	#$E,$sixteen(a0) 		move.b	#7,$17(a0) 		motion.b	#2,$1C(a0) 		addq.w	#5,$C(a0) 		motion.b	#0,$39(a0) 		moveq	#0,d0 		move.b	$3A(a0),d0 		add.west	d0,d0 		move.west	Dash_Speeds(pc,d0.w),$14(a0) 		motility.westward	$14(a0),d0 		subi.westward	#$800,d0 		add.w	d0,d0 		andi.w	#$1F00,d0 		neg.w	d0 		addi.w	#$2000,d0 		move.due west	d0,($FFFFEED0).w 		btst	#0,$22(a0) 		beq.s	loc_1ACF4 		neg.w	$14(a0)  loc_1ACF4: 		bset	#2,$22(a0) 		movement.b	#0,($FFFFD11C).west 		move.westward	#$BC,d0 		jsr	(PlaySound_Special).l 		bra.s	loc_1AD78 ; =========================================================================== Dash_Speeds:	dc.w  $800		; 0 		dc.west  $880		; i 		dc.due west  $900		; two 		dc.westward  $980		; 3 		dc.westward  $A00		; 4 		dc.w  $A80		; v 		dc.w  $B00		; 6 		dc.westward  $B80		; 7 		dc.w  $C00		; viii ; ===========================================================================  loc_1AD30:				; If still charging the nuance... 		tst.west	$3A(a0) 		beq.s	loc_1AD48 		motility.w	$3A(a0),d0 		lsr.w	#5,d0 		sub.westward	d0,$3A(a0) 		bcc.s	loc_1AD48 		movement.w	#0,$3A(a0)  loc_1AD48: 		move.b	($FFFFF603).due west,d0 		andi.b	#$70,d0	; 'p' 		beq.w	loc_1AD78 		motion.w	#$900,$1C(a0) 		move.west	#$E0,d0	; 'à' 		jsr	(PlaySound_Special).l 		addi.westward	#$200,$3A(a0) 		cmpi.west	#$800,$3A(a0) 		bcs.southward	loc_1AD78 		move.w	#$800,$3A(a0)  loc_1AD78: 		addq.fifty	#4,sp 		cmpi.w	#$60,($FFFFEED8).w 		beq.south	loc_1AD8C 		bcc.due south	loc_1AD88 		addq.due west	#four,($FFFFEED8).due west  loc_1AD88: 		subq.w	#two,($FFFFEED8).w  loc_1AD8C: 		bsr.due west	Sonic_LevelBound 		bsr.west	Sonic_AnglePos 		rts ; End of subroutine Sonic_SpinDash

At present, let's examination it! Build your ROM and open it in your emulator.

Spin Dashing with a strange animation

Uh-oh, it seems like it's a bit rough around the edges right now. First of all, Sonic's Spin Dashing animation isn't nowadays in Sonic 1, of course, and right now it'south using the blitheness from the spot that the Spin Nuance's animation information replaced. Also, the music and sounds seem to stop when yous first charging a Spin Nuance. That's because the sound ID that is the Spin Nuance sound in Sonic 2 has a unlike purpose in Sonic 1. The physics of the Spin Dash are conspicuously in place, notwithstanding. This is a good starting time!

Changing the animations and sounds

Now, you're going to make a few simple changes to the Spin Dash subroutine so it uses suitable animations and sounds that are already present in Sonic 1. First, notice any instances of the line move.due west #$E0,d0 followed past jsr (PlaySound_Special).l. This code loads the sound ID #$E0 into the data register d0 and jumps to the subroutine that is responsible for playing that sound. #$E0 is not a suitable sound for a Spin Dash in Sonic 1, as mentioned earlier--it silences the music. Replace the #$E0 with #$Be in each occurance. #$Be is the sound ID of a normal spin in Sonic i. Yous can check it in the audio test for yourself!

At present, go up to the line containing the code movement.b #9,$1C(a0), and supplant the #9 with #2. This code copies the animation number to be used when Sonic starts charging his Spin Dash. #9 is the ID of the blitheness used for Spin Nuance in Sonic 2; even so, in Sonic 1, it'due south the ID of an unused animation presumably for warping. Animation #2 is the animation used for jumping and rolling in Sonic one. You should accept something like this:

            motility.b	($FFFFF603).due west,d0 		andi.b	#$70,d0 		beq.w	locret_1AC8C 		move.b	#2,$1C(a0)	; changed from #9 		move.w	#$BE,d0		; changed from #$E0 		jsr	(PlaySound_Special).l

Now, find motion.westward #$900,$1C(a0) lower in the code. This puts the blitheness #9 and a flag to reset it to the first frame into Sonic's retentiveness. For now, allow's just annotate out this line by placing a ; in forepart of the code, like so:

loc_1AD48: 		motion.b	($FFFFF603).w,d0 		andi.b	#$seventy,d0	; 'p' 		beq.w	loc_1AD78 	;	movement.w	#$900,$1C(a0) 		motility.w	#$Exist,d0		; changed from #$E0 		jsr	(PlaySound_Special).l

Salve and build your ROM! Allow's run across how it does...

Spin Dashing with rolling animation

Success! The charging sound works fine, and the blitheness looks similar to the Spin Nuance constitute in Sonic CD. Not bad! However, at that place are a few bugs present.

First of all, collect a few rings, then start charging a Spin Dash somewhere that an enemy can shoot you or injure yous somehow. If yous get hit while charging, yous'll still be in a Spin Dash-charging country when you lot state. If yous let go of the down push button while bouncing backwards, Sonic will release his Spin Dash right away when he hits the ground. At present, this might be awesome in itself and certainly should kill whatever badnik hurt y'all in the get-go place, merely information technology isn't what should happen.

2nd, movement somewhere where the photographic camera has room to movement downwardly. If you hold the down button to duck, then get-go charging the Spin Dash, the camera stays depression until you lot are no longer rolling.

Spin Dashing with low camera

Another problem that results from this is that if you lot Spin Dash before an area where your vertical position radically changes (for instance, the double-S-tube in GHZ1), the camera takes too long to catch up to you lot.

camera lagging behind

Fixing bugs

First of all, let's fix the camera issue. Go to the end of the Spin Dash subroutine, and put move.west #$60,($FFFFF73E).w just above the rts. This will reset the vertical change in the camera'southward position. Y'all should have something like this:

loc_1AD8C: 		bsr.w	Sonic_LevelBound 		bsr.westward	Sonic_AnglePos 		movement.due west	#$60,($FFFFF73E).due west	; reset looking up/down 		rts ; End of subroutine Sonic_SpinDash

Save, build the ROM, and exam it. You should find that the camera does reset itself when y'all starting time to Spin Nuance, merely if you lot take the double-S-tube in GHZ1, yous still barely outrun the screen vertically and get killed. To fix this, find the code at the label Boundary_Bottom:. First, add together a characterization just before the rts at the end of the cake of code, named Boundary_Bottom_locret:. Then, at the beginning of Boundary_Bottom:, you lot're going to compare two values in memory. If ($FFFFF726).due west < ($FFFFF72E).due west, then the screen is still scrolling down and you don't want to die. In this case, it should skip the part beneath that jumps to the routine KillSonic. You lot should add the following lines of code below Boundary_Bottom:.

            motility.w	($FFFFF726).west,d0 		move.w	($FFFFF72E).w,d1 		cmp.w	d0,d1 		blt.s	Boundary_Bottom_locret

You lot should end up with something like this:

Boundary_Bottom: 		movement.westward	($FFFFF726).w,d0 		move.westward	($FFFFF72E).w,d1 		cmp.westward	d0,d1			; screen still scrolling down? 		blt.southward	Boundary_Bottom_locret	; if and so, don't kill Sonic 		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).west		; clear lamppost counter 		motility.w	#one,($FFFFFE02).w	; restart the level 		motion.w	#$103,($FFFFFE10).w	; prepare level to SBZ3 (LZ4)  Boundary_Bottom_locret: 		rts	 ; ===========================================================================

These fixes can also be found

Sonic Retro

here.

Now, you'll fix the problem where Sonic is still in his Spin Dashing state later on he gets injured. Find the subroutine HurtSonic:. This is the code that handles hurting Sonic, if you couldn't guess. You're going to take it clear the flag in memory that stores whether or not Sonic is Spin Dashing. Coil to the characterization Hurt_ChkSpikes: and add the line move.b #0,$39(a0) direct below it. Yous should end upwardly with:

Hurt_ChkSpikes: 		move.b	#0,$39(a0)	; clear Spin Dash flag 		move.west	#0,$14(a0) 		move.b	#$1A,$1C(a0) 		move.west	#$78,$30(a0)

Save, build, and exam. If all is well, those bugs should be gone! Now you have a functioning Spin Dash in Sonic ane. However, it doesn't look like the Spin Nuance from Sonic 2. In the adjacent sections, we will rectify this.

Adding new tiles

At present, you'll need to add the Spin Dash tiles from Sonic 2's tiles to Sonic 1's; However, you'll demand to pad the file artunc/sonic.bin to go room for the new tiles commencement. To do this, you have to create a batch file (.bat) with following code in the folder artunc:

fsutil file createnew padding.bin 16384  :: Create a file called "padding.bin" with 16KB  ren sonic.bin sonic_old.bin  :: Rename the original "sonic.bin" to "sonic_old.bin"  re-create /b sonic_old.bin+padding.bin sonic.bin  :: Copy the two files into a new "sonic.bin"

Run information technology and you volition find your sonic.bin 16KB bigger. If anything went wrong, use the fill-in file named equally sonic_old.bin


At present, in your tile editor, open the padded artunc/sonic.bin and Sonic two'southward art/uncompressed/Sonic's art.bin. These are the tiles you're after:

copying sonic's Spin Dash tiles

Re-create them from the Sonic two tiles to the end of the Sonic 1 tiles. Practise note that it shouldn't matter if yous employ the default palette of your tile editor, every bit long every bit the one you're using for Sonic ii's tiles matches the one you're using for Sonic i's tiles.

Relieve the Sonic 1 file artunc/sonic.bin and close your tile editor. Yous may rebuild the ROM, but there shouldn't be whatsoever noticeable changes, since the game isn't coded to actually exercise annihilation with the tiles we put there nonetheless.

Making PLCs for the tiles

Now, you lot'll add the design load cues to tell the game to load the tiles y'all just added. Open _inc/Sonic dynamic pattern load cues.asm in your text editor. At the lesser of the large table of offsets, and just before the characterization SonPLC_Blank:, add the following lines:

            dc.due west SonPLC_SpinDash1-SonicDynPLC	;58 		dc.w SonPLC_SpinDash2-SonicDynPLC	;59 		dc.westward SonPLC_SpinDash3-SonicDynPLC	;5A 		dc.w SonPLC_SpinDash4-SonicDynPLC	;5B 		dc.w SonPLC_SpinDash5-SonicDynPLC	;5C 		dc.west SonPLC_SpinDash6-SonicDynPLC	;5D

Note that the hex numbers commented to the side are indeces. If you were to number each line in the list you just added to in hex, starting at zero, those would be the numbers for those lines. These volition be of import later because they are the frame numbers that volition be used in your animation.

At present, at the very bottom of the file, but just earlier the even, insert the following lines:

SonPLC_SpinDash1:	dc.b i, $F5, $10	; 01 F 510 SonPLC_SpinDash2:	dc.b 1, $F5, $xx	; 01 F 520 SonPLC_SpinDash3:	dc.b 1, $F5, $thirty	; 01 F 530 SonPLC_SpinDash4:	dc.b i, $F5, $forty	; 01 F 540 SonPLC_SpinDash5:	dc.b one, $F5, $l	; 01 F 550 SonPLC_SpinDash6:	dc.b 1, $F5, $60	; 01 F 560

These lines will exist built in the ROM as the hex strings found commented abreast each one. The format for mappings in Sonic 1 is NN(STTT), where NN is how many times (STTT) is repeated after it. S is one less than the number of tiles to be loaded in order, and TTT is the tile index from which the game should start loading. In each of your PLCs, NN is 01, pregnant there is only i instance of (STTT) after it. Besides, in each of your PLCs, S is $F, which means that $10 tiles will be loaded for each. The remaining TTT is the number of the first tile in the pattern (the first row of Spin Dash tiles you copied starts at tile number $510, the 2d at $520, etc.).

For more information about pattern load cues in Sonic 1, visit Sonicology.

Mappings

Now you lot will brand the mappings for the Spin Dash, which define the shape and size of the area to be used in placing the tiles. Open the file _maps/Sonic.asm in your text editor. Again, you're going to add some entries in the big table at the beginning of the file, much similar you did in editing the PLCs. Just above the line byte_21292: dc.b 0, add the post-obit lines:

            dc.west byte_spdh1-Map_Sonic, byte_spdh2-Map_Sonic 		dc.w byte_spdh3-Map_Sonic, byte_spdh4-Map_Sonic 		dc.w byte_spdh5-Map_Sonic, byte_spdh6-Map_Sonic

Then, at the lesser of the file, merely before the even, add:

byte_spdh1:	dc.b one			; Spin Dash i 		dc.b $F8, $F, 0, 0, $F4 byte_spdh2:	dc.b i			; Spin Dash ii 		dc.b $F8, $F, 0, 0, $F4 byte_spdh3:	dc.b 1			; Spin Dash iii 		dc.b $F8, $F, 0, 0, $F4 byte_spdh4:	dc.b one			; Spin Dash 4 		dc.b $F8, $F, 0, 0, $F4 byte_spdh5:	dc.b 1			; Spin Dash 5 		dc.b $F8, $F, 0, 0, $F4 byte_spdh6:	dc.b 1			; Spin Dash 6 		dc.b $F8, $F, 0, 0, $F4

You might notice that these are all identical to each other, and are also very similar to the mappings for the jumping/rolling frames. The format of these mappings is structurally similar to the format of the PLCs: the beginning byte defines how many mapping pieces there are following it. The format is NN(YYSSFFTTXX), where NN is the number of (YYSSFFTTXX) following, YY is the Y position of the piece, SS is the size and shape (in this instance, $F is a 4x4 tile square), FF is the control for certain flip and palette changes (0 in this case means not to touch it), TT is the first tile in VRAM to get-go reading (in this instance 0 is the first tile), and XX is the X position of the piece. The Y position of these mappings, $F8, is slightly greater than that of the jumping/rolling animation, $F0. This is so Sonic doesn't appear to be hovering slightly above the ground while charging the Spin Nuance.

These mappings use 4x4 pieces to concord xvi tiles. You might accept noticed while you were copying the Spin Dash tiles earlier that each frame of the animation had a row of 16 tiles, one after the other. With these mappings, those tiles volition be loaded in lodge in four columns of four, starting with the peak left and working toward the bottom correct. Effort arranging the tiles yourself in your tile editor in a scratch file if you lot desire to understand how they are arranged. Only don't save over any files we're using!

For more information on mappings in Sonic 1, visit Sonicology.

Animation sequence

Yous're well-nigh done adding in the Spin Dash graphics! Now you will add the blitheness sequence containing the listing of frames to be used. Open the file _anim/Sonic.asm in your text editor. Nevertheless again, we will be adding a line to the bottom of the table in the start, only earlier the line 'SonAni_Walk: dc.b $FF, viii, 9, $A, $B, 6, seven, $FF.

            dc.westward SonAni_SpinDash-SonicAniData	;1F

The ;1F comment after it is again an index in the tabular array. If you were to enumerate all of the lines in this table, starting at zero, this new line would be the $1Fth line. Notice that at alphabetize 2 is the rolling animation that we are currently using, and at index 9 is the warping one that it used earlier we fixed it!

Now, you lot will over again add together data just before the even at the end of the file:

SonAni_SpinDash:	dc.b 0, $58, $59, $58, $5A, $58, $5B, $58, $5C, $58, $5D, $FF

The first byte in this animation script tells the game to use the fastest speed in this blitheness. Each subsequent byte until the $FF tells the game which animation frame to employ. Find that these numbers ($58, $59, etc...) are the indeces of your Spin Nuance PLCs. The $FF at the end tells the game to loop the entire animation. Basically, this script will accept the game cycle through the 1st, 2nd, 1st, 3rd, ..., 1st, 6th, 1st, 2nd, ... frames.

Irresolute the animation again

Now that you take added all the necessary information for using the new Spin Dash tiles in an blitheness, it's time for the final step in adding this animation: actually having the game use it! Open sonic1.asm in your text editor (if yous haven't already) and detect the Sonic_SpinDash: code you lot ported before. Change the line you changed before,

            movement.b	#2,$1C(a0)	; changed from #9

to use your new animation found at $1F:

            move.b	#$1F,$1C(a0)	; inverse from #9

Then, observe the line you commented out before,

uncomment it, and change the value to $1F00.

            motion.w	#$1F00,$1C(a0)	; changed from #$900

Finally, save your lawmaking, build your ROM, and endeavor it out.

Spin Dashing with Spin Dash animation

Success! However, there'due south a new issues that occurs now that the game is using this new animation: while charging a Spin Dash, let an enemy touch on you. Sonic gets injured, when instead the enemy should be destroyed.

Another fix

This is a relatively easy issues to ready. Find the routine Touch_Enemy:. Just above the line cmpi.b #2,$1C(a0) ; is Sonic rolling?, add the post-obit two lines:

            cmpi.b	#$1F,$1C(a0)	; is Sonic Spin Dashing? 		beq.westward	loc_1AF40	; if yes, branch

You should stop up with something like this:

Touch_Enemy:				; XREF: Touch_ChkValue 		tst.b	($FFFFFE2D).w	; is Sonic invincible? 		bne.s	loc_1AF40	; if yep, branch 		cmpi.b	#$1F,$1C(a0)	; is Sonic Spin Dashing? 		beq.w	loc_1AF40	; if yes, branch 		cmpi.b	#2,$1C(a0)	; is Sonic rolling? 		bne.w	Touch_ChkHurt	; if not, branch

This code adds a check to run across if the blitheness is #$1F, our new animation. If it is, it branches over the code that jumps to the routine to injure Sonic. Discover that there is some other comparing for if the animation is #two present, which concealed this issues before, since we were using that animation.

Save, build, and exam.

killing an enemy while Spin Dashing

Pop! Congratulations, you lot've successfully ported the Spin Dash from Sonic 2 into Sonic 1, complete with animations. The only matter remaining to add is the Spin Nuance fume object, and fix a few more bugs.

Appendix

The Sonic_SpinDash routine in its entirety, with comments:

; --------------------------------------------------------------------------- ; Subroutine to make Sonic perform a spindash ; ---------------------------------------------------------------------------   ; ||||||||||||||| S U B	R O U T	I Due north Eastward |||||||||||||||||||||||||||||||||||||||     Sonic_SpinDash: 		tst.b	$39(a0)			; already Spin Dashing? 		bne.southward	loc2_1AC8E		; if set, branch 		cmpi.b	#eight,$1C(a0)		; is anim duck 		bne.southward	locret2_1AC8C		; if not, render 		movement.b	($FFFFF603).due west,d0	; read controller 		andi.b	#$70,d0			; pressing A/B/C ? 		beq.w	locret2_1AC8C		; if not, return 		move.b	#$1F,$1C(a0)		; set Spin Nuance anim (9 in s2) 		movement.w	#$Exist,d0			; spin audio ($E0 in s2) 		jsr	(PlaySound_Special).l	; play spin audio 		addq.l	#iv,sp			; Add 4 bytes to the stack return accost to skip Sonic_Jump on adjacent rts to Obj01_MdNormal, preventing conflicts with push button presses. 		motion.b	#1,$39(a0)		; set Spin Dash flag 		move.west	#0,$3A(a0)		; fix charge count to 0 		cmpi.b	#$C,$28(a0)		; ??? oxygen remaining? 		bcs.s	loc2_1AC84		; ??? branch if carry 		move.b	#two,($FFFFD11C).w	; ??? $D11C is used for 						; the smoke/dust object loc2_1AC84: 		bsr.westward	Sonic_LevelBound 		bsr.w	Sonic_AnglePos  locret2_1AC8C: 		rts	 ; ---------------------------------------------------------------------------  loc2_1AC8E: 		move.b	($FFFFF602).w,d0	; read controller 		btst	#1,d0			; cheque down push button 		bne.w	loc2_1AD30		; if set, co-operative 		movement.b	#$E,$xvi(a0)		; $16(a0) is summit/2 		move.b	#7,$17(a0)		; $17(a0) is width/2 		move.b	#2,$1C(a0)		; set animation to curl 		addq.w	#five,$C(a0)		; $C(a0) is Y coordinate 		motion.b	#0,$39(a0)		; clear Spin Dash flag 		moveq	#0,d0 		move.b	$3A(a0),d0		; re-create charge count 		add together.w	d0,d0			; double information technology 		move.westward	Dash_Speeds(pc,d0.w),$xiv(a0) ; become normal speed 		move.w	$14(a0),d0		; go inertia 		subi.w	#$800,d0		; subtract $800 		add.w	d0,d0			; double information technology 		andi.w	#$1F00,d0		; mask it against $1F00 		neg.due west	d0			; negate it 		addi.w	#$2000,d0		; add together $2000 		move.due west	d0,($FFFFEED0).w	; move to $EED0 		btst	#0,$22(a0)		; is sonic facing right? 		beq.s	loc2_1ACF4		; if not, co-operative 		neg.w	$fourteen(a0)			; negate inertia  loc2_1ACF4: 		bset	#2,$22(a0)		; gear up unused (in s1) flag 		move.b	#0,($FFFFD11C).due west	; articulate $D11C (fume) 		move.w	#$BC,d0			; spin release audio 		jsr	(PlaySound_Special).fifty	; play it! 		bra.southward	loc2_1AD78 ; =========================================================================== Dash_Speeds: 		dc.w  $800		; 0 		dc.due west  $880		; one 		dc.w  $900		; two 		dc.w  $980		; 3 		dc.w  $A00		; 4 		dc.westward  $A80		; v 		dc.w  $B00		; half-dozen 		dc.w  $B80		; seven 		dc.w  $C00		; 8 ; ===========================================================================  loc2_1AD30:				; If still charging the nuance... 		tst.due west	$3A(a0)		; bank check charge count 		beq.due south	loc2_1AD48	; if zippo, branch 		move.w	$3A(a0),d0	; otherwise put information technology in d0 		lsr.w	#5,d0		; shift right v (dissever it by 32) 		sub.w	d0,$3A(a0)	; subtract from accuse count 		bcc.due south	loc2_1AD48	; ??? co-operative if comport clear 		move.west	#0,$3A(a0)	; set charge count to 0  loc2_1AD48: 		move.b	($FFFFF603).w,d0	; read controller 		andi.b	#$lxx,d0			; pressing A/B/C? 		beq.due west	loc2_1AD78		; if not, branch 		move.westward	#$1F00,$1C(a0)		; reset spdsh animation 		move.west	#$BE,d0			; was $E0 in sonic 2 		jsr	(PlaySound_Special).l	; play charge sound 		addi.w	#$200,$3A(a0)		; increase charge count 		cmpi.westward	#$800,$3A(a0)		; check if it's maxed 		bcs.s	loc2_1AD78		; if non, then branch 		move.w	#$800,$3A(a0)		; reset it to max  loc2_1AD78: 		addq.l	#4,sp			; Add 4 bytes to the stack render accost to skip Sonic_Jump on next rts to Obj01_MdNormal, preventing conflicts with button presses. 		cmpi.west	#$sixty,($FFFFEED8).w	; $EED8 only ever seems 		beq.s	loc2_1AD8C		; to be used in Spin Dash 		bcc.southward	loc2_1AD88 		addq.w	#4,($FFFFEED8).westward  loc2_1AD88: 		subq.due west	#2,($FFFFEED8).westward  loc2_1AD8C: 		bsr.w	Sonic_LevelBound 		bsr.west	Sonic_AnglePos 		motion.due west	#$60,($FFFFF73E).due west	; reset looking up/down 		rts ; End of subroutine Sonic_SpinDash

Notation: while non necessary, the loc_, locret_, etc. labels from the Sonic ii disassembly were replaced with loc2_, locret2_, etc. to avoid potential disharmonize.

GitHub disassembly

Previous preparation

This shouldn't exist completly necessary, only since we're using GitHub disassembly, we're going to practice it in GitHub's way. Open up Variables.asm and scroll downwardly to the end. There you will define a new RAM equate by adding this line:

You can skip this, but y'all will have to replace all f_spindash in the code for $39, and that's not what we want.

Straight copying the object code

Open sonic1.asm from the Sonic ane disassembly in your text editor, and search for the phrase SonicPlayer: (line 6734 in GitHub disassembly). This should bring you to the Sonic object's lawmaking, which is what you're interested in editing right at present. At present, open up s2.asm from the Sonic 2 disassembly in your text editor, and search for Object_Sonic (line 35720 in Aurochs' disassembly). This will bring y'all again to Sonic'southward object lawmaking. Having been based on the same code from Sonic i, it shows many similarities that yous should be able to spot. Thanks to the like code, our job in porting the Spin Dash should be pretty easy!

Find or curl to the location Sonic_MdNormal in Sonic 1's source, and loc_1A2B8 in Sonic ii's source. Beneath this characterization in each is a series of branches and jumps to subroutines that handle Sonic's actions in dissimilar situations. If you await carefully, you'll observe that at that place are nine of these branches in Sonic 2, but only eight in Sonic ane. That's because Sonic two has another branch to the code that handles the Spin Dash. Yous're going to add Spin Nuance to Sonic 1, so the kickoff matter to do is add a call to the Spin Dash function that yous're going to copy. Don't worry nigh the characterization names from Sonic 2, since you're going to name the subroutine Sonic_SpinDash when we copy information technology over.

In Sonic 1's code, brand a copy of the line bsr.w Sonic_Jump and change it to branch to Sonic_SpinDash, equally shown:

''';--------------------------------------------------------------------------- ;Modes for decision-making Sonic ;---------------------------------------------------------------------------''' Sonic_MdNormal:				; XREF: Sonic_Modes  		bsr.w Sonic_SpinDash ; add this line!  		bsr.westward Sonic_Jump  		bsr.w Sonic_SlopeResist  		bsr.w Sonic_Move  		bsr.due west Sonic_Roll  		bsr.w Sonic_LevelBound  		jsr SpeedToPos  		bsr.w Sonic_AnglePos  		bsr.w Sonic_SlopeRepel  		rts  ''';==========================================================================='''

Now, to actually copy the Spin Nuance subroutine. In Sonic 2, discover the label loc_1AC3E. This is the subroutine that we are going to re-create, so select from that line all the way downwards to where y'all see ; End of subroutine loc_1AC3E, and copy the lawmaking. In Sonic 1, create a new file within _incObj binder named Sonic Spindash.asm, open it and paste the code inside of it.

There are a few changes that nosotros demand to make so this code will cooperate with the residual of the Sonic one code, since some of the labels in each disassembly differ from each other (the same functions have different names). The following replacements should be made (use your text editor's find and replace function, if applicable):

  • loc_1AC3E with Sonic_SpinDash
  • loc_1A974 with Sonic_LevelBound
  • loc_1E234 with Sonic_AnglePos
  • play_SFX with PlaySound_Special
  • word_1AD0C with Dash_Speeds
  • $39 with f_spindash (Non #$39)
  • $1C with obAnim (NOT #$1C)
  • $14 with obInertia (NOT #$14)

Too, if you lot open _anim\Sonic.asm and ringlet to the end, you will meet animation's IDs. In Sonic ii's code, the numbers at the right will exist used then in Sonic 1'due south HiveBrain's disassembly; merely in GitHub'south one, the names at left are used, so for completion'southward sake, check every time that a number is moved into obAnim to supervene upon it with its correct name /example: movement.b #2,obAnim(a0) --> motility.b #id_roll,obAnim(a0)/.

Remove all this code since it is a leftover artifact of super sonic:

            tst.b	(Super_Sonic_flag).w 		beq.s	loc_1ACD0 		motility.due west	word_1AD1E(pc,d0.w),$xiv(a0)  loc_1ACD0:

remove this too since it is super sonic's nuance speeds:

word_1AD1E:  	dc.w $B00 ; 0  	dc.westward $B80 ; 1  	dc.w $C00 ; 2  	dc.w $C80 ; 3  	dc.due west $D00 ; iv  	dc.w $D80 ; 5  	dc.w $E00 ; 6  	dc.west $E80 ; 7  	dc.w $F00 ; viii

Washed! Salve the file and you should have something like this:

;--------------------------------------------------------------------------- ;Subroutine to brand Sonic perform a spindash ;--------------------------------------------------------------------------- ;||||||||||||||| S U B R O U T I Northward East |||||||||||||||||||||||||||||||||||||||  Sonic_SpinDash:  		tst.b f_spindash(a0)  		bne.s loc_1AC8E  		cmpi.b #id_duck,obAnim(a0)  		bne.s locret_1AC8C  		motility.b (v_jpadpress2).w,d0  		andi.b #$70,d0  		beq.westward locret_1AC8C  		motion.b #9,obAnim(a0)  		move.due west #$E0,d0  		jsr (PlaySound_Special).fifty  		addq.fifty #four,sp  		move.b #1,f_spindash(a0)  		motion.w #0,$3A(a0)  		cmpi.b #$C,$28(a0)  		bcs.s loc_1AC84  		motion.b #two,($FFFFD11C).w  loc_1AC84:  		bsr.w Sonic_LevelBound  		bsr.w Sonic_AnglePos  locret_1AC8C:  		rts  ;--------------------------------------------------------------------------- loc_1AC8E:  		move.b (v_jpadhold2).w,d0  		btst #ane,d0  		bne.due west loc_1AD30  		motion.b #$Eastward,$16(a0)  		move.b #7,$17(a0)  		motility.b #ii,obAnim(a0)  		addq.w #5,$C(a0)  		move.b #0,f_spindash(a0)  		moveq #0,d0  		move.b $3A(a0),d0  		add.w d0,d0  		motility.w Dash_Speeds(pc,d0.due west),$14(a0)  		move.westward obInertia(a0),d0  		subi.w #$800,d0  		add together.w d0,d0  		andi.w #$1F00,d0  		neg.w d0  		addi.w #$2000,d0  		motility.w d0,($FFFFEED0).w  		btst #0,$22(a0)  		beq.south loc_1ACF4  		neg.w $xiv(a0)  loc_1ACF4:  		bset #2,$22(a0)  		motility.b #0,($FFFFD11C).w  		move.w #$BC,d0  		jsr (PlaySound_Special).50  		bra.s loc_1AD78  ;=========================================================================== Dash_Speeds:  	dc.w $800 ; 0  	dc.west $880 ; 1  	dc.due west $900 ; two  	dc.w $980 ; three  	dc.w $A00 ; iv  	dc.w $A80 ; 5  	dc.w $B00 ; half-dozen  	dc.w $B80 ; seven  	dc.due west $C00 ; 8  ;=========================================================================== loc_1AD30: ; If yet charging the nuance...  		tst.westward $3A(a0)  		beq.southward loc_1AD48  		movement.west $3A(a0),d0  		lsr.west #5,d0  		sub.w d0,$3A(a0)  		bcc.s loc_1AD48  		move.westward #0,$3A(a0)  loc_1AD48:  		move.b (v_jpadpress2).west,d0  		andi.b #$70,d0 ; 'p'  		beq.west loc_1AD78  		motility.due west #$900,$1C(a0)  		move.due west #$E0,d0 ; 'à'  		jsr (PlaySound_Special).l  		addi.due west #$200,$3A(a0)  		cmpi.west #$800,$3A(a0)  		bcs.due south loc_1AD78  		motion.w #$800,$3A(a0)  loc_1AD78: 		addq.l #4,sp  		cmpi.w #$threescore,($FFFFEED8).w  		beq.s loc_1AD8C  		bcc.south loc_1AD88  		addq.w #4,($FFFFEED8).w  loc_1AD88:  		subq.w #2,($FFFFEED8).due west  loc_1AD8C:  		bsr.west Sonic_LevelBound  		bsr.w Sonic_AnglePos  rts  ;End of subroutine Sonic_SpinDash

Earlier building whatsoever ROM, you accept to tell the program to actually load the new file. Then go back to sonic.asm and go a bit lower from where you were, y'all should see this:

include "_incObj\Sonic Move.asm" include "_incObj\Sonic RollSpeed.asm" include "_incObj\Sonic JumpDirection.asm"

You just have to add this line either before or afterwards that;

include "_incObj\Sonic Spindash.asm"

Salvage the file again. Now, let'due south exam information technology! Build your ROM and open up it in your emulator.

Spin Dashing with a strange animation

Uh-oh, it seems like it'south a bit rough around the edges right now. Start of all, Sonic's Spin Dashing animation isn't present in Sonic ane, of course, and correct at present it's using the animation from the spot that the Spin Dash'south animation data replaced. Besides, the music and sounds seem to terminate when yous start charging a Spin Nuance. That's because the sound ID that is the Spin Dash sound in Sonic 2 has a dissimilar purpose in Sonic 1. The physics of the Spin Nuance are conspicuously in place, however. This is a proficient start!

Irresolute the animations and sounds

At present, you're going to make a few simple changes to the Spin Dash subroutine so it uses suitable animations and sounds that are already present in Sonic 1. First, find whatsoever instances of the line move.westward #$E0,d0 followed by jsr (PlaySound_Special).l. This code loads the sound ID #$E0 into the data register d0 and jumps to the subroutine that is responsible for playing that sound. #$E0 is not a suitable sound for a Spin Nuance in Sonic one, as mentioned earlier--it silences the music. Supersede the #$E0 with #$BE in each occurance. #$Be is the audio ID of a normal spin in Sonic 1. You can cheque information technology in the sound test for yourself!

Now, get upward to the line containing the code move.b #ix,obAnim(a0), and supersede the #9 with #id_roll. This code copies the blitheness number to exist used when Sonic starts charging his Spin Dash. #9 is the ID of the blitheness used for Spin Dash in Sonic 2; however, in Sonic 1, information technology'south the ID of an unused animation presumably for warping. Animation #two (rolling animation's ID) is the blitheness used for jumping and rolling in Sonic 1. You lot should have something like this:

            move.b (v_jpadpress2).w,d0  		andi.b #$70,d0  		beq.due west locret_1AC8C  		move.b #id_roll,obAnim(a0) ; changed from #9  		movement.west #$Exist,d0 ; changed from #$E0  		jsr (PlaySound_Special).l

Now, find move.westward #$900,obAnim(a0) lower in the lawmaking. This puts the animation #9 and a flag to reset it to the outset frame into Sonic's memory. For now, let's just comment out this line past placing a ; in front of the lawmaking, like so:

loc_1AD48:  		movement.b (v_jpadpress2).due west,d0  		andi.b #$lxx,d0 ; 'p' beq.w loc_1AD78  ;		move.w #$900,$1C(a0)  		motion.due west #$BE,d0 ; changed from #$E0  		jsr (PlaySound_Special).l

Save and build your ROM! Allow'due south run into how it does...

Spin Dashing with rolling animation

Success! The charging sound works fine, and the animation looks similar to the Spin Dash found in Sonic CD. Non bad! Even so, in that location are a few bugs present.

First of all, collect a few rings, then start charging a Spin Dash somewhere that an enemy can shoot you or injure you somehow. If yous go striking while charging, you'll even so exist in a Spin Dash-charging state when you lot land. If you lot let get of the down button while billowy backwards, Sonic will release his Spin Nuance right away when he hits the basis. Now, this might be awesome in itself and certainly should kill whatever badnik injure you in the first place, simply it isn't what should happen.

Second, motility somewhere where the photographic camera has room to move downwardly. If you concur the downwards button to duck, then start charging the Spin Dash, the photographic camera stays low until yous are no longer rolling.

Spin Dashing with low camera

Some other problem that results from this is that if you Spin Nuance earlier an area where your vertical position radically changes (for instance, the double-South-tube in GHZ1), the camera takes likewise long to take hold of upward to yous.

camera lagging behind

Fixing bugs

Start of all, let'south fix the camera issue. Become to the end of the Spin Dash subroutine, and add this line:

            motility.w #$threescore,(v_lookshift).west

just above the rts. This will reset the vertical modify in the camera's position. You should accept something like this:

loc_1AD8C:  		bsr.westward Sonic_LevelBound  		bsr.w Sonic_AnglePos  		move.w #$60,(v_lookshift).w ; reset looking upwardly/down  		rts  ''';End of subroutine Sonic_SpinDash'''

Salvage, build the ROM, and test it. You lot should notice that the photographic camera does reset itself when yous starting time to Spin Nuance, but if you take the double-S-tube in GHZ1, you lot even so barely outrun the screen vertically and get killed. To gear up this, open the file _incObj\Sonic LevelBound.asm and find the code at the label @bottom. Offset, add a characterization only earlier the rts at the end of the block of code, named @dontkill. And so, at the beginning of @lesser, yous're going to compare two values in memory. If (v_limitbtm1).w < (v_limitbtm2).w, then the screen is still scrolling downwardly and you don't want to die. In this case, it should skip the part below that jumps to the routine KillSonic. Yous should add the post-obit lines of code beneath @bottom:

            motion.w (v_limitbtm1).w,d0  		move.westward (v_limitbtm2).w,d1  		cmp.west d0,d1 ; screen still scrolling downward?  		blt.s @dontkill; if and so, don't kill Sonic

You should end up with something like this:

@bottom: 		move.w (v_limitbtm1).due west,d0  		motility.w (v_limitbtm2).w,d1  		cmp.w d0,d1 ; screen still scrolling down?  		blt.due south @dontkill; if so, don't kill Sonic  		cmpi.west	#(id_SBZ<<eight)+ane,(v_zone).w ; is level SBZ2 ? 		bne.w	KillSonic	; if not, kill Sonic 		cmpi.due west	#$2000,(v_player+obX).due west 		bcs.west	KillSonic 		clr.b	(v_lastlamp).westward	; articulate	lamppost counter 		move.west	#one,(f_restart).westward ; restart the level 		move.due west	#(id_LZ<<8)+3,(v_zone).w ; set level to SBZ3 (LZ4) 		rts	 @dontkill:  		rts ''';==========================================================================='''

These fixes can likewise be found

Sonic Retro

hither.

Now, you'll fix the problem where Sonic is nevertheless in his Spin Dashing state after he gets injured. Open _incObj\sub ReactToItem.asm and find the subroutine HurtSonic. This is the code that handles pain Sonic, if y'all couldn't guess. You lot're going to have information technology articulate the flag in retention that stores whether or not Sonic is Spin Dashing. Whorl to the label @isleft and add together the line move.b #0,(a0) directly below it. Y'all should end up with:

@isleft: 		move.b #0,f_spindash(a0) ; articulate Spin Nuance flag  		motility.westward #0,obInertia(a0)  		movement.b #id_Hurt,obAnim(a0)  		move.westward #$120,$30(a0)

Salve, build, and exam. If all is well, those bugs should be gone! Now yous take a performance Spin Dash in Sonic 1. However, information technology doesn't look like the Spin Dash from Sonic 2. In the next sections, we volition rectify this.

Adding new tiles

Now, yous'll need to add the Spin Nuance tiles from Sonic 2'southward tiles to Sonic i'southward; Still, you'll demand to pad the file artunc/sonic.bin to go room for the new tiles first. To practise this, you have to create a batch file (.bat) with post-obit code in the binder artunc:

fsutil file createnew padding.bin 16384

:: Create a file called "padding.bin" with 16KB        

ren sonic.bin sonic_old.bin

:: Rename the original "sonic.bin" to "sonic_old.bin"        

re-create /b sonic_old.bin+padding.bin sonic.bin

:: Copy the ii files into a new "sonic.bin"        

Run it and you volition detect your sonic.bin 16KB bigger. If anything went wrong, utilise the backup file named as sonic_old.bin.


Now, in your tile editor, open the padded artunc/sonic.bin and Sonic ii's art/uncompressed/Sonic's art.bin. These are the tiles you lot're later on:

copying sonic's Spin Dash tiles

Copy them from the Sonic two tiles to the stop of the Sonic 1 tiles. Do note that it shouldn't thing if you utilize the default palette of your tile editor, as long equally the one yous're using for Sonic ii'south tiles matches the one yous're using for Sonic ane's tiles.

Salve the Sonic 1 file artunc/sonic.bin and close your tile editor. You may rebuild the ROM, but at that place shouldn't be any noticeable changes, since the game isn't coded to really do anything with the tiles we put at that place yet.

Making PLCs for the tiles

Now, you lot'll add together the pattern load cues to tell the game to load the tiles you only added. Open _maps/Sonic -Dynamic Gfx Script.asm in your text editor. At the bottom of the big table of offsets, and just before the label SonPLC_Null, add the following lines:

            dc.w SonPLC_SpinDash1-SonicDynPLC ;58 		dc.w SonPLC_SpinDash2-SonicDynPLC ;59 		dc.w SonPLC_SpinDash3-SonicDynPLC ;5A 		dc.w SonPLC_SpinDash4-SonicDynPLC ;5B 		dc.due west SonPLC_SpinDash5-SonicDynPLC ;5C 		dc.westward SonPLC_SpinDash6-SonicDynPLC ;5D

Note that the hex numbers commented to the side are indeces. If you lot were to number each line in the list you just added to in hex, starting at aught, those would be the numbers for those lines. These will be of import after because they are the frame numbers that will exist used in your animation.

At present, at the very lesser of the file, but just earlier the fifty-fifty, insert the following lines:

SonPLC_SpinDash1: dc.b i, $F5, $10 ; 01 F 510  SonPLC_SpinDash2: dc.b i, $F5, $20 ; 01 F 520  SonPLC_SpinDash3: dc.b 1, $F5, $thirty ; 01 F 530  SonPLC_SpinDash4: dc.b ane, $F5, $40 ; 01 F 540  SonPLC_SpinDash5: dc.b 1, $F5, $50 ; 01 F 550  SonPLC_SpinDash6: dc.b ane, $F5, $lx ; 01 F 560

These lines volition be built in the ROM as the hex strings found commented beside each one. The format for mappings in Sonic 1 is NN(STTT), where NN is how many times (STTT) is repeated later it. S is one less than the number of tiles to be loaded in gild, and TTT is the tile index from which the game should start loading. In each of your PLCs, NN is 01, meaning there is only one case of (STTT) after it. As well, in each of your PLCs, S is $F, which means that $10 tiles volition be loaded for each. The remaining TTT is the number of the first tile in the pattern (the first row of Spin Dash tiles you copied starts at tile number $510, the 2d at $520, etc.).

For more information about design load cues in Sonic ane, visit Sonicology.

Mappings

Now you volition brand the mappings for the Spin Dash, which define the shape and size of the area to exist used in placing the tiles. Open the file _maps/Sonic.asm in your text editor. Again, you're going to add together some entries in the big tabular array at the beginning of the file, much like you did in editing the PLCs. Just above the line MS_Null: dc.b 0, add the following lines:

ptr_MS_Spindash1:	dc.w MS_Spindash1-Map_Sonic ptr_MS_Spindash2:	dc.w MS_Spindash2-Map_Sonic ptr_MS_Spindash3:	dc.w MS_Spindash3-Map_Sonic ptr_MS_Spindash4:	dc.w MS_Spindash4-Map_Sonic ptr_MS_Spindash5:	dc.due west MS_Spindash5-Map_Sonic ptr_MS_Spindash6:	dc.w MS_Spindash6-Map_Sonic

Then, at the terminate of the second table, just before the even, add:

MS_Spindash1:	dc.b 1		; Spindash 1 		dc.b	$F8, $F, 0, 0, $F4  MS_Spindash2:	dc.b 1		; Spindash 2 		dc.b	$F8, $F, 0, 0, $F4  MS_Spindash3:	dc.b 1		; Spindash 3 		dc.b	$F8, $F, 0, 0, $F4  MS_Spindash4:	dc.b ane		; Spindash 4 		dc.b	$F8, $F, 0, 0, $F4  MS_Spindash5:	dc.b ane		; Spindash 5 		dc.b	$F8, $F, 0, 0, $F4  MS_Spindash6:	dc.b 1		; Spindash 6 		dc.b	$F8, $F, 0, 0, $F4

You might notice that these are all identical to each other, and are as well very similar to the mappings for the jumping/rolling frames. The format of these mappings is structurally like to the format of the PLCs: the starting time byte defines how many mapping pieces at that place are following it. The format is NN(YYSSFFTTXX), where NN is the number of (YYSSFFTTXX) post-obit, YY is the Y position of the slice, SS is the size and shape (in this case, $F is a 4x4 tile square), FF is the control for certain flip and palette changes (0 in this case means not to touch it), TT is the first tile in VRAM to beginning reading (in this instance 0 is the first tile), and Xx is the X position of the piece. The Y position of these mappings, $F8, is slightly greater than that of the jumping/rolling animation, $F0. This is so Sonic doesn't announced to be hovering slightly higher up the ground while charging the Spin Dash.

These mappings use 4x4 pieces to hold sixteen tiles. You might have noticed while you were copying the Spin Nuance tiles earlier that each frame of the blitheness had a row of xvi tiles, one after the other. With these mappings, those tiles will be loaded in lodge in four columns of four, starting with the top left and working toward the bottom correct. Effort arranging the tiles yourself in your tile editor in a scratch file if you want to understand how they are arranged. Just don't save over any files nosotros're using!

And then open constants.asm, gyre down to the end of the file add these lines:

fr_Spindash1:	equ (ptr_MS_Spindash1-Map_Sonic)/two	; $58 fr_Spindash2:	equ (ptr_MS_Spindash2-Map_Sonic)/two	; $59 fr_Spindash3:	equ (ptr_MS_Spindash3-Map_Sonic)/ii	; $5A fr_Spindash4:	equ (ptr_MS_Spindash4-Map_Sonic)/ii	; $5B fr_Spindash5:	equ (ptr_MS_Spindash5-Map_Sonic)/ii	; $5C fr_Spindash6:	equ (ptr_MS_Spindash6-Map_Sonic)/2	; $5D

For more than information on mappings in Sonic 1, visit Sonicology.

Blitheness sequence

You're about done adding in the Spin Nuance graphics! Now yous will add the blitheness sequence containing the list of frames to exist used. Open the file _anim/Sonic.asm in your text editor. Yet once again, nosotros will be calculation a line to the bottom of the tabular array in the offset, only before the line

SonAni_Walk:	dc.b $FF, fr_walk13, fr_walk14,	fr_walk15, fr_walk16, fr_walk11, fr_walk12, afEnd

yous will add together

ptr_Spindash:	dc.w SonAni_SpinDash-Ani_Sonic ;1F

The ;1F comment after it is once more an index in the tabular array. If y'all were to enumerate all of the lines in this table, starting at zero, this new line would exist the $1Fth line. Notice that at index 2 is the rolling animation that we are currently using, and at index 9 is the warping 1 that it used earlier nosotros fixed it!

Now, you lot will again add data just later on the even at the end of the second table:

SonAni_SpinDash: dc.b 0, fr_Spindash1, fr_spindash2, fr_spindash1, fr_spindash3, fr_spindash1, fr_spindash4, fr_spindash1, fr_spindash5, fr_spindash1, fr_spindash6, afEnd 		even

The outset byte in this animation script tells the game to employ the fastest speed in this animation. Each subsequent discussion until the afEnd tells the game which animation frame to utilise. Observe that you lot could have utilize numbers ($58, $59, etc...) as they are the indeces of your Spin Nuance PLCs. The afEnd at the end tells the game to loop the unabridged blitheness. Basically, this script will accept the game cycle through the 1st, 2d, 1st, third, ..., 1st, 6th, 1st, 2nd, ... frames.

Now go to the very end of the file and add this line:

id_Spindash:	equ (ptr_Spindash-Ani_Sonic)/2	; $1F

Changing the blitheness again

Now that you lot accept added all the necessary information for using the new Spin Dash tiles in an animation, it's fourth dimension for the last step in calculation this animation: really having the game utilise it! Open Sonic Spindash.asm in your text editor (if y'all haven't already) and modify the line yous changed earlier,

            move.b #id_roll,obAnim(a0) ; changed from #nine

to use your new animation establish at $1F:

            movement.b #id_Spindash,obAnim(a0) ; changed from #nine

So, discover the line you lot commented out before,

;		move.w #$900,obAnim(a0)

uncomment it, and change the value to $1F00.

            move.w #$1F00,obAnim(a0) ; changed from #$900

Finally, save your code, build your ROM, and try it out.

Spin Dashing with Spin Dash animation

Success! However, in that location's a new bug that occurs now that the game is using this new animation: while charging a Spin Dash, let an enemy affect you lot. Sonic gets injured, when instead the enemy should exist destroyed.

Some other fix

This is a relatively easy bug to fix. Become dorsum to sub ReactToItem.asm and search for the routine React_Enemy. Simply to a higher place the line

            cmpi.b	#id_Roll,obAnim(a0) ; is Sonic rolling/jumping?

add the post-obit two lines:

            cmpi.b	#id_Spindash,obAnim(a0)	; is Sonic Spin Dashing?  		beq.due west @donthurtsonic	; if yes, branch

You should end up with something like this:

React_Enemy: 		tst.b	(v_invinc).w	; is Sonic invincible? 		bne.s	@donthurtsonic	; if yes, branch 		cmpi.b	#id_Spindash,obAnim(a0)	; is Sonic Spin Dashing?  		beq.w @donthurtsonic	; if yeah, branch  		cmpi.b	#id_Roll,obAnim(a0) ; is Sonic rolling/jumping? 		bne.w	React_ChkHurt	; if not, branch

This code adds a cheque to see if the blitheness is #$1F, our new animation. If information technology is, it branches over the code that jumps to the routine to hurt Sonic. Notice that there is another comparison for if the blitheness is #2 present, which concealed this problems earlier, since we were using that blitheness.

Save, build, and test.

killing an enemy while Spin Dashing

Popular! Congratulations, you've successfully ported the Spin Dash from Sonic ii into Sonic i, complete with animations. The only matter remaining to add is the Spin Nuance smoke object, and prepare a few more bugs.

Appendix

The Sonic_SpinDash routine in its entirety, with comments:

; --------------------------------------------------------------------------- ; Subroutine to make Sonic perform a spindash ; ---------------------------------------------------------------------------   ; ||||||||||||||| S U B	R O U T	I N East |||||||||||||||||||||||||||||||||||||||     Sonic_SpinDash: 		tst.b	f_spindash(a0)			; already Spin Dashing? 		bne.due south	loc2_1AC8E		; if ready, branch 		cmpi.b	#id_duck,obAnim(a0)		; is anim duck 		bne.s	locret2_1AC8C		; if non, render 		move.b	(v_jpadpress2).west,d0	; read controller 		andi.b	#$lxx,d0			; pressing A/B/C ? 		beq.westward	locret2_1AC8C		; if not, render 		move.b	#id_spindash,obAnim(a0)		; ready Spin Dash anim (nine in s2) 		move.w	#$BE,d0			; spin sound ($E0 in s2) 		jsr	(PlaySound_Special).l	; play spin sound 		addq.l	#4,sp			; Add 4 bytes to the stack return address to skip Sonic_Jump on next rts to Obj01_MdNormal, preventing conflicts with button presses. 		move.b	#i,f_spindash(a0)		; fix Spin Nuance flag 		motility.westward	#0,$3A(a0)		; fix charge count to 0 		cmpi.b	#$C,$28(a0)		; ??? oxygen remaining? 		bcs.southward	loc2_1AC84		; ??? branch if carry 		move.b	#2,($FFFFD11C).westward	; ??? $D11C is used for 						; the fume/dust object loc2_1AC84: 		bsr.w	Sonic_LevelBound 		bsr.w	Sonic_AnglePos  locret2_1AC8C: 		rts	 ; ---------------------------------------------------------------------------  loc2_1AC8E: 		movement.b	(v_jpadhold2).w,d0	; read controller 		btst	#i,d0			; check downwards button 		bne.w	loc2_1AD30		; if fix, co-operative 		movement.b	#$East,$16(a0)		; $sixteen(a0) is acme/2 		motility.b	#vii,$17(a0)		; $17(a0) is width/ii 		move.b	#id_roll,obAnim(a0)		; set animation to roll 		addq.w	#v,$C(a0)		; $C(a0) is Y coordinate 		movement.b	#0,f_spindash(a0)		; articulate Spin Dash flag 		moveq	#0,d0 		motion.b	$3A(a0),d0		; copy charge count 		add together.westward	d0,d0			; double information technology 		motion.westward	Dash_Speeds(pc,d0.w),obInertia(a0) ; get normal speed 		motion.w	obInertia(a0),d0		; get inertia 		subi.westward	#$800,d0		; subtract $800 		add.w	d0,d0			; double it 		andi.w	#$1F00,d0		; mask it against $1F00 		neg.w	d0			; negate it 		addi.w	#$2000,d0		; add $2000 		move.west	d0,($FFFFEED0).w	; move to $EED0 		btst	#0,$22(a0)		; is sonic facing right? 		beq.s	loc2_1ACF4		; if not, co-operative 		neg.westward	obInertia(a0)			; negate inertia  loc2_1ACF4: 		bset	#2,$22(a0)		; set unused (in s1) flag 		move.b	#0,($FFFFD11C).w	; clear $D11C (smoke) 		move.w	#$BC,d0			; spin release audio 		jsr	(PlaySound_Special).50	; play it! 		bra.s	loc2_1AD78 ; =========================================================================== Dash_Speeds: 		dc.due west  $800		; 0 		dc.w  $880		; 1 		dc.w  $900		; 2 		dc.w  $980		; iii 		dc.westward  $A00		; 4 		dc.due west  $A80		; 5 		dc.w  $B00		; six 		dc.westward  $B80		; vii 		dc.westward  $C00		; 8 ; ===========================================================================  loc2_1AD30:				; If still charging the dash... 		tst.west	$3A(a0)		; bank check accuse count 		beq.s	loc2_1AD48	; if zero, branch 		move.w	$3A(a0),d0	; otherwise put it in d0 		lsr.w	#5,d0		; shift correct v (divide it by 32) 		sub.due west	d0,$3A(a0)	; subtract from charge count 		bcc.s	loc2_1AD48	; ??? co-operative if behave clear 		motility.westward	#0,$3A(a0)	; set charge count to 0  loc2_1AD48: 		move.b	(v_jpadpress2).w,d0	; read controller 		andi.b	#$70,d0			; pressing A/B/C? 		beq.w	loc2_1AD78		; if not, branch 		move.w	#$1F00,obAnim(a0)	; reset spdsh animation 		move.w	#$Exist,d0			; was $E0 in sonic 2 		jsr	(PlaySound_Special).l	; play charge sound 		addi.w	#$200,$3A(a0)		; increase charge count 		cmpi.w	#$800,$3A(a0)		; cheque if it's maxed 		bcs.s	loc2_1AD78		; if non, so branch 		move.westward	#$800,$3A(a0)		; reset it to max  loc2_1AD78: 		addq.50	#iv,sp			; Add together 4 bytes to the stack return address to skip Sonic_Jump on next rts to Obj01_MdNormal, preventing conflicts with button presses. 		cmpi.west	#$60,($FFFFEED8).w	; $EED8 only ever seems 		beq.southward	loc2_1AD8C		; to exist used in Spin Dash 		bcc.s	loc2_1AD88 		addq.westward	#4,($FFFFEED8).w  loc2_1AD88: 		subq.w	#ii,($FFFFEED8).westward  loc2_1AD8C: 		bsr.w	Sonic_LevelBound 		bsr.westward	Sonic_AnglePos 		move.w	#$60,(v_lookshift).w	; reset looking up/downwards 		rts ; Cease of subroutine Sonic_SpinDash

Note: while non necessary, the loc_, locret_, etc. labels from the Sonic 2 disassembly were replaced with loc2_, locret2_, etc. to avert potential conflict.

Pu7o's continuation

Pu7o has written a wonderful guide that picks up from this point.

SCHG How-To Guide: Sonic the Hedgehog (xvi-fleck)
Fixing Bugs
Fix Demo Playback | Fix a Race Condition with Pattern Load Cues | Set the SEGA Sound | Display the Press Beginning Button Text | Set up the Level Select Menu | Gear up the Subconscious Points Bug | Fix Accidental Deletion of Scattered Rings | Fix Band Timers | Fix the Walk-Jump Issues | Correct Drowning Bugs | Set the Decease Boundary Bug | Set up the Camera Follow Bug | Fix Vocal Restoration Bugs | Fix the HUD Blinking | Gear up the Level Select Graphics Bug | Set up a remember sprite related bug
Changing Design Choices
Change Fasten Behavior | Collide with Water After Being Hurt | Ready Special Phase Jumping Physics | Improve the Fade In\Fade Out Progression Routines | Prepare Scattered Rings' Underwater Physics | Remove the Speed Cap | Port the REV01 Background Furnishings | Port Sonic 2'south Level Fine art Loader | Retain Rings Between Acts | Add Sonic two (Simon Wai Prototype) Level Select | Improve ObjectMove Subroutines | Port Sonic ii Level Select
Adding Features
Add Spin Dash ( Part 1 / Role 2 / Part three / Part 4 ) | Add Eggman Monitor | Add Super Sonic | Add the Air Roll
Audio Features
Aggrandize the Sound Index | Play Dissimilar Songs Per Act | Port Sonic 2 Last Audio Driver | Port Sonic iii'southward Sound Driver | Port Flamewing'southward Sonic 3 & Knuckles Sound Commuter
Extending the Game
Load Chunks From ROM | Add together Extra Characters | Brand an Alternative Title Screen | Utilise Dynamic Tilesets | Make GHZ Load Alternate Art | Add a New Zone | Set Up the Goggle Monitor | Add New Moves | Add a Dynamic Collision System | Dynamic Special Stage Walls System | Extend Sprite Mappings and Art Limit | Enigma Credits | Use Dynamic Palettes
Miscellaneous
Catechumen the Hivebrain 2005 Disassembly to ASM68K
Split Disassembly Guides
Ready a Split up Disassembly | Basic Level Editing | Basic Art Editing | Basic ASM Editing (Spin Nuance)

|Add Spin Dash to Sonic ane/Function one]]

How To Add Spin Dash To Sonic 1,

Source: http://info.sonicretro.org/SCHG_How-to:Add_Spin_Dash_to_Sonic_1/Part_1

Posted by: harrisfroplithe.blogspot.com

0 Response to "How To Add Spin Dash To Sonic 1"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel