Sonic 1 - Have an Option Screen up using the level select, and seperating the two

Discussion in 'Tutorials' started by warr1or2, Jun 23, 2020.

  1. warr1or2

    warr1or2 I AM CLG Member

    Joined:
    Apr 7, 2008
    Messages:
    394
    Location:
    Town Creek, AL
    Here's how to get an option menu working in Sonic 1, using the level select, and seperaing the two.
    First off you'd need to have the game read the level select as ASCII.
    You're gonna need to replace the LevelMenuText with...
    Code:
    LevelMenuText:
         dc.b    "GREEN HILL ZONE  STAGE 1"
            dc.b    "                 STAGE 2"
            dc.b    "                 STAGE 3"
            dc.b    "LABYRINTH        STAGE 1"
            dc.b    "                 STAGE 2"
            dc.b    "                 STAGE 3"
            dc.b    "MARBLE ZONE      STAGE 1"
            dc.b    "                 STAGE 2"
            dc.b    "                 STAGE 3"
            dc.b    "STAR LIGHT ZONE  STAGE 1"
            dc.b    "                 STAGE 2"
            dc.b    "                 STAGE 3"
            dc.b    "SPRING YARD ZONE STAGE 1"
            dc.b    "                 STAGE 2"
            dc.b    "                 STAGE 3"
            dc.b    "SCRAP BRAIN ZONE STAGE 1"
            dc.b    "                 STAGE 2"
            dc.b    "                 STAGE 3"
            dc.b    "FINAL ZONE              "        
            dc.b    "SPECIAL STAGE           "      
            dc.b    "SOUND TEST              "          
            even
    OptionMenuText:   
            dc.b    "GREEN HILL ZONE  STAGE 1"
            dc.b    "                 STAGE 2"
            dc.b    "                 STAGE 3"
            dc.b    "MARBLE ZONE      STAGE 1"
            dc.b    "                 STAGE 2"
            dc.b    "                 STAGE 3"
            dc.b    "SPRING YARD ZONE STAGE 1"
            dc.b    "                 STAGE 2"
            dc.b    "                 STAGE 3"
            dc.b    "LABYRINTH        STAGE 1"
            dc.b    "                 STAGE 2"
            dc.b    "                 STAGE 3"
            dc.b    "STAR LIGHT ZONE  STAGE 1"
            dc.b    "                 STAGE 2"
            dc.b    "                 STAGE 3"
            dc.b    "SCRAP BRAIN ZONE STAGE 1"
            dc.b    "                 STAGE 2"
            dc.b    "                 STAGE 3"
            dc.b    "FINAL ZONE              "        
            dc.b    "SPECIAL STAGE           "      
            dc.b    "SOUND TEST              "
    
    You can change the option text to anything later
    go to Loc_3598 and replace
    Code:
     add.w    d3,d0        ; combine char with VRAM setting
            move.w    d0,(a6)        ; send to VRAM
            dbf        d2,Loc_3588   
            rts
    
    with...
    Code:
     cmp.w    #$40, d0    ; Check for $40 (End of ASCII number area)
            blt.s        @notText    ; If this is not an ASCII text character, branch
            sub.w    #$3,d0        ; Subtract an extra 3 (Compensate for missing characters in the font)
        @notText:
            sub.w    #$30,d0        ; Subtract #$33 (Convert to S2 font from ASCII)
            add.w    d3,d0        ; combine char with VRAM setting
            move.w    d0,(a6)        ; send to VRAM
            dbf        d2,Loc_3588   
            rts
    
    and go to levsel_ChgSnd and change the addi.b #7,d0 to addi.b #4,d0
    The way I have it, Pushing start enters the Options screen first. Since The Level Select And the Region Check code won't be needed, it will be deleted.
    Go to loc_317C and make bcs.s Title_ChkRegion branch to loc_3210 instead
    Here is what I have
    Code:
      cmpi.w #$1C00,d0 ; has Sonic object passed x-position $1C00?
      bcs.s loc_3210; ; if not, branch
       move.b #0,($FFFFF600).w ; go to Sega screen
      rts
    ; ===========================================================================
    ;  Region Check Is Gone
    ; ===========================================================================
    ;   The Level Select Code is gone
    ; ===========================================================================
    loc_3210:
    
    Now the Start Button should bring you to a glitched level select. time to fix it.
    open any tile editor, I done it with TLP (Tile Layer Pro), and open artunc/menutext twice.
    Fix this by having it to read
    0123456789$-=>AB
    CDEFGHIJKLMNOPQR
    STUVWXYZ>
    Then everything should read fine.
    Time to seperate. Go to LevSelTextLoad and make a check for Options
    Code:
    LevSelTextLoad:
      cmpi.b #1,(LevelselectRam) ; Is this the level select?
      beq LevSelLoad   ; if so, load level select text
      lea (OptionMenuText).l,a1 ; Load the Option text
      bra TextRead   ; continue here
    LevSelLoad: lea (LevelMenuText).l,a1 ; load level select text
    TextRead:
    
    and another further down
    Code:
    loc_34FE:    ; XREF: LevSelTextLoad+26j
      move.l d4,4(a6)
      bsr.w LevSel_ChgLine
      addi.l #$800000,d4
      dbf d1,loc_34FE
      moveq #0,d0
      move.w ($FFFFFF82).w,d0
      move.w d0,d1
      move.l #$62100003,d4
      lsl.w #7,d0
      swap d0
      add.l d0,d4
      cmpi.b #1,(LevelselectRam)
      beq LevSelLoad2
      lea (OptionMenuText).l,a1
      bra TextRead2
    LevSelLoad2: lea (LevelMenuText).l,a1
    TextRead2:
    
    Now we can work with setting up the options. Find some free ram to use.
    mine reads as
    LevelSelectRam = $FFFFF5C1

    Go to LevSelControls, go to line 5 and change it to read your first option
    mine
    Code:
    LevSelControls:    ; XREF: LevelSelect
      move.b ($FFFFF605).w,d1
      andi.b #3,d1  ; is up/down pressed and held?
      bne.s LevSel_UpDown ; if yes, branch
      subq.w #1,($FFFFFF80).w ; subtract 1 from time to next move
      bpl.s LevSel_Char ; if time remains, branch
    
    do the same with Levsel_UpDown
    Code:
    LevSel_UpDown:
      move.w #$B,($FFFFFF80).w ; reset time delay
      move.b ($FFFFF604).w,d1
      andi.b #3,d1  ; is up/down pressed?
      beq.s LevSel_Char ; if not, branch
      move.w ($FFFFFF82).w,d0
      btst #0,d1  ; is up pressed?
      beq.s LevSel_Down ; if not, branch
      subq.w #1,d0  ; move up 1 selection
      bcc.s LevSel_Down
      moveq #$14,d0  ; if selection moves below 0, jump to selection $14
    
    Now you can program in each option, leaving $14 as Sound Test
    an example to use
    Code:
      cmpi.b #1,(LevelSelectRam)
      beq LevSel_NoMove
      tst.w ($FFFFFF82).w ; is item $00 selected?
      bne.s LevSel_Debug_Mode ; if not, branch
    
    Now what's needed is an option for the LevelSelect. This is how I got mine to work
    Code:
    LevSel_TheLevelSelect:
      cmpi.b #1,(LevelSelectRam)
      beq LevSel_NoMove
      cmpi.w #$02,($FFFFFF82).w ; is item $14 selected?
      bne LevSel_SndTest ; if not, branch
      move.b ($FFFFF605).w,d1
      andi.b #ButtonStart,d1  ; is left/right pressed?
      beq.s LevSel_NoMove
     
      Move.b #1,(LevelSelectRam)
      jsr Titlescreen
      rts
    
    with this, Option 2 is the level Select. you can change it though.
    however what's needed is to have the Level Select pointers set for Level Select and not options.
    We need to make some checks.
    LevSel_Level, change it to
    Code:
    Option_Level_SS:   ; Levsel_Level_SS loads Level Select Pointers, this jumps back to LevelSelect
      JMP LevelSelect
    ; ===========================================================================
    LevSel_Level:  ; Stay at the Level Select if this is Options
      tst.b (LevelSelectRam)
      beq Option_Level_SS   ; XREF: LevSel_Level_SS
      andi.w #$3FFF,d0
      cmpi.b #1,(LevelSelectRam)
      bne LevelSelect
      move.w d0,($FFFFFE10).w ; set level number
    
    in LevelSelect, below the move.w ($FFFFFF82)
    Code:
      tst.b (LevelSelectRam)
      beq SkipLSelect
      cmpi.w #$14,d0  ; have you selected item $14 (sound test)?
      bne LevSel_Level_SS ; if not, go to Level/SS subroutine
      bra JapCredits
    SkipLSelect: cmpi.w #$14,d0  ; have you selected item $14 (sound test)?
      bne.s Option_Level_SS ; if not, skip the pointers, return to LevelSelect
    JapCredits:
    
    If everything worked out you can change the text. an example
    Code:
    OptionMenuText:
         dc.b    "CHARACTER               " ; Character Change
            dc.b    "DEBUGGER                " ; Activate Debug Mode
            dc.b    "LEVEL SELECT            " ; This is to switch to the level select
            dc.b    "START                   " ; just start the game
            dc.b    "NULL                    " ; This on down..
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    "
            dc.b    "NULL                    " ; .. Here does nothing yet.
            dc.b    "SOUND TEST              "
            even
    
    and there you go. So far I haven't seen a bug, except Sound Test works only in options and not Level Select. If anything else, let me know. Also, suggestions on improving this is welcomed.
    Edit2: There were 2 bugs.
    1. Game Over needs to reset the Level Select Ram
    2. Ending needs to reset it too.
    Instead of adding a Clr.b to ending and game over, go to SegaScreen: and add a clr (levelselectram) anywhere. I put one between where it loads Sega logo patterns and mappings, below bsr.w nemdec above Lea ($Ff0000).l,a1. This fixes both and resets at SegaScreen.
     
    Last edited: Jul 4, 2020
    Narcologer and mrcat-pixel like this.