Use Dynamic Palettes in Sonic 1
From Sonic Retro
(Original guide by Cinossu and Shadow Fire)
This guide will show you how to use dynamic palettes in Sonic 1. You will need to have some basic ASM knowledge before doing this. This guide is designed for use with Hivebrain's 2005 ASM68K disassembly.
Make copies of "Pallet pointers.asm" and rename them to "Pallet pointers2.asm" and "Pallet pointers3.asm". Make sure they're all in the "_inc" folder. Now, it's time to edit them. Open "Pallet pointers2.asm".
Change these words: Pal_GHZ, Pal_LZ, Pal_MZ, Pal_SLZ, Pal_SYZ, and Pal_LZWater...
...into: Pal_GHZ2, Pal_LZ2, Pal_MZ2, Pal_SLZ2, Pal_SYZ2, and Pal_LZWater2.
Save and close. Open "Pallet pointers3.asm" and do the same edits, only replacing 2 with 3. Save and close. Now, we move onto editing the main ASM file, called "sonic1.asm".
Open "sonic1.asm" and run a search for "Pallet pointers" (without the quotes), and replace the following lines...
PalPointers:
include "_inc\Pallet pointers.asm"
...with...
PalPointers:
include "_inc\Pallet pointers.asm"
PalPointers2:
include "_inc\Pallet pointers2.asm"
PalPointers3:
include "_inc\Pallet pointers3.asm"
Now, just below that, you should see a routine labelled "Pallet data". Move down to where "Pal_GHZ"'s routine ends. (After incbin pallet\ghz.bin) Create a new line and add the following...
Pal_GHZ2: incbin pallet\ghz2.bin
Pal_GHZ3: incbin pallet\ghz3.bin
The next line will show "Pal_LZ". Copy that data twice and paste underneath, being sure to rename it accordingly. In the end, this is how it should read...
; ---------------------------------------------------------------------------
; Pallet data
; ---------------------------------------------------------------------------
Pal_SegaBG: incbin pallet\sega_bg.bin
Pal_Title: incbin pallet\title.bin
Pal_LevelSel: incbin pallet\levelsel.bin
Pal_Sonic: incbin pallet\sonic.bin
Pal_GHZ: incbin pallet\ghz.bin
Pal_GHZ2: incbin pallet\ghz2.bin
Pal_GHZ3: incbin pallet\ghz3.bin
Pal_LZ: incbin pallet\lz.bin
Pal_LZ2: incbin pallet\lz2.bin
Pal_LZ3: incbin pallet\lz3.bin
Pal_LZWater: incbin pallet\lz_uw.bin ; LZ underwater pallets
Pal_LZWater2: incbin pallet\lz_uw2.bin ; LZ underwater pallets
Pal_LZWater3: incbin pallet\lz_uw3.bin ; LZ underwater pallets
Pal_MZ: incbin pallet\mz.bin
Pal_MZ2: incbin pallet\mz2.bin
Pal_MZ3: incbin pallet\mz3.bin
Pal_SLZ: incbin pallet\slz.bin
Pal_SLZ2: incbin pallet\slz2.bin
Pal_SLZ3: incbin pallet\slz3.bin
Pal_SYZ: incbin pallet\syz.bin
Pal_SYZ2: incbin pallet\syz2.bin
Pal_SYZ3: incbin pallet\syz3.bin
Pal_SBZ1: incbin pallet\sbz_act1.bin ; SBZ act 1 pallets
Pal_SBZ2: incbin pallet\sbz_act2.bin ; SBZ act 2 & Final Zone pallets
Pal_Special: incbin pallet\special.bin ; special stage pallets
Pal_SBZ3: incbin pallet\sbz_act3.bin ; SBZ act 3 pallets
Pal_SBZ3Water: incbin pallet\sbz_a3uw.bin ; SBZ act 3 (underwater) pallets
Pal_LZSonWater: incbin pallet\son_lzuw.bin ; Sonic (underwater in LZ) pallet
Pal_SBZ3SonWat: incbin pallet\son_sbzu.bin ; Sonic (underwater in SBZ act 3) pallet
Pal_SpeResult: incbin pallet\ssresult.bin ; special stage results screen pallets
Pal_SpeContinue:incbin pallet\sscontin.bin ; special stage results screen continue pallet
Pal_Ending: incbin pallet\ending.bin ; ending sequence pallets
Now, you need to navigate to the subroutine labelled "Subroutines to load pallets". Simply run a search to find this. You should then see the following...
; ---------------------------------------------------------------------------
; Subroutines to load pallets
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PalLoad1:
lea (PalPointers).l,a1
lsl.w #3,d0
adda.w d0,a1
movea.l (a1)+,a2
movea.w (a1)+,a3
adda.w #$80,a3
move.w (a1)+,d7
loc_2110:
move.l (a2)+,(a3)+
dbf d7,loc_2110
rts
; End of function PalLoad1
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PalLoad2:
lea (PalPointers).l,a1
lsl.w #3,d0
adda.w d0,a1
movea.l (a1)+,a2
movea.w (a1)+,a3
move.w (a1)+,d7
loc_2128:
move.l (a2)+,(a3)+
dbf d7,loc_2128
rts
; End of function PalLoad2
; ---------------------------------------------------------------------------
; Underwater pallet loading subroutine
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PalLoad3_Water:
lea (PalPointers).l,a1
lsl.w #3,d0
adda.w d0,a1
movea.l (a1)+,a2
movea.w (a1)+,a3
suba.w #$80,a3
move.w (a1)+,d7
loc_2144:
move.l (a2)+,(a3)+
dbf d7,loc_2144
rts
; End of function PalLoad3_Water
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PalLoad4_Water:
lea (PalPointers).l,a1
lsl.w #3,d0
adda.w d0,a1
movea.l (a1)+,a2
movea.w (a1)+,a3
suba.w #$100,a3
move.w (a1)+,d7
loc_2160:
move.l (a2)+,(a3)+
dbf d7,loc_2160
rts
; End of function PalLoad4_Water
Now, where the line "PalLoad1:" begins, replace the following line...
lea (PalPointers).l,a1
...with the following...
move.b $FFFFFE11,d1
lea (PalPointers).l,a1
cmp.b #0,d1
beq.w PalLoad#_Continue
lea (PalPointers2).l,a1
cmp.b #1,d1
beq.w PalLoad#_Continue
lea (PalPointers3).l,a1
PalLoad#_Continue:
Note: "PalLoad#_Continue:" must be changed to whatever palette number you have pasted under. In this first case, it should be "PalLoad1_Continue".
Do the same for the other PalLoad routines, only changing the PalLoad#_Continue numbers. If you did it right, you should see the following for all subroutines...
; ---------------------------------------------------------------------------
; Subroutines to load pallets
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PalLoad1:
move.b $FFFFFE11,d1
lea (PalPointers).l,a1
cmp.b #0,d1
beq.w PalLoad1_Continue
lea (PalPointers2).l,a1
cmp.b #1,d1
beq.w PalLoad1_Continue
lea (PalPointers3).l,a1
PalLoad1_Continue:
lsl.w #3,d0
adda.w d0,a1
movea.l (a1)+,a2
movea.w (a1)+,a3
adda.w #$80,a3
move.w (a1)+,d7
loc_2110:
move.l (a2)+,(a3)+
dbf d7,loc_2110
rts
; End of function PalLoad1
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PalLoad2:
move.b $FFFFFE11,d1
lea (PalPointers).l,a1
cmp.b #0,d1
beq.w PalLoad2_Continue
lea (PalPointers2).l,a1
cmp.b #1,d1
beq.w PalLoad2_Continue
lea (PalPointers3).l,a1
PalLoad2_Continue:
lsl.w #3,d0
adda.w d0,a1
movea.l (a1)+,a2
movea.w (a1)+,a3
move.w (a1)+,d7
loc_2128:
move.l (a2)+,(a3)+
dbf d7,loc_2128
rts
; End of function PalLoad2
; ---------------------------------------------------------------------------
; Underwater pallet loading subroutine
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PalLoad3_Water:
move.b $FFFFFE11,d1
lea (PalPointers).l,a1
cmp.b #0,d1
beq.w PalLoad3_Continue
lea (PalPointers2).l,a1
cmp.b #1,d1
beq.w PalLoad3_Continue
lea (PalPointers3).l,a1
PalLoad3_Continue:
lsl.w #3,d0
adda.w d0,a1
movea.l (a1)+,a2
movea.w (a1)+,a3
suba.w #$80,a3
move.w (a1)+,d7
loc_2144:
move.l (a2)+,(a3)+
dbf d7,loc_2144
rts
; End of function PalLoad3_Water
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PalLoad4_Water:
move.b $FFFFFE11,d1
lea (PalPointers).l,a1
cmp.b #0,d1
beq.w PalLoad4_Continue
lea (PalPointers2).l,a1
cmp.b #1,d1
beq.w PalLoad4_Continue
lea (PalPointers3).l,a1
PalLoad4_Continue:
lsl.w #3,d0
adda.w d0,a1
movea.l (a1)+,a2
movea.w (a1)+,a3
suba.w #$100,a3
move.w (a1)+,d7
loc_2160:
move.l (a2)+,(a3)+
dbf d7,loc_2160
rts
; End of function PalLoad4_Water
If that's all correct, save your ASM files and copy your new palette files into the "pallet" folder. You must provide your own palette files. (Oh, and you don't need to worry about SBZ3/LZ4.)
Then, build your ROM and test. If you run into errors, you obviously made a mistake and forgot to do something. However, assuming you followed the guide properly, you should have dynamic zone palettes. Congratulations. You ownz!
|Use Dynamic Palettes]]