continua (next page) Frasi Famose index main index Qui sotto, alcune mie considerazioni e calcoli sulla generazione dell'immagine video per lo Zx Spectrum. I calcoli sono fatti sui T-states dello Z80, che sullo Spectrum 48k era clockato a 3.5 MHz mentre sul 128k era un filino più veloce.

Il Chrome è un computer compatibile con i vari modelli dello Zx Spectrum della Sinclair prima e Amstrad poi. Mario, che ha progettato e creato il Chrome, vedeva le cose dal punto di vista dell'hardwarista purosangue mentre io, impegnato sul fronte dell'emulazione dello Spectrum sul P900, vedevo le cose dal punto di vista del softwarista purosangue...

Ecco qui sotto il riassunto delle principali discussioni in merito che scrissi qualche tempo fa nella mailing-list italiana dedicata allo Zx Spectrum.


Assumendo che il clock da 3,5MHz dello Spectrum tiri fuori davvero 3.500.000 cicli al secondo (in natura i quarzi non saranno così rigorosamente precisi) volevo vedere perché non riuscivo a sincronizzare quel benedetto emulatore software.

Sullo Spectrum 48k il tracciamento di un frame video dovrebbe richiedere in teoria 70000 cicli di clock (quindi tre milioni e mezzo di cicli al secondo); al termine di ogni frame parte un interrupt (che quindi comincia ad eseguire istruzioni durante l'inizio del tracciamento del nuovo frame video; la ULA contenderebbe dunque la RAM solo durante il tracciamento dell'area più interna da 256×192 pixels). La ULA continua a generare autonomamente l'immagine, anche se un po' di pixel vengono ignorati (le parti laterali più esterne per l'horizontal retrace, e qualcosa delle scanline iniziali per il vertical retrace).

In realtà sul 48k il frame dura solo 68988 cicli (otto pixel ogni quattro cicli di clock, perché la ULA genera 448×312 pixel totali), cioè lo Spectrum traccia i frame video ad un po' più di 50Hz: sarebbero circa 50,73 Hz, ma siamo appena sotto l'1,5% di tolleranza... Tutto questo sempre assumendo che il quarzo del 48k sia assolutamente preciso nei suoi tre milioni e mezzo di cicli al secondo; eventuali differenze andrebbero ad aumentare quell'1,5% (se il clock è più veloce) oppure a diminuirlo (se il clock è più lento). Ci vorrebbe infatti un clock da 68988*50 = 3.449.400 Hz per generare con quel formato frame esattamente 50 Hz (il problema finale è comunque solo del televisore o del monitor; i demo andranno benissimo perché il tempo lo misurano su "quanti cicli di clock sono passati", non su "a quanti Hz vengono generati i frame video").

Sullo Spectrum 128k e successivi ci sono 3.546.900 cicli al secondo (sempre assumendo un clock rigoroso) contro 3.545.400 cicli richiesti per generare 50 frame (parlo dello schermo a 311 scanline), ognuno in 70908 cicli di clock. Dunque il frame rate finale sarà assai più preciso del 48k, perché 3546900/70908 = 50,021 Hz.

Sul Chrome il clock è da 3,58 MHz (la metà di 7.160.000 Hz), e per questo si potrebbe essere tentati di generare i frame un pochino più grandi. Tracciando il frame in stile "128k/+2/+3" (311 scanlines, ossia 70908 cicli) si ottiene 3580000/70908 = 50,4879 Hz, che è poco sotto l'uno per cento di tolleranza del televisore (e comunque meglio dello Spectrum 48k originale).

Con 312 scanlines anziché 311 (una possibile "licenza poetica" del progetto Chrome sul formato video... ovviamente non sarà mai applicata; e comunque in realtà solo il 48k della Sinclair generava 312 scanline) i pixel di un frame, border compreso, sarebbero 456*312=142272, che richiedono 71136 cicli per frame, ossia 3556800 cicli per 50 frame - risultato: 50,3261 Hz; non è il rigore dei 128k ma è comunque un certo miglioramento rispetto ai 50,48 Hz di cui sopra. Infatti per andare vicino ai 50 Hz occorrerebbe generare non 311 o 312 scanlines, ma frame da circa 3580000/50 = 71600 cicli di clock, ossia da 314 scanline!! In questo caso, al prezzo di un impercettibile spostamento verso l'alto nel TV dell'area grafica 256×192, avresti 71592 cicli per frame, cioè 50,00558 Hz, meglio degli stessi Spectrum 128/+2/+3... Ma io ovviamente non lo consiglio.

Per la cronaca, l'autore del progetto Chrome ha preferito lavorare sulla compatibilità con lo Spectrum 128 piuttosto che arzigogolare sui formati video.

Tutte queste considerazioni mi hanno fatto capire varie cose:

1) anche ammettendo di avere un clock assolutamente esatto, generare un'immagine video a 50 Hz precisi è un'impresa alquanto ardua perché bisognerebbe farla rientrare in x/50 cicli di clock (con x = frequenza del quarzo); è assolutamente normale che il TV (o il monitor) si "beva" poco più o poco meno dei canonici 50 frame al secondo, e non ci sono altre controindicazioni. Al contrario, nello scrivere un emulatore software dello Zx Spectrum, il problema è di sincronizzare al tempo reale la macchina virtuale (che può comodamente seguire in modo rigoroso il numero esatto di cicli di clock);

