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.
Congratulazioni, Giuseppe!
RispondiEliminaNon sarei mai in grado di fare quanto hai fatto tu per due motivi: la mia piattaforma di riferimento era il C64 (ci capivo comunque troppo poco, anche se qualche piccolo effetto di scrolling di caratteri lo riuscivo a fare; restavo in ogni caso sempre infinitamente lontano da quello che vedevo fare dai nordeuropei!) e non conosco MSX; tuttavia ho capito diciamo al 90% quello che mettevi in pratica. Ho letto con interesse il tuo post e ti manifesto tutta la mia stima! 💪💪💪
Ti ringrazio immensamente per il commento. Fa piacere sapere di aver scritto in modo abbastanza chiaro da far capire cosa si è fatto, soprattutto quando sai benissimo di aver usato delle tecniche cervellotiche :)
EliminaCiao Giuseppe, se non ho capito male, copi i tiles nei 3 set. E qui viene il mio dubbio: Non basta impostare le schermo in screen2, quindi 256 tiles in totale e lavorare solo su un unico set?
RispondiEliminascusa intendevoi questo settaggio per avere un unico set di 256 char per tutto lo schermo:
RispondiElimina10 SCREEN 1
20 VDP(0)=VDP(0) OR 2
30 VDP(1)=VDP(1) AND &HE7
40 VDP(3)=&h9F:VDP(4)=0
Purtroppo la soluzione che proponi non è attuabile per diversi motivi. Il primo motivo è che non è compatibile con tutti gli MSX. Infatti funziona solo sui vdp Texas Instruments. Su quelli Toshiba non funziona affatto.
RispondiEliminaE se anche funzionasse c'è un altro grossissimo problema. Questa "modalità " non ufficiale purtroppo ha un bug: oltre a replicare la definizione dei tile in tutte e tre le zone (infatti non riduce il numero dei tileset, semplicemente effettua un mirroring) effettua anche un mirroring dei primi 8 sprites a video su tutte e tre le zone. Per cui ci si dovrebbe limitare ad usare solo gli sprite da 8 a 31 (p e 7 sono fuori gioco). Questa "conseguenza" si può usare nelle demo.competition perché apparentemente permette di mettere su schermo 24 sprites (8x3) + 24 sprites non moltiplicati (quindi 48 oggetti su schermo invece che 32). Il problema è che NON è una cosa su cui fare affidamento, perché se il vdp è torchiato a dovere e inizia a scaldare il mirroring scompare.
E, ripeto, non è compatibile con tutti i modelli msx perché non replicabile su vdp toshiba.
A questo proposito è possibile utilizzare il mirroring NON per la definizione dei pattern ma per i colori. Il mirroring dei colori NON causa mirroring degli sprites. Ma resta sempre l'incompatibilità con i vdp Toshiba. Puoi vedere ad esempio che Uridium per MSX1 ha nella schermata principale proprio la scelta per vdp Toshiba perché usa il mirroring delle tabelle colori per migliorare le performance. Io non ho voluto farlo perché volevonche il gioco avesse le stesse prestazioni su tutti gli msx
Sono alle prese con un esperimento di scroll fluido.
RispondiEliminaIn pratica ho questa configurazione:
Pattern e Color da 0 a 127 (nei 3 banchi)
Color e Pattern da 128 a 255 (nei 3 banchi), quindi con Pattern e Color scambiati rispetto al set precedente
Valorizzo il set da 0 a 127 e visualizzo il set da 128 a 255
Scambio Pattern e Color tramite registri
Valorizzo il set da 128 a 255 e visualizzo il set da 0 a 127
e così via
Poichè valorizzo un set ma nè visualizzo un altro, secondo te devo sempre attendere il VBLANK?
oppure è sufficiante farlo solo quando vado a visualizzare?
Grazie ancora per il supporto
Puoi tranquillamente farlo fuori dal vblank. La routine di scrolling di Freedom Fighter lavora fuori dal vblank proprio perché l'area di lavoro non è visualizzata. È a tutti gli effetti una tecnica di double buffering
Elimina