Uno sguardo dentro al Nintendo DS: la grafica 2D

Pubblichiamo un contributo di Antonio Barba, sviluppatore software specializzato nel ramo videogiochi.

Come accennato nell’articolo precedente, il Nitro Processor, il componente principale del Nintendo DS, contiene 3 distinti coprocessori grafici denominati:
⁃ 2D Graphics Engine A
⁃ 2D Graphics Engine B
⁃ 3D Graphics Engine

La grafica 2D
I due coprocessori 2D Graphics Engine A e B, come intuibile, si occupano di disegnare la grafica 2D su ciascuno dei due schermi del Nintendo DS. Sono quasi gemelli, fatta eccezione per alcuni particolari che rendono l’engine B leggermente meno flessibile dell’engine A. Il programmatore può decidere arbitrariamente di collegare ciascun engine 2D allo schermo superiore o a quello inferiore, e può modificare questa impostazione in qualunque momento durante la pausa del Vertical Blanking (è quel breve periodo di tempo che intercorre tra la fine di un frame video e l’inizio del successivo).

Il timing dei due schermi è perfettamente sincronizzato, questo per evitare problemi nel caso si vogliano scambiare frequentemente gli agganci tra engine e schermo.
Nonostante il Nintendo DS sia provvisto esclusivamente di schermi a cristalli liquidi, l’engine grafico simula la presenza di un segnale video analogico. Questo significa che dopo il disegno di una riga orizzontale ci sarà una pausa definita Horizontal Blanking, che nei display a tubo catodico serve per riportare il pennello elettronico all’inizio della riga successiva. Dopo la scansione delle 192 righe orizzontali del display, segue il Vertical Blanking, più lungo dell’H-Blank, che serve per riportare il pennello elettronico (simulato) all’inizio della prima riga dello schermo per disegnare il frame successivo.

La presenza di queste pause consente di “infilare” delle istruzioni tra il disegno di una riga e la successiva, oppure tra un frame e il successivo, in modo perfettamente sincronizzato con lo schermo. Questa caratteristica consente di scrivere i giochi esattamente come si faceva nelle vecchie console casalinghe e nei primi Home Computer, che erano sostanzialmente legati (nella temporizzazione) allo standard televisivo PAL o NTSC (a seconda del paese).
Ad esempio, è possibile modificare al volo i registri video durante la schermata, per simulare effetti grafici particolari come visualizzare migliaia di colori usando palette da soli 16 colori (basta usare una palette diversa per ogni riga). Tuttavia questa tecnica, pur essendo attuabile, non è necessaria sul DS, perchè è possibile visualizzare immagini fino a 15 bit di colore (cioè 32768 colori).
Composizione di una schermata tipica
I due engine 2D compongono la schermata utilizzando tipicamente 3 elementi:
⁃ BG
⁃ OBJ
⁃ Backdrop

BG sta per Background. Si tratta di grosse schermate in formato Bitmap o Text. Si usano prevalentemente per gli sfondi. Possiamo avere fino a 4 diversi BG sovrapposti.
OBJ sta per Objects, e si tratta dei famosi Sprites. Sono piccoli elementi grafici che possono muoversi in modo indipendente dallo sfondo. Anch’essi possono essere in formato Bitmap o Text.

Infine il Backdrop non è altro che “tutto il resto”, cioè un colore omogeneo che copre il fondo dello schermo. Tipicamente il colore di Backdrop coincide con il colore numero 0 della palette principale (c’è sempre una palette principale con una sua memoria dedicata, ma possono essere caricate delle palette estese sulla comune VRAM).

A seconda della modalità video selezionata, cambiano il tipo e la dimensione dei 4 BG presenti in ciascun engine, inoltre i due engine 2D vengono configurati in modo indipendente, e devono spartirsi di conseguenza i vari banchi di VRAM.
Si va dal Mode 0 che imposta tutti e 4 i BG in modalità Text, fino al Mode 5 che imposta i primi 2 come Text e gli altri 2 come Affine Extended. Il 2D Engine A, a differenza del B, può impostare il BG0 in modalità 3D il che consente di visualizzare le immagini generate dal 3D Engine come se fossero un BG, quindi facilmente mescolabili insieme alla grafica 2D.

La dimensione di un BG va da un minimo di 128×128 (utile per rappresentare grossi oggetti che non entrano in uno Sprite) fino ad un massimo di 1024×1024 (utile per fare lo scrolling di grosse mappe). Il numero di colori va da un minimo di 16 fino ad un massimo di 32768. La combinazione di dimensioni, colori e formato influiscono sulla quantità di VRAM occupata, e di questo il programmatore deve tener conto quando progetta la composizione di una schermata di gioco.

