\articolo{XFA: Libreria per la gestione di animazioni ad alta velocità}
{Michele Puccini}

%\commento{Anche qui i titoli li ho messi io, ho tolto i
%le indicazioni dei registri nelle funzioni. Consiglerei di togliere
%oppure abbreviare (e rendere un po` piu` seria l'introduzione---Reinhard}
%
%\paragrafo{Introduzione}
%Anch'io, come migliaia di altri ho iniziato a muovere i miei primi bit su
%macchine Commodore.
%
%Frequentavo la terza classe del famigerato ITIS di Livorno, specializzazione
%Informatica, quando feci storcere la bocca alla mitica prof. Tesini la
%quale, chiedendomi quale fosse la mia esperienza nel campo dei calcolatori,
%si sentì rispondere un orgoglioso ``basic sul Vic20!".
%
%Aveva ragione: programmare in basic sul Vic con 3,5k di ram era roba da
%sadomasochisti e veramente diseducativo; decisi di passare all'assembler
%6502 per sfuttare al meglio quel poco che la macchinetta di Commodore
%metteva a disposizione.
%
%Quando finalmente la bocca della Tesini si distese, io cominciai a prendere
%visione di quello che per me era un vero computer.
%
%Purtroppo non potevo portarmi a casa il sistema Data General dei laboratori
%di informatica, e neanche il terminale grafico Tektronics sul quale plottavo
%assurde funzioni tridimensionali (solo a vettori, poiché questo era l'unico
%modo di visualizzare qualcosa su quel sistema senza memoria grafica!
%Figuratevi che il plottaggio consisteva nel pilotare un punto luminoso,
%scrivendo sulla matrice a fosfori del terminale, la quale rimaneva attiva).
%
%Dopo uno Spectrum 16k, 48k, supercarrozzato, ecc,ecc, ecco la luce dei miei
%occhi: il QL della defunta Sinclair.
%
%Una memoria illimitata, un processore a 16 bit (quasi: 16 interni ed 8
%esterni) su cui programmare in assembler ``umano'', un sistema operativo
%lontanamente multitasking, due microdrives (il peggior aborto concepito da
%Sinclair) e grafica, grafica, grafica a volontà.
%
%Ecco che il mio genio si scatenava in programmi di paint a icone (pilotati
%da tastiera\ldots), rotazione di solidi, titolatori, effetti speciali, e
%tutto ciò che la mia vena creativa mi dettava.
%
%Una cartolina rosa mi avvertì che dovevo salutare amici, famiglia e
%computer per dedicarmi con ``senso del dovere, spirito di sacrificio e totale
%abnegazione" alla difesa della patria e delle istituzioni (quante
%manganellate ai tifosi ``facinorosi'' durante il servizio militare nei
%Carabinieri).
%
%Tornato a casa, dopo varie peripezie lavorative (ho fatto anche il
%rappresentante di stazioni Unix Olivetti, con scarso profitto\ldots) vengo
%ingaggiato in vece di programmatore da una ditta locale.
%
%Io il PC non avrei mai voluto conoscerlo\ldots\, e invece eccomelo sulla
%scrivania, camuffato da M24, con quell'aria tra il serio e il triste.
%
%Squallido, con quel suo ``Bip'' che annunciava una nuova giornata di lavoro,
%era diventato giocoforza il mio compagno, lo strumento su cui sviluppavo i
%programmi per muovere macchine, assi, relè, con il quale posizionavo punte,
%facevo fori e disegni sui pannelli di legno.
%
%L'automazione industriale è stata comunque una materia appassionante e
%saltuariamente divertente, specialmente quando un sensore non diceva la
%verità (!!!!).
%
%In quei tempi, mi era giunta all'orecchio la notizia di un computer di nome
%\A, con prestazioni e tecnologie assolutamente innovative.
%
%Vederlo all'opera e innamorarsene è stato tutt'uno.
%
%Dopo averlo acquistato, sentivo il fuoco della passione avvamparmi e la luce
%della ragione perdere di intensità davanti alla sconfinatezza del nuovo
%mondo informatico che per me \A rappresentava.
%
%Quando poi, i primi megademo di entusiasti coder del nord sbattevano a terra
%gli amici picciisti, la soddisfazione raggiungeva un livello che Freud
%avrebbe denominato ``sessuale''.
%
%In ditta, intanto, i capi mi avevano ``noleggiato'' a una ditta di Verona
%(Tecnint) perché facessi parte di un team di sviluppo per un progetto molto
%impegnativo.
%
%Si trattava di sviluppare alcune parti del software per il controllo di una
%linea di lavorazione composta da più macchine.
%
%Domanda: quale computer poteva controllare in real time qualche migliaio di
%sensori, decine di assi e fornire un feedback adeguato al gestore?
%
%Un piccì? NOOOO.
%
%Due piccì? NOOO.
%
%Un mac? NOOO.
%
%\A? Quasi.
%
%Il computer, altri non era che un magnifico set di schede VME-Bus (standard
%per automazione industriale) con processori 68020 a 25\,Mhz, MMU, FPU, sistema
%operativo multitasking, maree di ram, chip grafici custom e ammenicoli vari
%di interfacciamento.
%
%Si, mi trovavo di fronte un'AMIGONA galattica, senza i limiti che ormai
%avevo imparato a riconoscere anche nell'A2000 con due floppy che avevo a
%casa.
%
%Il sistema di sviluppo per questa bestiaccia consisteva in un cross-compiler
%Aztec C v3.6 per PC (\ldots mmmmmhhhh Aztec ? quello che usavo con \A\ldots)
%per generare il codice 680x0 che scaricavo via seriale al sistema di
%sviluppo.
%
%A breve, dopo qualche exploit delle mie arti programmatorie in fatto di
%grafica (avevo rovistato tra i sorgenti del driver per il processore
%grafico), l'Ing. Granuzzo della Tecnint volle stimolarmi ulteriormente,
%passandomi una nuova scheda VME per sviluppatori, dotata di un bel 68030 e
%di un mega-processore video molto veloce.
%
%Zac, il megademo (\ldotssviluppato sull'\A e ``portato'' sull'Amigona) era
%pronto.
%
%Non era altro che una bruttacopia dei favolosi demo di \A, senza audio né
%copperlists né fluidissimi scroll.
%
%Consisteva in un tranquillo starfield con un catafascio di oggetti
%vettoriali che si muovevano in prospettiva, calcolati in tempo reale da una
%routine in floating point (grazie FPU) e plottati senza rimozione delle
%linee nascoste.
%
%Inutile dire che ogni cliente della Tecnint, prima di visionare il programma
%che avrebbe dovuto muovere miliardi di macchinari, veniva messo
%nell'``impressionatoio'', dove veniva proiettato quotidianamente il Mik-Demo
%con l'orgoglio di tutti.
%
%Finito il lavoro con questa ditta e ripresa la mia consueta mansione, ho
%continuato per diverso tempo a programmare sui piccì, ma più il tempo
%passava, più nella mente si sviluppava una pazza idea: licenziarmi e
%mettermi in proprio a sviluppare software grafico e per DTV su \A.
%
%È doloroso per me ripercorrere il primo anno di attività, fatto di grossi
%errori, delusioni, senso di disorientamento.
%
%Adesso ho capito che la vita imprenditoriale non può essere basata solo
%sulla passione per quello che fai, ma è soprattutto oculatezza, saggezza,
%lungimiranza, rapidità di esecuzione, pignoleria, decisione e un pizzico
%di spregiudicatezza.
%
%Ora, grazie alle molte esperienze accumulate, la ClassX ha una direzione, un
%intento, una stabilità, un obbiettivo da perseguire.
%
%Naturalmente, la mia passione per \A non morirà mai, e non serviranno
%orde di piccisti, processori intel, scelte comuni, standardizzazioni di
%massa e di pensiero, per farmi cambiare idea.
%
%Io sono sicuro, come tutti voi, di essere dalla parte giusta, dove la
%fantasia, la creatività e il senso di libertà sono una scelta e non
%l'imposizione di un Gates qualsiasi.

\paragrafo{XFA: un nuovo formato di animazione}
Durante lo sviluppo di X-DVE, il noto sistema di titolazione/animazione,
siamo stati costretti a scegliere un formato di animazione che fosse adatto
alle risoluzioni video PAL ed NTSC e che fornisse la massima fluidità di
esecuzione anche in presenza di fotogrammi complessi e schermi con molti
bitplane.

Abbiamo iniziato testando diversi formati di animazione ``standard'', come
ANIM5, ANIM7 ecc.~con risultati non proprio incoraggianti per quanto
concerne velocità di play e compressione.

Altre feature messe a disposizione da tali formati, come il supporto di
palette e frame rate multipli, non erano utili ai fini dell'utilizzo che ci
eravamo prefissati.

L'unico formato ``quasi standard'' che poteva avvicinarsi ai requisiti
richiesti era l'ANIM16I o l'ANIM32I di SCALA; sfortutamente non siamo stati
in grado di reperire documentazione specifica; tali formati inoltre mostrano
vistosi lampeggiamenti in condizioni difficili, evidenziando carenze nel sistema
di double buffering.

Abbiamo allora deciso di iniziare a lavorare su una nuova tecnica di compressione
ed esecuzione delle animazioni, dando vita al formato XFA.

\sottoparagrafo{Tecnica di compressione di XFA}
La tecnica è quella classica, basata sulla compressione delle differenze
tra un fotogramma e l'altro (delta frame compression), normalmente usata nel
formato ANIM5, 7, ecc. Quello che cambia è la codifica del delta, realizzata
in modo da facilitare e ridurre il più possibile le operazioni necessarie
per la  decodifica (la {\az ClassX} mi impedisce di rivelare altri
particolari). Il formato XFA supporta quattro diverse modalità di
compressione, due a 16 bit e due a 32 bit:
\begin{itemize}
\item \c{XFA\_Mode16};
\item \c{XFA\_Mode32};
\item \c{XFA\_Mode16I} (necessita di schermo interlacciato);
\item \c{XFA\_Mode32I} (necessita di schermo interlacciato).
\end{itemize}

\noindent Mentre animazioni \c{XFA\_Mode16} e \c{XFA\_Mode32} possono essere
eseguite in qualsiasi risoluzione e sono adatte per il play da disco,
\c{XFA\_Mode16I} e \c{XFA\_Mode32I} necessitano di uno schermo interlacciato
(ideale per applicazioni video).

Come già accennato, i delta in formato XFA possono essere decompressi con
una piccola (sta tutta nelle cache del 68040) e veloce routine assembler che
permette di ottenere prestazioni molto maggiori di qualsiasi ANIM5/7.

Inoltre, per i formati 16I e 32I ho ottenuto all'incirca in un sol colpo il raddoppio
della velocità di esecuzione e il dimezzamento delle informazioni
da comprimere, grazie a un ``trucco'' usato e abusato nel mondo del video:
l'interlace cunning.

Il principio dell'interlace cunning è semplice:
supponiamo di avere due immagini, A e B in formato PAL.
Alternando A e B su uno schermo PAL interlacciato e sincronizzando la
visualizzazione con la frequenza di refresh video (50\,Hz), ne risulterà
una immagine C composta dalle rasterline pari di A e le
rasterline dispari di B.
Questo significa che metà delle informazioni di A e di B non verranno
visualizzate e quindi potranno essere trascurate.

L'esecuzione di animazioni nelle modalità 16I e 32I richiede pertanto una
perfetta sincronizzazione con il vertical blanking di schermo (per la
precisione occorre sapere anche quale dei due semiquadri è correntemente
attivo), una elevatissima velocità di decompressione dei fotogrammi e un
sistema veloce per la visualizzazione delle bitmap per effettuare un
efficace double buffering.

\paragrafo{La libreria XFA}

La \f{xfa.library} è stata sviluppata per consentire un veloce e flessibile
accesso alle animazioni in formato XFA.
Essa consente di gestire completamente le fasi di compressione, di
esecuzione e di archiviazione, fornendo ai programmatori un
set completo (spero) di funzioni.

I realizzatori di software PD sono fortemente incoraggiati a usare questa
libreria, poiché possiede un interfaccia di programmazione ``umana'' e
interessanti caratteristiche tecniche.

Una delle prime applicazioni che mi piacerebbe vedere è un completo
XFA-DataType (\ldots anche se non visualizzerà animazioni a 50\,fps, sarebbe
bellissimo che MultiView mostrasse una XFA in una finestra Intuition!).

Il formato XFA attualmente non supporta palette multiple, frame-rate
multipli e schermi a 24 bit. Per quanto riguarda l'affidabilità, possiamo dire
che ci sono ottime speranze che \f{xfa.library} non sia distruttiva.

A parte gli scherzi, \f{xfa.library} correda un prodotto commerciale e per
questo è stata provata su diverse configurazioni e nelle condizioni più
critiche, senza rivelare alcun malfunzionamento. Ho messo molta cura nella
programmazione, evitando sistematicamente tecniche sporche o pericolose.
Alcune parti della libreria contengono codice condizionale e seguono
percorsi diversi in base alla versione del sistema operativo ospite.

Sotto Release 2 non è possibile eseguire velocemente un double buffering system
friendly, quindi sono stato costretto a scrivere alcune routine che
``curiosano'' tra le copper list generate dal sistema (vi assicuro che le
copper list vengono solo lette). In questo modo sono riuscito a realizzare
un perfetto double buffering che opera in meno di 1/50 di
secondo.

Con la Release 3 non ci sono problemi, grazie alle velocissime nuove funzioni che
la \f{graphics.library} mette a disposizione per cambiare la bitmap di una
viewport.

\paragrafo{Funzioni della libreria XFA}
Segue un piccolo riassunto delle funzioni contenute nella libreria,
raggruppate in base alla funzionalità e al ruolo che svolgono. Tutto ciò
serve a dare una prima idea dell'organizzazione della libreria e di ciò che
essa rende possibile.

Ho sviluppato questa libreria con l'intento di fornire a eventuali
programmatori esterni una sorta di black box, di cui non sono tenuti a
sapere il funzionamento, ma solo come si usa. Naturalmente, i più smaliziati
potranno accedere alle funzioni più a basso livello per ottenere prestazioni
diverse da quelle da me suggerite.

\sottoparagrafo{Funzioni di errore}

{% Da qui gli item sono in tt e seguiti da ":"
\renewcommand{\descriptionlabel}[1]{\hspace{\labelsep}\c{#1}:}

\begin{description}
\item[XFA\_LibErr()] restituisce il codice di errore generato dall'ultima funzione chiamata.
Nonostante i miei buoni propositi, non ho avuto il tempo di scrivere le
funzioni della libreria in modo da gestire un codice di errore interno più
esplicativo del semplice \c{NULL}.
\end{description}

\sottoparagrafo{Funzioni di compressione}

\begin{description}
\item[XFA\_PackMem\_W(src0,src1,dest,size,¦mode)]
%   (a0/a1/a2,d0/d1)}
com\-pri\-me i dati in modo XFA16/XFA16I.
\item[XFA\_PackMem\_L(src0,src1,dest,size,¦mode)]
%(a0/a1/a2,d0/d1)}
com\-pri\-me i dati in modo XFA32/XFA32I.
\item[XFA\_PackBitMap(sbmap0,sbmap1,dest,mode)]
%(a0/a1/a2,d0)}
com\-pri\-me i dati in base al modo di compressione attuale (PackMode).
\end{description}

\noindent Queste sono funzioni di compressione XFA a basso livello, da usare solo in
caso di particolari esigenze. Consiglio di consultare lo pseudo-autodoc
della libreria prima dell'uso.

\sottoparagrafo{Funzioni di decompressione}

\begin{description}
\item[XFA\_UnPackBitMap\_W(bitmap,pkdata)]
de\-com\-pri\-me su bitmap i dati in modo XFA16/¦XFA16I.
\item[XFA\_UnPackBitMap\_L(bitmap,pkdata)]
de\-com\-pri\-me su bitmap i dati in modo XFA32/¦XFA32I.
\item[XFA\_UnPackBitMap(bitmap,pkdata)]
de\-com\-pri\-me su bitmap in base al modo di compressione attuale (PackMode).
\end{description}

\noindent Queste sono funzioni di decompressione XFA a basso livello, da usare solo in
caso di particolari esigenze.
Consiglio di consultare lo pseudo-autodoc della libreria prima dell'uso.

\sottoparagrafo{Funzioni di gestione del PackMode}
\begin{description}
\item[XFA\_SetPack(screen,packmode)]
inizializza il necessario per la compressione di una animazione.
\item[XFA\_GetPackMode()]
restituisce il modo di compressione attualmente utilizzato.
\item[XFA\_OpenPackStuff()]
alloca i buffer e le bitmap necessarie per la compressione di una animazione.
\item[XFA\_ClosePackStuff(closemode)]
libera ciò che è stato allocato con la \c{XFA\_OpenPackStuff()}.
\end{description}

\noindent Queste funzioni sono dedicate alla gestione del PackMode corrente, alle
inizializzazioni e alle allocazioni necessarie per la compressione delle
animazioni.

\sottoparagrafo{Funzioni di gestione dell'animazione}

\begin{description}
\item[XFA\_SetFramesArray(framesarray,¦numframes)]
indica alla libreria di utilizzare un array di fotogrammi allocato
esternamente (utile per gestire più animazioni contemporaneamente).
\item[XFA\_AllocFrames(numframes)]
alloca e inizializza l'array di fotogrammi interno alla libreria.
\item[XFA\_FreeFrames()]
libera l'animazione in memoria e l'array di fotogrammi che la contiene.
\item[XFA\_FreeAnim()]
libera l'animazione in memoria lasciando allocato l'array di fotogrammi che la contiene.
\item[XFA\_AnimMem()]
restituisce in byte la memoria occupata dall'animazione.
\item[XFA\_AnimFrames()]
restituisce il numero di fotogrammi totali dell'animazione.
\end{description}

\noindent Queste sono le funzioni dedicate alla gestione dell' animazione in memoria,
compresa allocazione e disallocazione di animazioni multiple.


\sottoparagrafo{Funzioni di caricamento e salvataggio}

\begin{description}
\item[XFA\_SaveAnim(fname)]
salva l'animazione correntemente in memoria in formato IFF-XFA.
\item[XFA\_LoadAnim(fname,xfa\_head,xfa\_cmap,ldmode)]
carica in memoria una animazione residente su disco.
\end{description}

\noindent Ecco le funzioni per il caricamento e il salvataggio in formato IFF-XFA (il
loro uso è veramente elementare).

\sottoparagrafo{Funzioni di posizionamento}

\begin{description}
\item[XFA\_PosOnFrame(frame)]
inizializza i buffer per permettere la compressione del fotogramma \c{frame}.
\item[XFA\_PutFrame(frame)]
compatta il fotogramma e lo memorizza nella posizione \c{frame} dell'animazione.
\item[XFA\_PutSkip(frame)]
inserisce un fotogramma invariante (delta nulli) nell'animazione in
posizione \c{frame} (utile per inserire pause, ecc.).
\item[XFA\_IsSkip(frame)]
controlla che il fotogramma \c{frame} sia invariante.
\end{description}

\noindent Queste quattro funzioni permettono di accedere alla compressione di una
animazione XFA in modo totalmente casuale, passando da un fotogramma
all'altro senza problemi. Grazie a queste funzioni si potrebbe già scrivere
un editor di animazioni XFA con controlli alla (D/P)Paint con poche righe di
codice.

Una caratteristica unica (forse) di \f{xfa.library} è la capacità di
gestire le animazioni in memoria senza bisogno di transcodifica.
Normalmente, i programmi di paint caricano le animazioni convertendole in
un formato interno (normalmente un ANIM5 modificato con ``xor'' tra i delta, per
consentire il play avanti-dietro), che deve essere di nuovo codificato in
``vero'' ANIM5 durante il salvataggio. Questo provoca una grossa perdita di
tempo (immaginiamo di dover ritoccare un singolo fotogramma in una grossa
animazione) che il formato XFA evita sistematicamente.

\sottoparagrafo{Funzioni di gestione Schermo}
\begin{description}
\item[XFA\_Play(loop,autopause,waitstart)]
esegue l'animazione secondo diverse modalità.
\item[XFA\_UseHead(xfa\_head)]
imposta i vari parametri della libreria in base all'header letto da disco.
\item[XFA\_UseCMap(screen,xfa\_cmap)]
copia la palette residente nella memoria dell'animazione in uno schermo.
\item[XFA\_OpenPlayStuff(wbmodeid)]
esegue le opportune allocazioni necessarie al play dell'animazione.
\item[XFA\_ClosePlayStuff()]
chiude e libera tutto quello che è stato allocato con \c{XFA\_OpenPlayStuff()}.
\item[XFA\_HeadPtr()]
restituisce il puntatore alla struttura head corrente (permette l'accesso
diretto da parte del programmatore).
\item[XFA\_CMapPtr()]
restituisce il puntatore alla struttura \c{CMap} corrente (permette l'accesso
diretto da parte del programmatore).
\end{description}

\noindent Questo gruppo di funzioni permette di aprire e inizializzare lo schermo ed
eventuali bitmap necessari al play dell'animazione.
Tra le funzioni presenti c'è ovviamente quella che si occupa
dell'esecuzione vera e propria dell'animazione.

\sottoparagrafo{Funzioni di conversione}

\begin{description}
\item[XFA\_ChangePackBitMap(bitmap)]
cambia il bitmap da cui attingere il frame da compattare (utile per
convertire in XFA animazioni in double buffering).
\item[XFA\_PutSeqFrame(frame)]
compatta in modo sequenziale il fotogramma (non consente l'accesso
casuale all'animazione ma è utile per convertire in XFA animazioni in double
buffering).
\end{description}

\noindent Per i maniaci delle conversioni, questa coppia di funzioni è l'ideale per
convertire in una sola passata una qualsiasi sequenza di fotogrammi
organizzata per il double buffering (tutti i formati ANIM, tranne
l'animbrush).

\sottoparagrafo{Funzioni di output}

\begin{description}
\item[XFA\_SaveScreen(screen,fname)]
salva lo schermo in formato IFF.
\end{description}

\noindent Un piccolo omaggio per tutti i programmatori che utilizzano questa libreria
e che non hanno alcuna voglia di scriversi il codice di salvataggio di una
schermata in IFF-ILBM. Si ringrazia NewIff39 per la gentile collaborazione.

\sottoparagrafo{Funzioni su Frame}

\begin{description}
\item[XFA\_OpenRead(fname,head,cmap)]
apre in lettura un file XFA.
\item[XFA\_ReadFrame(iff,mem)]
legge un fotogramma dal file.
\item[XFA\_CloseRead(iff)]
chiude il file aperto in lettura.
\item[XFA\_FreeFrame(mem)]
libera un fotogramma.
\end{description}

} % Da qui gli item sono di nuovo normali

\noindent Queste funzioni sono state da me aggiunte per consentire un facile accesso
sequenziale a ogni singolo fotogramma di una animazione XFA residente su
disco. Grazie a queste funzioni, non si è obbligati a caricare tutta
l'animazione in memoria, ed è possibile scrivere con facilità un player di
animazioni da disco, un convertitore XFA$\to$Anim, ecc.

\paragrafo{Conclusioni}

Ricordo che la documentazione della libreria, gli esempi dimostrativi e il
materiale per gli sviluppatori BlitzII, C ed E sono a disposizione negli atti
di IPISA~'95. Per ulteriori informazioni, suggerisco di consultare
attentamente la documentazione (in inglese) della libreria.


\autore{Michele Puccini\\
ClassX Development\\
Via Francesca 463\\
I-56030 Pisa PI\\
Tel./Fax:~(0587)749206}
{}

\citazione{\selectlanguage{english}Any sufficiently advanced bug is indistinguishable from a feature.}{Rich Kulawiec}
