SNES programming tutorial. Example 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.
I put BG1 on the main screen (gray rocks) and BG2 on the sub screen (color bars).
No effect. Color Math disabled.
Just the Sub screen. (seen by setting the “clipping always to black” bits in the color math logic, and adding the sub screen).
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.
Color Math Adding and Halving.
Color Math Subtracting.
Color Math Subtracting and Halving.
Fixed color only (red at 50%), Color Math Adding.
Here’s a YouTube video of the 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
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
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
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.
Windowing can affect where the color math applies. With HDMA adjusting the window, you can make some cool effects.
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.
Smooth Transparencies (add and halving). This is the most common transparency effect on the SNES.
Sparkster, the water.
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.