Actions

SCHG How-to

Difference between revisions of "Port Sonic 2's Level Select to Sonic 1"

From Sonic Retro

(Make changes to the Title Screen)
(Insert the new screens for Level Select, Options, and 2 Player VS)
Line 235: Line 235:
 
; ===========================================================================
 
; ===========================================================================
  
 +
</asm>
 +
 +
and finally remove this:
 +
<asm>
 +
; ---------------------------------------------------------------------------
 +
; Subroutine to change what you"re selecting in the level select
 +
; ---------------------------------------------------------------------------
 +
 +
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
 +
 +
 +
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_SndTest ; if time remains, branch
 +
 +
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_SndTest ; 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
 +
 +
LevSel_Down:
 +
btst #1,d1 ; is down pressed?
 +
beq.s LevSel_Refresh ; if not, branch
 +
addq.w #1,d0 ; move down 1 selection
 +
cmpi.w #$15,d0
 +
bcs.s LevSel_Refresh
 +
moveq #0,d0 ; if selection moves above $14, jump to selection 0
 +
 +
LevSel_Refresh:
 +
move.w d0,($FFFFFF82).w ; set new selection
 +
bsr.w LevSelTextLoad ; refresh text
 +
rts
 +
; ===========================================================================
 +
 +
LevSel_SndTest: ; XREF: LevSelControls
 +
cmpi.w #$14,($FFFFFF82).w ; is item $14 selected?
 +
bne.s LevSel_NoMove ; if not, branch
 +
move.b ($FFFFF605).w,d1
 +
andi.b #$C,d1 ; is left/right pressed?
 +
beq.s LevSel_NoMove ; if not, branch
 +
move.w ($FFFFFF84).w,d0
 +
btst #2,d1 ; is left pressed?
 +
beq.s LevSel_Right ; if not, branch
 +
subq.w #1,d0 ; subtract 1 from sound test
 +
bcc.s LevSel_Right
 +
moveq #$4F,d0 ; if sound test moves below 0, set to $4F
 +
 +
LevSel_Right:
 +
btst #3,d1 ; is right pressed?
 +
beq.s LevSel_Refresh2 ; if not, branch
 +
addq.w #1,d0 ; add 1 to sound test
 +
cmpi.w #$50,d0
 +
bcs.s LevSel_Refresh2
 +
moveq #0,d0 ; if sound test moves above $4F, set to 0
 +
 +
LevSel_Refresh2:
 +
move.w d0,($FFFFFF84).w ; set sound test number
 +
bsr.w LevSelTextLoad ; refresh text
 +
 +
LevSel_NoMove:
 +
rts
 +
; End of function LevSelControls
 +
 +
; ---------------------------------------------------------------------------
 +
; Subroutine to load level select text
 +
; ---------------------------------------------------------------------------
 +
 +
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
 +
 +
 +
LevSelTextLoad: ; XREF: TitleScreen
 +
lea (LevelMenuText).l,a1
 +
lea ($C00000).l,a6
 +
move.l #$62100003,d4 ; screen position (text)
 +
move.w #$E680,d3 ; VRAM setting
 +
moveq #$14,d1 ; number of lines of text
 +
 +
loc_34FE: ; XREF: LevSelTextLoad+26�j
 +
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
 +
lea (LevelMenuText).l,a1
 +
lsl.w #3,d1
 +
move.w d1,d0
 +
add.w d1,d1
 +
add.w d0,d1
 +
adda.w d1,a1
 +
move.w #$C680,d3
 +
move.l d4,4(a6)
 +
bsr.w LevSel_ChgLine
 +
move.w #$E680,d3
 +
cmpi.w #$14,($FFFFFF82).w
 +
bne.s loc_3550
 +
move.w #$C680,d3
 +
 +
loc_3550:
 +
move.l #$6C300003,($C00004).l ; screen position (sound test)
 +
move.w ($FFFFFF84).w,d0
 +
addi.w #$80,d0
 +
move.b d0,d2
 +
lsr.b #4,d0
 +
bsr.w LevSel_ChgSnd
 +
move.b d2,d0
 +
bsr.w LevSel_ChgSnd
 +
rts
 +
; End of function LevSelTextLoad
 +
 +
 +
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
 +
 +
 +
LevSel_ChgSnd: ; XREF: LevSelTextLoad
 +
andi.w #$F,d0
 +
cmpi.b #$A,d0
 +
bcs.s loc_3580
 +
addi.b #7,d0
 +
 +
loc_3580:
 +
add.w d3,d0
 +
move.w d0,(a6)
 +
rts
 +
; End of function LevSel_ChgSnd
 +
 +
 +
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
 +
 +
 +
LevSel_ChgLine: ; XREF: LevSelTextLoad
 +
moveq #$17,d2 ; number of characters per line
 +
 +
