In questi ultimi giorni nel tempo libero mi sono spolpato un po' FBZX, un emulatore Spectrum originariamente pensato per lo schermo in modalita' FrameBuffer. FBZX usa una libreria Z80 che fa tutta l'emulazione del processore; a questa libreria Z80 di Marat Fayzullin occorre fornire solo alcune funzioni (RdZ80, WrZ80, OutZ80, IntZ80...). FBZX inizializza la libreria Z80, azzera tutte le sue variabili che riguardano l'hardware dello Spectrum (carica la ROM, etc), e parte con l'emulazione dello Spectrum. Ogni tanto, quando sono passati abbastanza T-states, "autorizza" la libreria Z80 a far partire un interrupt. Concettualmente l'emulazione e' semplicissima: sapendo quanti T-states (cicli di clock) sono passati da un'istruzione all'altra, ci si puo' regolare su come "muovere" l'hardware (nastro, immagine video, shadow-ROM, etc). In questo modo si puo' rigenerare fisicamente l'immagine video (FBZX produce anche l'effetto neve, emula qualcosa degli effetti sul border, etc) con un'accuratezza proporzionale alle... sue conoscenze della ULA :-) (quell'"our investigations" dei RamSoft mi suona allucinante... chissa' cosa hanno scoperto!!) Ovviamente rigenerare pixel per pixel l'intero schermo e border per cinquanta volte al secondo richiede parecchia potenza di calcolo, spesso sprecata perche' tra un frame video e il successivo e' assai raro che cambi una grossa percentuale dello schermo. L'alternativa, sacrificando gli effetti sul border, sarebbe di aggiornare lo schermo emulato solo quando lo Z80 virtuale scrive sulla memoria video (oppure cambia il colore del bordo): dato che piu' di 16 bit alla volta non scrive (e quasi sempre ne scrive solo 8) allora sarebbe un gran bel risparmio... FBZX e' scritto purtroppo in modo un po' frettoloso (molte cose sono riciclate ovunque col "cut & paste" dell'editor) e alloca una quantita' mostruosa di variabili (spesso sovradimensionate: due kilobytes per un filename!!!) con nomi anche di 15-20 caratteri (maniaco!!!) a meta' strada tra lo spagnolo e l'inglese e un'indentazione da mal di testa... L'uso della libreria SDL permette di usare FBZX oltre che su console (framebuffer graphics) anche sotto X/free di Linux, ma al prezzo di bruciare ancor piu'risorse nell'emulare sullo schermo X11 il framebuffer su cui si basa (ci vuole una macchina da almeno 600 MHz per emulare lo Spectrum a velocita' 100%). E pare pure che l'autore di FBZX non abbia pensato alcun modo di sincronizzare il clock virtuale con quello reale. L'autore ha scelto di usare il framebuffer a 8 bit perche' cosi' ogni byte dello schermo (256 possibili colori, ma ne usa solo 15, i 15 dello Spectrum) rappresenta un pixel. Ho imparato un sacco di cose studiandomi i suoi listati; un mito che mi e' caduto era della difficolta' dell'emulazione dei vari 128 +2 +3 etc, e la difficolta' per questi era invece solo nell'emulare l'AY; la gestione dei banchi di memoria e' meno drammatica di quel che pensavo. Fra le altre cose mi e' venuta l'idea (spero quasi quasi di non trovare mai il tempo di applicarmici) di costruire a software (con l'engine Z80 di cui sopra) la macchina con otto processori Z80 in parallelo e 16Mb RAM tutti "bankabili"... :-) L'idea principale e' sempre quella di creare un emulatore Spectrum abbastanza pulito da andare su una macchina non velocissima come il mio cellulare (320x208 di grafica e processore a 156MHz); penso di aver finalmente fatto una buona "full immersion" nel problema, ma per ora ancora non so decidere se e' il caso di lavorare come un matto su questi sorgenti (che sono pur sempre 245k di codice C) oppure se e' il caso di cercare un engine Z80 piu' completo di questo di Fayzullin (che e' del 2002) e poi costruirci a poco a poco tutto il malloppo intorno (recuperando i "pezzi duri" da FBZX). Fra parentesi l'engine Z80 in questione, una volta compilato qui sul Pentium III, occupa da 96 a 109k dell'eseguibile finale!! Sospetto che tagliuzzando un po' con l'assembler si potrebbe ridurlo di tre quarti o piu'. La libreria libz80 dell'uruguaiano Gabriel Gambetta (pure del 2002) ha piu' o meno gli stessi principi di quella di Fayzullin ma mi sembra meno veloce perche' crea una funzione per ogni opcode utile. Una volta compilata, richiede da 126 a 131k dell'eseguibile finale; nel codice e' incluso pero' anche il testo delle istruzioni (per cui si possono usare per creare un disassemblatore). Eh, la ricerca continua...