Actions

SCHG How-to

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!

SCHG How-To Guide: Sonic the Hedgehog (16-bit)
Fixing Bugs
Fix Demo Playback | Fix a Race Condition with Pattern Load Cues | Fix the SEGA Sound | Display the Press Start Button Text | Fix the Level Select Menu | Fix the Hidden Points Bug | Fix Accidental Deletion of Scattered Rings | Fix Ring Timers | Fix the Walk-Jump Bug | Correct Drowning Bugs | Fix the Death Boundary Bug | Fix the Camera Follow Bug | Fix Song Restoration Bugs | Fix the HUD Blinking | Fix the Level Select Graphics Bug | Fix a remember sprite related bug
Changing Design Choices
Change Spike Behavior | Collide with Water After Being Hurt | Fix Special Stage Jumping Physics | Improve the Fade In\Fade Out Progression Routines | Fix Scattered Rings' Underwater Physics | Remove the Speed Cap | Port the REV01 Background Effects | Port Sonic 2's Level Art Loader | Retain Rings Between Acts | Add Sonic 2 (Simon Wai Prototype) Level Select | Improve ObjectMove Subroutines | Add Sonic 2 Level Select | Collide with Water After Being Hurt | Smooth Out Rotation in Special Stages
Adding Features
Add Spin Dash ( Part 1 (GitHub)/(Hivebrain) / Part 2 / Part 3 / Part 4 ) | Add Eggman Monitor | Add Super Sonic | Add Extended Camera | Add the Air Roll | Add 6-Button Support
Sound Features
Expand the Sound Index | Play Different Songs Per Act | Port Sonic 2 Final Sound Driver | Port Sonic 3's Sound Driver | Change The SEGA Sound
Extending the Game
Load Chunks From ROM | Add Extra Characters | Make an Alternative Title Screen | Use Dynamic Tilesets | Make GHZ Load Alternate Art | Make Ending Load Alternate Art | Add a New Zone | Set Up the Goggle Monitor | Add New Moves | Add a Dynamic Collision System | Dynamic Special Stage Walls System | Extend Sprite Mappings and Art Limit | Enigma Credits | Use Dynamic Palettes
Miscellaneous
Convert the Hivebrain 2005 Disassembly to ASM68K
Split Disassembly Guides
Set Up a Split Disassembly | Basic Level Editing | Basic Art Editing | Basic ASM Editing (Spin Dash)

|Use Dynamic Palettes]]