SNES Development
Translucency

Translucency is a cool effect, an example would be the water effects in Secret of Mana. I’m just not in the mood to chat, so let’s get right into it.

We normally set things to the Main Screen register ($212C) in order to see them on the screen. Now we will write to the sub screen register. It’s simple. You just set the layer you want to be translucent as a subscreen. I read a doc that says the subscreens are actually the opaque layers, but that confused me when I tried to apply it. So I just go by saying that you set the subscreen to what you want to appear as being translucent. got it? so say you want BG2 to be translucent. You’d start by making BG2 a subscreen:

Register $212D: Sub Screen Designation (W/1b)
---s4321  s: sprites enable  4-1: BG(1-4) enable

lda #%00000010
sta $212D

That’s done. Now you need to learn how to make it translucent.

To tell the SNES you want to use subscreen Addition/Subtraction (which this is called on the SNES, because you are adding or subtracting colors to get the translucency effect) you need to set bit 1 of $2130. Let’s take a look at that register.

Note: Some info used from Anomie’s Register Doc.

Register $2130 - Color Addition Select (W/1b)
ccmm--sd  cc: Clip colors to black before math
                00 = never
                01 = Outside Color Window only
                10 = Inside Color Window only
                11 = Always (whole screen)
          mm: Prevent color math
                00 = never
                01 = Outside Color Window only
                10 = Inside Color Window only
                11 = Always
          s: Determines type of Addition/Subtraction (ADD/SUB)
                0 = Fixed Color ADD/SUB
                1 = Subscreen ADD/SUB
          d: Direct color mode for 256-color BGs

The most important bits for us in this register are 1, 4-5, and 6-7.

Bit 1 determines the type of Color ADD/SUB we will use. We want to add/sub a subscreen, so we set the bit.

Bits 4-5: Prevents color math in the specified areas. Our Init routine originally sets these bits to prevent color math, but now we want color math. We’ll set these to ‘never disable color math,’ 00.

Bits 6-7: This clips all the pixels in the specified area black. Well we don’t want that so we’ll keep that as ‘never,’ 00.

In the end this is just a 'lda #$02' + 'sta $2130'.

Now you have to tell the SNES a couple more things in $2131.

Register $2131 - Color Math Designation (W/1b)
Shbs4321  S: ADD/SUB select
                0 = Add the colors
                1 = Subtract the colors
          h: Half color math
                result of color math is divided by 2.
                (except in fixed color mode or when color is clipped)
4/3/2/1/s/b: Enable color math on BG1-4, Sprites, or backdrop color
                when enabling for sprites, only sprites using palette entries 
                4-7 are affected by translucency.

Not too hard right? All done.. Let’s apply it.

Here’s source, assuming that header.inc, InitSNES.inc, and LoadGraphics.asm are in the same directory. I couldn’t think of anything to do so I just ripped the ghost house image and redid the translucent cloud effect.

;== Include MemoryMap, Vector Table, and HeaderInfo ==
.INCLUDE "header.inc"

;== Include SNES Initialization routines ==
.INCLUDE "InitSNES.asm"
.INCLUDE "LoadGraphics.asm"


;============================================================================
; Main Code
;============================================================================

.BANK 0 SLOT 0
.ORG 0
.SECTION "MainCode"

Start:
    InitSNES
    
    rep #$10
    sep #$20
    
    LoadPalette CloudPalette, 0, 2          ; simple cloud palette, only 2 colors
    LoadPalette LandPalette, 16, 20         ; The ghosthouse scene palette
    LoadBlockToVRAM LandTiles, $0000, $E80  ; Ghosthouse tiles
    LoadBlockToVRAM CloudTiles, $1000, $170 ; Cloud tiles
    LoadBlockToVRAM Maps, $0800, $1000      ; Ghosthouse and Cloud tilemaps
                                            ; stored sequentially
    
    jsr SetupVideo                          ; you know the drill
    
    lda #$80
    sta $4200                               ; enable VBlank
    
Loop:
    WAI
    
    jmp Loop
    
VBlank:
    rep #$30
    pha
    phx
    phy
    
    rep #$10
    sep #$20
    
    lda $4210
    
    lda $00
    ina
    and #$03
    sta $00
    bne end         ; This slowly scrolls the clouds
    lda $01
    ina
    sta $01
    sta $2111

end:    
    rep #$30
    ply
    plx
    pla
    RTI
    
    
SetupVideo:
    rep #$10
    sep #$20
    
    lda #$09
    sta $2105       ; mode 1 with priority bit set (give BG3 more priority)
    
    lda #%00001000
    sta $2107       ; $0800 = BG1 Map
    lda #%00001100  ; $0C00 = BG3 Map
    sta $2109
    
    stz $210B       ; $0000 = BG1 graphics data
    lda #$01
    sta $210C       ; $1000 = BG2 graphics data
    
    lda #%00000001
    sta $212C       ; Set BG1 mainscreen
    
    lda #%00000100
    sta $212D       ; Set BG3 subscreen
    
    lda #$02
    sta $2130       ; Enable Subscreen Color ADD/SUB
    
    lda #%00100001
    sta $2131       ; Color addition on BG1 and Backdrop color
    
    lda #$0F
    sta $2100       ; Screen on!
    
    RTS
    
.ENDS

.SECTION "CharacterData"
LandPalette:
    .INCBIN "gfx/ghosthouse.clr"
    
CloudPalette:
    .INCBIN "gfx/clouds.clr"        ; holds the backdrop color (black) & dark blue
                                    ; for the clouds
LandTiles:
    .INCBIN "gfx/ghosthouse.pic"    ; $E80 bytes
    
CloudTiles:
    .INCBIN "gfx/clouds.pic"        ; $170 bytes
  
Maps:
    .INCBIN "gfx/ghosthouse2.map"
    .INCBIN "gfx/clouds.map"
    
.ENDS

Complete Source Code: Translucency Tutorial

Tutorial by bazz