[Sonic 1] How to make the Special Stages in Sonic 1 Not progress if you lose

Discussion in 'Tutorials Archive' started by DarkLeach, Jan 28, 2012.

Thread Status:
Not open for further replies.
  1. DarkLeach

    DarkLeach Well-Known Member Member

    Joined:
    Jul 3, 2011
    Messages:
    193
    Location:
    In the middle of desert heat
    If you had a special stage (In Sonic 1) That was hard and when you lost you had to re-cycle through all the other stages to get back to the first one and not remembering how to beat it? This guide is for you! This will make it so that until you beat a special stage it won't make you play the next one!


    You start off with this:



    Code:
    
    SS_Load:	; XREF: SpecialStage
    
      moveq #0,d0
    
      move.b ($FFFFFE16).w,d0 ; load number of last special stage entered
    
      addq.b #1,($FFFFFE16).w
    
      cmpi.b #6,($FFFFFE16).w
    
      bcs.s SS_ChkEmldNum
    
      move.b #0,($FFFFFE16).w ; reset if higher than 6
    
    SS_ChkEmldNum:
    
      cmpi.b #6,($FFFFFE57).w ; do you have all emeralds?
    
      beq.s SS_LoadData ; if yes, branch
    
      moveq #0,d1
    
      move.b ($FFFFFE57).w,d1
    
      subq.b #1,d1
    
      bcs.s SS_LoadData
    
      lea ($FFFFFE58).w,a3 ; check which emeralds you have
    
    SS_ChkEmldLoop:
    
      cmp.b (a3,d1.w),d0
    
      bne.s SS_ChkEmldRepeat
    
      bra.s SS_Load
    
    ; ===========================================================================
    
    SS_ChkEmldRepeat:
    
      dbf d1,SS_ChkEmldLoop
    
    SS_LoadData:
    
      lsl.w #2,d0
    
      lea SS_StartLoc(pc,d0.w),a1
    
      move.w (a1)+,($FFFFD008).w
    
      move.w (a1)+,($FFFFD00C).w
    
      movea.l SS_LayoutIndex(pc,d0.w),a0
    
      lea ($FF4000).l,a1
    
      move.w #0,d0
    
      jsr (EniDec).l
    
      lea ($FF0000).l,a1
    
      move.w #$FFF,d0
    
    SS_ClrRAM3:
    
      clr.l (a1)+
    
      dbf d0,SS_ClrRAM3
    
      lea ($FF1020).l,a1
    
      lea ($FF4000).l,a0
    
      moveq #$3F,d1
    
    loc_1B6F6:
    
      moveq #$3F,d2
    
    loc_1B6F8:
    
      move.b (a0)+,(a1)+
    
      dbf d2,loc_1B6F8
    
      lea $40(a1),a1
    
      dbf d1,loc_1B6F6
    
      lea ($FF4008).l,a1
    
      lea (SS_MapIndex).l,a0
    
      moveq #$4D,d1
    
    loc_1B714:
    
      move.l (a0)+,(a1)+
    
      move.w #0,(a1)+
    
      move.b -4(a0),-1(a1)
    
      move.w (a0)+,(a1)+
    
      dbf d1,loc_1B714
    
      lea ($FF4400).l,a1
    
      move.w #$3F,d1
    
    loc_1B730:
    
      clr.l (a1)+
    
      dbf d1,loc_1B730
    
      rts
    
    ; End of function SS_Load
    
    


    However that isn't what you want here.

    First find this:



    Code:
    
    SS_Load:	; XREF: SpecialStage
    
      moveq #0,d0
    
      move.b ($FFFFFE16).w,d0 ; load number of last special stage entered
    
      addq.b #1,($FFFFFE16).w
    
      cmpi.b #6,($FFFFFE16).w
    
      bcs.s SS_ChkEmldNum
    
      move.b #0,($FFFFFE16).w ; reset if higher than 6
    
    



    and replace it with this:



    Code:
    
    SS_Load:	; XREF: SpecialStage
    
      cmpi.b #5,($FFFFFE57).w ; Does sonic have 5 emeralds?
    
      bls.s SS_SpecialStageNumLoad ; If lower or same, branch
    
      move.b #0,($FFFFFE16).w ; reset if higher than 6
    
    
    This obviously won't work by itself because the Assembler will get an error because "SS_SpecialStageNumLoad" isn't defined.

    let's fix that.



    Add this directly below the last line:

    Code:
    
    SS_SpecialStageNumLoad:
    
      move.b  ($FFFFFE57).w,($FFFFFE16).w   ; move the value of address $FFFFFE57 to $FFFFFE16
    
      move.b ($FFFFFE16).w,d0 ; move the value of $FFFFFE16 to d0 for later use
    
      bra.s  SS_LoadData
    
    
    You should have something like this:

    Code:
    
    SS_Load:	; XREF: SpecialStage
    
      cmpi.b #5,($FFFFFE57).w ; Does sonic have 5 emeralds?
    
      bls.s SS_SpecialStageNumLoad ; If lower or same, branch
    
      move.b #0,($FFFFFE16).w ; reset if higher than 6
    
    
    
    SS_SpecialStageNumLoad:
    
      move.b  ($FFFFFE57).w,($FFFFFE16).w   ; move the value of address $FFFFFE57 to $FFFFFE16
    
      move.b ($FFFFFE16).w,d0
    
      bra.s  SS_LoadData
    
    
    This of course will cause an illegal value error when assembling so you need to fix something else as well.



    Next add this line:

    Code:
    
    jmp SS_ClrRAM3 ;Yes This has to be jmp, because when trying bra.s the game crashed upon loading a special stage
    
    
    after this line:

    Code:
    
    SS_LoadData:
    
      lsl.w #2,d0
    
      lea SS_StartLoc(pc,d0.w),a1
    
      move.w (a1)+,($FFFFD008).w
    
      move.w (a1)+,($FFFFD00C).w
    
      movea.l SS_LayoutIndex(pc,d0.w),a0
    
      lea ($FF4000).l,a1
    
      move.w #0,d0
    
      jsr (EniDec).l
    
      lea ($FF0000).l,a1
    
      move.w #$FFF,d0
    
    ;-> Put the line right here!
    
    
    This still can't be assembled.



    You must change

    Code:
    
    bra.s SS_Load
    
    
    To this for whatever reason:

    Code:
    
    jmp SS_Load
    
    
    Now one last thing:



    Move SS_LayoutIndex and SS_StartLoc from here:

    Code:
    
    ; ---------------------------------------------------------------------------
    
    ; Special stage layout pointers and start locations
    
    ; ---------------------------------------------------------------------------
    
    SS_LayoutIndex:
    
    include "_incSpecial stage layout pointers.asm"
    
    ; ---------------------------------------------------------------------------
    
    ; Special stage start locations
    
    ; ---------------------------------------------------------------------------
    
    SS_StartLoc: incbin miscsloc_ss.bin
    
      even
    
    ; ===========================================================================
    
    
    To Here (To Look like this):

    Code:
    
    ...
    
    				move.w #$FFF,d0
    
      jmp SS_ClrRAM3 ;Yes This has to be jmp, because when I tried bra.s the game crashed upon loading a special stage
    
    
    
    ;----------------
    
    SS_StartLoc: incbin miscsloc_ss.bin
    
      even
    
    
    
    SS_LayoutIndex:
    
    include "_incSpecial stage layout pointers.asm"
    
    ;--------------------
    
    SS_ClrRAM3:
    
      clr.l (a1)+
    
      dbf d0,SS_ClrRAM3
    
    ...
    
    
    Final Code (For lazy people that can't bother to do things themselves :) )

    Code:
    
    ; ---------------------------------------------------------------------------
    
    ; Subroutine to load special stage layout
    
    ; ---------------------------------------------------------------------------
    
    ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    
    SS_Load:	; XREF: SpecialStage
    
      cmpi.b #5,($FFFFFE57).w ; Does sonic have 5 emeralds?
    
      bls.s SS_SpecialStageNumLoad ; If lower or same, branch
    
      move.b #0,($FFFFFE16).w ; reset if higher than 6
    
    
    
    SS_SpecialStageNumLoad:
    
      move.b  ($FFFFFE57).w,($FFFFFE16).w   ; move the value of address $FFFFFE57 to $FFFFFE16
    
      move.b ($FFFFFE16).w,d0
    
      bra.s  SS_LoadData
    
    
    
    SS_ChkEmldNum:
    
      cmpi.b #6,($FFFFFE57).w ; do you have all emeralds?
    
      beq.s SS_LoadData ; if yes, branch
    
      moveq #0,d1
    
      move.b ($FFFFFE57).w,d1
    
      subq.b #1,d1
    
      bcs.s SS_LoadData
    
      lea ($FFFFFE58).w,a3 ; check which emeralds you have
    
    SS_ChkEmldLoop:
    
      cmp.b (a3,d1.w),d0
    
      bne.s SS_ChkEmldRepeat
    
      jmp SS_Load
    
    ; ===========================================================================
    
    SS_ChkEmldRepeat:
    
      dbf d1,SS_ChkEmldLoop
    
    SS_LoadData:
    
      lsl.w #2,d0
    
      lea SS_StartLoc(pc,d0.w),a1
    
      move.w (a1)+,($FFFFD008).w
    
      move.w (a1)+,($FFFFD00C).w
    
      movea.l SS_LayoutIndex(pc,d0.w),a0
    
      lea ($FF4000).l,a1
    
      move.w #0,d0
    
      jsr (EniDec).l
    
      lea ($FF0000).l,a1
    
      move.w #$FFF,d0
    
      jmp SS_ClrRAM3 ;Yes This has to be jmp, because when trying bra.s the game crashed upon loading a special stage
    
    
    
    ;----------------
    
    SS_StartLoc: incbin miscsloc_ss.bin
    
      even
    
    
    
    SS_LayoutIndex:
    
    include "_incSpecial stage layout pointers.asm"
    
    ;--------------------
    
    SS_ClrRAM3:
    
      clr.l (a1)+
    
      dbf d0,SS_ClrRAM3
    
      lea ($FF1020).l,a1
    
      lea ($FF4000).l,a0
    
      moveq #$3F,d1
    
    loc_1B6F6:
    
      moveq #$3F,d2
    
    loc_1B6F8:
    
      move.b (a0)+,(a1)+
    
      dbf d2,loc_1B6F8
    
      lea $40(a1),a1
    
      dbf d1,loc_1B6F6
    
      lea ($FF4008).l,a1
    
      lea (SS_MapIndex).l,a0
    
      moveq #$4D,d1
    
    loc_1B714:
    
      move.l (a0)+,(a1)+
    
      move.w #0,(a1)+
    
      move.b -4(a0),-1(a1)
    
      move.w (a0)+,(a1)+
    
      dbf d1,loc_1B714
    
      lea ($FF4400).l,a1
    
      move.w #$3F,d1
    
    loc_1B730:
    
      clr.l (a1)+
    
      dbf d1,loc_1B730
    
      rts
    
    
    
    ; End of function SS_Load
    
    
    Now you should be able to build your ROM and have it not advance Special Stages when you lose one! Now you all can make Special Stages that need to be practiced over and over without having the game advance before you beat one!


    Tutorial - Version 1.0 by DarkLeach7 - January 28, 2012


    Thanks to vladikcomper because without him this tutorial probably wouldn't have been possible (for me anyway :) ). :)


    Please leave any comment's below if this works or doesn't work for you or if I left out anything important (This is my first tutorial after all :eek: ). Thanks for reading!

    [/CODE]
     
    Last edited by a moderator: Jan 28, 2012
  2. SSGD

    SSGD "I can't believe what cool boots you have on!" Member

    Joined:
    Nov 14, 2011
    Messages:
    125
    Location:
    Room 101
    Gave the code a test run and I can't find any problems. Does what it's set out to do without skipping over any of the special stages. Indeed a useful code for those who wish to try for an emerald again in a stage instead of having to wait a couple of turns.
     
  3. EMK-20218

    EMK-20218 The Fuss Maker Exiled

    Joined:
    Aug 8, 2008
    Messages:
    1,067
    Location:
    Jardim Capelinha, São Paulo
    Ahah, I did this to Sonic 1 Harder Levels a VERY LONG time (3 years) ago. It's useful, specially if you aim a hack to be harder or if you're preparing secrets for every special stage. This code looks a bit unoptimized, but it's good. Thanks!
     
    Last edited by a moderator: Jan 29, 2012
Thread Status:
Not open for further replies.