Thursday, October 12, 2017

Knuckles in Sonic 2: player sprites

As we've seen before, when playing as Knuckles, a different palette is loaded into the player palette slot. The only real difference between it and the regular Sonic palette is that Sonic's three blues are replaced with Knuckles' three reds:


Now, in order to take advantage of DMA, all player sprites must be stored uncompressed, which takes up a lot of ROM space. In fact, Knuckles' sprites alone use up about 1 of the 16 megabits in the Sonic & Knuckles ROM! That's half the total capacity of the Knuckles in Sonic 2 patch ROM!

Obviously, we would like to reuse Knuckles' sprites from the Sonic & Knuckles ROM in Sonic 2. However, therein lies a problem: although most of them are either similar or exactly the same, the order of the colors in Sonic 2's player palette is completely different from the one in Sonic & Knuckles:


Unfortunately, we can't just apply the Sonic & Knuckles palette directly because a lot of graphics depend on the Sonic 2 colors. For example, all the enemies in Emerald Hill Zone are rendered exclusively using the player palette:


So what's the solution?

Instead of DMAing Knuckles' sprites directly from ROM to VRAM, we first run them through a conversion routine which reads each tile from ROM, swaps all the color indices around to fit the Sonic 2 palette, and writes them to RAM. Finally, the fully-converted sprite then is DMA'd from RAM to VRAM.

The code for this can be found in the LoadKnucklesDynPLC routine of the Knuckles in Sonic 2 disassembly. It uses a lookup table to map each of the 256 byte values that may show up in the source data to their corresponding value once the Sonic 2 palette is applied:
ArtConvTable:   dc.b $00,$06,$05,$03,$02,$04,$0C,$0D,$0E,$0F,$0A,$0B,$07,$08,$09,$01
                dc.b $60,$66,$65,$63,$62,$64,$6C,$6D,$6E,$6F,$6A,$6B,$67,$68,$69,$61
                dc.b $50,$56,$55,$53,$52,$54,$5C,$5D,$5E,$5F,$5A,$5B,$57,$58,$59,$51
                dc.b $30,$36,$35,$33,$32,$34,$3C,$3D,$3E,$3F,$3A,$3B,$37,$38,$39,$31
                dc.b $20,$26,$25,$23,$22,$24,$2C,$2D,$2E,$2F,$2A,$2B,$27,$28,$29,$21
                dc.b $40,$46,$45,$43,$42,$44,$4C,$4D,$4E,$4F,$4A,$4B,$47,$48,$49,$41
                dc.b $C0,$C6,$C5,$C3,$C2,$C4,$CC,$CD,$CE,$CF,$CA,$CB,$C7,$C8,$C9,$C1
                dc.b $D0,$D6,$D5,$D3,$D2,$D4,$DC,$DD,$DE,$DF,$DA,$DB,$D7,$D8,$D9,$D1
                dc.b $E0,$E6,$E5,$E3,$E2,$E4,$EC,$ED,$EE,$EF,$EA,$EB,$E7,$E8,$E9,$E1
                dc.b $F0,$F6,$F5,$F3,$F2,$F4,$FC,$FD,$FE,$FF,$FA,$FB,$F7,$F8,$F9,$F1
                dc.b $A0,$A6,$A5,$A3,$A2,$A4,$AC,$AD,$AE,$AF,$AA,$AB,$A7,$A8,$A9,$A1
                dc.b $B0,$B6,$B5,$B3,$B2,$B4,$BC,$BD,$BE,$BF,$BA,$BB,$B7,$B8,$B9,$B1
                dc.b $70,$76,$75,$73,$72,$74,$7C,$7D,$7E,$7F,$7A,$7B,$77,$78,$79,$71
                dc.b $80,$86,$85,$83,$82,$84,$8C,$8D,$8E,$8F,$8A,$8B,$87,$88,$89,$81
                dc.b $90,$96,$95,$93,$92,$94,$9C,$9D,$9E,$9F,$9A,$9B,$97,$98,$99,$91
                dc.b $10,$16,$15,$13,$12,$14,$1C,$1D,$1E,$1F,$1A,$1B,$17,$18,$19,$11
You might recall how back when the earth was still flat, I mentioned tiles are made up of 4-bit color indices. This means each byte actually represents two separate pixels. As such, the actual pixel conversion function can be seen on the left nybble when going down the table, and the right nybble when going across.

All that's left is to apply the same procedure as in Sonic & Knuckles: take the regular player palette and replace Sonic's four blues with Knuckles' three reds, as well as the green of his socks:


Next time, we'll finish up our look at Knuckles in Sonic 2 by looking at the consequences of modifying those four colors, and the graphical replacements that came as a result.

1 comment:

  1. I'm calling that the grey shield... I mean barrier is part of the study.

    ReplyDelete