Sonic and Sega Retro Message Board: Sega Palette Encoding? - Sonic and Sega Retro Message Board

Jump to content

Hey there, Guest!  (Log In · Register) Help
Page 1 of 1
    Locked Forum

Sega Palette Encoding? Spitballing Ideas...

#1 User is offline Dandaman 

Posted 13 December 2015 - 12:40 AM

  • Also known as Dandaman955
  • Posts: 85
  • Joined: 30-August 09
  • Gender:Male
  • Location:UK
  • Wiki edits:30
So a while back, I posted some notes for Streets of Rage. In that thread, I noted how the game uses an palette encryption/encoding which positions it in the palette buffer appropriately:


Streets of Rage uses a different method compared to the usual 0BGR method. It is encoded so that the subroutine it is loaded to knows exactly what palette line to load it to, which entry in that palette line to load it to (to where it is then positioned appropriately in the palette buffer) and the length of the data string. Rather than the typical bitfield:

0000 BBB0 GGG0 RRR0

...It uses:


For instance, take the value $6EFE for instance:

0110 1110 1111 1110

The XXXX in this case is represented by the number 6. Palette entries are $0-$F, so this one is loaded to palette entry $6 in this case. Next, the first N is 0, while the second N is 1. Group them together, and you get 01. Now look at this chart:

00 - Palette line 0
01 - Palette line 1
10 - Palette line 2
11 - Palette line 3

This shows which palette line the palette will end up in. Since this is 01, it will end up in the "1st" one. You can usually tell if an N bit is checked by it having an odd number in the number it's representing in hex. So for example, the second digit 'E' isn't odd, so the N bit isn't checked, while the third digit is, so the N bit is checked. You can't have odd numbers for palettes, so the game makes use of it before it is written to the palette buffer. In this case, T isn't checked, so the game will treat the following word as a palette, and will try to decode it. If it's the end of the palette data, set T to 1 (or put an odd number into the final digit). Afterwards, the original data is anded by $0EEE (White, as you can't get a higher value than that), and the value is positioned appropriately in the palette buffer. $6EFE anded by $0EEE is $0EEE, so white will be moved to palette line 1, entry 6 during the next CRAM DMA in VBlank (Setting $FFFA01 to 1 activates it, otherwise CRAM DMA is skipped).

Now, I thought this was specific to the game and I just ignored it. However, when I was looking at Flicky, I noticed that it was also used in the game (offset $1196), albeit with different data registers used and only used for the main palette. If this post is to be believed, then there may be another game that uses this format (although may just be Flicky), which leads me to believe that this might be an official format, similar to how Nemesis and Kosinski are?

Here's the commented routine from Flicky:

DecodePalettes:                                  ; $1196
                movem.l d0-d2/a0,-(sp)           ; Store register values.
                lea     ($FFFFF7E0).w,a0         ; Load the start of the palette buffer into a0.
                move.w  (a5),d0                  ; Load first palette into d0.
                andi.w  #$10,d0                  ; Get the tenth; strip the rest of the bits except for the lower N bit.
                move.w  (a5),d1                  ; Reload the palette value.
                rol.w   #4,d1                    ; Get palette entry value.
                andi.w  #$F,d1                   ; Strip the rest of the bits.
                or.w    d1,d0                    ; Add onto the tenth.
                move.w  (a5),d1                  ; Reload the palette value.
                andi.w  #$100,d1                 ; Get the hundredth; strip the rest of the bits except for the higher N bit.
                lsr.w   #3,d1                    ; Divide to get into the byte range.
                or.w    d1,d0                    ; Add onto the rest of the bits.
                add.w   d0,d0                    ; Multiply by 2 to account for the word size.
                move.w  (a5)+,d2                 ; Reload the palette value.
                move.w  d2,d1                    ; Copy into d1.
                andi.w  #$0EEE,d1                ; Ensure that white is the highest value attainable.
                move.w  d1,(a0,d0.w)             ; Load to the appropriate position in the palette buffer.
                lsr.w   #1,d2                    ; Shift right to check for the presence of the T bit.
                bcc.s   loc_119e                 ; If it's not there, continue decoding palettes.
                movem.l (sp)+,d0-d2/a0           ; Restore register values.
                rts                              ; Return.

Page 1 of 1
    Locked Forum

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users