Dopo aver analizzato e valutato la complessità implementativa del controllore video packed nelle sue funzioni basilari, passiamo a quelle più avanzate e per le quali l’Amiga è stato apprezzato: scroll e overscan.
Il controllore video – bitplane – Scroll e overscan
Una delle caratteristiche più note e acclamate dell’Amiga è stata, infatti, l’estrema fluidità dello scroll della grafica, con giochi come Kick Off che hanno contributo a marchiare a fuoco nelle menti di milioni di persone. Mentre con lo scroll verticale ci sono pochi problemi (la rogna maggiore è il dover cambiare i puntatori di tutti i bitplane. Cosa alquanto difficile usando molti bitplane, a causa del poco tempo a disposizione durante l’intervallo di horizontal retrace), con quello orizzontale l’inconveniente è rappresentato dal dover programmare il controllore video in modo da leggere anzitempo 16 pixel (leggendo una word aggiuntiva dai bitplane) e scartando quelli che non saranno visualizzati, com’è spiegato con dovizia di particolari nell’Hardware Manual. Allo scopo esiste un registro, BPLCON1
, in cui impostare di quanti pixel/bit scrollare la word aggiuntiva (servono 4 bit allo scopo).
Ciò significa partire dallo slot $30 anziché dal $38 per la lettura dei dati di tutti bitplane, in modo da dare la possibilità al controllore video di avere abbastanza tempo per scrollare via via i pixel buttando via quelli non necessari (non visualizzati) per poi cominciare a elaborare quelli che vanno visualizzati.
Disgrazia vuole che in questo modo modo si perda, però, l’utilizzo del DMA per poter leggere i dati dell’ultimo sprite (#7), come riportato sempre nel suddetto manuale. Per cui se lo si volesse visualizzare ugualmente sarebbe necessario caricare i suoi dati manualmente (tramite CPU o Copper).
La disgrazia si tramuta in tragedia passando all’AGA, in quanto abilitando il bus a 64 bit per la lettura dei dati dei bitplane si è obbligati a partire dallo slot $18 per prelevarne i valori in caso di scroll dello schermo. Il che, diagramma degli slot alla mano, significa perdere tutti gli sprite (ben sette!) tranne il primo (#0). Situazione parzialmente mitigata abilitando soltanto 32 bit per il bus dati, che in questo caso richiedono l’inizio della lettura dei dati soltanto dallo slot $28 in caso di scroll, perdendo soltanto tre sprite.
Situazione simile si verifica se invece dello scroll si utilizzi l’overscan (sempre orizzontalmente): per visualizzare più pixel orizzontalmente si va a passi di 16 per OCS/ECS e 64 (o 32) per AGA, e ciò richiede di spostare indietro lo slot inizialmente, esattamente come per lo scroll. Molto più granulare con OCS/ECS (perché si aggiungono 16 pixel alla volta e si scende 8 slot alla volta), ma inflessibile con AGA e bus a 64 bit (si possono aggiungere soltanto 64 pixel visualizzati, partendo dallo slot $18) e un po’ meno con bus a 32 bit (si possono aggiungere 32 pixel, partendo dallo slot $28).
E’ chiaro che con l’AGA si cercherà di preferire sempre l’utilizzo del bus dati a 64 bit, perché consente di lasciare molti più slot liberi a disposizione per la CPU e gli altri coprocessori (in particolare per il Blitter), il che è assolutamente fondamentale per poter muovere molta più grafica (in termini di numero di oggetti a video e/o di loro dimensione e/o di numero di colori utilizzati). Ma il prezzo da pagare rimane altissimo in termini di utilizzo degli sprite (uno solo rimasto) e di flessibilità (la risoluzione orizzontale dovrà essere sempre un multiplo di 64 pixel).
Il controllore video – packed (OCS/ECS/AGA) – Scroll e overscan
Col controllore video “packed” il problema dello scroll non si pone: si può usare tranquillamente senza intaccare alcuno sprite. Infatti e come già visto, il primo slot per la lettura dei dati dello schermo è il $3F (esattamente uno slot prima che parta l’elaborazione dei pixel, che richiede 5 slot per il completamento e la visualizzazione del primo pixel).
Ma ciò che risulta fondamentale, quando si parla di grafica packed, è capire esattamente quanti bit (quindi non parliamo di pixel!) scartare prima di poter utilizzare quelli che c’interessano per visualizzare un certo pixel. Per implementare ciò, in realtà il controllore utilizza un meccanismo di ritardo che viene introdotto per i pixel aggiuntivi che sono stati letti, com’è spiegato in questa parte del manuale ed è visibile in questa didascalia.
Non cambia, quindi, molto da questo punto di vista, rispetto al controllore con grafica planare: è necessario introdurre un opportuno ritardo per i bit (non pixel!) per i pixel, a seconda di quale si voglia visualizzare per primo.
Ciò che cambia radicalmente, è invece, il come debba essere effettuato e questo dipende strettamente dalla profondità di colore (quanti colori sono visualizzati).
Con 8 colori sono necessari 3 bit per rappresentarne l’indice, e sappiamo che una word (16-bit) contiene fino a 5 pixel più eventualmente un bit del sesto pixel. Se vogliamo visualizzare il primo pixel non serve alcuno scroll, per cui tutto rimane come già mostrato; situazione identica alla grafica planare, insomma.
Se vogliamo visualizzare la grafica partendo dal secondo pixel dobbiamo, invece, effettuare uno shift di 3 bit dei dati letti, in modo da posizionare i bit del secondo pixel opportunamente (sarà il primo a essere visualizzato). Per far questo si utilizza lo stesso registro usato nell’Amiga per specificare la quantità di scroll (da 0 a 15), ma con utilizzo molto diverso di tale valore. Esso serve, infatti, a indicare ai due barrel shifter (quelli per il buffer e il byte interno) di quanto shiftare i valori (bit! Non pixel!) in essi contenuti, in modo da togliere di mezzo i bit che non servono e posizionare quelli interessati al posto giusto. Quindi il problema viene risolto impostando nel registro di scroll il valore 3: alla prima elaborazione si scarta il primo pixel, e alla seconda sarà pronto il secondo pixel che sarà quello da visualizzare.
Situazione simile partendo dal terzo pixel: basta impostare il registro di scroll a 6.
Diventa un problema, invece, partire col quarto pixel, perché il registro di scroll va impostato a 9, ma i due barrel shifter del controllore video sono a 8 bit e consentono di consentono di spostare i bit di al massimo 7 posizioni. In questo caso la soluzione è quella di shiftare del massimo consentito (7) e decrementare della stessa quantità il registro di scroll, che a questo punto assume il valore 2. Al secondo clock di sistema si shifterà di due posizioni, e finalmente il controllore video avrà ottenuto i dati del quarto pixel correttamente posizionati.
Lo stesso si verificherà col quinto pixel (registro di scroll impostato a 12), mentre torneranno i problemi col sesto pixel, perché il registro di scroll dovrà essere impostato a 15. In questo caso serviranno 3 clock di sistema per avere finalmente i suoi dati correttamente posizionati, dopo aver effettuato degli shift di 7, 7, e, infine, di una posizione.
In buona sostanza, a ogni clock di sistema si utilizzerà il barrel shifter per shiftare di una certa quantità / posizione i bit, finché i bit non saranno perfettamente posizionati sul primo bit del pixel da visualizzare. Quindi sarà necessario un massimo di 3 shift (sempre per i limiti dei due barrel shifter: si può shiftare al massimo di 7 posizioni per clock di sistema. Quindi lo scroll massimo di 15 bit richiede 3 operazioni di shift, pari a 7, 7 e 1 bit rispettivamente), pari a 3 clock di sistema, per poter gestire lo scroll di qualunque pixel.
Quello illustrato è un meccanismo generale, che consente di gestire lo scroll di schermi con qualunque profondità di colore (da 1 a 8 bit per pixel) e con la grafica che può iniziare in qualunque parte dei dati dello schermo (ad esempio si possono scartare i primi 7 bit e visualizzare il primo pixel partendo dall’ottavo bit) programmando opportunamente il registro di scroll dell’Amiga.
L’enorme vantaggio rispetto all’Amiga è che viene richiesto sempre un massimo di 3 cicli di clock di sistema (pari a 1.5 slot / color clock), come già detto, contro i 16 / 8 slot fissi necessari altrimenti, con benefici in termini di sprite disponibili (nessuno viene sacrificato) e di latenza (al massimo servono 2 slot per caricare i dati e cominciare l’elaborazione).
In caso di scroll sarà, quindi, necessario tenere conto al massimo di un paio di slot / color clock di ritardo per l’inizio della lettura dei dati dello schermo, per cui lo slot iniziale dovrà essere impostato a $3E anziché $3F. Lo stesso vale per l’overscan, perché non richiede di anticipare tanto il caricamento dei dati, come avviene su Amiga (dove è il rigidissimo sistema di caricamento dei dati dai bitplane a multipli di 8 slot / color clock a limitare la piattaforma), e quindi consente di avere latenze molto più ridotte per la loro visualizzazione, oltre al fatto che praticamente nessuno sprite viene sacrificato (a meno di overscan estremi con annesso scroll).
Il costo da pagare è, però, rappresentato dalla necessità di utilizzare 2 sommatori/sottrattori a 4 bit: uno per controllare se il valore nel registro di scroll è maggiore di 7 (perché in questo caso il primo scorrimento dei dati dev’essere pari a 7) e un altro per sottrarre da tale registro lo shift utilizzato poi nei barrel shifter. Inoltre serve un registro interno da 4 bit (4 celle SRAM) per memorizzare il valore dello scroll, in modo da caricarlo a ogni inizio di riga di raster (o ogni qual volta il registro venga scritto da CPU o Copper) in tale registro interno e utilizzarlo per il meccanismo sopra descritto (altrimenti verrebbe azzerato irrimediabilmente dopo aver visualizzato la prima riga).
In ogni caso il tutto rimane per nulla esoso in termini di risorse necessarie, come già visto in precedenza (i risparmi dovuti alla mancanza di tanti puntatori ai bitplane coi loro registri annessi consentono di riutilizzare un po’ di queste risorse allo scopo).
Il prossimo articolo si occuperà di un’altra delle caratteristiche che hanno reso famoso l’Amiga: il Dual Playfield.