2) nel peggiore dei casi (lo Spectrum 48k reale) siamo a 50,73 Hz, che è poco meno dell'1,5% di tolleranza. Grazie alla buona combinazione di dimensioni del frame video e velocità del quarzo dei vari 128k/+2/etc, la generazione dei frame è assai più precisa (50,02 Hz);

3) tutto questo significa che degli ipotetici programmi "demo" per lo Spectrum che tengono conto della lunghezza esatta del frame video (anche se magari aspettassero con l'istruzione HALT dello Z80 l'inizio del frame successivo per risincronizzarsi), se sono fatti per il 48k allora non gireranno bene sul 128k, e se sono fatti secondo le temporizzazioni del 128k non gireranno bene sul 48k; i due computer hanno frame video di lunghezza diversa (nel primo caso si aspettano un frame video lungo 68988 cicli con scanline larghe 448 pixel, nel secondo si aspettano un frame video di 70908 cicli con scanline larghe 456 pixel); questo ragionamento è indipendente dai clock di sistema;

4) per essere perfettamente compatibile coi demo 128/+2/+3 il Chrome dovrebbe generare frame video da 70908 cicli; in questo modo i demo gireranno un po' più veloci (lo 0,933% in più) a causa del clock di sistema da 3,58 MHz, ma resteranno rigorosamente allineati al frame video (anche se questo arriva al TV un filino più frequentemente);

5) se il Chrome generasse frame da 456×312 (o da 456×313 o da 456×314) anziché da 456×311, il tracciamento del frame video richiederebbe centinaia di cicli di clock in più anziché i "canonici" 70908; per i programmi che aspettano con HALT non c'è differenza, ma per chi conta esattamente su quei 70908 allora sballa tutto; data l'ampia tolleranza dei TV e monitor, direi che si può lasciar perdere questa ipotesi;

6) per l'emulazione perfetta dei frame 48k e 128/+2/+3 occorrerebbe purtroppo implementare nei PLD Xylinx entrambe le logiche video: quella 448×312 dello Spectrum originale e quella 456×311 dei successori (il che contrasta con l'ipotesi minimalistica di un solo PLD sulla motherboard). Nel caso peggiore, cioè del 48k con un clock da 3,58 MHz (il Chrome in modalità 48k, insomma) avremmo certamente l'immagine video generata come ULA Ferranti comanda, ma con 3580000/68988 = 51,893 Hz sul TV; ricordo vagamente di aver sentito da qualche parte che monitor "compositi" e TV si bevevano fino a 52-53Hz (ossia 6% di tolleranza) ma non posso giurarlo;

