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.7z
Tutorial by bazz