Demo
Screenshot
Screen brightness transitions for fade in/out effects.
Learning Objectives
After this lesson, you will understand:
- How SNES screen brightness control works
- Creating smooth fade transitions
- Different fade speeds and styles
- Using fades for scene transitions
Prerequisites
- Completed background examples
- Understanding of VBlank timing
What This Example Does
Demonstrates multiple fade effects:
- Fade from black to full brightness
- Fade from full brightness to black
- Fast and slow fade speeds
- Button-triggered transitions
Frame 1: ████████████████ (Black)
Frame 5: ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ (25%)
Frame 10: ░░░░░░░░░░░░░░░░ (50%)
Frame 15: ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ (75%)
Frame 20: [Full Image] (100%)
Controls:
- Any button: Advance to next fade effect
Code Type
C with Direct Register Access
| Component | Type |
| Background setup | Library functions |
| Brightness control | Direct register (REG_INIDISP) |
| Fade timing | Frame counting with WaitForVBlank() |
| Input detection | Direct register access |
INIDISP Register
The INIDISP register ($2100) controls screen brightness:
Bits 0-3: Brightness level (0-15)
Bit 4: Force blank (1 = screen off)
Bits 5-7: Unused
| Value | Effect |
| $00 | Brightness 0 (black, screen on) |
| $0F | Brightness 15 (full) |
| $80 | Force blank (screen completely off) |
| $8F | Force blank at full brightness |
Basic Fade Implementation
Already in the lib. fadeOut(u8 speed) and fadeIn(u8 speed) are exposed from snes/console.h since v0.20.x — same signature, same semantics as the snippets below. The example calls those directly; the algorithm below is kept for pedagogical purposes so you can see how a fade works on the wire.
Fade In (Black to Full)
for (brightness = 0; brightness <= 15; brightness++) {
for (
u8 i = 0;
i < speed;
i++) {
}
}
}
void fadeIn(u8 speed)
Fade the screen from black (0) up to full brightness (15).
void WaitForVBlank(void)
Wait for next VBlank period.
static u8 i
Definition main.c:156
#define REG_INIDISP
Display control (W).
Definition registers.h:49
unsigned char u8
8-bit unsigned integer (0 to 255)
Definition types.h:47
Fade Out (Full to Black)
for (brightness = 15; brightness > 0; brightness--) {
for (
u8 i = 0;
i < speed;
i++) {
}
}
}
void fadeOut(u8 speed)
Fade the screen from full brightness (15) down to black (0).
Fade Speeds
Different speeds for different purposes:
| Speed | Frames per step | Total frames | Duration |
| 1 | 1 | 15 | 0.25 sec |
| 2 | 2 | 30 | 0.5 sec |
| 4 | 4 | 60 | 1.0 sec |
| 8 | 8 | 120 | 2.0 sec |
Quick Flash
Scene Transition Pattern
void changeScene(void) {
loadNewBackground();
loadNewSprites();
}
#define INIDISP_FORCE_BLANK
Definition registers.h:430
Build & Run
cd $OPENSNES_HOME
make -C examples/transitions/fading
Then open fading.sfc in your emulator (Mesen2 recommended).
Files
| File | Purpose |
| main.c | Fade logic and demo sequence |
| data.asm | Background graphics |
| Makefile | Build configuration (LIB_MODULES := console sprite dma input background) |
Exercises
Exercise 1: Smooth Fade
Create smoother fades using sub-frame timing (though limited by 16 brightness levels):
for (
u8 wait = 0; wait < 8; wait++) {
}
Exercise 2: Directional Wipe
Combine with window masking for a wipe effect instead of fade.
Exercise 3: Color Fade
Use color math to fade to a specific color instead of black:
void colorMathSetFixedColor(u8 r, u8 g, u8 b)
Set fixed color for blending.
static u16 b
Definition main.c:157
Exercise 4: Pulse Effect
Create a pulsing brightness effect:
static u8 brightness = 8;
brightness += pulse_dir;
if (brightness >= 15 || brightness <= 4) {
pulse_dir = -pulse_dir;
}
Technical Notes
Force Blank vs Brightness 0
- Brightness 0: Screen shows black, but PPU still renders
- Force Blank: PPU stops rendering, VRAM access is safe
Use force blank when updating graphics, brightness 0 for visual fades.
Fade During Gameplay
For in-game fades without stopping action:
- Use force blank only briefly for VRAM updates
- Fade brightness while game continues
- Game logic runs normally during fade
Alternative: Palette Fade
Instead of hardware brightness, modify palette colors:
for (
u8 i = 0;
i < 256;
i++) {
}
void dmaCopyCGram(const u8 *source, u16 startColor, u16 size)
Copy palette data to CGRAM (PVSnesLib compatible).
static u8 fade_level
Definition main.c:172
This allows fading specific layers independently.
What's Next?
Mosaic: Mosaic Example - Pixelation transitions
Parallax: Parallax Scrolling - Multi-speed scrolling with HDMA