Articolo pubblicato sul n. 61 di MCmicrocomputer (Edizioni Technimedia Srl - Roma) nel marzo 1987
Commodore 128: (seconda parte) Secondo appuntamento con la "misteriosa" grafica 640x200 dell'ancor più "misterioso" Commodore 128. Questo mese è la volta di due utility grafiche praticamente indispensabili, la prima per tracciare linee tra due punti, la seconda per ottenere una copia su carta dei vostri output grafici di altissima risoluzione.
Funzione DRAWTO
Il nome di questa prima funzione indica il fatto che non si tratta di tracciamento di linea tra due punti indicati, ma più semplicemente tra l'ultimo punto tracciato precedentemente e il punto indicato. Come dire che per tracciare una linea tra il punto di coordinate (20,30) e il punto (200,100) occorre prima effettuare un plot del primo e successivamente dare un comando di DRAWTO fino a (200,100). Questo apparente appesantimento di gestione viene immediatamente riappagato quando si tratta di disegnare (e capita molto spesso) linee sequenziali ovvero quando abbiamo che l'ultimo punto della linea A è il primo punto della linea B e così via. Ad esempio quando dobbiamo tracciare un rettangolo, un cerchio o una funzione qualsiasi per approssimazione di punti non troppo vicini l'un l'altro. Operativamente parlando, dunque, per disegnare un rettangolo di vertici (10,10) (10,100) (100,100) e (100,10) con una normale funzione di tracciamento linee dovremmo scrivere:
DRAW 10,10,10,100 DRAW 10,100,100,100 DRAW 100,100,100,10 DRAW 100,10,10,10
in cui, notiamo, la seconda coordinata di ogni draw è uguale alla prima del successivo comando. Con una funzione DRAWTO scriveremmo:
PLOT10,10 DRAWTO 10,100 DRAWTO 100,100 DRAWTO 100,10 DRAWTO 10,10
L'implementazione sul 128
A dire il vero, la scelta circa il DRAWTO invece che una semplice DRAW sul Commodore 128 è stata forzata anche dal fatto che tale macchina, quando si chiama una SYS non accetta più di tre parametri di 8 bit l'uno da assegnare rispettivamente ai registri A,X,Y. Come abbiamo già fatto lo scorso mese per il comando PLOT, la SYS relativa al DRAWTO sarà seguita dal valore di ascissa, suddivisa in parte passa e parte alta, e dal valore di ordinata. Il listato 1 contiene, sottoforma di linee DATA, i due programmi in linguaggio macchina di questo mese. Va fatto notare che per eseguire un DRAWTO, c'è bisogno (ovviamente) dei programmi pubblicati il mese scorso che servivano per accedere alla pagina grafica, per ripulirla, per tracciare punti e per tornare in modo testo... quindi prima di far partire il listato 1 bisogna avere in memoria le suddette funzioni. Fatto questo, per tracciare una linea dal punto (A,B) al punto (C,D) scriveremo:
SYS 4928, A and 255, A / 256, B SYS 5200, C and 255, C / 256, D
dove la prima SYS è il PLOT del punto iniziale e la seconda il DRAWTO sino al punto finale. Ricordiamo che l'espressione "X and 255" restituisce la parte bassa della X (gli 8 bit meno significativi), mentre "X/256" restituisce la parte alta (gli 8 bit più significativi). Nel corpo della funzione nessun controllo è effettuato circa la validità del punto di arrivo, ovvero se tracciamo una linea da (0,0) a (100,250), quindi con punto di arrivo fuori campo, apparirà sul video grafico solo la porzione di retta visibile (e con la giusta angolazione). Dato che i tre parametri della SYS sono ad otto bit e per la Y, che normalmente varia tra 0 e 199, è utilizzato un solo parametro, se tentiamo di tracciare una linea la cui Y eccede il limite di 255, il 128 segnalerà un errore ILLEGAL QUANTITY (è la sys stessa a provocarlo, la routine non c'entra niente). L'algoritmo di tracciamento linea è il ben noto Bransemahn ed ha la particolarità di non richiedere né moltiplicazioni né divisioni né qualsiasi calcolo in virgola mobile qualunque linea si tracci, quindi è particolarmente indicato per essere trascritto in un linguaggio macchina come quello del 6502 che offre ben pochi strumenti di calcolo. Praticamente tale algoritmo traccia il primo punto, si calcola il segno dell'andamento verso il punto di arrivo e poi incementa la x o la y a seconda di alcuni contatori interni, tracciando i punti via via calcolati fino al punto finale. Di per se stesso è molto veloce anche se a causa della strana architettura del 128 (memoria video separata e indirizzabile indirettamente tramite alcuni registri anch'essi indirizzabili indirettamente) non sembra essere tale. Fatto funzionare in modo FAST riesce ad essere abbastanza accettabile. Tutta la routine di DRAWTO è mostrata nel listato 2: i lettori più "tosti" potranno eventualmente provare a migliorarla, non senza comunicarci i loro risultati, scrivendo a questa rubrica (vedi riquadro in fondo). Infine, i listati 5 e 6 sono un piccolo esempio di applicazioni lineerecce, la prima solo orizzontali e verticali, la seconda con tutte le angolazioni. Date ovviamente il run dopo aver caricato la parte di codice del numero scorso e quella di listato 1. Per fermare l'esecuzione dei due demo basta premere qualsiasi tasto, se trattasi della freccettina a sinistra otterremo un hard copy (stampante collegata, accesa e rispondente ai requisiti indicati qui di seguito).
Hard Copy 640x200
Prima di passare alla routine di HardCopy mostrata nei listati 3 e 4 avvertiamo i lettori che tale programma non gira sulla stampante MPS 803 (e famiglia: 801, 1515, 1525 ecc.) dato che queste hanno una risuluzione di 480 punti per riga e la grafica del 128 ne mette a disposizione 640. Per i nostri esperimenti abbiamo usato una stampante STAR NL-10 dotata di interfaccia Commodore la quale riesce a stampare fino a 1920 punti per linea. Noi l'abbiamo usata in modo 1280 punti in modo da ottenere una stampa quanto più proporzionata possibile al rapporto altezza/larghezza dell'immagine sul monitor. Tale stampante, per accedere al modo grafico necessita di una serie di caratteri di controllo che settano la spaziatura verticale (per far combaciare le linee di stampa), ed indicano il tipo di risoluzione e il numero di pixel grafici per linea. Per semplicità, inoltre, è stato utilizzato il modo grafico 8 pixel che permette una più veloce trasformazione dal modo di memorizzare i pixel da parte del 128 al modo di stamparli da parte della NL-10. In definitiva i codici inviati (ve li indichiamo in modo da poter facilmente adattare la routine ad altre stampanti, fateci sapere...) sono un ESC+"A"+CHR$(6) per la spaziatura e un ESC+"L"+CHR$(128)+CHR$(2) per indicare le specifiche grafiche. I listati 3 e 4, come detto, eseguono l'hard copy: commentiamoli brevemente. La prima parte trasferisce l'immagine in memoria, un venticinquesimo per volta (pari a una linea di 8 pixel) in una zona di memoria libera del 128, nelle celle $C00-$E80. Ciò per semplificare più possibile la faccenda. Ad ogni iterazione è invocata la routine di stampa all'indirizzo 15A0. Questa, dopo aver salvato nello stack i registri X e Y, apre un file di stampa. Per fare ciò utilizza 4 routine del sistema operativo atte allo scopo (si utilizzano per qualsiasi tipo di file). La prima, locata all'indirizzo $FFBA permette di settare numero file, numero periferica e indirizzo secondario, nel nostro caso la tripla 4,4,0. La seconda routine, $FFBD, si usa per indicare il nome del file, mettendo nel registro A la lunghezza del nome e nei registri X e Y, come sempre spezzato in parte alta e parte bassa, la locazione in memoria di tale nome. Dal momento che noi non dovevamo indicare alcun nome di file è bastato settare pari a zero il contenuto dell'accumulatore. La routine di $FFC0 esegue la open vera e propria riferendosi ai valori precedentemente settati con le due routine. Infine, con $FFC9, dopo aver indicato nel registro X a quale file ci riferiamo, effettuiamo una sorta di CMD 4 con la quale stabiliamo che da questo momento in poi i caratteri inviati devono arrivare alla stampante. Per inviare caratteri si usa la routine $FFD2, caricando nell'accumulatore il codice ascii di questi. Il ciclo che segue le operazioni di open serve per inviare i 7 codici di controllo di cui sopra. Essi sono stati mappati a partire dall'indirizzo $1598 (in testa alla routine) ed è lì che si dovrà mettere le mani per modificare tale sequenza. Importante: i caratteri sono messi in memoria al contrario per semplificare il loop. In altre parole il primo ESC è all'indirizzo $159F l'ultimo carattere di controllo a $1599. Segue la vera e propria trasformazione di formato e relativo invio di dati da stampare. Terminata la linea si manda un return ($0D) per far avanzare la carta e si chiude il canale e il file con la stampante. Tutto ciò 25 volte come da listato 3. RTS.
Listati 7 e 8
Il listato 7 è un ulteriore esempio: traccia la funzione grafica mostrata in figura 1. Si tratta della ben nota Z=SIN(Q)/Q dove Q è la distanza dall'origine degli assi, misurata sul piano X-Y. Terminato il disegno (data la complessità dei calcoli e soprattutto il numero delle iterazioni necessarie trascorrono alcune decine di minuti) premendo la classica freccettina a sinistra ottenuamo l'hard copy su carta. Infine, il listato 8 mostra le linee da aggiungere al programma math pack 128 presentato il mese scorso, per ottenere l'hard copy e per un tracciamento degli assi cartesiani più rapido. Come al solito, la copia su carta avviene premendo la freccettina quando è presente su video la funzione disegnata. Ovviamente è necessario aggiungere anche le linee data del listato 1 adoperando numeri linea diversi, ad esempio dal 1800 in poi, per non calpestare altre linee del vecchio listato. In figura 2 è presente un output di math pach trasferito su carta.
Espansioni future
Non è proprio nello stile di MC fare anticipazioni, specialmente quando la notizia non implica una promessa da parte del sottoscritto, ma devo riconoscere che programmare a colpi di sys è davvero penoso. Per la verità quanto presentato in questi due articoli è un embrione di ADP BASIC per il 128 che da molto tempo sto maturando dentro di me. Anticipazione per anticipazione vorrei aggiungere che il lavoro ancora non è iniziato quindi non conterei troppo su brevi scadenze: del resto fare una espansione basic su una macchina così difficile come il 128 sicuramente non è facile, specialmente considerato che ancora non se ne sono viste sotto nessuna specie. Questo nuovo ADP BASIC, come intuibile, riguarderà istruzioni grafiche per l'altissima risoluzione, versante per il quale la Commodore davvero non s'è sforzata affatto. Avremo le solite istruzioni per disegnare punti, linee, cerchi, riempimenti di aree, più altre meno diffuse come come il clip di aree di schermo o il modo grafico X-OR di punti e linee. Questo per citare qualcosa. Tutto il resto potrà saltar fuori da suggerimenti e/o consigli di lettori che interverranno scrivendoci. Arrivederci al prossimo numero.
Impaginato originale... Articolo pubblicato su www.digiTANTO.it - per ulteriori informazioni clicca qui |