Rieccomi, sono riuscito a preparare anche questo capitolo XD
Oggi parliamo dei tiled background
Regular tiled background
Le tilemap sono utilizzate dalla maggior parte dei giochi per gba, il motivo è che richiedono molto meno spazio in memoria rispetto alla grafica bitmap.
Prendete l’immagine 9.1 a, noterete che ci sono parti ripetute. Questi sono i tile. L’elenco di tile unici è il tileset (figura 9.1 b) , ogni elemento dell’immagine ha un indice di tile che indica quale tile deve essere renderizzato (figura 9.1 c). Sostanzialmente è così che funzionano le tilemap, non disegniamo l’intera immagine ma raggruppiamo i pixel in tile e usiamo questi per comporre l’immagine.
Ora nel gba abbiamo tre modalità tile (0,1 e 2). È possibile avere fino a 4 sfondi che usano le tilemap. Le dimensioni delle tilemap sono definite dai registri di controllo e sono dai 128x128 ai 1024x1024 pixel. Ogni tile deve essere 8x8 pixel.
Sia i tile che la tilemap si trovano nella VRAM, che è suddivisa in charblocks e screenblocks. Il tileset si trova nei charblock e la tilemap negli screenblock. Poiché la parola tile si usa sia per i tile grafici che per gli elementi della tilemap, chiameremo Screen Entry (SE) gli oggetti che si trovano negli screenblock e tile quelli del tileset.
Per le tilemap abbiamo a disposizione 64KB di VRAM (indirizzi 0600:0000h – 0600:FFFFh), che sono utilizzati per gli screenblock e i charblock. Possiamo scegliere quali dei due utilizzare attraverso i registri di controllo ma, dato che condividono la stessa area in memoria, dobbiamo fare attenzione a non scrivere i charblock e gli screenblock agli stessi indirizzi (vedi tabella 9.1).
Ogni screenblock è lungo 2048 byte, ossia 32 screenblock totali. Mentre ogni charblock è lungo 16KB, cioè 4 blocchi totali.
Ora, ci sono quattro passaggi necessari a impostare un tiled background:
1. carica la grafica: i tile nei charblock e i colori nella background palette
2. carica una mappa in uno o più screenblock
3. imposta la modalità corretta in REG_DISPCNT e attiva un background
4. Inizializza il registro di controllo dei background per usare i Character Base Block, Screen Base Block e bitdepth corretti
Tipi di background
Come per gli sprite, ci sono due tipi di tiled background: regular e affine. Il tipo dipende dalla modalità video (tabella 9.2). Essenzialmente funzionano allo stesso modo, ma quelli affine usano più registri e le mappe sono formattate diversamente. Per ora vediamo solo i regular.
Tutti i background hanno tre registri di controllo fondamentali. Il primo è il REG_BGxCNT dove alla x dovete sostituire 0,1,2 o 3. Qui indichiamo qual è la dimensione della tilemap e quali charblock e screenblock usa.
Gli altri due registri fondamentali sono i registri di scrolling, REG_BGxHOFS (quello di scroll orizzontale) e REG_BGxVOFS (scroll verticale).
Ciascuno di questi registri è da 16bit. REG_BG0CNT si trova all’indirizzo 0400:0008h, seguito dagli altri. Gli offset sono accoppiati con i background, formando coppie di coordinate. Che iniziano da 0400:0010h (tabella 9.3)
Nella tabella seguente è spiegato a cosa serve ciascun bit del registro e le dimensioni supportati dai due tipi di background:
Ci sono due cose da tenere a mente per quanto riguarda i registri di scrolling:
1. Sono registri di SOLA SCRITTURA, il che significa che non è possibile leggere i valori che contengono purtroppo, ad esempio REG_BG0HOFS++ non funziona.
2. cosa indicano: la posizione dello schermo sulla mappa, cioè non la posizione della mappa sullo schermo (che è come funzionano gli sprite).
La tabella seguente invece mostra cosa fanno i bit degli screen entry:
Layout della mappa
L'indice di screenblock impostato in REG_BGxCNT è lo screen base block, cioè il blocco da cui inizia la tilemap.
Supponiamo di avere una mappa grande tw×th tile. Trattandosi di una matrice, vi aspettereste di trovare lo screen entry alla posizione (tx, ty) con la formula n = tx + ty*tw, come funziona di solito con le matrici. E in effetti funziona… ma solo all'interno di un singolo screenblock.
Il problema è che i background più grandi di 32×32 tile non si limitano a usare più screenblock in modo lineare: vengono trattati come quattro mappe separate (vedi tabella 9.5). Ogni blocco numerato è un blocco consecutivo in memoria, quindi per trovare l'indice di uno screen entry dovete prima capire in quale screenblock vi trovate, e poi calcolare la posizione dello SE all'interno di quello screenblock.
È più semplice di quanto sembri, perché sappiamo che ogni screenblock contiene 32×32 tile. Procediamo così:
Trovare lo screenblock. Dividiamo le coordinate del tile per 32 per ottenere le coordinate dello screenblock:
sbx = tx/32 e sby = ty/32
Poi convertiamo questa coppia in un numero singolo con la solita formula, ricordando che qui la larghezza va espressa in screenblock (tw/32), non in tile:
screen base block = sbx + sby*(tw/32)
Trovare lo SE dentro lo screenblock. Calcoliamo il resto della divisione per avere le coordinate locali (tx%32 e ty%32) e riusiamo la stessa formula di conversione coppia → numero. Dato che ogni riga dello screenblock è larga 32 tile:
se_locale = (tx%32) + (ty%32)*32
Combinare i due. L'indice finale è la SE locale, spostata in avanti di tanti screenblock interi quanti ne precedono. Ogni screenblock contiene 1024 SE (32×32), quindi:
n = sbb*1024 + se_locale
Momento Demo:
A differenza delle altre volte, qui sono proprio una serie di passaggi da seguire, quindi non ho preparato una mia demo. Userò la demo del tutorial che seguo. La demo completa se siete interessati a provarla la trovate qui.
Questi sono i passaggi che ho elencato prima per caricare la mappa:
1. carica la grafica: i tile nei charblock e i colori nella background palette
2. carica una mappa in uno o più screenblock
3. imposta la modalità corretta in REG_DISPCNT e attiva un background
4. Inizializza il registro di controllo dei background per usare i Character Base Block, Screen Base Block e bitdepth corretti
ma fatti direttamente in C:
nota: se provate a caricare i tile e la mappa nella stessa posizione in memoria, vedrete una cosa del genere:
Fonte: https://gbadev.net/tonc/regbg.html
Con questo abbiamo finito il tutorial base Se siete riusciti a seguire tutto, questi vi danno le basi per fare un gioco per gba (per ora senza audio).
Seguendo i capitoli fatti finora e mettendo tutto assieme, ho fatto Pong se volete esplorare un po' il codice o semplicemente provare il giochino, ve lo lascio qui
pong.zip
Se siete interessati, c'è un'altra sezione che tocca questi argomenti (alcuni più brevi di altri, quelli dov'è scritto affine sono un po' più complicati: contengono matematica un po' avanzata):
GBA Extended
10. The affine transformation matrix
11. Affine sprites
12. Affine tiled backgrounds
13. Graphic effects
14. Direct Memory Access
15. Timers
16. Hardware interrupts
17. BIOS calls
18. Beep! GBA sound introduction
Fatemi sapere se volete vedere anche questi @ZedeFire @VincyDarkHeart @evilespeon @Macca