Actions

SCHG How-to

Change the Special Stage characters to use normal DPLCs

From Sonic Retro

(Original guide by Flamewing)

The Sonic 2 Special Stages use a custom format for storing characters' Dynamic Pattern Loading Cues (or DPLCs for short). This is inconvenient if you want to edit their art (for example, for making a character hack), especially if you use programs such as SonMapEd, which cannot read this custom format. This guide explains how to use normal DPLCs for the Special Stages. This guide also explores the custom format used for those that want to know how they work.

The format explained

To explore the difference between the normal DPLCs and the custom ones used in Sonic 2 Special Stages, I will first explain how normal DPLCs work. For that, the best way is by using a simple example:

Sample_DPLC:
	dc.w	DPLC_Entry_0-Sample_DPLC
	dc.w	DPLC_Entry_1-Sample_DPLC

DPLC_Entry_0:
	dc.w	4	; Number of entries in DPLC
	dc.w	(3 << 12) | $100
	dc.w	(2 << 12) | $200
	dc.w	(0 << 12) | $000
	dc.w	(1 << 12) | $080
DPLC_Entry_1:
	dc.w	3	; Number of entries in DPLC
	dc.w	(3 << 12) | $060
	dc.w	(2 << 12) | $020
	dc.w	(0 << 12) | $005

This example shows how the DPLC file starts with an offset table; there is one entry in this table for each mapping frame. Each mapping frame's DPLC has a field indicating how many DPLC entries exist for this frame. The DPLC entries are then in the following format:

$STTT

where S is (number of tiles-1) and TTT is the offset (in tiles) from the start of the art file [1].

The custom DPLC scheme used by the Sonic 2 Special Stage characters is very similar to this: you have an offset table at the start of the file. The differences start right away, though: the first difference is that only the first $24 mapping frames have the 'number of entries in DPLC' field; after them, all frames are assumed to have only one DPLC entry.

The second difference is in the format of each DPLC entry:

$STTT

Here, the S has the same meaning; but TTT is the number of words from the start of a hard-coded offset from the start of the art file. Specifically:

DPLC art origin
Mapping frame Art offset (in tiles)
$00 to $03 $0000
$04 to $0B $0058
$0C to $0F $0124
$10 to $11 $0171
$12 to $15 $0183
$16 to $1D $01C0
$1E to $21 $0264
$22 to $23 $029E
$24 to $2A $02AE
$2B to $31 $02E3
$32 or more $031E

Additionally, the character art in Special Stages is loaded from main RAM, and it is decompressed at the start of the Special Stage.

Getting rid of it

Editing these DPLCs by hand is an error-prone and time-consuming enterprise, because you have to pay attention to the hard-coded art offsets (or edit them too) and you can only check your work on a built ROM. The easiest way to deal with these mappigns is by not using them.

For starters, grab this file: File:SpecStagS2-DPLC.7z. It contains pre-converted DPLCs for Sonic, Tails and Tails' tails. These still use the single art file for all 3, but the DPLCs have been split and converted from the Special Stage format. Decompress it to the mappings/spriteDPLC dir and make sure that all files are BINCLUDEd in the disassembly. From here on, I will assume that you have labelled these BINCLUDEd DPLCs as 'Obj09_MapRUnc', 'Obj10_MapRUnc' and 'Obj88_MapRUnc'.

Next, open up your disassembly and find label 'dword_33AA2'. Delete it and the next 4 lines. Now find label 'loc_33AD8' (2007 disassembly) or 'LoadSSPlayerDynPLC' (Hg disassembly). Just above it, there is a line referring to 'dword_33AA2'. Replace this line with this:

	move.l	#$FF0000,d6
	lea	(Obj09_MapRUnc).l,a2

Now select everything from 'loc_33AD8'/'LoadSSPlayerDynPLC' up until the rts and replace it by this:

	moveq	#0,d0
	move.b	mapping_frame(a0),d0
	cmp.b	(a4),d0
	beq.s	+
	move.b	d0,(a4)
	add.w	d0,d0
	adda.w	(a2,d0.w),a2
	move.w	(a2)+,d5
	subq.w	#1,d5
	bmi.s	+
-
	moveq	#0,d1
	move.w	(a2)+,d1
	move.w	d1,d3
	lsr.w	#8,d3
	andi.w	#$F0,d3
	addi.w	#$10,d3
	andi.w	#$FFF,d1
	lsl.w	#5,d1
	add.l	d6,d1
	move.w	d4,d2
	add.w	d3,d4
	add.w	d3,d4
	jsr	(QueueDMATransfer).l
	dbf	d5,-
