Finally, after making you wait too long, I am about to reveal how Freedom Fighter's smooth scrolling works.
Geppo's MSX Adventure
mercoledì 27 aprile 2022
FREEDOM FIGHTER SMOOTH SCROLLING (ENG)
martedì 26 aprile 2022
FREEDOM FIGHTER SMOOTH SCROLLING (ITA)
Finalmente, dopo aver rinviato troppo a lungo, mi accingo a rivelare come funziona lo smooth scrolling di Freedom Fighter.
Poiché devo presumere che l'articolo verrà letto anche da persone che non conoscono bene il sistema MSX (e in questo caso specifico MSX1) dovrò ovviamente accennare anche a come è organizzata la memoria video (VRAM) di questo sistema (almeno nel modo video Graphic2 che è quello usato in Freedom Fighter).
Comiciamo con la nametable. La nametable è l'area dello schermo, quella in cui in tutti i sistemi (almeno quelli che conosco) sono “contenuti” i caratteri che appaiono sullo schermo. Lo schermo dell'MSX ha una risoluzione di 256x192 pixels. Per cui è formato da 24 righe, ognuna delle quali contiene 32 caratteri 8x8 pixel. In totale abbiamo quindi 768 caratteri, per cui la nametable è lunga 768 bytes.
La particolarità dell'MSX, rispetto ad altri computer, riguarda proprio l'uso di questi caratteri. In computer come il Commodore64 abbiamo un character set di 256 caratteri, liberamente posizionabili in qualsiasi punto dello schermo. Nel sistema MSX, invece, nel modo Graphic2 lo schermo viene diviso in 3 zone da 8 righe ciascuna. Ognuna di queste zone ha un proprio charater set di 256 caratteri (32x8=256) per cui lo schermo può essere riempito con 768 caratteri tutti diversi uno dall'altro (questo è particolarmente utile per le schermate in grafica bitmap).
Questo significa che per avere gli stessi caratteri in tutte e 3 le zone dello schermo dovremo ridefinirli 3 volte.
Gran parte della memoria VRAM è utilizzata proprio per memorizzare le forme dei caratteri e i loro attributi colore.
Ogni “blocco” di caratteri occupa 256x8=2048 Bytes. Quindi le definizioni di tutti e tre i blocchi di caratteri usano 6144 Bytes dei 16384 disponibili nella VRAM dell'MSX1. La tabella degli attributi colori ha esattamente la stessa lunghezza, perchè per ogni linea di 8 pixel di ogni carattere possono essere specificati 2 colori (primo piano e sfondo): poiché l'MSX1 ha solo 16 colori, con un singolo byte possiamo inserire entrambi (uno del nibble alto e uno nel nibble basso). Quindi anche le definizioni dei colori occupano 6144 Bytes. Insomma, 12 KB se ne sono già andati per le definizioni dei nostri caratteri (la comunità MSX li identifica come “tiles”).
Fortunatamente, una volta definite forme e colori ogni carattere avrà un codice univoco, per cui richiamando il carattere 0 (ad esempio) esso comparirà a schermo completo dei suoi colori.
Quindi per quanto concerne i caratteri, essi occupano (compresa la nametable) circa 13KB. I rimanenti 3KB contengono le definizioni dei 32 sprites hardware e i loro rispettivi attributi (ma non ne parlerò perché non è rilevante per la tecnica dello scrolling di cui sto per parlare).
Come molti di voi sapranno, l'MSX1 non possiede nessun tipo di ausilio hardware allo scrolling. Per cui, tutto quello che scorre sullo schermo è frutto di tecniche software: dagli scrolling a blocchi a quelli che in diversi modi hanno cercato di portare fluidità nello shift degli schermi delle macchine dotate di tms9918 (nelle sue varie incarnazioni) e compatibili (quindi non solo MSX ma anche Colecovision, Sega SG-1000 e TI99/4A, per dirne alcuni).
Prima di descrivere la mia tecnica personale vediamo quale siano quelle più comunemente utilizzata per simulare uno scrolling verticale su MSX. Diamo ovviamente per scontato che tutti e tre i blocchi da 256 caratteri siano definiti allo stesso modo, perchè i caratteri che sono nel primo blocco attraverseranno tutto lo schermo e passeranno quindi al secondo e terzo blocco...
La prima tecnica è quella più semplice. Si tratta ovviamente dello scrolling a blocchi (caratteri), quindi con lo spostamento di 8 pixel per volta. Come detto, lo schermo MSX è formato da 24 righe da 32 caratteri ciascuna:
La seconda tecnica, comunemente usata per avere uno scrolling verticale sufficientemente fluido su MSX è quella dello scrolling a passi di 2 pixel. In pratica, dobbiamo tenere memorizzati in VRAM i vari fotogrammi che compongono lo spostamento di un carattere verso un altro. In questo modo, ad ogni “passo” dello scrolling sostituiamo tutti i caratteri presenti nell'area di gioco con il loro fotogramma successivo (per eseguire lo scrolling completo di un carattere servono 4 fotogrammi). Dopo aver “sostituito” i caratteri 4 volte si ritorna al carattere di partenza e allo stesso tempo si effettua uno scrolling di 8 pixel.
Vediamo un esempio con la grafica di Freedom Fighter.
Ma forse è più chiaro con un esempio visivo:
Oppure no.
Ecco come ho affrontato la sfida per il mio Freedom Fighter.
Il primo passo è stato ovviamente decidere le coppie di caratteri con i quali avrei costruito la mappa (abbiamo detto che lo scrolling avviene sempre tra due caratteri, no?). Cominciamo col dire che ho scelto di tenere disponibili tutte le lettere dell'alfabeto (oltre ai numeri e alla punteggiatura). Dopodiché ho selezionato 30 coppie di caratteri, ottenute mescolando 14 caratteri unici. Pochi per avere un risultato sufficiente. Per cui ad un certo punto del livello il tileset (gli MSXisti usano il termine tile per riferirsi alle “mattonelle” che compongono la grafica) viene cambiato con un altro di 30 coppie di caratteri, alcuni dei quali sono in comune, per facilitare la transizione da un tileset all'altro.
Questi sono i due tileset del primo livello (3 righe di “coppie” per ogni tileset):
Il tile di partenza per lo scrolling è, tra i due, il carattere che sta sotto (quello che verrà “compenetrato” dal carattere sovrastante). Il lavoro che viene eseguito, per ogni scorrimento di un pixel (e per ogni coppia di caratteri) è questo:
Queste coppie di tiles sono memorizzate nella ROM della cartuccia (ma nella primissima versione della routine di scrolling erano memorizzate in RAM) una di seguito all'altra, prima le definizioni dei caratteri e di seguito gli attributi colore. Quindi da ogni coppia di tiles “estraggo” (puntando alla giusta locazione di memoria con un offset) gli 8 bytes della definizione del carattere e li scrivo in VRAM, in tutti e tre i blocchi caratteri (è infatti necessario che i caratteri siano gli stessi in tutti e tre i blocchi). Subito dopo ripeto l'operazione per gli attributi colore: estraggo gli 8 bytes corrispondenti dei 30 caratteri e li scrivo in VRAM in tutti e tre i blocchi.