Color Math

SNES programming tutorial. Example 12.

https://github.com/nesdoug/SNES_12

 

What is color math? If you’ve ever worked with Photoshop, it would be like blending 2 different layers. In this case the layers are the MAIN screen and the SUB screen. Everything we have done so far deals with the MAIN screen. So let me try to explain the SUB screen.

All that stuff that the SNES does to produce a picture, putting layers on top of each other, tile priorities, sprite priorities, etc… it does all that TWICE. If you set the settings for the MAIN screen exactly the same as the settings for the SUB screen, it would produce the exact same picture TWICE… with 1 difference.  The main screen uses color index zero as the backdrop color (any pixel that is transparent), and the sub screen uses the “fixed color” as the backdrop color (register $2132).

You would never see the SUB screen, unless you turned on the color math registers, which would then blend the 2 pictures together, using either addition or subtraction. And then there is an optional halving step after that. Each pixel on the screen, the R values are added or subtracted, and the G value, then the B value. That value is clamped to the max and min without overflow. (each RBG value is 0-31)

Let’s say we have it set to ADD. And the main screen pixel is gray 15,15,15, and the sub screen pixel is dark red 10,0,0. The final pixel would be 25,15,15.

If we added the HALF option, each value would shift right once (rounding down), giving a final pixel of 12,7,7.

If we set the color math to SUBTRACT (no halving), the final pixel would be 5,15,15. The RGB values of the sub screen are subtracted from the RBG values on the main screen.

If we added the HALF option, each value would shift right once (rounding down), giving a final pixel of 2,7,7.

Note, any pixel in the sub screen that is transparent will not be halved.

The main use for Color Math is for transparency effects. You will want Adding and Halving. That would equally blend the main and sub screen.

The least useful setting is the subtract and halving. That would just produce a very dark picture, and almost no games used this.

.

There is a completely different kind of color math operation, that uses ONLY the fixed color. That color is applied to the entire MAIN screen, and if halving is set, it will work for the whole screen. If you set the fixed color register to green, and had the color math set to ADD, it would add a green tint to the screen.

The fixed color register is weird. The wiki example suggest writing each color separately to it (3 writes for R,B, and G). However, you could set them all to a specific value with 1 write. Such as LDA #$E0, STA $2132 would set all fixed colors to zero.

Before we dive into the code, here’s a video. You can probably skip most of this video, which goes into too many details about how the 2 different screens are generated.

 

Example ROM

I put BG1 on the main screen (gray rocks) and BG2 on the sub screen (color bars).

No effect. Color Math disabled.

SNES_12_000

 

Just the Sub screen. (seen by setting the “clipping always to black” bits in the color math logic, and adding the sub screen).

SNES_12_006

Note, the top left is black (non-zero index). The bottom left is zero index (transparent).  The sub screen will show the “fixed color” (register 2132) where there is transparent. Right now the fixed color is black. Color halving will not work for a transparent pixel on the sub screen. If you notice, the bottom left square will not change at all for these examples, even when halving is indicated.

 

Color Math Adding.

SNES_12_001

 

Color Math Adding and Halving.

SNES_12_002

 

Color Math Subtracting.

SNES_12_003

 

Color Math Subtracting and Halving.

SNES_12_004

 

Fixed color only (red at 50%), Color Math Adding.

SNES_12_005

 

Here’s a YouTube video of the Example code.

 

Example Code

$2130 
ccmm--sd
cc = main screen black if... *
--mm---- = prevent color math if... *
------0- = fixed color
------1- = sub screen
d is for an unrelated thing

* 00 => Never
  01 => Outside Color Window only
  10 => Inside Color Window only
  11 => Always

$2131
shbo4321
0------- add
1------- subtract
-0------ normal
-1------ result is halved
b = backdrop, o = sprites, 4321 = layers enabled for color math

 

So let’s go over each examples.

1- no effect, turn off color math

lda #$30 ; = off
sta color_add_sel ; $2130
;and make sure fixed color is black
lda #$e0 ; RGB, value = 0
sta color_fixed ; $2132

2- adding

lda #$02 ; color math with subscreen
sta color_add_sel ; $2130

;adding, not half, affect all layers 
lda #$3f
sta color_add_des ; $2131

3- adding and half, same as last one, just add one bit to the 2131 write

;adding, half, affect all layers 
lda #$7f
sta color_add_des ; $2131

4- subtracting

lda #$02 ; color math with subscreen
sta color_add_sel ; $2130

;subtracting, not half, affect all layers 
lda #$bf
sta color_add_des ; $2131

5- subtracting and half. Same as last one, but add one bit to the 2131 write

;subtract, half, affect all layers	
lda #$ff
sta color_add_des ; $2131

6- fixed color only

;turn on color math, fixed color mode
lda #$00
sta color_add_sel ; $2130

;adding, not half, affect all layers 
lda #$3f
sta color_add_des ; $2131

;set the fixed color to red 50%
lda #$2f ;red at 50%
sta color_fixed ; $2132

We could have also set half mode.

7- see just the sub screen. We did this by setting the “always clip main screen to black” bits in 2130, and then adding the sub screen to the now completely black main screen.

lda #$c2 ;= clip main always to black
sta color_add_sel ; $2130

;adding, not half, affect all layers 
lda #$3f
sta color_add_des ; $2131

 

Other examples

Color math only affects some sprites. Only sprites that use palettes 4-7 are affected by color math. That is why Mario (and the little ghosts) are solid.

Super Mario World (USA)_006

Windowing can affect where the color math applies. With HDMA adjusting the window, you can make some cool effects.

Contra III - The Alien Wars (USA)_000

Metroid1

Super Mario World (USA)_008

 

Tint the whole screen (adding a fixed color)… actually, upon further investigation, this is subtracting, which makes the screen slightly darker than the original. Also, the COLOR MATH is not in fixed color mode, it’s in subscreen mode, but NOTHING is enabled on the subscreen, so the subscreen is filled with the backdrop color (which for the sub screen is the fixed color). I guess that works too.

Legend of Zelda, The - A Link to the Past (USA)_000

 

Smooth Transparencies (add and halving). This is the most common transparency effect on the SNES.

Legend of Zelda, The - A Link to the Past (USA)_001

Sparkster, the water.

Sparkster (USA)_000

 

And creating shadows (subtracting) Mortal Kombat II. It’s hard to tell, but their shadows are created by color math subtraction. You could also give the appearance of clouds moving overhead by subtracting a cloud shape and having it scroll.

Mortal Kombat II (USA)_000

 

Links.

http://www.romhacking.net/documents/428/

https://wiki.superfamicom.org/transparency

 

SNES main page

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s