+
	rts

This takes care of Sonic; time now for Tails. Find label 'dword_349B8' and, once again, delete it and the four lines below it. Then find the next line that references 'dword_349B8' and replace it by this:

	move.l	#$FF0000,d6
	lea	(Obj10_MapRUnc).l,a2

Just below this, you will find this line:

	moveq	#$12,d1

Replace it by this:

	moveq	#0,d1

In the Special Stage, Tails uses the same DPLC routine as Sonic, so this is enough for Tails too. Time now for Tails' tails. Find label 'dword_34AA0'; delete it and the next 3 lines.

Now find this line right after:

	bsr.w	JmpTo43_DisplaySprite

Select it and everything below it until the following rts and delete it. If you are using the Hg disassembly, paste this at that location:

	jsrto	(DisplaySprite).l, JmpTo43_DisplaySprite
	move.l	#$FF0000,d6
	lea	(Obj88_MapRUnc).l,a2
	lea	(TailsTails_LastLoadedDPLC).w,a4
	move.w	#tiles_to_bytes(ArtTile_ArtNem_SpecialTails_Tails),d4
	moveq	#0,d1
	bra.w	LoadSSPlayerDynPLC

If you are using the aging 2007 disassembly, paste this instead:

	bsr.w	JmpTo43_DisplaySprite
	move.l	#$FF0000,d6
	lea	(Obj88_MapRUnc).l,a2
	lea	($FFFFF7DF).w,a4
	move.w	#$62C0,d4
	moveq	#0,d1
	bra.w	loc_33AD8

If you did everything right, you can now build the ROM and the Special Stage will be using the normal DPLC format, and you can easily edit it at your heart's contents.

SCHG How-To Guide: Sonic the Hedgehog 2 (16-bit)
Fixing Bugs
Fix Demo Playback | Fix a Race Condition with Pattern Load Cues | Fix Super Sonic Bugs | Use Correct Height When Roll Jumping | Fix Jump Height Bug When Exiting Water | Fix Spin Dash Code and Add Spin Dash Speeds | Fix Screen Boundary Spin Dash Bug | Correct Drowning Bugs | Fix Camera Y Position for Tails | Fix Tails Subanimation Error | Fix Tails' Respawn Speeds | Fix Accidental Deletion of Scattered Rings | Fix Ring Timers | Fix Rexon Crash | Fix Monitor Collision Bug | Fix EHZ Deformation Bug | Correct CPZ Boss Attack Behavior | Fix Bug in ARZ Boss Arrow's Platform Behavior | Fix ARZ Boss Walking on Air Glitch | Fix ARZ Boss Sprite Behavior | Fix Multiple CNZ Boss Bugs | Fix HTZ Background Scrolling Mountains | Fix OOZ Launcher Speed Up Glitch | Fix DEZ Giant Mech Collision Glitch | Fix Boss Deconstruction Behavior | Fix Speed Bugs
Design Choices
Remove the Air Speed Cap | Disable Floor Collision While Dying | Modify Super Sonic Transformation Methods & Behavior | Enable/Disable Tails in Certain Levels | Collide with Water After Being Hurt | Retain Rings When Returning at a Star Post | Improve the Fade In\Fade Out Progression Routines | Fix Scattered Rings' Underwater Physics | Insert LZ Water Ripple Effect | Restore Lost CPZ Boss Feature | Prevent SCZ Tornado Spin Dash Death | Improve ObjectMove Subroutines | Port S3K Rings Manager | Port S3K Object Manager | Port S3K Priority Manager | Edit Level Order with ASM‎ | Alter Ring Requirements in Special Stages | Make Special Stage Characters Use Normal DPLCs | Speed Up Ring Loss Process | Add beta spindash to Sonic 2 | Change spike behaviour in Sonic 2
Adding Features
Create Insta-kill and High Jump Monitors | Create Clone and Special Stage Monitors | Port Knuckles
Sound Features
Port Sonic 1 Sound Driver | Port Sonic 2 Clone Driver | Port Sonic 3 Sound Driver | Expand the Music Index to Start at $00 (Sonic 2 Clone Driver Version)
Extending the Game
Extend the Level Index Past $10 | Extend the Level Select | Extend Water Tables | Add Extra Characters | Free Up 2 Universal SSTs