Actions

SCHG How-to

Create Clone and Special Stage Monitors

From Sonic Retro

Revision as of 11:57, 13 September 2011 by Scarred Sun (talk | contribs)

This guide will show you how to make two new monitors for Sonic 2, which are a Clone monitor and a Special Stage monitor, both which are featured in my hack, Sonic 2 Loco. Please give credit to me if you use these new monitors. For our purposes, we will be using the Nov 2010 .svn disasm, though, I’m sure these modifications will work with slightly older S2 disasms.


In a Sonic and Tails game OR Sonic-alone game, the clone monitor will enable a flag which will allow Sonic to call an extra Tails character upon pressing A while on the ground (at the expense of using 10 rings). Hitting the clone monitor will give the player a free Tails character. Upon pressing A and if Sonic has at least 10 rings, Sonic will display his unused “Whistle” sprites from Sonic 3, and a Tails character will appear at Sonic’s X and Y coordinates. If Sonic does not have at least 10 rings, the “buzzer” sound effect will play, and nothing will happen.

This extra Tails character interacts with chunks, monitors, and enemies/bosses, but not with other objects. Moreover, the mappings of the extra Tails characters will be garbled. (Making the extra Tails characters interact with other objects and fixing the mappings would need an extreme rewrite of the Sonic 2 Engine to handle multiple Tails objects, which I didn’t feel like doing.)

This monitor will not work in a Tails-alone game, because even if you try to force the game to load a Sonic object at Tails X and Y coordinates, an extra Tails object will appear instead. (In a Tails-along game, if any extra Tails object dies, you die!). Keeping this fact in mind, it is strongly recommended to make this monitor do something different in a Tails-alone game.


The Special Stage monitor, upon being hit, will launch the player into the special stage, like if he hit a starpost with 50 rings. Moreover, if the player has all 7 emeralds, this monitor will give the player 50 rings. Using this monitor is a good alternative to allowing the player to enter the special stage by starposts, and is similar to the Special Stage monitor in Sonic SMS games. Since the monitor does not save your position, it is strongly recommended to put a checkpoint before the Special stage monitor. This guide will also show how to disable the starposts for entering the special stage.


Creating a clone monitor:

For our purposes, we will be using the question mark monitor, which is unused in the main game. If you would like, you can use SonMapEd to change the question mark monitor’s icon to an appropriate one, say the Tails 1-up icon.

First, goto “Obj2E_Types”. You should see something like this:


<asm> Obj2E_Types: offsetTable offsetTableEntry.w robotnik_monitor ; 0 - Static offsetTableEntry.w sonic_1up ; 1 - Sonic 1-up offsetTableEntry.w tails_1up ; 2 - Tails 1-up offsetTableEntry.w robotnik_monitor ; 3 - Robotnik offsetTableEntry.w super_ring ; 4 - Super Ring offsetTableEntry.w super_shoes ; 5 - Speed Shoes offsetTableEntry.w shield_monitor ; 6 - Shield offsetTableEntry.w invincible_monitor ; 7 - Invince offsetTableEntry.w teleport_monitor ; 8 - Teleport offsetTableEntry.w qmark_monitor ; 9 - ? mark </asm>

Next, goto “qmark_monitor”. Since the Special Stage monitor will replace the teleport monitor, I have used the “teleport_flag” variable as our flag for the Clone monitor. If you have extra space in s2.constants.asm, you could use a user-made flag if you would like.

Under “qmark_monitor”, you should see something like this:

<asm> qmark_monitor: addq.w #1,(a2) rts </asm>

Replace it with this:

<asm> qmark_monitor: ;** move.b #1,(Teleport_flag).w ;Used as Clone flag

cmpi.w #2,(Player_mode).w ;If it is a Tails alone game, do nothing beq.s +

bsr.w SingleObjLoad ;Load a Tails object at... bne.w + move.b #2,id(a1) move.w (MainCharacter+x_pos).w,x_pos(a1) ;Sonic's X pos move.w (MainCharacter+y_pos).w,y_pos(a1) ;Sonic's y pos move.w #MusID_ExtraLife,d0 ;Play extra life music jmp (PlayMusic).l + rts </asm>

Next, goto “Obj01_MdNormal”. You should see something like this:

<asm>

loc_1A2B8

Obj01_MdNormal: bsr.w Sonic_CheckSpindash bsr.w Sonic_Jump bsr.w Sonic_SlopeResist bsr.w Sonic_Move bsr.w Sonic_Roll bsr.w Sonic_LevelBound jsr (ObjectMove).l bsr.w AnglePos bsr.w Sonic_SlopeRepel