loc_3588:
 +
moveq #0,d0
 +
move.b (a1)+,d0
 +
bpl.s loc_3598
 +
move.w #0,(a6)
 +
dbf d2,loc_3588
 +
rts
 +
; ===========================================================================
 +
 +
loc_3598: ; XREF: LevSel_ChgLine
 +
add.w d3,d0
 +
move.w d0,(a6)
 +
dbf d2,loc_3588
 +
rts
 +
; End of function LevSel_ChgLine
 +
 +
; ===========================================================================
 +
; ---------------------------------------------------------------------------
 +
; Level select menu text
 +
; ---------------------------------------------------------------------------
 +
LevelMenuText: binclude misc/menutext.bin
 +
align 2
 +
</asm>
 +
in order to remove the old level select and make way for the new one.
 +
 +
==Add a new color Palette to replace the old one==
 +
This part is where we do it even better than Sega did, we will even replace the old palette:
 +
<asm>
 +
Pal_LevelSel: binclude pallet/levelsel.bin
 
</asm>
 
</asm>
  

Revision as of 09:37, 26 February 2011

You probably saw an old method of adding the sonic 2 level select to sonic 1 on SSRG by Esreal, well time we added it the exact same way Sonic 2 does it.

Edit the Main Game Mode Array

the main game mode array in sonic 1 does not have entries for the sonic 2 menu system, we will add them here.

main game loop

first we update the main game loop: <asm> MainGameLoop: move.b ($FFFFF600).w,d0 ; load Game Mode andi.w #$1C,d0 jsr GameModeArray(pc,d0.w) ; jump to apt location in ROM bra.s MainGameLoop </asm>

notice that $1C up there? that prevents us from adding new entries, Sonic 2 use $3C there, so we will update it to: <asm> MainGameLoop: move.b ($FFFFF600).w,d0 ; load Game Mode andi.w #$3C,d0 jsr GameModeArray(pc,d0.w) ; jump to apt location in ROM bra.s MainGameLoop </asm>

Main Game Mode Array

Yes, we can add the new game modes now, in Sonic 1 we have: <asm> bra.w SegaScreen ; Sega Screen ($00)

===========================================================================

bra.w TitleScreen ; Title Screen ($04)

===========================================================================

bra.w Level ; Demo Mode ($08)

===========================================================================

bra.w Level ; Normal Level ($0C)

===========================================================================

bra.w SpecialStage ; Special Stage ($10)

===========================================================================

bra.w ContinueScreen ; Continue Screen ($14)

===========================================================================

bra.w EndingSequence ; End of game sequence ($18)

===========================================================================

bra.w Credits ; Credits ($1C)

===========================================================================

rts

===========================================================================

</asm> the rts is meant to mark the end of the screen set. Lets look at the one in Sonic 2: <asm> GameModesArray: ;; bra.w SegaScreen ; $00 SEGA screen mode bra.w TitleScreen ; $04 Title screen mode bra.w Level ; $08 Demo mode bra.w Level ; $0C Zone play mode bra.w SpecialStage ; $10 Special stage play mode bra.w ContinueScreen ; $14 Continue mode bra.w TwoPlayerResults ; $18 2P results mode bra.w LevelSelectMenu2P ; $1C 2P level select mode bra.w JmpTo_EndingSequence ; $20 End sequence mode bra.w OptionsMenu ; $24 Options mode bra.w LevelSelectMenu ; $28 Level select mode

===========================================================================

</asm> the rts isnt there because the list cannot get as high as $3C and the normal locations for the screens, are at the credits and ending slots, that just wont do, so we will have them load from slots after the normal ones. Slots $20, $24, $28, and $2C are open, so we will make our changes: <asm> bra.w SegaScreen ; Sega Screen ($00)

===========================================================================

bra.w TitleScreen ; Title Screen ($04)

===========================================================================

bra.w Level ; Demo Mode ($08)

===========================================================================

bra.w Level ; Normal Level ($0C)

===========================================================================

bra.w SpecialStage ; Special Stage ($10)

===========================================================================

bra.w ContinueScreen ; Continue Screen ($14)

===========================================================================

bra.w EndingSequence ; End of game sequence ($18)

===========================================================================

bra.w Credits ; Credits ($1C)

===========================================================================

bra.w TwoPlayerResults ; 2 Player Results ($20)

===========================================================================

bra.w LevelSelectMenu2P ; 2 Player Level Select ($24)

===========================================================================

bra.w OptionsMenu ; Options Menu ($28)

===========================================================================

bra.w LevelSelectMenu ; Level Select ($2C)

===========================================================================

</asm>

Make changes to the Title Screen