7) l'audio che si sente sul beeper è generato "man mano" (non come sui nostri PC dove prepari un blocco dati e poi lo passi in pasto alla scheda sonora, la quale provvede a fare l'output a velocità esatta a 44.5 KHz o 48 KHz o che altro, e tu devi avere un altro blocco pronto non appena questa dice che ha finito, e potrebbe finire non proprio quando te lo aspetti... per questo funziona ad interrupts!!). Quindi avere uno Spectrum 48k con un clock da 3,58 MHz (il Chrome in modo 48k) significa che le frequenze in uscita sul ronzatore piezoelettrico saranno il 2,28% più alte. Penso che all'orecchio non sarà facile distinguere un Chrome in modo 48k da uno Spectrum originale. Il guaio è certamente di chi scrive un emulatore perché deve "ridistribuire" su 44.5 KHz o 48 KHz l'uscita audio "raccolta man mano"... questo può essere facile se si fa "a posteriori", ma è una cosa complicata farlo "in tempo reale"; l'ideale sarebbe una sound card programmabile con decente precisione tra i 300 e i 400 KHz in uscita, perché così ad ogni bit sul beeper (che richiede non meno di 11 cicli di clock per una OUT sulla porta giusta: per questo ho detto 300-400 KHz, circa un decimo del clock originale applicato allo Z80 dei nostri beneamati Sinclair) corrisponderebbe un byte in uscita sulla scheda sonora del PC (sto sprecando un byte quando il ronzatore piezoelettrico è di un solo bit, ma questo è un altro discorso);

8) l'audio dell'AY, da quel che mi è dato di capire, pure dipende dal clock di sistema, e quindi un AY sul Chrome/48k genererebbe al nostro orecchio frequenze il 2,28% più alte di quelle che i programmatori, e sul Chrome/128k genererebbe al nostro orecchio frequenze del 0,933% più alte; stesso ragionamento che per il beeper: è arduo emulare a software la macchina reale, ed il Chrome sarà solo un filino più veloce. Sarebbe invece un bel guaio se l'AY avesse delle sue temporizzazioni autonome (come invece le nostre adorate schede audio dei PC). Suppongo (traduzione: voglio sperare) che anche il più isterico dei programmatori di "demo" e giochi conceda almeno l'1% di tolleranza quando si tratta di aspettare un chip... :-)