return_1A2DE: rts

End of subroutine Obj01_MdNormal
====================================

</asm>

Add this before all of the “bsr.w” jumps:

<asm> btst #button_A,(Ctrl_1_Press).w ;** is A being pressed for whistle? bne.w Sonic_Whistle ;**If yes, branch </asm>

After the end of subroutine “Obj01_MdNormal”, add this subfunction:

<asm> Sonic_whistle: ;**

cmpi.w #2,(Player_mode).w ;Is it NOT a Tails only game? beq.s + ;If it is a Tails-only game, branch

tst.b (Teleport_flag). w ; is clone flag enabled? beq.s + ; if not, branch

cmpi.w #10,(Ring_count).w ; does Sonic have at least 10 rings? blo.s + ; if not, branch

sub.w #10,(Ring_count).w ;Subtract 10 rings ori.b #1,(Update_HUD_rings).w ; set flag to update ring counter in the HUD

move.b #AniIDSonAni_Whistle,anim(a0) ;Run whistle animation (optional)

bsr.w SingleObjLoad bne.w + move.b #2,id(a1) ;Load Tails clone at... move.w (MainCharacter+x_pos).w,x_pos(a1) ;Sonic's x pos move.w (MainCharacter+y_pos).w,y_pos(a1) ;Sonic's y pos

move.w #SndID_Sparkle,d0 ;Play sparkle sfx jsr (PlaySound).l rts + move.w #SndID_Error,d0 ;Play buzzer sfx jsr (PlaySound).l rts </asm>

Optionally, you can make Sonic run the unused whistle animation from Sonic 3. Using SonMapEd, add the three sprites at $E5, $E6, and $E7, or wherever you find room. Then, goto “SonicAniData” (or “off_1B618”) and add an offset table entry. Next, define the animation for the whistle sprites.

Sample:

<asm>

---------------------------------------------------------------------------
Animation script - Sonic
---------------------------------------------------------------------------
off_1B618

SonicAniData: offsetTable SonAni_Walk_ptr: offsetTableEntry.w SonAni_Walk ; 0 ; 0 SonAni_Run_ptr: offsetTableEntry.w SonAni_Run ; 1 ; 1

SonAni_Whistle_ptr: offsetTableEntry.w SonAni_Whistle ; 35 ; $23**

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_Whistle: dc.b $2F, $E5,$E6,$E7,$FF;** Even </asm>

Now you have a working clone monitor!


Creating a Special stage monitor:

For our purposes, we will be using the teleport monitor, which is unused in a story mode game. If you would like, you can use SonMapEd to change the teleport monitor’s icon to an appropriate one, say an emerald icon.

First, goto “Obj2E_Types”. You should see something like this:

<asm> Obj2E_Types: offsetTable offsetTableEntry.w robotnik_monitor ; 0 - Static offsetTableEntry.w sonic_1up ; 1 - Sonic 1-up offsetTableEntry.w tails_1up ; 2 - Tails 1-up offsetTableEntry.w robotnik_monitor ; 3 - Robotnik offsetTableEntry.w super_ring ; 4 - Super Ring offsetTableEntry.w super_shoes ; 5 - Speed Shoes offsetTableEntry.w shield_monitor ; 6 - Shield offsetTableEntry.w invincible_monitor ; 7 - Invince offsetTableEntry.w teleport_monitor ; 8 - Teleport offsetTableEntry.w qmark_monitor ; 9 - ? mark </asm>

Next, goto “teleport_monitor”. You should see something like this:

<asm> teleport_monitor: addq.w #1,(a2) cmpi.b #6,(MainCharacter+routine).w ; is player 1 dead or respawning? bhs.s + ; if yes, branch cmpi.b #6,(Sidekick+routine).w ; is player 2 dead or respawning? blo.s swap_players ; if not, branch + ; can't teleport if either player is dead rts </asm>

Change it to this:

<asm> teleport_monitor: ;** SS monitor cmpi.b #7,(Emerald_count).w ;Does main character have all 7 emeralds? bne.s warp_toSS ;If not, branch to goto Special Stage jsr super_ring ;give 10 rings jsr super_ring jsr super_ring jsr super_ring jsr super_ring ;=total of 10 rings rts </asm>

Underneath “teleport_monitor”, add this:

<asm> warp_toSS: move.b #1,(unk_F7CD).w move.b #GameModeID_SpecialStage,(Game_Mode).w ; => SpecialStage rts </asm>