this part probably isn't that big, remember what screen number we gave the level select? Now we get to set this in the title screen code so that it will load just like it does in sonic 2, sonic 3, s&k, sonic2k, and sonic3k, lets look at the offending code: <asm> Title_ChkLevSel: tst.b ($FFFFFFE0).w ; check if level select code is on beq.w PlayLevel ; if not, play level btst #6,($FFFFF604).w ; check if A is pressed beq.w PlayLevel ; if not, play level moveq #2,d0 bsr.w PalLoad2 ; load level select pallet lea ($FFFFCC00).w,a1 moveq #0,d0 move.w #$DF,d1

</asm> looks like checks for the cheat being active, but no screen change code, lets fix that. <asm> Title_ChkLevSel: tst.b ($FFFFFFE0).w ; check if level select code is on beq.w PlayLevel ; if not, play level btst #6,($FFFFF604).w ; check if A is pressed beq.w PlayLevel ; if not, play level move.b #$2C,($FFFFF600).w ; => LevelSelectMenu rts </asm> then we remove: <asm>

Title_ClrScroll: move.l d0,(a1)+ dbf d1,Title_ClrScroll ; fill scroll data with 0

move.l d0,($FFFFF616).w move #$2700,sr lea ($C00000).l,a6 move.l #$60000003,($C00004).l move.w #$3FF,d1

Title_ClrVram: move.l d0,(a6) dbf d1,Title_ClrVram ; fill VRAM with 0

bsr.w LevSelTextLoad

---------------------------------------------------------------------------
Level Select
---------------------------------------------------------------------------

LevelSelect: move.b #4,($FFFFF62A).w bsr.w DelayProgram bsr.w LevSelControls bsr.w RunPLC_RAM tst.l ($FFFFF680).w bne.s LevelSelect andi.b #$F0,($FFFFF605).w ; is A, B, C, or Start pressed? beq.s LevelSelect ; if not, branch move.w ($FFFFFF82).w,d0 cmpi.w #$14,d0 ; have you selected item $14 (sound test)? bne.s LevSel_Level_SS ; if not, go to Level/SS subroutine move.w ($FFFFFF84).w,d0 addi.w #$80,d0 tst.b ($FFFFFFE3).w ; is Japanese Credits cheat on? beq.s LevSel_NoCheat ; if not, branch cmpi.w #$9F,d0 ; is sound $9F being played? beq.s LevSel_Ending ; if yes, branch cmpi.w #$9E,d0 ; is sound $9E being played? beq.s LevSel_Credits ; if yes, branch

LevSel_NoCheat: cmpi.w #$94,d0 ; is sound $80-$94 being played? bcs.s LevSel_PlaySnd ; if yes, branch cmpi.w #$A0,d0 ; is sound $95-$A0 being played? bcs.s LevelSelect ; if yes, branch

LevSel_PlaySnd: bsr.w PlaySound_Special bra.s LevelSelect

===========================================================================

LevSel_Ending: ; XREF: LevelSelect move.b #$18,($FFFFF600).w ; set screen mode to $18 (Ending) move.w #$600,($FFFFFE10).w ; set level to 0600 (Ending) rts

===========================================================================

LevSel_Credits: ; XREF: LevelSelect move.b #$1C,($FFFFF600).w ; set screen mode to $1C (Credits) move.b #$26,d0 bsr.w PlaySound_Special ; play credits music move.w #0,($FFFFFFF4).w rts

===========================================================================

LevSel_Level_SS: ; XREF: LevelSelect add.w d0,d0 move.w LSelectPointers(pc,d0.w),d0 ; load level number bmi.w LevelSelect cmpi.w #$700,d0 ; check if level is 0700 (Special Stage) bne.s LevSel_Level ; if not, branch move.b #$10,($FFFFF600).w ; set screen mode to $10 (Special Stage) clr.w ($FFFFFE10).w ; clear level move.b #3,($FFFFFE12).w ; set lives to 3 moveq #0,d0 move.w d0,($FFFFFE20).w ; clear rings move.l d0,($FFFFFE22).w ; clear time move.l d0,($FFFFFE26).w ; clear score rts

===========================================================================

LevSel_Level: ; XREF: LevSel_Level_SS andi.w #$3FFF,d0 move.w d0,($FFFFFE10).w ; set level number

PlayLevel: ; XREF: ROM:00003246�j ... move.b #$C,($FFFFF600).w ; set screen mode to $0C (level) move.b #3,($FFFFFE12).w ; set lives to 3 moveq #0,d0 move.w d0,($FFFFFE20).w ; clear rings move.l d0,($FFFFFE22).w ; clear time move.l d0,($FFFFFE26).w ; clear score move.b d0,($FFFFFE16).w ; clear special stage number move.b d0,($FFFFFE57).w ; clear emeralds move.l d0,($FFFFFE58).w ; clear emeralds move.l d0,($FFFFFE5C).w ; clear emeralds move.b d0,($FFFFFE18).w ; clear continues move.b #$E1,d0 bsr.w PlaySound_Special ; fade out music rts

