El sistema gráfico de la SNES es uno de los más avanzados de su época, con capacidades únicas que permiten efectos visuales impresionantes.
La SNES tiene 8 modos gráficos principales que determinan cómo se organizan los fondos y sprites.
| Modo | Fondos | BPP | Colores | Uso Típico |
|---|---|---|---|---|
| 0 | 4 fondos | 2bpp | 16 (4 paletas) | Interfaces, texto |
| 1 | BG1:4bpp, BG2:4bpp, BG3:2bpp | Mixto | BG1/2:16, BG3:4 | Juegos con profundidad |
| 3 | BG1:8bpp, BG2:4bpp | Mixto | BG1:256, BG2:16 | Gráficos detallados |
| 7 | 1 fondo | 8bpp | 256 | Full-screen imágenes |
; Configurar Modo 1 con prioridad para BG3
lda #$09 ; %00001001
; Bit 0-2: Modo 1
; Bit 3: BG3 prioridad alta
sta $2105 ; Registro BGMODE
Los tiles son bloques de 8x8 o 16x16 píxeles que forman los elementos gráficos básicos.
2bpp (16 colores):
- Cada píxel usa 2 bits (4 colores por paleta)
- 16 bytes por tile (8x8)
4bpp (16 colores):
- Cada píxel usa 4 bits (16 colores)
- 32 bytes por tile (8x8)
8bpp (256 colores):
- Cada píxel usa 8 bits
- 64 bytes por tile (8x8)
; Cargar tileset en VRAM $0000
LoadTileset:
lda #$80 ; VRAM incremento +1 después de $2119
sta $2115
lda #$00 ; Dirección VRAM $0000
sta $2116
lda #$00
sta $2117
; Configurar DMA
lda #$01 ; Banco de datos
sta $4304
lda #$18 ; Puerto $2118 (VRAM data)
sta $4301
ldx #tileset_data ; Dirección fuente
stx $4302
ldx #$2000 ; Tamaño: 8KB
stx $4305
lda #$01 ; Modo 1 (transferencia de bytes)
sta $4300
lda #$01 ; Iniciar DMA canal 1
sta $420B
La SNES usa paletas de 16 colores (15-bit RGB) compartidas entre fondos y sprites.
Formato de color (2 bytes por color):
Bit 0-4: Azul (0-31)
Bit 5-9: Verde (0-31)
Bit 10-14: Rojo (0-31)
Bit 15: Sin uso
; Cargar paleta en CGRAM
LoadPalette:
stz $2121 ; Empezar en entrada 0 de CGRAM
; Configurar DMA
lda #$02 ; Banco de datos
sta $4304
lda #$22 ; Puerto $2122 (CGRAM data)
sta $4301
ldx #palette_data ; Dirección fuente
stx $4302
ldx #$0020 ; 32 bytes (16 colores)
stx $4305
lda #$00 ; Modo 0 (transferencia de bytes)
sta $4300
lda #$01 ; Iniciar DMA canal 1
sta $420B
; Paleta de 16 colores (32 bytes)
palette_data:
.dw $0000, $7FFF, $1CE7, $027F ; Gris, blanco, rojo, azul
; ... más colores
Cada fondo tiene sus propios registros de control:
| Registro | Fondo | Propósito |
|---|---|---|
| $2107-$210A | BG1-BG4 | Configuración de tiles (SC) |
| $210B-$210C | BG1/BG2, BG3/BG4 | Asignación de bloques de tiles (NBA) |
| $210D-$2114 | BG1-BG4 | Scroll (HOFS, VOFS) |
; Configurar BG1 en Modo 1
lda #%00001001 ; Tamaño tilemap 32x32, tiles en $0000
sta $2107 ; BG1SC
lda #$01 ; Tiles de BG1 en $1000
sta $210B ; BG12NBA
; Cargar tilemap
LoadTilemap:
lda #$80 ; VRAM incremento +1
sta $2115
ldx #$1000 ; Dirección VRAM del tilemap
stx $2116
; Configurar DMA
lda #$02 ; Banco de datos
sta $4304
lda #$18 ; Puerto $2118
sta $4301
ldx #tilemap_data
stx $4302
ldx #$0800 ; 32x32 tiles = 2048 bytes
stx $4305
lda #$01 ; Modo 1
sta $4300
lda #$01 ; DMA canal 1
sta $420B
Cada entrada de tilemap son 2 bytes:
Byte bajo:
Bit 0-9: Número de tile
Bit 10: Flip horizontal
Bit 11: Flip vertical
Byte alto:
Bit 0-2: Paleta (0-7)
Bit 3: Prioridad
Bit 4-7: Sin uso
; Scroll paralaje
UpdateParallax:
lda scroll_x
lsr a ; BG1: velocidad completa
sta $210D ; BG1HOFS
lsr a ; BG2: mitad de velocidad
sta $210F ; BG2HOFS
lsr a ; BG3: cuarto de velocidad
sta $2111 ; BG3HOFS
; Configurar Modo 7
lda #$07
sta $2105 ; BGMODE
; Matriz de transformación
; A = $211B (16-bit), D = $211E (16-bit)
; B = $211C (16-bit), C = $211F (16-bit)
; X = $211D (16-bit), Y = $2120 (16-bit)
; Rotación 45 grados (valores aproximados)
lda #$00B6 ; cos(45) ≈ 0.707 ≈ $B6/$100
sta $211B
lda #$00B6
sta $211C
lda #$FF4A ; -sin(45) ≈ -0.707 ≈ $FF4A
sta $211D
lda #$00B6
sta $211E
; Centro en (128,112)
lda #$0080
sta $211F ; Center X
sta $2120 ; Center Y
; Configurar HDMA para cambiar paleta en scanline
SetupHDMA:
lda #$02 ; Canal HDMA 2
sta $4300 ; Modo indirecto
lda #$32 ; Puerto $2132 (CGRAM data)
sta $4301
ldx #hdma_table
stx $4302
lda #$02 ; Banco de datos
sta $4304
lda #$04 ; Habilitar HDMA canal 2
sta $420C
; Tabla HDMA
hdma_table:
.db $20 ; 32 líneas
.db $00, $00 ; Color 0: negro
.db $40 ; 64 líneas
.db $1F, $00 ; Color 0: rojo
.db $00 ; Terminar
Organización recomendada:
$0000-$1FFF: Tiles de BG1 (4KB)
$2000-$3FFF: Tiles de BG2 (4KB)
$4000-$5FFF: Tiles de Sprites (4KB)
$6000-$7FFF: Tilemaps (8KB)
Consejo: Compartir paletas entre fondos y sprites cuando sea posible para maximizar el uso de colores.
; Configurar modo gráfico con 3 fondos
SetupLayers:
lda #$09 ; Modo 1, BG3 prioridad alta
sta $2105
; BG1: Capa principal (16x16 tiles)
lda #%00010001 ; Tilemap en $1000, 32x32
sta $2107
lda #$01 ; Tiles en $0000
sta $210B
; BG2: Capa de nubes (8x8 tiles)
lda #%00000010 ; Tilemap en $2000, 32x32
sta $2108
lda #$02 ; Tiles en $2000
sta $210B
; BG3: Interfaz (8x8 tiles)
lda #%00000011 ; Tilemap en $3000, 32x32
sta $2109
lda #$03 ; Tiles en $3000
sta $210C
; Efecto de fade out
FadeOut:
ldx #$10 ; 16 pasos
FadeLoop:
phx
jsr WaitVBlank
; Oscurecer todos los colores
ldy #$00
sty $2121 ; Empezar en color 0
ColorLoop:
lda $213B ; Leer CGRAM
pha
lda $213B
ply
; Reducir componentes RGB
dey
dey
; Escribir nuevo color
sty $2122
cpy #$200 ; 256 colores (512 bytes)
bne ColorLoop
plx
dex
bne FadeLoop