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:
where S is (number of tiles-1) and TTT is the offset (in tiles) from the start of the art file .
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:
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:
|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:
Replace it by this:
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:
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.