Lastly, to disable entering the special stage by starposts, goto “Obj79_CheckActivation:” and change it to this:

<asm> Obj79_CheckActivation: andi.b #$7F,d1 move.b subtype(a0),d2 andi.b #$7F,d2 cmp.b d2,d1 bhs.w loc_1F222 move.w x_pos(a3),d0 sub.w x_pos(a0),d0 addi.w #8,d0 cmpi.w #$10,d0 bhs.w return_1F220 move.w y_pos(a3),d0 sub.w y_pos(a0),d0 addi.w #$40,d0 cmpi.w #$68,d0 bhs.w return_1F220 move.w #SndID_Checkpoint,d0 ; checkpoint ding-dong sound jsr (PlaySound).l jsr (SingleObjLoad).l bne.s loc_1F206 _move.b #ObjID_Starpost,id(a1) ; load obj79 move.b #6,routine(a1) ; => Obj79_Dongle move.w x_pos(a0),objoff_30(a1) move.w y_pos(a0),objoff_32(a1) subi.w #$14,objoff_32(a1) move.l mappings(a0),mappings(a1) move.w art_tile(a0),art_tile(a1) move.b #4,render_flags(a1) move.b #8,width_pixels(a1) move.b #4,priority(a1) move.b #2,mapping_frame(a1) move.w #$20,objoff_36(a1) move.w a0,parent(a1) ;tst.w (Two_player_mode).w ;bne.s loc_1F206 ;cmpi.b #7,(Emerald_count).w ;beq.s loc_1F206 ;cmpi.w #50,(Ring_count).w ;blo.s loc_1F206 ;** bsr.w Obj79_MakeSpecialStars </asm>

You now have disabled the starposts, and have created a special stage monitor! Enjoy your new monitors, and don’t forget to credit me, Tamkis

SCHG How-To Guide: Sonic the Hedgehog 2 (16-bit)
Fixing Bugs
Fix Demo Playback | Fix a Race Condition with Pattern Load Cues | Fix Super Sonic Bugs | Use Correct Height When Roll Jumping | Fix Jump Height Bug When Exiting Water | Fix Screen Boundary Spin Dash Bug | Correct Drowning Bugs | Fix Camera Y Position for Tails | Fix Tails Subanimation Error | Fix Tails' Respawn Speeds | Fix Accidental Deletion of Scattered Rings | Fix Ring Timers | Fix Rexon Crash | Fix Monitor Collision Bug | Fix EHZ Deformation Bug | Correct CPZ Boss Attack Behavior | Fix Bug in ARZ Boss Arrow's Platform Behavior | Fix ARZ Boss Walking on Air Glitch | Fix ARZ Boss Sprite Behavior | Fix Multiple CNZ Boss Bugs | Fix HTZ Background Scrolling Mountains | Fix OOZ Launcher Speed Up Glitch | Fix DEZ Giant Mech Collision Glitch | Fix Boss Deconstruction Behavior | Fix Speed Bugs | Fix 14 Continues Cheat | Fix Debug Mode Crash | Fix 99+ Lives | Fix Sonic 2's Sega Screen
Design Choices
Remove the Air Speed Cap | Disable Floor Collision While Dying | Modify Super Sonic Transformation Methods & Behavior | Enable/Disable Tails in Certain Levels | Collide with Water After Being Hurt | Retain Rings When Returning at a Star Post | Improve the Fade In\Fade Out Progression Routines | Fix Scattered Rings' Underwater Physics | Insert LZ Water Ripple Effect | Restore Lost CPZ Boss Feature | Prevent SCZ Tornado Spin Dash Death | Improve ObjectMove Subroutines | Port S3K Rings Manager | Port S3K Object Manager | Port S3K Priority Manager | Edit Level Order with ASM‎ | Alter Ring Requirements in Special Stages | Make Special Stage Characters Use Normal DPLCs | Speed Up Ring Loss Process | Change spike behaviour in Sonic 2
Adding Features
Create Insta-kill and High Jump Monitors | Create Clone and Special Stage Monitors | Port Knuckles
Sound Features
Expand Music Index to Start at $00 | Port Sonic 1 Sound Driver | Port Sonic 2 Clone Driver | Port Sonic 3 Sound Driver | Port Flamewing's Sonic 3 & Knuckles Sound Driver | Expand the Music Index to Start at $00 (Sonic 2 Clone Driver Version) | Play Different Songs Per Act
Extending the Game
Extend the Level Index Past $10 | Extend the Level Select | Extend Water Tables | Add Extra Characters | Free Up 2 Universal SSTs