home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / software / testi / corsoasm / sorgenti4 / lezione8n.s < prev    next >
Text File  |  1995-09-29  |  9KB  |  256 lines

  1.  
  2. ; Lezione8n.s - Routine di stampa di punti (plot), ottimizzata precalcolando
  3. ;        i multipli di 40 in una tabella, rimuovendo la moltiplicazione
  4. ;        nella routine PlotPix, che si prende il valore giusto dalla
  5. ;        tabella ogni volta.
  6.  
  7.     Section    dotta,CODE
  8.  
  9. ;    Include    "DaWorkBench.s"    ; togliere il ; prima di salvare con "WO"
  10.  
  11. *****************************************************************************
  12.     include    "startup1.s"    ; con questo include mi risparmio di
  13.                 ; riscriverla ogni volta!
  14. *****************************************************************************
  15.  
  16.  
  17. ; Con DMASET decidiamo quali canali DMA aprire e quali chiudere
  18.  
  19.         ;5432109876543210
  20. DMASET    EQU    %1000001110000000    ; copper e bitplane DMA abilitati
  21. ;         -----a-bcdefghij
  22.  
  23. LargSchermo    equ    40    ; Larghezza dello schermo in bytes.
  24.  
  25. START:
  26. ;     PUNTIAMO IL NOSTRO BITPLANE
  27.  
  28.     MOVE.L    #BITPLANE,d0
  29.     LEA    BPLPOINTERS,A1
  30.     move.w    d0,6(a1)
  31.     swap    d0
  32.     move.w    d0,2(a1)
  33.  
  34. ; PRECALCOLIAMO UNA TABELLA CON I MULTIPLI DI 40, ossia della larghezza dello
  35. ; schermo, per evitare di fare una moltiplicazione per ogni plottaggio.
  36.  
  37.     lea    MulTab,a0    ; Indirizzo spazio di 256 words dove scrivere
  38.                 ; i multipli di 40...
  39.     moveq    #0,d0        ; Iniziamo da 0...
  40.     move.w    #256-1,d7    ; Numero di multipli di 40 necessari
  41. PreCalcLoop
  42.     move.w    d0,(a0)+    ; Salviamo il multiplo attuale
  43.     add.w    #LargSchermo,d0    ; aggiungiamo larghschermo, prossimo multiplo
  44.     dbra    d7,PreCalcLoop    ; Creiamo tutta la MulTab
  45.  
  46. ; Puntiamo la cop...
  47.  
  48.     MOVE.W    #DMASET,$96(a5)        ; DMACON - abilita bitplane, copper
  49.                     ; e sprites.
  50.  
  51.     move.l    #COPPERLIST,$80(a5)    ; Puntiamo la nostra COP
  52.     move.w    d0,$88(a5)        ; Facciamo partire la COP
  53.     move.w    #0,$1fc(a5)        ; Disattiva l'AGA
  54.     move.w    #$c00,$106(a5)        ; Disattiva l'AGA
  55.     move.w    #$11,$10c(a5)        ; Disattiva l'AGA
  56.  
  57. mouse:
  58.     MOVE.L    #$1ff00,d1    ; bit per la selezione tramite AND
  59.     MOVE.L    #$13000,d2    ; linea da aspettare = $130, ossia 304
  60. Waity1:
  61.     MOVE.L    4(A5),D0    ; VPOSR e VHPOSR - $dff004/$dff006
  62.     ANDI.L    D1,D0        ; Seleziona solo i bit della pos. verticale
  63.     CMPI.L    D2,D0        ; aspetta la linea $130 (304)
  64.     BNE.S    Waity1
  65.  
  66.     move.w    #160,d0        ; coordinata X
  67.     move.w    #128,d1        ; coordinata Y
  68.     lea    bitplane,a0    ; Indirizzo del bitplane dove stampare in a0
  69.     lea    MulTab,a1    ; Indirizzo della tabella con i multipli della
  70.                 ; largh. schermo precalcolati in a1
  71.  
  72.     bsr.s    PlotPIXP    ; stampa il punto alla coord. X=d0, Y=d1
  73.  
  74.     MOVE.L    #$1ff00,d1    ; bit per la selezione tramite AND
  75.     MOVE.L    #$13000,d2    ; linea da aspettare = $130, ossia 304
  76. Aspetta:
  77.     MOVE.L    4(A5),D0    ; VPOSR e VHPOSR - $dff004/$dff006
  78.     ANDI.L    D1,D0        ; Seleziona solo i bit della pos. verticale
  79.     CMPI.L    D2,D0        ; aspetta la linea $130 (304)
  80.     BEQ.S    Aspetta
  81.  
  82.     btst    #6,$bfe001    ; mouse premuto?
  83.     bne.s    mouse
  84.     rts            ; esci
  85.  
  86. *****************************************************************************
  87. ;        Routine di plot dei punti (dots) ottimizzata
  88. *****************************************************************************
  89.  
  90. ;    Parametri in entrata di PlotPIXP:
  91. ;
  92. ;    a0 = Indirizzo bitplane destinazione
  93. ;    a1 = Indirizzo della tabella con i multipli di 40 precalcolati
  94. ;    d0.w = Coordinata X (0-319)
  95. ;    d1.w = Coordinata Y (0-255)
  96.  
  97. ;           ________________
  98. ;     _____/                \_____  __  _
  99. ;    |   _/                  \_   ||  || |
  100. ;    |   \  ______    ______  /   ||  || |
  101. ;    |   _\ \  ___\  /___  / /_   ||  || |
  102. ;    |   /¯  \/   `  `   \/  ¯\   ||  || |
  103. ;    |   ¯\_     /|  |\     _/¯   ||  || |
  104. ;    |      \    ¯¯  ¯¯    /zO!   ||  || |
  105. ;    |       \_.--.--.--._/       ||  || |
  106. ;    `        `|  |  |  |`        ||  || |
  107. ;    __/\__    |  |  |  |         ||  || |
  108. ;    \ +O /    |  |  |  |         ||  || |
  109. ;    / --_\    |  |  |  |         ||  || |
  110. ;    ¯¯\/_ ____|  |  |  |_________||__||_|
  111. ;              `--`--`--`
  112.  
  113. PlotPIXP:
  114.     move.w    d0,d2        ; Copia la coordinata X in d2
  115.     lsr.w    #3,d0        ; Intanto trova l'offset orizzontale,
  116.                 ; dividendo per 8 la coordinata X.
  117.  
  118. ; ** INIZIO MODIFICA: ecco le 2 istruzioni originali:
  119. ;
  120. ;    mulu.w    #largschermo,d1
  121. ;    add.w    d1,d0        ; Somma scost. verticale a quello orizzontale
  122. ;
  123. ; e quelle senza MULU:
  124.  
  125. ; Ora troviamo l'offset verticale, ossia la Y, prendendo il giusto valore
  126. ; precalcolato dalla tabella Multab, il cui indirizzo e' in a1
  127.  
  128.     add.w    d1,d1        ; Moltiplichiamo la Y per 2, trovando l'offset
  129.                 ; dalla tabella dei multipli, infatti ogni
  130.                 ; multiplo e' una word, ossia 2 bytes. Ora, se
  131.                 ; per esempio la coordinata era 0, prendiamo
  132.                 ; il primo valore della tabella, che e' zero.
  133.                 ; Se e' 3, allora prendiamo il terzo valore
  134.                 ; della tabella, che pero' si trova al sesto
  135.                 ; byte, dato che dobbiamo saltare 2 bytes, 1
  136.                 ; word, per ogni valore in tabella.
  137.     add.w    (a1,d1.w),d0    ; Aggiungiamo lo scostamento verticale giusto,
  138.                 ; preso dalla tabella, all'offset orizzontale
  139.  
  140. ; ** FINE DELLA MODIFICA
  141.  
  142.     and.w    #%111,d2    ; Seleziona solo i primi 3 bit di X (resto)
  143.     not.w    d2
  144.  
  145.     bset.b    d2,(a0,d0.w)    ; Setta il bit d2 del byte distante d0 bytes
  146.                 ; dall'inizio dello schermo.
  147.     rts
  148.  
  149. *****************************************************************************
  150.  
  151.     SECTION    GRAPHIC,DATA_C
  152.  
  153. COPPERLIST:
  154.  
  155.     dc.w    $8E,$2c81    ; DiwStrt
  156.     dc.w    $90,$2cc1    ; DiwStop
  157.     dc.w    $92,$0038    ; DdfStart
  158.     dc.w    $94,$00d0    ; DdfStop
  159.     dc.w    $102,0        ; BplCon1
  160.     dc.w    $104,$24    ; BplCon2 - Tutti gli sprite sopra i bitplane
  161.     dc.w    $108,0        ; Bpl1Mod
  162.     dc.w    $10a,0        ; Bpl2Mod
  163.             ; 5432109876543210
  164.     dc.w    $100,%0001001000000000    ; 1 bitplane LOWRES 320x256
  165.  
  166. BPLPOINTERS:
  167.     dc.w $e0,0,$e2,0    ;primo     bitplane
  168.  
  169.     dc.w    $0180,$000    ; color0 - SFONDO
  170.     dc.w    $0182,$1af    ; color1 - SCRITTE
  171.  
  172.     dc.w    $FFFF,$FFFE    ; Fine della copperlist
  173.  
  174.  
  175. *****************************************************************************
  176.  
  177.     SECTION    MIOPLANE,BSS_C
  178.  
  179. BITPLANE:
  180.     ds.b    40*256    ; un bitplane lowres 320x256
  181.  
  182. ; Tabella che conterra' i multipli della larghezza dello schermo precalcolati
  183. ; per eliminare la moltiplicazione nella routine PlotPIX, aumentando la sua
  184. ; velocita'.
  185.  
  186.     SECTION    Precalc,bss
  187.  
  188. MulTab:
  189.     ds.w    256
  190.  
  191.     end
  192.  
  193. Con questo listato facciamo una piccola introduzione alla lezione sulle
  194. ottimizzazioni, infatti "TABELLIAMO" una moltiplicazione. Questa operazione e'
  195. molto frequente nel codice delle piu' veloci demo o nei giochi 3d.
  196. La nostra routine di stampa di un pixel funziona egregiamente, ma contiene una
  197. LENTISSIMA moltiplicazione. dobbiamo toglierla assolutamente. Non essendo una
  198. moltiplicazione per una potenza di 2, non possiamo sostituirlo con un LSL come
  199. abbiamo furbescamente fatto nella routine di print in Lezione8b.s.
  200. Ma le vie del coding sono infinite. Considerate la situazione che abbiamo:
  201.  
  202.     mulu.w    #largschermo,d1
  203.     add.w    d1,d0        ; Somma scost. verticale a quello orizzontale
  204.  
  205. Larghschermo in questo caso e' 40. In d1 abbiamo ogni volta un valore diverso,
  206. a seconda della Y, ma sappiamo che puo' andare da 0 a 255 come massimo.
  207. Dunque ci sono 256 risultati possibili, a seconda che capiti uno dei 256
  208. possibili valori di Y, ossia di d1. Questi 256 risultati, se dassimo ogni
  209. volta in entrata un numero crescende da 0 a 245 sarebbe:
  210.  
  211. 0,40,80,120,160,200    ossia    40*0,40*1,40*2,40*3,40*4....
  212.  
  213. Immaginiamo di "prepararci" tutti questi 256 risultati possibili in uno spazio
  214. azzerato preventivamente preparato:
  215.  
  216. MulTab:
  217.     ds.w    256
  218.  
  219. Per creare la tabella dei multipli di 40 basta un semplicissimo loop:
  220.  
  221.     lea    MulTab,a0    ; Indirizzo spazio di 256 words dove scrivere
  222.                 ; i multipli di 40...
  223.     moveq    #0,d0        ; Iniziamo da 0...
  224.     move.w    #256-1,d7    ; Numero di multipli di 40 necessari
  225. PreCalcLoop
  226.     move.w    d0,(a0)+    ; Salviamo il multiplo attuale
  227.     add.w    #LargSchermo,d0    ; aggiungiamo larghschermo, prossimo multiplo
  228.     dbra    d7,PreCalcLoop    ; Creiamo tutta la MulTab
  229.  
  230. Ora abbiamo la tabella coi "risultati" pronti. Ma come facciamo a "prendere"
  231. dalla tabella il risultato giusto ogni volta? In entrata abbiamo la coordinata
  232. Y, ossia un numero da 0 a 255. Se Y e' zero, basta prendere il primo valore
  233. della tabella, ossia la word $0000. Se invece fosse y=1, dobbiamo prendere il
  234. secondo valore della tabella, che pero' si trova a 2 bytes dal suo inizio,
  235. dato che i sui valori sono words. Allo stesso modo, se volessimo prendere il
  236. risultato giusto per la coord. Y = 50, il risultato sarebbe la cinquantesima
  237. word della tabella, ad una distanza cioe' di 100 bytes. tutto cio' non vi
  238. suggerisce la soluzione? Per calcolare l'offset, ossia la distanza dall'inizio
  239. della tabella, basta moltiplicare per 2 la Y! E siccome si puo' moltiplicare
  240. per 2 con un:
  241.  
  242.      add.w    d1,d1
  243.  
  244. Siamo sempre senza moltiplicazioni. Ora in d1 abbiamo l'offset dall'inizio
  245. della tabella; dobbiamo "prenderlo" e aggiungerlo a d0. Questo si puo' fare
  246. con un'unica operazione:
  247.  
  248.     add.w    (a1,d1.w),d0    ; Aggiungiamo lo scostamento verticale giusto,
  249.                 ; preso dalla tabella, all'offset orizzontale
  250.  
  251. Avendo in a1 l'indirizzo della tabella MulTab.
  252.  
  253. Troveremo questo sistema di "tabellaggio" sempre piu' spesso nei listati
  254. che svolgono molti calcoli.
  255.  
  256.