Improving Sonic 2's level select

Discussion in 'Tutorials' started by ADudeCalledLeo, Jun 15, 2019.

  1. ADudeCalledLeo

    ADudeCalledLeo I'll make a ROM hack one of these days... Member

    Joined:
    Oct 21, 2017
    Messages:
    13
    Location:
    Null Space
    Here's a ROM with all the following changes applied: https://www.dropbox.com/s/zsnnytoxrnwbhzz/Sonic 2 Improved Level Select.bin?dl=0

    Adding a way to change character
    Go to "LevelSelect_DrawSoundNumber", and duplicate the entire routine, renaming the label to "LevelSelect_DrawPlayerOption". In your newly duplicated routine, change:
    Code:
        move.l    #vdpComm(VRAM_Plane_A_Name_Table+planeLocH40(34,18),VRAM,WRITE),(VDP_control_port).l
        move.w   (Sound_test_sound).w,d0
    to:
    Code:
        move.l    #vdpComm(VRAM_Plane_A_Name_Table+planeLocH40(4,24),VRAM,WRITE),(VDP_control_port).l
        move.w   (Player_option).w,d0
    Then, go to "LevelSelect_MarkFields", and scroll down until you see this bit of code:
    Code:
        cmpi.w    #$15,(Level_select_zone).w
        bne.s    +    ; rts
        bsr.w    LevelSelect_DrawSoundNumber
    +
        rts
    Change it to:
    Code:
        cmpi.w    #$15,(Level_select_zone).w
        beq.w   LevelSelect_DrawSoundNumber
        bra.w   LevelSelect_DrawPlayerOption
    
    The currently selected character will now be drawn on the level select. It'll be drawn highlighted, unless the Sound Test option is selected.
    Now to add a way to actually change it. Go to "LevSelControls_SwitchSide", and just before the "rts", add this code:
    Code:
    ;LevSelControls_SwitchPlayerOption:
        btst    #button_C,(Ctrl_1_Press).w    ; is C pressed?
        beq.s    +                ; if not, branch
        addq.w    #1,(Player_option).w        ; select next character
        cmpi.w    #2,(Player_option).w        ; did we go over the limit?
        bls.s    +                ; if not, branch
        clr.w    (Player_option).w        ; reset to 0
    +
    This will make it so that if you press C on anything that's not the Sound Test, the next character will be selected, wrapping around to 0 if you go over the maximum.
    The number in the cmpi.w line should be the number of characters in your hack. If you added Knuckles, for example, you'd change that number to be 3 instead of 2.

    Improving the sound test
    Go to the 3rd + label after "LevSelControls_CheckLR". You should see the following line there:
    Code:
        andi.w    #button_B_mask|button_C_mask,d1
    Replace it with:
    Code:
        andi.w    #button_C_mask,d1
    Now, only pressing C will cause the sound to be played.
    Then, go back to the 3rd + label and directly after it, add the following code:
    Code:
        btst    #button_B,d1
        beq.s    +
        subi.b    #$10,d0
        andi.b    #$7F,d0
    
    +
    This will make it so that pressing B will lower the 2nd digit by 1.

    The sound test in the options screen can also be improved in the same way.
    Go to the 5th + label after "OptionScreen_Controls" You should see the following line there:
    Code:
        andi.w    #button_B_mask|button_C_mask,d0
    Replace it with:
    Code:
        andi.w    #button_C_mask,d0
    Then, go to the + label just before the one you're at and replace everything up to the 5th + label with:
    Code:
        cmpi.b    #2,(Options_menu_box).w
        bne.s    ++
    
        btst    #button_A,d0
        beq.s    +
        addi.b    #$10,d2
        andi.b    #$7F,d2
    
    +
        btst    #button_B,d0
        beq.s    +
        subi.b    #$10,d2
        andi.b    #$7F,d2
    
    +
    A tiny side effect of this fix is that the "maximum" bit in the "OptionsScreen_Choices" entry for the sound test will go unused.

    NOTE: If you've made the sound IDs start at 0 instead of $80, remove the "andi.b #$7F" lines. These lines limit the sound test number to a maximum of $7F.

    Return to the level select after pressing Start+A
    Go to "Pause_Loop", and change the line:
    Code:
        move.b    #GameModeID_TitleScreen,(Game_Mode).w ; set game mode to 4 (title screen)
    To:
    Code:
        move.b    #GameModeID_LevelSelect,(Game_Mode).w ; set game mode to $28 (level select)
    This will make the game return to the level select rather than the title screen when pressing Start+A.
    However, staring a new level after returning from a level causes some issues, since the level select doesn't completely reset level data (since it relies on the title screen resetting them, as there was no way to get to the level select without going through the title screen).
    To fix these issues, go to "MenuScreen_LevelSelect", and before "bsr.w Pal_FadeFromBlack" add:
    Code:
        clr.b    (Water_fullscreen_flag).w
    This prevents a palette issue when returning to the level select while the entire screen is underwater. Then, go to "LevelSelect_StartZone", and after "move.w d0,(Current_ZoneAndAct).w", add:
    Code:
        moveq    #PLCID_Std1,d0
        bsr.w    RunPLC_ROM
    This reloads Sonic's lives counter, as well as a few other graphics. Then, after "move.b d0,(Continue_count).w", add:
    Code:
        move.b    d0,(Last_star_pole_hit).w
        move.b    d0,(Last_star_pole_hit_2P).w
    This makes the game think that no checkpoints have been reached, meaning that you'll always start at the beginning of the level properly.
     
    Last edited: Nov 21, 2019
    EMK-20218, maple_t, Painto and 4 others like this.
  2. TheFieldWarrior

    TheFieldWarrior Warrior of the Fields Member

    Joined:
    Oct 9, 2015
    Messages:
    95
    Location:
    United Kingdom
    There are three bugs which are the result of making Start+A return to the level select. I checked your example build to see if I messed up somewhere in the tutorial and it appears these bugs occur in your build as well. The common theme with these bugs is that the game doesn't reset data when switching to another character from the level select

    1. If you select Tails on the level select, enter a level, return to the level select, switch to Sonic and enter a level his life icon still shows Tails'

    2. If you enter act 2 of a zone, go far enough, return to the level select and pick a different zone (or act 1 of the same zone) the start positioning is screwed up causing you to start far into the stage, this also messes with levels with water (CPZ2 and ARZ) as the water covers the entire zone. It also causes Tails' sprites to show up as a glitched up Sonic

    3. If you hit a checkpoint, return to the level select and then enter the same level again you'll start at the checkpoint you hit earlier, if you decide to enter a different level then the starting position gets screwed up again this time putting you in the coordinates of the checkpoint
     
    ProjectFM and MarkeyJester like this.
  3. ADudeCalledLeo

    ADudeCalledLeo I'll make a ROM hack one of these days... Member

    Joined:
    Oct 21, 2017
    Messages:
    13
    Location:
    Null Space
    Guide has been updated with (untested!) fixes to these issues. ROM has not been rebuilt yet.
     
    Last edited: Jun 16, 2019
    TheFieldWarrior likes this.
  4. Inferno

    Inferno Rom Hacker Member

    Joined:
    Oct 27, 2015
    Messages:
    132
    Location:
    Sky Base Zone, South Island
    Noticed a singular issue with this guide.

    In the OptionScreen_Controls segment, this is the code you said we needed to replace:
    Code:
       andi.w    #button_B_mask|button_C_mask,d1
    And you said to replace it with this:
    Code:
       andi.w    #button_C_mask,d1
    However, in this case, you are performing andi on the wrong data register, which causes a bug where pressing C does not play the music in the options menu's sound test. This is verified by looking at the same line in the main Sonic 2 Github disasm:
    Code:
       andi.w    #button_B_mask|button_C_mask,d0
    So, in actuality, anyone following this tutorial needs to replace that line in OptionScreen_Controls with this:
    Code:
       andi.w    #button_C_mask,d0
    I've performed this on multiple kinds of Sonic 2 disasms before, and the same result has occurred.
     
    Bluestreak likes this.
  5. ADudeCalledLeo

    ADudeCalledLeo I'll make a ROM hack one of these days... Member

    Joined:
    Oct 21, 2017
    Messages:
    13
    Location:
    Null Space
    heck. i'm like 90% sure this is an issue with the guide itself and not the example ROM, but i can't check rn.
    edit: guide itself has been fixed
     
    Inferno likes this.