9) video e audio sono i punti su cui più ci accorgeremmo che qualcosa non quadra (un pixel di troppo o un "click-click" durante l'output audio sono assai fastidiosi); lo stesso discorso si propaga alle altre periferiche, su cui l'uno o due per cento in più di velocità può essere niente (attesa di un settore da microdrive) o troppo (attesa di una condizione di "ready"). Mi spiego: immagina un driver di una periferica che ha un suo clock autonomo; il programmatore sa che dopo la OUT sulla porta, prima di leggere il risultato e dare un nuovo comando, deve aspettare due millisecondi esatti: sul 48k della Sinclair sono 7000 cicli di clock, dunque il baldo programmatore scrive un ciclo a vuoto che spreca 7057 cicli a suon di NOP, va a rileggere la porta e trova ancora la periferica "busy" (infatti non erano passati 2msec, perché ai 3,58 MHz del Chrome, in due millisecondi c'entrano 7160 cicli! e 103 cicli a 3,58 MHz fanno ben 0,028msec)... allora lui, tutto obbediente alle specifiche del suo hardware paranoico, aspetta di nuovo altri 7057 cicli di clock (o addirittura lanciare un nuovo comando che non verrà eseguito perché è ancora in fase di completamento il precedente), e alla fine trova finalmente "ready", avendoci però impiegato quasi il doppio del tempo! Subito creerà un sito per dichiarare a tutto il mondo che il Chrome sarebbe lento e incompatibile, convocherà conferenze stampa, apparirà in TV la sera del 31 dicembre alle 23:59 per un messaggio a reti unificate per denigrare ingiustamente il Chrome, intenterà causa a chiunque dice che era colpa sua che non aveva aspettato un centinaio di cicli di clock in più... :-)

Ah, in tutto questo non ho parlato della memoria contesa (per la mia ignoranza e confusione in materia) sulla quale certamente qualche demo va a bruciare deliberatamente cicli di clock... :-)



Ed ecco le previste rettifiche... (sigh!)

Se il quarzo del Chrome è 14.3 MHz allora devo dedurre che la velocità sarà 3.575 MHz anziché 3.58 MHz come avevo scritto io.

Tragicamente FBZX fa passare solo 13488 T-states prima di tracciare il primo dei 256×192 pixel a video (solo 60 scanline più 96 pixel); questo lo posso correggere ma resto sempre con un'approssimazione perché lì l'unità di misura per il video sono "otto pixel in quattro T-states".

Anche se io non fossi tifoso dei Ramsoft, mi fiderei più delle loro misurazioni "sul campo" che dei calcoli teorici altrui (la realtà oggettiva vale più di mille idee e discorsi!).

Infatti i 14336 T-states tanto famosi delle FAQ ufficiali sono 64 scanline (ossia vertical retrace, e la parte visibile più alta dello schermo). Ma poi c'è il bordo della sessantacinquesima (prima che la ULA abbia bisogno di leggere il primo byte video), bordo che nel mio emulatore io avevo erroneamente calcolato in 64 pixels e stabilito uguale per entrambi i lati del video (cioè 32 T-states ognuno), e quindi con quello potevo arrivare a 14368 T-states. Se Ramsoft dice 14347 (cioè 14336+11) posso dedurre che il bordo sinistro parte dopo 22 pixel (anziché i miei 64).

Riassumo:

mia tabella originale:

448×312 con un bordo di 96 pixel a sx, 96 a dx, 60 su, 60 giù (immagine teoricamente centrata; in realtà il vertical retrace succhia un po' di tempo e quindi alcune scanline delle prime 60, per giunta con l'ultima che non è intera, non sarebbero da conteggiare come tali!!). E dire che mi era venuto, il dubbio... conoscere la durata dei retrace verticale e orizzontale avrebbe aiutato a non prendere la cantonata;

versione Ramsoft (cioè quella giusta) della generazione del frame video:

Così descritta, l'immagine sembrerebbe spostata assai a sinistra e un pelino più in basso; in realtà questo è dovuto al vertical retrace, che "occupa" circa poco più di tre scanline di tempo, cioè 1418 pixel, ossia 709 cicli di clock, ovvero 0,2027 millisecondi (!!). Quindi non è che l'estrema sinistra del frame video sia sincronizzata con l'interrupt...

Fra parentesi il centraggio della scanline non poteva essere esattamente di 96 pixel a sinistra e 96 a destra, perché sulla destra c'è la pausa dell'horizontal retrace, e quindi per centrare perfettamente l'immagine occorrerebbe dare qualche pixel in più al bordo destro a scapito del sinistro.

Purtroppo ho problemi a far girare Aquaplane nel mio emulatore, dovrò modificare l'FBZX originale per verificare queste ipotesi (c'è da dire che FBZX, così com'è, tiene il bordo di Aquaplane parecchi pixel più su, assai più di quelle fatidiche quattro scanline...

Rifacendo lo stesso ragionamento per il 128k, con 14368 T-states per la prima lettura, otterremmo:

Le dimensioni curiose del bordo destro mi suggeriscono che per tracciare un frame video occorre aspettare davvero il vertical retrace. Cioè, quando "parte l'interrupt", aspettare un po' di tempo prima di tracciare (per evitare di avere la sinistra del border larga solo otto pixel!!)

Per "normalizzare" le tabelle allora suggerirei (sia per l'eventuale secondo PLD del Chrome, sia per il mio emulatore Zx Spectrum):

48k (frame: 448×312)

128k (frame: 456×311)

In questo modo l'emulatore software (e i PLD del Chrome) produrranno l'immagine rigorosamente "a norme ULA Ferranti", proprio come sugli Zx Spectrum originali Sinclair. Un brindisi alla compatibilità!!! :-)


Google
 
Web www.alfonsomartone.itb.it

Bufale al pascolo, fotografate da treno in corsa

send e-mail - continua (next page)