Different songs EVERYWHERE [Sonic 1 / Hivebrain 2006]

Discussion in 'Tutorials Archive' started by nineko, Nov 18, 2013.

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

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    So, some years ago I came up with a very rudimentary implementation of "different songs in different acts" for Sonic 1, and I did the mistake to post it as it was; I later refined it a lot for my own hack, and I never went back to post the improved version. I'll do that now. With this guide you will be able to have:

    • a different song in each act of each zone;
    • a different song for each boss;
    • a different song for each special stage;
    • a different song for the good and bad credits;
    • a different song for the good and bad mini-GHZ at the end;
    • a different song for each note monitor (actually let's scrap this point since you don't have them in your hack);
    • it also implies that you use a song for the Speed Shoes rather than the default speed-up, and it allows you to have an even different song for Invincibility + Speed Shoes at the same time (either obtained by a working "S" monitor or simply by collecting an Invincibility monitor and a Speed Shoes monitor within the time limits);
    • it will also fix the bug with drowning countdown and invincibility music in Labyrinth Zone as a side effect.
    Before you follow this guide, I highly recommend you to apply one of the methods which allow you to have more song slots, or you'll run into a paradox where you can choose different songs but you don't actually have them available. I won't recommend you to make a backup, because if you aren't smart enough to make a backup without me telling you to do so you deserve to lose all your work and suffer eternal pain. And yes, I like to write words in italics for no reason at all.

    One last note: you can't apply this guide on top of the previous one, since I didn't keep track of the differences between them, so I'll be writing this by comparing the soniNeko disassembly with a clean one in real time while I type it, and I hope I can find all the things to edit, since I did this 5 years ago and I forgot many things. My fault for being lazy back then.


    Summary:

    I'm sorry if I made multiple posts in a row, but IPB is retarded and it likes to destroy CODE boxes when an edit is made, so I preferred to work on smaller posts.
     
    Last edited by a moderator: Nov 19, 2013
  2. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    Step 1: we have more playlists now!


    Find:

    ; ---------------------------------------------------------------------------
    ; Music to play after invincibility wears off
    ; ---------------------------------------------------------------------------
    MusicList2: incbin miscmuslist2.bin
    even
    ; ===========================================================================
    And delete it.

    Find:

    Code:
    ; ---------------------------------------------------------------------------
    ; Music	playlist
    ; ---------------------------------------------------------------------------
    MusicList:	incbin	miscmuslist1.bin
    		even
    ; ===========================================================================
    
    And change it to:
    Code:
    ; ---------------------------------------------------------------------------
    ; Music	playlist
    ; ---------------------------------------------------------------------------
    MusicList1:	incbin	soundmuslist1.bin
    		even
    MusicList2:	incbin	soundmuslist2.bin
    		even
    MusicList3:	incbin	soundmuslist3.bin
    		even
    MusicList4:	incbin	soundmuslist4.bin
    		even
    MusicList5:	incbin	soundmuslist5.bin
    		even
    MusicList6:	incbin	soundmuslist6.bin
    		even
    MusicList7:	incbin	soundmuslist7.bin
    		even
    MusicList8:	incbin	soundmuslist8.bin
    		even
    ; ===========================================================================
    
    The first 4 playlists will now refer to the 4 acts of each zone; 5 is for the Special Stages, 6 is for the Credits, 7 is for the mini-GHZ ending, 8 is for the bosses. I have a 9th playlist in my hack, but as I said I'm not going to cover note monitors here since you don't have them.
     
  3. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    Step 2: the Level_GetBgm routine


    Find:

    Code:
    Level_GetBgm:
    		tst.w	($FFFFFFF0).w
    		bmi.s	loc_3946
    		moveq	#0,d0
    		move.b	($FFFFFE10).w,d0
    		cmpi.w	#$103,($FFFFFE10).w ; is level SBZ3?
    		bne.s	Level_BgmNotLZ4	; if not, branch
    		moveq	#5,d0		; move 5 to d0
    
    Level_BgmNotLZ4:
    		cmpi.w	#$502,($FFFFFE10).w ; is level FZ?
    		bne.s	Level_PlayBgm	; if not, branch
    		moveq	#6,d0		; move 6 to d0
    
    Level_PlayBgm:
    		lea	(MusicList).l,a1 ; load	music playlist
    		move.b	(a1,d0.w),d0	; add d0 to a1
    		bsr.w	PlaySound	; play music
    		move.b	#$34,($FFFFD080).w ; load title	card object
    Replace it with:
    Code:
    Level_GetBgm:
    		tst.w	($FFFFFFF0).w
    		bmi.w	loc_3946		; change bmi.s to bmi.w or it won't work!
    		moveq	#0,d0
    		move.b	($FFFFFE10).w,d0
    
    		cmpi.b	#$0,($FFFFFE11).w	; is this act 1?
    		bne.s	Level_GetBgm2	; if not, branch
    		lea	(MusicList1).l,a1	; load Music Playlist for Acts 1
    		bra.s	Level_PlayBgm	; go to PlayBgm
    
    Level_GetBgm2:
    		cmpi.b	#$1,($FFFFFE11).w	; is this act 2?
    		bne.s	Level_GetBgm3	; if not, branch
    		lea	(MusicList2).l,a1	; load Music Playlist for Acts 2
    		bra.s	Level_PlayBgm	; go to PlayBgm
    
    Level_GetBgm3:
    		cmpi.b	#$2,($FFFFFE11).w	; is this act 3?
    		bne.s	Level_GetBgm4	; if not, branch
    		lea	(MusicList3).l,a1	; load Music Playlist for Acts 3
    		bra.s	Level_PlayBgm	; go to PlayBgm
    
    Level_GetBgm4:
    		lea	(MusicList4).l,a1	; load Music Playlist for Acts 4
    
    Level_PlayBgm:
    		move.b	(a1,d0.w),d0	; get d0-th entry from the playlist
    		move.b	d0,($FFFFFFFE).w	; put music number in RAM for later use
    		bsr.w	PlaySound	; play music
    		move.b	#$34,($FFFFD080).w ; load title	card object
    The comments are a bit outdated, now I know what lea actually does. It loads the address of a particular music list, and then d0 is used to pick the correct entry. This code is quite simple and it looks almost like the old version, but there's a new thing: look at this line:
    Code:
    move.b	d0,($FFFFFFFE).w	; put music number in RAM for later use
    In this way, the song being currently played is stored in a RAM address. $FFFFFFFE is usually usable since it's only used for the checksum check and never touched again.
     
    Last edited by a moderator: Nov 19, 2013
  4. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    Step 3: Invincibility and Speed Shoes


    Find:

    Obj2E_ChkShoes:
    cmpi.b #3,d0 ; does monitor contain speed shoes?
    bne.s Obj2E_ChkShield
    move.b #1,($FFFFFE2E).w ; speed up the BG music
    move.w #$4B0,($FFFFD034).w ; time limit for the power-up
    move.w #$C00,($FFFFF760).w ; change Sonic's top speed
    move.w #$18,($FFFFF762).w
    move.w #$80,($FFFFF764).w
    move.w #$E2,d0
    jmp (PlaySound).l ; Speed up the music
    ; ===========================================================================Replace it with:
    Code:
    Obj2E_ChkShoes:
    		cmpi.b	#3,d0		; does monitor contain speed shoes?
    		bne.s	Obj2E_ChkShield
    		move.w	#$4B0,($FFFFD034).w ; time limit for the power-up
    
    		cmpi.b	#$1,($FFFFFE2E).w	; am I already speed shoe'd?
    		beq.s	Obj2E_NoMusic2	; if so, branch
    
    		move.b	#1,($FFFFFE2E).w ; speed up the	BG music
    		move.w	#$C00,($FFFFF760).w ; change Sonic's top speed
    		move.w	#$18,($FFFFF762).w
    		move.w	#$80,($FFFFF764).w
    
    		cmpi.b	#$1,($FFFFFE2D).w	; do I also have invincibility?
    		bne.b	Obj2E_spd_only	; if I don't then play regular speed shoes music
    		move.w	#$F2,d0		; if I do, then play awesome music
    		bra.b	Obj2E_spd_play
    Obj2E_spd_only:
    		move.w	#$FB,d0
    Obj2E_spd_play:
    		jmp	(PlaySound).l	; Speed	up the music
    ; ===========================================================================
    Obj2E_NoMusic2:
    		rts
    Please note that there are two things to edit here: $FB is the song I used for the Speed Shoes, but you're likely to want to use a different ID there; likewise, $F2 is the song I used for Speed Shoes + Invincibility, but maybe you don't even have that one. Note the nice Obj2E_NoMusic2 label: in this way, if you collect another monitor with Speed Shoes while the first one didn't wear off yet, the music won't restart playing, but it will simply keep on playing, with the Speed Shoes timer reset to 20 seconds (yes, reset to, not increased by; you can change this behaviour by fiddling with a specific move.w, I won't tell you how, anyway).

    Now, find:

    Obj2E_ChkInvinc:
    cmpi.b #5,d0 ; does monitor contain invincibility?
    bne.s Obj2E_ChkRings
    move.b #1,($FFFFFE2D).w ; make Sonic invincible
    move.w #$4B0,($FFFFD032).w ; time limit for the power-up
    move.b #$38,($FFFFD200).w ; load stars object ($3801)
    move.b #1,($FFFFD21C).w
    move.b #$38,($FFFFD240).w ; load stars object ($3802)
    move.b #2,($FFFFD25C).w
    move.b #$38,($FFFFD280).w ; load stars object ($3803)
    move.b #3,($FFFFD29C).w
    move.b #$38,($FFFFD2C0).w ; load stars object ($3804)
    move.b #4,($FFFFD2DC).w
    tst.b ($FFFFF7AA).w ; is boss mode on?
    bne.s Obj2E_NoMusic ; if yes, branch
    move.w #$87,d0
    jmp (PlaySound).l ; play invincibility music
    ; ===========================================================================Replace it with:
    Code:
    Obj2E_ChkInvinc:
    		cmpi.b	#5,d0		; does monitor contain invincibility?
    		bne.w	Obj2E_ChkRings
    		move.w	#$4B0,($FFFFD032).w ; time limit for the power-up
    
    		cmpi.b	#$1,($FFFFFE2D).w	; am I already invincible?
    		beq.s	Obj2E_NoMusic	; if so, branch
    
    		move.b	#1,($FFFFFE2D).w ; make	Sonic invincible
    
    		move.b	#$38,($FFFFD200).w ; load stars	object ($3801)
    		move.b	#1,($FFFFD21C).w
    		move.b	#$38,($FFFFD240).w ; load stars	object ($3802)
    		move.b	#2,($FFFFD25C).w
    		move.b	#$38,($FFFFD280).w ; load stars	object ($3803)
    		move.b	#3,($FFFFD29C).w
    		move.b	#$38,($FFFFD2C0).w ; load stars	object ($3804)
    		move.b	#4,($FFFFD2DC).w
    		tst.b	($FFFFF7AA).w	; is boss mode on?
    		bne.s	Obj2E_NoMusic	; if yes, branch
    
    		cmpi.b	#$1,($FFFFFE10).w	; is this Labyrinth?
    		bne.s	NotLZinv	; if not, branch
    		move.w	($FFFFFE14).w,d0 ; check air remaining
    		cmpi.w	#$C,d0
    		bhi.s	NotLZinv	; if air is above $C, branch
    		bra.s	Obj2E_NoMusic
    
    NotLZinv:
    		cmpi.b	#$1,($FFFFFE2E).w	; do I also have speed shoes?
    		bne.b	Obj2E_inv_only	; if I don't then play regular invincibility music
    		move.w	#$F2,d0		; if I do, then play awesome music
    		bra.b	Obj2E_inv_play
    Obj2E_inv_only:
    		move.w	#$87,d0
    Obj2E_inv_play:
    		jmp	(PlaySound).l	; play invincibility music
    ; ===========================================================================
    Things to note:
    • like the Speed Shoes, this code will keep on playing the Invincibility music if you collect a second monitor while the first one isn't worn off yet (it's easy to test that in GHZ1, for example);
    • it won't start the invincibility music if your air is below $C (e.g. the countdown jingle is playing);
    • $87 is the music ID for Invincibility only, and $F2 is still the music ID for Invincibility + Speed Shoes: fix those IDs accordingly.

    Now, let's take care of them when they wear off, shall we?


    Find:

    Code:
    Obj01_ChkInvin:
    		tst.b	($FFFFFE2D).w	; does Sonic have invincibility?
    		beq.s	Obj01_ChkShoes	; if not, branch
    		tst.w	$32(a0)		; check	time remaining for invinciblity
    		beq.s	Obj01_ChkShoes	; if no	time remains, branch
    		subq.w	#1,$32(a0)	; subtract 1 from time
    		bne.s	Obj01_ChkShoes
    		tst.b	($FFFFF7AA).w
    		bne.s	Obj01_RmvInvin
    		cmpi.w	#$C,($FFFFFE14).w
    		bcs.s	Obj01_RmvInvin
    		moveq	#0,d0
    		move.b	($FFFFFE10).w,d0
    		cmpi.w	#$103,($FFFFFE10).w ; check if level is	SBZ3
    		bne.s	Obj01_PlayMusic
    		moveq	#5,d0		; play SBZ music
    
    Obj01_PlayMusic:
    		lea	(MusicList2).l,a1
    		move.b	(a1,d0.w),d0
    		jsr	(PlaySound).l	; play normal music
    
    Obj01_RmvInvin:
    		move.b	#0,($FFFFFE2D).w ; cancel invincibility
    
    Obj01_ChkShoes:
    		tst.b	($FFFFFE2E).w	; does Sonic have speed	shoes?
    		beq.s	Obj01_ExitChk	; if not, branch
    		tst.w	$34(a0)		; check	time remaining
    		beq.s	Obj01_ExitChk
    		subq.w	#1,$34(a0)	; subtract 1 from time
    		bne.s	Obj01_ExitChk
    		move.w	#$600,($FFFFF760).w ; restore Sonic's speed
    		move.w	#$C,($FFFFF762).w ; restore Sonic's acceleration
    		move.w	#$80,($FFFFF764).w ; restore Sonic's deceleration
    		move.b	#0,($FFFFFE2E).w ; cancel speed	shoes
    		move.w	#$E3,d0
    		jmp	(PlaySound).l	; run music at normal speed
    ; ===========================================================================
    
    Obj01_ExitChk:
    		rts
    Replace it with:
    Code:
    Obj01_ChkInvin:
    		tst.b	($FFFFFE2D).w	; does Sonic have invincibility?
    		beq.s	Obj01_ChkShoes	; if not, branch
    		tst.w	$32(a0)		; check	time remaining for invinciblity
    		beq.s	Obj01_ChkShoes	; if no	time remains, branch
    		subq.w	#1,$32(a0)	; subtract 1 from time
    		bne.b	Obj01_ChkShoes
    		cmpi.b	#$1,($FFFFFFFF).w	; boss
    		beq.b	Obj01_RmvInvin
    		cmpi.w	#$C,($FFFFFE14).w	; underwater
    		bcs.b	Obj01_RmvInvin
    
    		cmpi.b	#$1,($FFFFFE2E).w	; does Sonic have speed shoes?
    		bne.s	Obj01_Load_inv	; if no, branch, and load regular stage music
    		move.b	#$FB,d0		; if yes, load regular speed shoes music
    		bra.b	Obj01_Play_inv
    Obj01_Load_inv
    		move.b	$FFFFFFFE,d0	; loads song number from RAM
    Obj01_Play_inv:
    		jsr	(PlaySound).l	; play normal music
    
    Obj01_RmvInvin:
    		move.b	#0,($FFFFFE2D).w ; cancel invincibility
    
    Obj01_ChkShoes:
    		tst.b	($FFFFFE2E).w	; does Sonic have speed	shoes?
    		beq.s	Obj01_ExitChk	; if not, branch
    		tst.w	$34(a0)		; check	time remaining
    		beq.s	Obj01_ExitChk
    		subq.w	#1,$34(a0)	; subtract 1 from time
    		bne.s	Obj01_ExitChk
    		move.w	#$600,($FFFFF760).w ; restore Sonic's speed
    		move.w	#$C,($FFFFF762).w ; restore Sonic's acceleration
    		move.w	#$80,($FFFFF764).w ; restore Sonic's deceleration
    		move.b	#0,($FFFFFE2E).w ; cancel speed	shoes
    
    		cmpi.b	#$1,($FFFFFFFF).w	; boss
    		beq.b	Obj01_ExitChk
    
    		cmpi.b	#$1,($FFFFFE2D).w	; does Sonic have invincibility?
    		bne.s	Obj01_Load_spd	; if no, branch, and load regular stage music
    		move.b	#$87,d0		; if yes, load regular invincibility music
    		bra.b	Obj01_Play_spd
    Obj01_Load_spd:
    		move.b	$FFFFFFFE,d0	; loads song number from RAM
    Obj01_Play_spd:
    		jmp	(PlaySound).l	; run music at normal speed
    ; ===========================================================================
    
    Obj01_ExitChk:
    		rts
    The new code is quite more complex, as it takes more cases into account. Please note that $F2 and $87 are still the separate song IDs for Speed Shoes and Invincibility respectively, so you'll have to change them. Note the introduction of a new RAM address, $FFFFFFFF, which is used to store a boss flag (I'll explain that soon). Also note how $FFFFFFFE is used, avoiding the need to redo all those zone/act checks. I will handle the ResumeMusic routine (the one used when the drowning music is canceled) in a later step.
     
  5. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    Step 4: the Boss music


    Ok, this is boring. Find the FIVE instances of:


    move.w #$8C,d0
    bsr.w PlaySound ; play boss musicReplace them ALL with:
    Code:
    		move.b	($FFFFFE10).w,d0	; set boss number
    		lea	(MusicList8).l,a1	; load Music Playlist for bosses
    		move.b	(a1,d0.w),d0	; get d0-th entry from the playlist
    		bsr.w	PlaySound	; play boss music
    		move.b	#1,($FFFFFFFF).w	; set boss flag
    Keep whatever there is above and below (typically stuff which involves $FFFFF742 and $FFFFF7AA).

    Now, this is even more boring. Find these 5 things:

    Code:
    loc_179E0:
    		clr.w	$12(a0)
    		move.w	#$81,d0
    		jsr	(PlaySound).l	; play GHZ music
    Code:
    loc_18112:
    		move.w	#$82,d0
    		jsr	(PlaySound).l	; play LZ music
    		bset	#0,$22(a0)
    		addq.b	#2,$25(a0)
    Code:
    loc_1856C:
    		clr.w	$12(a0)
    		move.w	#$83,d0
    		jsr	(PlaySound).l	; play MZ music
    Code:
    loc_18BB4:
    		clr.w	$12(a0)
    		move.w	#$84,d0
    		jsr	(PlaySound).l	; play SLZ music
    Code:
    loc_194E0:
    		clr.w	$12(a0)
    		move.w	#$85,d0
    		jsr	(PlaySound).l	; play SYZ music
    Replace them, respectively, with:
    Code:
    loc_179E0:
    		clr.w	$12(a0)
    		
    		clr.w	d0
    		move.b	d0,$FFFFFFFF	; clear Boss flag
    		cmpi.b	#$1,($FFFFFE2D).w	; does Sonic have invincibility?
    		beq.b	loc_179E0_inv 	; if yes, load invincibility music
    		cmpi.b	#$1,($FFFFFE2E).w	; does Sonic have speed shoes?
    		beq.b	loc_179E0_speed	; if yes, load speed shoes music
    
    		move.b	$FFFFFFFE,d0	; loads music from RAM
    		bra.s	loc_179E0_play
    
    loc_179E0_speed:
    		move.b	#$FB,d0
    		bra.s	loc_179E0_play
    loc_179E0_inv:
    		cmpi.b	#$1,($FFFFFE2E).w	; does Sonic have also speed shoes?
    		beq.s	loc_179E0_inv_and_speed
    		move.b	#$87,d0
    		bra.s	loc_179E0_play
    loc_179E0_inv_and_speed:
    		move.b	#$F2,d0
    loc_179E0_play:
    		jsr	(PlaySound).l	; play some music
    Code:
    loc_18112:
    		clr.w	d0
    		move.b	d0,$FFFFFFFF	; clear Boss flag
    
    		cmpi.b	#$1,($FFFFFE2D).w	; does Sonic have invincibility?
    		beq.b	loc_18112_inv 	; if yes, load invincibility music
    		cmpi.b	#$1,($FFFFFE2E).w	; does Sonic have speed shoes?
    		beq.b	loc_18112_speed	; if yes, load speed shoes music
    		move.b	$FFFFFFFE,d0	; loads music from RAM
    		bra.s	loc_18112_play
    loc_18112_speed:
    		move.b	#$FB,d0
    		bra.s	loc_18112_play
    loc_18112_inv:
    		cmpi.b	#$1,($FFFFFE2E).w	; does Sonic have also speed shoes?
    		beq.s	loc_18112_inv_and_speed
    		move.b	#$87,d0
    		bra.s	loc_18112_play
    loc_18112_inv_and_speed:
    		move.b	#$F2,d0
    loc_18112_play:
    		jsr	(PlaySound).l	; play some music
    		bset	#0,$22(a0)
    		addq.b	#2,$25(a0)
    Code:
    loc_1856C:
    		clr.w	$12(a0)
    		clr.w	d0
    		move.b	d0,$FFFFFFFF	; clear Boss flag
    		cmpi.b	#$1,($FFFFFE2D).w	; does Sonic have invincibility?
    		beq.b	loc_1856C_inv 	; if yes, load invincibility music
    		cmpi.b	#$1,($FFFFFE2E).w	; does Sonic have speed shoes?
    		beq.b	loc_1856C_speed	; if yes, load speed shoes music
    		move.b	$FFFFFFFE,d0	; loads music from RAM
    		bra.s	loc_1856C_play
    loc_1856C_speed:
    		move.b	#$FB,d0
    		bra.s	loc_1856C_play
    loc_1856C_inv:
    		cmpi.b	#$1,($FFFFFE2E).w	; does Sonic have also speed shoes?
    		beq.s	loc_1856C_inv_and_speed
    		move.b	#$87,d0
    		bra.s	loc_1856C_play
    loc_1856C_inv_and_speed:
    		move.b	#$F2,d0
    loc_1856C_play:
    		jsr	(PlaySound).l	; play some music
    Code:
    loc_18BB4:
    		clr.w	$12(a0)
    		clr.w	d0
    		move.b	d0,$FFFFFFFF	; clear Boss flag
    		cmpi.b	#$1,($FFFFFE2D).w	; does Sonic have invincibility?
    		beq.b	loc_18BB4_inv 	; if yes, load invincibility music
    		cmpi.b	#$1,($FFFFFE2E).w	; does Sonic have speed shoes?
    		beq.b	loc_18BB4_speed	; if yes, load speed shoes music
    		move.b	$FFFFFFFE,d0	; loads music from RAM
    		bra.s	loc_18BB4_play
    loc_18BB4_speed:
    		move.b	#$FB,d0
    		bra.s	loc_18BB4_play
    loc_18BB4_inv:
    		cmpi.b	#$1,($FFFFFE2E).w	; does Sonic have also speed shoes?
    		beq.s	loc_18BB4_inv_and_speed
    		move.b	#$87,d0
    		bra.s	loc_18BB4_play
    loc_18BB4_inv_and_speed:
    		move.b	#$F2,d0
    loc_18BB4_play:
    		jsr	(PlaySound).l	; play some music
    Code:
    loc_194E0:
    		clr.w	$12(a0)
    		clr.w	d0
    		move.b	d0,$FFFFFFFF	; clear Boss flag
    		cmpi.b	#$1,($FFFFFE2D).w	; does Sonic have invincibility?
    		beq.b	loc_194E0_inv 	; if yes, load invincibility music
    		cmpi.b	#$1,($FFFFFE2E).w	; does Sonic have speed shoes?
    		beq.b	loc_194E0_speed	; if yes, load speed shoes music
    		move.b	$FFFFFFFE,d0	; loads music from RAM
    		bra.s	loc_194E0_play
    loc_194E0_speed:
    		move.b	#$FB,d0
    		bra.s	loc_194E0_play
    loc_194E0_inv:
    		cmpi.b	#$1,($FFFFFE2E).w	; does Sonic have also speed shoes?
    		beq.s	loc_194E0_inv_and_speed
    		move.b	#$87,d0
    		bra.s	loc_194E0_play
    loc_194E0_inv_and_speed:
    		move.b	#$F2,d0
    loc_194E0_play:
    		jsr	(PlaySound).l	; play some music
    All this code ensures that the correct song is played after a boss is defeated; also, Invincibility and/or Speed Shoes songs are restored instead. I understand that this step is long and boring, but it's unavoidable. Of course, the meaning of $F2, $FB, and $87, is still the same from the previous steps. The Speed Shoes check in LZ can be probably removed, but it's there for consistency.
     
    Last edited by a moderator: Nov 19, 2013
  6. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    Step 5: «oh fuck oh fuck air bubble air bubble»


    I wanted to take care of the boss music in the previous step, to introduce the concept of Playlist 8. Now the replacement below will make much more sense.


    Find:

    ResumeMusic: ; XREF: Obj64_Wobble; Sonic_Water; Obj0A_ReduceAir
    cmpi.w #$C,($FFFFFE14).w
    bhi.s loc_140AC
    move.w #$82,d0 ; play LZ music
    cmpi.w #$103,($FFFFFE10).w ; check if level is 0103 (SBZ3)
    bne.s loc_140A6
    move.w #$86,d0 ; play SBZ music

    loc_140A6:
    jsr (PlaySound).lReplace it with:
    Code:
    ResumeMusic:				; XREF: Obj64_Wobble; Sonic_Water; Obj0A_ReduceAir
    		cmpi.w	#$C,($FFFFFE14).w
    		bhi.b	loc_140AC
    
    		cmpi.b	#$1,($FFFFFFFF).w	; am I fighting the boss?
    		bne.s	NotBoss	; if not, branch
    		move.b	($FFFFFE10).w,d0	; set boss number
    		lea	(MusicList8).l,a1	; load Music Playlist for bosses
    		move.b	(a1,d0.w),d0	; get d0-th entry from the playlist
    		bra.s	loc_140A6
    
    NotBoss:
    		cmpi.b	#$1,($FFFFFE2D).w	; am I invincible?
    		bne.s	NotInv	; if not, branch
    		move.b	#$87,d0
    		bra.s	loc_140A6
    
    NotInv:
    		move.b	$FFFFFFFE,d0	; loads song number from RAM
    loc_140A6:
    		jsr	(PlaySound).l
    Look at the magic of $FFFFFFFE. Once again, no need to recheck zone and act: the correct song ID will always be there. Playlist 8 is used to play the boss song if you breathe while fighting the LZ boss, and invincibility is checked, to play the appropriate song instead of the level theme (but it's checked after the Boss is checked (via $FFFFFFFF), since I give priority to the Boss music). Again, replace $87 with another ID if you used another song for invincibility in your hack. Speed Shoes aren't checked because they shouldn't exist in Labyrinth Zone. Feel free to improve this code if you applied the guide which properly handle Speed Shoes in water levels -- it's only a matter of adding a couple of checks.

    This step was simple, wasn't it?
     
    Last edited by a moderator: Nov 19, 2013
  7. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    Step 6: Special Stages


    Find these two lines:

    Code:
    		move.w	#$89,d0
    		bsr.w	PlaySound	; play special stage BG	music
    Things are about to get MUCH beefier. Replace them with:
    Code:
    		moveq	#0,d0
    		move.b	($FFFFFE16).w,d0
    		cmpi.b	#$0,d0
    		bne.b SS_Num_Not_Zero
    		move.b	#$6,d0
    
    SS_Num_Not_Zero:
    		subi.w	#$1,d0
    
    		lea	(MusicList5).l,a1 ; load Music Playlist for Special Stages
    		move.b	(a1,d0.w),d0 ; get d0-th entry from the playlist
    		bsr.w	PlaySound	; play special stage BG	music
    This code takes the Special Stage number -1, don't ask me why, but it works in this way.
     
    Last edited by a moderator: Nov 19, 2013
  8. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    Step 7: ending and credits


    If you want, you can have different songs to play in the mini-GHZ at the end, as well as during the Staff Roll, depending if you collected the 6 chaos emeralds or not.


    Find:


    move.w #$600,($FFFFFE10).w ; set level number to 0600 (extra flowers)Below that line, add:
    Code:
    		move.b	#$0,($FFFFFFFD).w	; puts a 0 in this flag
    Find:
    Code:
    		move.w	#$601,($FFFFFE10).w ; set level	number to 0601 (no flowers)
    Below that line, add:
    Code:
    		move.b	#$1,($FFFFFFFD).w	; puts a 1 in this flag
    In this way, a new flag is created, at (usually unused) RAM address $FFFFFFFD. 0 means good ending, 1 means bad ending.

    Find:

    Code:
    		move.w	#$8B,d0
    		bsr.w	PlaySound	; play ending sequence music
    Replace it with:
    Code:
    		move.b	($FFFFFFFD).w,d0
    		lea	(MusicList7).l,a1 ; load Music Playlist for Endings
    		move.b	(a1,d0.w),d0 ; get d0-th entry from the playlist
    Find:
    Code:
    		move.b	#$91,d0
    		bsr.w	PlaySound_Special ; play credits music
    		move.w	#0,($FFFFFFF4).w ; set credits index number to 0
    		rts
    Replace it with:
    Code:
    		clr.w	d0
    		move.b	($FFFFFFFD).w,d0	; get kind of ending (0 = good, 1 = bad)
    		lea	(MusicList6).l,a1	; load Music Playlist for credits
    		move.b	(a1,d0.w),d0	; get d0-th entry from the playlist
    
    		bsr.w	PlaySound_Special ; play credits music
    		move.w	#0,($FFFFFFF4).w ; set credits index number to 0
    		rts
    This was another simple step.
     
  9. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    Step 8: set up the new playlists


    Delete files miscmuslist1.bin and miscmuslist2.bin; I thought it would make more sense to have the playlists in the "sound" directory instead of "misc".


    So, go to the "sound" directory and create files with the following HEX contents (to mimic a clean Sonic 1 setup).

    • soundmuslist1.bin:
      Code:
      81 82 83 84 85 86
    • soundmuslist2.bin:
      Code:
      81 82 83 84 85 86
    • soundmuslist3.bin:
      Code:
      81 82 83 84 85 8D
      (note that the last byte refers to SBZ3 aka FZ)
    • soundmuslist4.bin:
      Code:
      xx 86 xx xx xx xx
      (xx means any value, since the only Act 4 slot is used for LZ4 aka SBZ3)
    • soundmuslist5.bin:
      Code:
      89 89 89 89 89 89
    • soundmuslist6.bin:
      Code:
      91 91
    • soundmuslist7.bin:
      Code:
      8B 8B
    • soundmuslist8.bin:
      Code:
      8C 8C 8C 8C 8C
    You can now alter those values to suit your needs. Good luck finding that many songs.
     
  10. MarkeyJester

    MarkeyJester ♡ ! Member

    Joined:
    Jun 27, 2009
    Messages:
    2,867
    Aha, nice work there.

    You've nicely aligned code boxes between text, used clean font sizes, and split the parts up into individual posts. I'm in favour of such a wonderfully clean and well presented guide! God knows how difficult that must have been given how fussy I.P.B can be =I
     
  11. SuperEgg

    SuperEgg I'm a guy that knows that you know that I know Member

    Joined:
    Oct 17, 2009
    Messages:
    Location:
    THE BEST GOD DAMN STATE OF TEXAS
    I'm glad you've also fixed that issue where in stock Sonic 1 uses an alternate music list for returning the music to normal after you get invincibility.
     
  12. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    Thanks :)
     
  13. EditChris

    EditChris STH:DB - Someday... Member

    Joined:
    Jul 31, 2013
    Messages:
    41
    Location:
    somewhere
    I saw a small problem, but isn't a problem rightly.

    The Special Stage playlist, is untidy; so, for example, this is an example of music order for SS: 01 02 03 04 05 06

    When I put these numbers in the playlist, the game don't recognizes the real order, and the game plays in this order: 06 01 02 03 04 05

    Only to fix this, this will be the order: 02 03 04 05 06 01

    Anyways, all works wonderful! Good job nineko!

    Edit: Grammar
     
    Last edited by a moderator: Nov 19, 2013
  14. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    This is weird, I remember the Special Stage number was being off by one for some reason when I worked on my hack, so I had to insert a "-1" there (the "subi.w #$1,d0", but only if the number isn't 0). I tried to apply that code to a clean disassembly, and it worked fine. Try to remove everything from the cmpi.b to the subi.w, it is possible that you did something else which fixes the "-1" anomaly.
     
    Last edited by a moderator: Nov 19, 2013
  15. EditChris

    EditChris STH:DB - Someday... Member

    Joined:
    Jul 31, 2013
    Messages:
    41
    Location:
    somewhere
    Meh, isn't a big problem, and I tested it a lot of times when it has been repaired. All works fine.
     
  16. Cinossu

    Cinossu A blend of secret herbs and spices Member

    Joined:
    Aug 14, 2007
    Messages:
    282
    Location:
    London, UK
    The Special Stage issue; it depends exactly where this code is placed as to whether or not the -1 issue is relevant. The reason for it is there's a piece of code before it that uses that Special Stage number to determine which Layout to use, then increments it to the next one you haven't beaten. It does this at the beginning of the Special Stage rather than at the end, as by that point it doesn't matter what is there; the Emerald you get isn't chosen by the Special Stage number, but by SS object number.

    Placing the check before this happens and storing it in your RAM variable for later use of playing would solve the issue. I'll try to find the relevant code later, as I don't have time right now. :U
     
    Last edited by a moderator: Nov 20, 2013
  17. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    Yeah, I guessed it had something to do with the Special Stage number being already incremented for the next one, but I couldn't figure out where to perform the check otherwise. This also means that my code above has been wrong for all this time, because if you didn't collect an emerald and you go back to a previous stage later, the -1'd Special Stage number might be one you already completed, so a better place for this code is necessary. I never thought about this because I never fail to collect the emeralds :|
     
Thread Status:
Not open for further replies.