12.06.2013 Views

1 - Amiga Magazine Online

1 - Amiga Magazine Online

1 - Amiga Magazine Online

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

2:v=O<br />

3: for y=yO to yO+OnScreenDim-1<br />

4: u = o<br />

5: screen = ScreenBase + 320 * y<br />

6: texture = TextureBase + TextureDim*int(v)<br />

7: for x=xO to xO+OnScreenDim-1<br />

8: screen[x] = texture[u]<br />

9: u += Step<br />

10: endfor<br />

11: v+=Step<br />

12: endfor<br />

Per facilitare la comprensione abbiamo inserito dei nu-<br />

meri di riga, per mettere in evidenza come le istruzioni in<br />

pseudo-linguaggio vengono tradotte in assembly:<br />

;a0 = ptr alla texture<br />

;al = ptr allo schermo chunky<br />

;dO = u (nel formato 16.16)<br />

;dl = v (nel formato 16.16)<br />

;d2 = xO + OnScreenDim - 1<br />

;d3 = yO + OnScreenDim - 1<br />

;d4 = Step (nel formato 16.16)<br />

;d6 = x<br />

;d7 = y<br />

1: moveq #0,d4<br />

m0ve.w TextureDim,d4<br />

swap d4<br />

moveq #0,d5<br />

m0ve.w OnScreenDim,d5<br />

divu.1 d5,d4 ;d4=Step<br />

2: moveq #O,dl ;dl=v<br />

3: m0ve.w yO,d7 ;d7=y<br />

m0ve.w d7,d3<br />

add.w OnScreenDim,d3<br />

subq.w #l,d3<br />

loopy :<br />

4: moveq #O,dO ; dO=u<br />

5: m0ve.w d7,d5<br />

mu1u.w #320,d5<br />

;al=ptr alla riga attuale dello schermo<br />

move.1 ScreenBase,al<br />

adda.1 d5,al<br />

6: move.1 dl,d5<br />

swap d5<br />

mu1u.w TextureDim,d5<br />

move.1 TextureBase,aO<br />

;aO=ptr alla riga attuale della texture<br />

adda.1 d5,aO<br />

7: m0ve.w xO,d6 ;d6=x<br />

m0ve.w d6,d2<br />

add.w OnScreenDim,d2<br />

subq.w #l,d2<br />

loopx:<br />

8: swap do<br />

m0ve.b (aO,dO.w),(al,d6.w) ;Scrive il pixel<br />

swap do<br />

9: add.1 d4,dO ; u+=Step<br />

10: addq.w #l,d6<br />

cmp.w d2,d6<br />

b1e.s loopx<br />

11: add.1 d4,dl ;v+=Step<br />

12: addq.w #l,d7<br />

cmp.w d3,d7<br />

b1e.s loopy<br />

Analizziamone le parti più importanti. La riga numero 1<br />

esegue la divisione tra due numeri interi, con risultato in<br />

virgola fissa. Questo significa che il dividendo deve esse-<br />

re preventivamente convertito nel formato 16.16 (con l'i-<br />

struzione swap), al contrario del divisore che rimane in<br />

formato intero. Alla riga numero 5 c'è una moltiplicazio-<br />

ne per 320 che serve per calcolare l'offset alla riga di<br />

schermo in cui bisogna scrivere. Immagino sia noto che<br />

è possibile ottimizzare tale operazione in almeno due<br />

modi. I1 primo consiste nel convertire la moltiplicazione<br />

in una serie di operazioni più semplici:<br />

che in assembly può essere scritto come:<br />

I1 secondo metodo è quello più efficiente se si dispone<br />

di fast RAM, e consiste nell'accedere a una tabella precal-<br />

colata di tutte le moltiplicazioni per 320 che ci interessa-<br />

no.<br />

Nel caso di uno schermo da 320x200, una tabella costi-<br />

tuita da 200 long (800 byte) è quello che serve, e la mol-<br />

tiplicazione si scrive semplicemente:<br />

dove a0 contiene l'indirizzo della tabella. La moltiplica-<br />

zione per TextureDim presente alla linea 6 può essere<br />

sostituita con una più veloce istruzione di shift. Le di-<br />

mensioni delle texture sono sempre delle potenze di 2<br />

(nel nostro caso, 128) proprio per permettere ottimizza-<br />

zioni di questo genere.<br />

Come i più esperti avranno notato, il precedente listato<br />

assembly è tradotto direttamente da quello in pseudo-lin-<br />

guaggio, e non è in alcun modo ottimizzato. È decisa-<br />

mente il caso di migliorarlo, portando fuori dai cicli i cal-<br />

coli ridondanti e utilizzando le istruzioni di decremento e<br />

salto (dbra) per la chiusura dei cicli:<br />

moveq #0,d4

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!