===========================================================================
---------------------------------------------------------------------------
Level select - level pointers
---------------------------------------------------------------------------

LSelectPointers: binclude misc/ls_point.bin align 2

---------------------------------------------------------------------------
Level select codes
---------------------------------------------------------------------------

LevelSelectCode_J: binclude misc/ls_jcode.bin align 2

LevelSelectCode_US: binclude misc/ls_ucode.bin align 2

===========================================================================

</asm>

and finally remove this: <asm>

---------------------------------------------------------------------------
Subroutine to change what you"re selecting in the level select
---------------------------------------------------------------------------
||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||


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_SndTest ; if time remains, branch

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_SndTest ; 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

LevSel_Down: btst #1,d1 ; is down pressed? beq.s LevSel_Refresh ; if not, branch addq.w #1,d0 ; move down 1 selection cmpi.w #$15,d0 bcs.s LevSel_Refresh moveq #0,d0 ; if selection moves above $14, jump to selection 0

LevSel_Refresh: move.w d0,($FFFFFF82).w ; set new selection bsr.w LevSelTextLoad ; refresh text rts

===========================================================================

LevSel_SndTest: ; XREF: LevSelControls cmpi.w #$14,($FFFFFF82).w ; is item $14 selected? bne.s LevSel_NoMove ; if not, branch move.b ($FFFFF605).w,d1 andi.b #$C,d1 ; is left/right pressed? beq.s LevSel_NoMove ; if not, branch move.w ($FFFFFF84).w,d0 btst #2,d1 ; is left pressed? beq.s LevSel_Right ; if not, branch subq.w #1,d0 ; subtract 1 from sound test bcc.s LevSel_Right moveq #$4F,d0 ; if sound test moves below 0, set to $4F

LevSel_Right: btst #3,d1 ; is right pressed? beq.s LevSel_Refresh2 ; if not, branch addq.w #1,d0 ; add 1 to sound test cmpi.w #$50,d0 bcs.s LevSel_Refresh2 moveq #0,d0 ; if sound test moves above $4F, set to 0

LevSel_Refresh2: move.w d0,($FFFFFF84).w ; set sound test number bsr.w LevSelTextLoad ; refresh text

LevSel_NoMove: rts

End of function LevSelControls
---------------------------------------------------------------------------
Subroutine to load level select text
---------------------------------------------------------------------------
||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||


LevSelTextLoad: ; XREF: TitleScreen lea (LevelMenuText).l,a1 lea ($C00000).l,a6 move.l #$62100003,d4 ; screen position (text) move.w #$E680,d3 ; VRAM setting moveq #$14,d1 ; number of lines of text

loc_34FE: ; XREF: LevSelTextLoad+26�j 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 lea (LevelMenuText).l,a1 lsl.w #3,d1 move.w d1,d0 add.w d1,d1 add.w d0,d1 adda.w d1,a1 move.w #$C680,d3 move.l d4,4(a6) bsr.w LevSel_ChgLine move.w #$E680,d3 cmpi.w #$14,($FFFFFF82).w bne.s loc_3550 move.w #$C680,d3

loc_3550: move.l #$6C300003,($C00004).l ; screen position (sound test) move.w ($FFFFFF84).w,d0 addi.w #$80,d0 move.b d0,d2 lsr.b #4,d0 bsr.w LevSel_ChgSnd move.b d2,d0 bsr.w LevSel_ChgSnd rts

End of function LevSelTextLoad


||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||


LevSel_ChgSnd: ; XREF: LevSelTextLoad andi.w #$F,d0 cmpi.b #$A,d0 bcs.s loc_3580 addi.b #7,d0

loc_3580: add.w d3,d0 move.w d0,(a6) rts

End of function LevSel_ChgSnd


||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||


LevSel_ChgLine: ; XREF: LevSelTextLoad moveq #$17,d2 ; number of characters per line

loc_3588: moveq #0,d0 move.b (a1)+,d0 bpl.s loc_3598 move.w #0,(a6) dbf d2,loc_3588 rts

===========================================================================

loc_3598: ; XREF: LevSel_ChgLine add.w d3,d0 move.w d0,(a6) dbf d2,loc_3588 rts

End of function LevSel_ChgLine
===========================================================================
---------------------------------------------------------------------------
Level select menu text
---------------------------------------------------------------------------

LevelMenuText: binclude misc/menutext.bin align 2 </asm> in order to remove the old level select and make way for the new one.

Add a new color Palette to replace the old one

This part is where we do it even better than Sega did, we will even replace the old palette: <asm> Pal_LevelSel: binclude pallet/levelsel.bin </asm>

Insert the new screens for Level Select, Options, and 2 Player VS