On this page
  1. Related
  2. Games
  3. References
  4. Sources

Color math combines the screen with a second picture or a fixed color. In Final Fantasy VI, 73 of the 565 attack animation scripts set it, adding the sprites to a background for the summons or a fixed color that changes line by line1, and the battle screen opens by subtracting white from all but a widening band2. EarthBound’s battle swirl subtracts a tint inside its window3.

  • Add a colorFinal Fantasy VI (1994). 73 of 565 attack animation scripts set color math, some adding a fixed color line by line.1
  • SubtractEarthBound (1994). The battle swirl subtracts a fixed color inside its window.3Final Fantasy VI (1994). The battle screen opens by subtracting white outside a widening band.2

Games

GameYearHowNote
Final Fantasy VI1994Add a color73 of 565 attack animation scripts set color math, some adding a fixed color line by line
EarthBound1994Subtractthe battle swirl subtracts a fixed color inside its window
Final Fantasy VI1994Subtractthe battle screen opens by subtracting white outside a widening band
Every claim about this mechanic, by game (8)
The Legend of Zelda: A Link to the Past 1991A dark room is darkened by subtractive color math, not by darker palettes. Every room's setup selects the subscreen as the addend ($02) and subtracts it from BG1, BG2, sprites in palettes 4 to 7, and the backdrop ($B3); when bit 0 of the room's first header byte is set, it also sets the fixed color to a gray of level 31, the brightest of 0 to 31, and a lit room gets a gray of 0. With the lantern and no torch lit, the code turns BG1 on the subscreen, so the subtraction takes that layer's colors instead, and each frame scrolls BG1 to set its cone picture in front of Link: one of four positions in the layer, chosen by his facing, offset from his position and clamped. Each torch he lights turns the subscreen off and lowers the gray: 8 with one torch, 4 with two, 0 with three or more, which leaves the room at full brightness.Code
Before the story counter reaches 2 (Zelda's rescue), and on screen $70 until bit $20 of its saved flags is set, the overworld's rain is BG1 alone on the subscreen, halved and added to BG2, the sprites, and the backdrop (color math $72). Every 4 frames the code steps the layer's scroll through a four-step cycle that alternately adds 4,352 (17 × 256) to its vertical scroll and 256 to its horizontal scroll. Lightning is a change of color math on fixed values of the game's 8-bit frame counter: on 3, 36, and 88 it becomes $32, the same add without halving, which brightens the screen, and on 5, 44, and 90 it goes back to $72; on 36 the thunder sound plays (bank 2, number $36). In each 256 frames the screen therefore flashes for 2, 8, and 2 frames (computed).Code
Each overworld area chooses its moving overlay, a BG1 picture alone on the subscreen: on screens $00 and $40 a fog (overlay $9D), except that screen $00 gets overlay $9E once bit $40 of special screen $80's saved flags is set; on screens $03, $05, and $07 overlay $95; on $43, $45, and $47 overlay $9C; on $70 the rain ($9F) until bit $20 of its saved flags is set, then overlay $9C; elsewhere the rain before the story counter reaches 2 and overlay $96 after. The fog, the rain, overlay $9E, and three special areas' overlays ($93, $94, and $97) are halved and added to BG2, the sprites, and the backdrop ($72); overlays $95 and $9C are added to the backdrop alone ($20). The fogs $97 and $9D drift on their own by 1/8 pixel a frame right and down (computed). Other overlays follow the camera's horizontal steps: at half the step, or a quarter for $95 and $9E. Overlay $9C instead rises by 1/8 pixel a frame (computed) and keeps BG2's horizontal scroll, except on screen $47, where neither drift runs.Code
Final Fantasy IV 1991Spells flash the screen with color math: a fixed color, any mix of red, green and blue, is added to BG1 and BG2, the monsters and the battle background, by the color math HDMA table, which covers the top 140 lines (computed) and turns color math off below them, over the menu. Five kinds of flash exist: on 2 frames and off 2 until stopped, a pulse rising from 0 to full (31) and back a step a frame until stopped, a single frame, a rise to a set level that holds, and a fall to 0 that ends it. Scripts start one with command $88; routines call it by color. The routine the source names Black Hole darkens the background and flashes white for 32 frames; Big Bang flashes green, red, yellow, blue and white for 8 frames each, four times over.Code
In the 2 battles flagged for transparent monsters (of 512; computed), the monsters show at half strength over the battle background: color math puts BG2 on the sub screen and adds it to BG1, the monsters' layer, halving the sum. Odin's summon sets the same color math partway through its attack loop, from the 17th of its 64 frames (computed).Code
Donkey Kong Country 1994In the first US release, Torchlight Trouble dims the stage with color math outside its beam (dkc-av/torchlight-beam-window). The start code of its 6 entrances loads 128 background colors into color memory with every bit inverted, sets color 0, the backdrop, to a gray of 16 of 31 in each channel (converted from hex), writes 255 to both bytes of color 17 (white, converted from hex), and fills the third background layer's map with one tile word (in the value). It puts the third layer alone on the main screen with window 1, inverted, applied to it, and the first and second layers and the sprites on the subscreen, with no color window in use. Color math subtracts the subscreen from the third layer and from the backdrop, and the cave display routine writes the same layers and color math again every frame. Where the third layer shows color 17, 31 less an inverted channel gives the channel back (computed), so the stage shows its own background colors; where the backdrop shows, 16 less the inverted channel leaves the channel 15 lower (computed). While a countdown the game keeps is above 0, each frame takes 1 off it, writes to the backdrop the color the new count picks from four (in the value, for counts 0 to 3), and turns off the main screen's layers and color math, so that frame shows the backdrop alone.Code
In the first US release, Poison Pond lays its third background layer over the rest of the stage at half strength. The second start step of its 2 entrances (by the disassembly's names, its start and its checkpoint) puts the third layer alone on the main screen and the first and second layers and the sprites on the subscreen, and sets color math to add the subscreen at half to the third layer and the backdrop. It turns on HDMA channels 2, 5 and 6; the underwater stages' channel setup points them at tables in RAM that set the second layer's horizontal scroll, the first layer's scroll and the third's down the screen. The other 7 underwater entrances (Croctopus Chase's, Coral Capers', Clam City's and Enguarde's bonus room's) take a second step that turns on channels 2 and 5 and sets the color math's layers and operation and the fixed color from a per-entrance table: adding on the second layer and the backdrop for Croctopus Chase, Coral Capers and Enguarde's bonus room, and subtracting at half on the second layer for Clam City.Code
Super Metroid 1994Rooms with fireflea FX darken BG2 and the backdrop by subtracting a gray fixed color, and the darkness pulses. Every 6 frames the pulse steps through 12 shades, 0, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, and 1, a 72-frame cycle (computed), and the gray's intensity is the shade plus a darkness level: 0, 6, 12, 18, 24, and 25 for 0 to 5 flies killed, since each fly killed adds a level. From the fifth fly on, the pulse holds at 6, so the screen stays at 31 (6 + 25, computed), the darkest. The HDMA object exists only for its per-frame routine, which also sets the room's layer blending to the fireflea configuration.Code

References

  1. ^ abCodeeverything8215, FF6 disassemblyanim_cmd.asm 7605–7621, 1822–1858; attack_anim_script.asm 14716–14744, 668–683, 5–22054; +1 files
    How we know
    7605; [ battle animation command $d4: set color math HDMA ]
    ⋮
    7610        lda     [zAnimScriptPtr]
    7611        sta     $10
    7612        lda     [zAnimScriptPtr],y
    7613        sta     $11
    7614        iny
    7615        lda     [zAnimScriptPtr],y                 ; main screen layers
    7616        jsr     SetColorMathHDMA
    
    src/btlgfx/anim_cmd.asm lines 7605–7621 at 8130132 · upstream ↗
    1823; [ set color add/sub data ]
    ⋮
    1825; +$10: shbo4321 mmss--cd (+$2130)
    ⋮
    1836SetColorMathHDMA:
    ⋮
    1840        lda     $10
    1841@c243:  sta     near w7e8993+1,x     ; set hdma data
    1842        sta     near w7e8993+101,x
    ⋮
    1853        sta     near w7e898e       ; set subscreen designation
    
    src/btlgfx/anim_cmd.asm lines 1822–1858 at 8130132 · upstream ↗
    14716; [ hide characters for esper attack (bg1) ]
    ⋮
    14718_d05516:
    14719        set_blank_frame 15
    14720        sfx PRE_GENJU_B
    14721        hide_bg1_thread
    14722        disable_char_pal_update
    14723        blank_frame
    14724        wait_scanline
    14725        color_math {ADD, SUBSCREEN}, BG2, SPRITE
    ⋮
    14729        loop 16
    14730                mod_pal CHAR, SUB, WHITE, +1
    14731                hide_chars
    ⋮
    
    src/btlgfx/attack_anim_script.asm lines 14716–14744 at 8130132 · upstream ↗

    3 more excerpts on the claim page

  2. ^ abCodeeverything8215, FF6 disassemblyinit.asm 638–646, 738–743, 839–846; init_2.asm 199–240; +2 files
    How we know
    639        lda     #$ff97          ; full subtract, all layers, white
    640@1213:  sta     near w7eea32,x
    641        inx2
    642        cpx     #$01c0
    643        bne     @1213
    644        shorta0
    645        lda     #$80
    646        sta     near w7ee9f9
    
    src/btlgfx/init.asm lines 638–646 at 8130132 · upstream ↗
    738; init fade in
    739        lda     #$4c
    740        sta     near w7ee9f7
    741        stz     near w7ee9f8
    742        lda     #1
    743        sta     near w7ee9f6                 ; enable fade in
    
    src/btlgfx/init.asm lines 738–743 at 8130132 · upstream ↗
    199; [ update screen fade in ]
    ⋮
    201UpdateFadeIn:
    ⋮
    207; increment screen brightness
    208        lda     near w7ee9f9
    209        and     #$0f
    210        cmp     #$0f
    211        beq     @b8b6
    212        inc
    213        sta     near w7ee9f9
    ⋮
    215; update hdma for fade bars
    216@b8b6:  shorti
    217        lda     near w7ee9f7
    ⋮
    
    src/btlgfx/init_2.asm lines 199–240 at 8130132 · upstream ↗

    3 more excerpts on the claim page

  3. ^ abCodeHerringway/ebsrc · SNESdev Wiki, “PPU registers”battle_swirl_sequence.asm 12–91; hardware.asm 70–94; +1 files
    How we know
    12	LDA #$0001
    13	STA $16
    14	LDA #$0004
    15	STA @SWIRL_RED
    16	STA @SWIRL_GREEN
    17	LDY #$0000
    18	STY @SWIRL_BLUE
    19	LDA BATTLE_INITIATIVE
    20	BEQ @UNKNOWN0
    21	CMP #INITIATIVE::PARTY_FIRST
    22	BEQ @UNKNOWN1
    23	CMP #INITIATIVE::ENEMIES_FIRST
    ⋮
    
    src/overworld/battle_swirl_sequence.asm lines 12–91 at 68aec5c · upstream ↗
    70.ENUM CGWSEL_BITS
    ⋮
    75	COLOUR_MATH_ENABLE_ALWAYS = 0 << 4
    76	COLOUR_MATH_ENABLE_MATHWIN = 1 << 4
    ⋮
    79	SUBSCREEN_BGOBJ_ENABLE = 1 << 1
    80	SUBSCREEN_BGOBJ_DISABLE = 0 << 1
    ⋮
    85.ENUM CGADSUB_BITS
    86	COLOUR_MATH_ADDSUB = 1 << 7
    87	COLOUR_MATH_DIV2 = 1 << 6
    
    include/hardware.asm lines 70–94 at 68aec5c · upstream ↗
    451	BOSS_FRANK = 448
    
    include/constants/enemy_groups.asm line 451 at 68aec5c · upstream ↗
    +--------- Operator type (0 = add, 1 = subtract) … |+-------- Half color math
    CGADSUB - Color math designation ($2131 write) · archived copy ↗
    |||| +-- Addend (0 = fixed color, 1 = subscreen) … ||++------ Sub screen color window transparent region … 1 |Outside color window … The sub-screen setting is for masking color math.
    CGWSEL - Color addition select ($2130 write) · archived copy ↗

    Claim page

Sources

Code

Secondary