Also, do you know what the "Special Stage 1" is for in the level select? Is it remnant of the super emerald special stages?Doesn't look like it, but it's interesting nonetheless.
The special stage entries in the level select actually refer to an invalid zone ID, zone $40. When this zone is selected, a special handler prevents the invalid zone from getting loaded, and instead modifies the value of the Game_mode RAM variable, setting it to $2C for act 1, and $34 for act 2:
LevelSelect_PressStart: move.w ($FFFFFF82).w,d0 add.w d0,d0 move.w LS_Level_Order(pc,d0.w),d0 bmi.w LevelSelect_Return cmpi.w #$5555,d0 ; This is used for the S&K zones beq.w LevelSelect_Main cmpi.w #$4001,d0 ; Is Special Stage 2 selected? beq.w LevelSelect_SpecialStage ; If so, branch cmpi.w #$4000,d0 ; Is Special Stage 1 selected? bne.w LevelSelect_StartZone ; If not, branch move.b #$2C,(Game_mode).w rts ; --------------------------------------------------------------------------- LevelSelect_SpecialStage: move.b #$34,(Game_mode).w rtsOnce this variable is changed, the game instantly switches away from the current mode, $28 (level select) to whichever one got picked above. In Sonic & Knuckles, mode $2C refers to the title screen for the Blue Sphere bonus game, but in S3A, both it and $34 point at the special stage game mode.
GameModes: dc.l Sega_Screen ; 0 dc.l Title_Screen ; 4 dc.l Level ; 8 dc.l Level ; $C dc.l JumpToSegaScreen ; $10 dc.l ContinueScreen ; $14 dc.l JumpToSegaScreen ; $18 dc.l LevelSelect_S2Options ; $1C dc.l S3Credits ; $20 dc.l LevelSelect_S2Options ; $24 dc.l LevelSelect_S2Options ; $28 dc.l SpecialStage ; $2C dc.l SpecialStage ; $30 dc.l SpecialStage ; $34 dc.l Competition_Menu ; $38 dc.l Competition_PlayerSelect ; $3C dc.l Competition_LevelSelect ; $40 dc.l Competition_Results ; $44 dc.l SpecialStage_Results ; $48 dc.l SaveScreen ; $4C dc.l TimeAttack_Records ; $50At the end of the special stage mode's main loop, the Game_mode RAM variable is checked. If it's anything other than $34, then instead of jumping back to the start of the loop, execution progresses into a second loop, in which the screen progressively fades to white. The equivalent code can be found at loc_851A in the S&K disassembly.
cmpi.b #$34,(Game_mode).w beq.s loc_77D2 tst.w (Demo_mode_flag).w beq.s loc_7828 move.b #0,(Game_mode).w loc_7828: move.w #$3C,(Demo_timer).w move.w #$3F,(Palette_fade_info).w clr.w ($FFFFF794).w loc_7838: move.b #$1C,(V_int_routine).w bsr.w Wait_VSync jsr (Process_Sprites).l bsr.w Animate_SSRings bsr.w sub_8C1A jsr (Render_Sprites).l jsr Draw_SSSprites(pc) bsr.w sub_8B9A bsr.w sub_89E2 bsr.w Process_Nem_Queue_Init jsr (Process_Kos_Module_Queue).l subq.w #1,($FFFFF794).w bpl.s loc_787C move.w #2,($FFFFF794).w bsr.w Pal_ToWhite loc_787C: tst.w (Demo_timer).w bne.s loc_7838Now, if the debug cheat is enabled, then pressing the A button while the game is paused makes the game jump directly to the level select. This is achieved by setting the Game_mode variable to $28, the value for the level select mode:
Pause_Loop: move.b #$10,(V_int_routine).w bsr.w Wait_VSync tst.b (Slow_motion_flag).w beq.s Pause_NoSlowMo btst #6,(Ctrl_1_pressed).w beq.s Pause_ChkFrameAdvance ; branch if A isn't pressed move.b #$28,(Game_mode).w nop bra.s Pause_ResumeMusicAnd that's what that check in the special stage mode was for. When the Game_mode variable changes from its regular value of $34, the game knows that it has to exit the special stage and go someplace else (for instance, the level select) so it begins fading to white, and once the fade is over, it jumps to the new game mode.
Except that, when we choose the "special stage 1" option, the Game_mode variable starts off with the value $2C. This calls up the special stage mode all the same, except the check fails immediately, triggering a fade out. Once the fade is over, the game jumps to the "new" game mode, $2C... which calls up the special stage mode all over again.
The cherry on top of the cake is this code at the end of that second loop:
loc_787C: tst.w (Demo_timer).w bne.s loc_7838 addq.b #1,($Current_special_stage).w cmpi.b #7,(Current_special_stage).w bcs.s locret_7894 move.b #0,(Current_special_stage).w locret_7894: rtsThis code ensures that the current stage value is properly incremented when the player exits the stage using the debug shortcut. That way, next time a special stage is accessed, the game will advance to the next stage in line, just like if the previous one had completed normally.
Inadvertently, this causes the "special stage 1" bug to cycle through each stage in an infinite loop. In Sonic & Knuckles, not only was the bug fixed, but the debug shortcut now leads to the SEGA screen, so the above code was removed.
Was there a reason they didn't make it do nothing when selected?
ReplyDeleteMy guess is that mode $2C did something interesting at one point, but the developers just forgot to remove the entry point from the level select like they did with the S&K stages.
DeletePerhaps mode $2C was Blue Sphere before that mode was shifted to S&K and removed from S3A?
DeleteIs the level select screen from an early build that predates everything after Sandopolis? It would be quite helpful to have a prototype...
DeleteKinda unrelated, I know, but this just popped into my head a while ago...
ReplyDeleteWhy does the Lava Reef Giant Hand miniboss crush characters when they are in their Super form and spindashing? And I think Tails always get crushed too. Is it because of their size? It's kinda odd to have a miniboss being able to kill you in such an unexpected way...
Could you talk about the removed water in Launch Base act 1?
ReplyDelete