Gli OBJ hanno dimensioni che variano da 8×8 fino a 64×64 pixel, possono avere forma rettangolare purchè le dimensioni siano sempre potenze di 2 (ad esempio 32×16 è una dimensione valida, mentre 40×20 non lo è). Si possono utilizzare fino a 128 OBJ contemporaneamente, e possono stare tutti e 128 contemporaneamente sulla stessa riga (il Graphics Engine del GameBoy Advance e tutte le precedenti console avevano dei limiti per quanto riguarda il numero massimo di sprite su una linea).

Come per i BG, anche gli OBJ possono avere da 16 a 32768 colori.
Characters, Bitmap e trasformazioni affini
Sia i BG (sfondi) che gli OBJ (sprite), possono essere rappresentati in memoria in due diversi formati.

Il formato Character è quello più utilizzato per i BG, perchè consente di disegnare grandi aree usando poca memoria. L’immagine viene scomposta sostanzialmente in caselle quadrate da 8×8 pixel, e a ciascuna casella è assegnato un numero, è la cosiddetta Screen Map. Il 2D Graphics Engine legge questo numero e lo usa come “indice” per andare a pescare la corrispondente casella 8×8 all’interno della Character Map.

Sembra complicato come meccanismo, ma basta guardare la grafica un vecchio gioco per capire subito come funziona. Ad esempio nella classica schermata di un gioco di tipo RPG possiamo vedere che il tipico cespuglietto d’erba è sempre identico ovunque si trovi. L’immagine di questo cespuglietto sarà rappresentato, ad esempio, dalla casellina numero 5 della Character Map. Se vogliamo disegnare una fila di 4 cespugli sullo schermo, basterà scrivere una file di byte nella Screen Map contenente i valori 5555.

È chiaro che l’uso intelligente di questa tecnica consente di risparmiare moltissima memoria video.

La Character Map, a sua volta, rappresenta i pixel delle caselline utilizzando una Palette di colori per risparmiare ulteriore memoria. In questo modo, anziché usare 16 bit per ogni singolo pixel, si usano solo 4 bit (16 colori) oppure 8 bit (256 colori) per pixel. Il numero rappresentato dai 4-8 bit è considerato come un indice per andare a pescare il vero colore, contenuto nella Palette, che è formato da 15 bit (5 per il Rosso, 5 per il Verde e 5 per il Blu), il sedicesimo bit in alcuni casi viene usato per indicare che il colore è trasparente, ma spesso è semplicemente ignorato.

Ricapitolando, per ogni pixel del BG il 2D Graphics Engine legge il valore della ScreenMap corrispondente, usa il numero come indice per pescare una casellina 8×8 dalla CharacterMap, poi prende il numero corrispondente al pixel da disegnare, e lo usa come indice per pescare dalla Palette il vero colore in formato RGB. Tutte queste operazioni sono eseguite dall’hardware dedicato del 2D Graphics Engine, quindi il risparmio di memoria è ottenuto senza nessun tipo di sacrificio della potenza di calcolo della CPU.

Il formato Bitmap è più semplice. Ciascun pixel contiene un valore a 4,8 o 16 bit che rappresenta direttamente il colore. Se i bit sono 4-8, questi vengono usati come indice per pescare il colore RGB da una Palette. Se i bit sono 16 vengono usati i primi 15 come canali RGB (5 bit per canale) e il sedicesimo bit se è impostato a 1 significa che il pixel corrente è un pixel normale, se viene impostato a 0 significa che quel pixel non deve venire disegnato, e al suo posto si vedrà lo sfondo. Possiamo considerarlo un sorta di canale Alpha ad un solo bit (completamente opaco o completamente trasparente).

Le Trasformazioni Affini sono degli effetti che possono venire applicati agli OBJ ed ai BG (solo nelle modalità Affine e Affine Extended, che a loro volta possono essere sia di tipo Character che Bitmap). Tale nome è preso in prestito dalla geometria e, in sostanza, si riferisce alla possibilità di applicare 3 effetti di base: scala, rotazione, traslazione.
Combinando queste tre trasformazioni si possono creare effetti di scrolling, rotazione e zoom con una fluidità perfetta, perchè tutti i calcoli necessari sono effettuati da hardware dedicato.
Effetti grafici

Sui BG e sugli OBJ, in base al loro tipo ed alla modalità video scelta, possono essere applicati alcuni effetti grafici, come alpha blending a 5 bit (32 livelli trasparenza), effetto Mosaico (per vedere l’immagine “a quadrettoni”, effetto molto utilizzato nei vecchi giochi come transizione tra una scena e l’altra), flip orizzontale e verticale (utile per avere immagini invertite ad effetto specchio, si usa spessissimo nella modalità Character per evitare di memorizzare le varianti speculari di ogni casellina risparmiando ulteriore memoria).
Conclusione

In questo articolo abbiamo visto a grandi linee quali sono le funzioni dei 2D Graphics Engine. Nel prossimo prenderemo in esame il 3D Graphics Engine e vedremo come questo si integri con il già citato BG0 del 2D Graphics Engine A, per dar vita ad un interessante quanto utile mix tra scene poligonali ed elementi 2D.

Press ESC to close