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

  1.  
  2. ; Lezione7m.s    Posizionamento degli sprite tramite una routine universale
  3. ; Questo esempio mostra una routine universale per spostare gli sprite che
  4. ; considera tutti i bit delle posizioni orizzontali e verticali degli sprite.
  5. ; Inoltre aggiunge automaticamente gli offsets (128 per le coordinate
  6. ; orizzontali, $2c per le verticali).
  7. ; In questo modo le coordinate nelle tabelle possono essere quelle reali,
  8. ; cioe` da 0 a 320 per le coordinate orizzontali e da 0 a 256 per le
  9. ; coordinate verticali
  10.  
  11.  
  12.     SECTION    CiriCop,CODE
  13.  
  14. Inizio:
  15.     move.l    4.w,a6        ; Execbase
  16.     jsr    -$78(a6)    ; Disable
  17.     lea    GfxName(PC),a1    ; Nome lib
  18.     jsr    -$198(a6)    ; OpenLibrary
  19.     move.l    d0,GfxBase
  20.     move.l    d0,a6
  21.     move.l    $26(a6),OldCop    ; salviamo la vecchia COP
  22.  
  23. ;    Puntiamo la PIC "vuota"
  24.  
  25.     MOVE.L    #BITPLANE,d0    ; dove puntare
  26.     LEA    BPLPOINTERS,A1    ; puntatori COP
  27.     move.w    d0,6(a1)
  28.     swap    d0
  29.     move.w    d0,2(a1)
  30.  
  31. ;    Puntiamo lo sprite
  32.  
  33.     MOVE.L    #MIOSPRITE,d0        ; indirizzo dello sprite in d0
  34.     LEA    SpritePointers,a1    ; Puntatori in copperlist
  35.     move.w    d0,6(a1)
  36.     swap    d0
  37.     move.w    d0,2(a1)
  38.  
  39.     move.l    #COPPERLIST,$dff080    ; nostra COP
  40.     move.w    d0,$dff088        ; START COP
  41.     move.w    #0,$dff1fc        ; NO AGA!
  42.     move.w    #$c00,$dff106        ; NO AGA!
  43.  
  44. mouse:
  45.     cmpi.b    #$aa,$dff006    ; Linea $aa?
  46.     bne.s    mouse
  47.  
  48.     btst    #2,$dff016
  49.     beq.s    aspetta
  50.     bsr.w    MuoviSprite    ; Muovi lo sprite 0
  51.  
  52. Aspetta:
  53.     cmpi.b    #$aa,$dff006    ; linea $aa?
  54.     beq.s    Aspetta
  55.  
  56.     btst    #6,$bfe001    ; mouse premuto?
  57.     bne.s    mouse
  58.  
  59.     move.l    OldCop(PC),$dff080    ; Puntiamo la cop di sistema
  60.     move.w    d0,$dff088        ; facciamo partire la vecchia cop
  61.  
  62.     move.l    4.w,a6
  63.     jsr    -$7e(a6)    ; Enable
  64.     move.l    gfxbase(PC),a1
  65.     jsr    -$19e(a6)    ; Closelibrary
  66.     rts
  67.  
  68. ;    Dati
  69.  
  70. GfxName:
  71.     dc.b    "graphics.library",0,0
  72.  
  73. GfxBase:
  74.     dc.l    0
  75.  
  76. OldCop:
  77.     dc.l    0
  78.  
  79.  
  80. ;    Per muovere correttamente lo sprite, prima leggiamo le tabelle per
  81. ;    sapere quali posizioni deve assumere lo sprite, poi comunichiamo tali
  82. ;    posizioni, nonche' l'indirizzo e l'altezza degli sprite, alla routine
  83. ;    UniMuoviSprite, tramite i registri a1,d0,d1,d2
  84.  
  85. MuoviSprite:
  86.     bsr.s    LeggiTabelle    ; Legge le posizioni X ed Y dalle tabelle,
  87.                 ; mettendo nel registro a1 l'indirizzo dello
  88.                 ; sprite, in d0 la pos. Y, in d1 la pos. X
  89.                 ; e in d2 l'altezza dello sprite.
  90.  
  91. ;
  92. ;    Parametri in entrata di UniMuoviSprite:
  93. ;
  94. ;    a1 = Indirizzo dello sprite
  95. ;    d0 = posizione verticale Y dello sprite sullo schermo (0-255)
  96. ;    d1 = posizione orizzontale X dello sprite sullo schermo (0-320)
  97. ;    d2 = altezza dello sprite
  98. ;
  99.  
  100.     bsr.w    UniMuoviSprite  ; esegue la routine universale che posiziona
  101.                     ; lo sprite
  102.     rts
  103.  
  104.  
  105.  
  106.  
  107. ; Questa routine legge dalle 2 tabelle le coordinate reali degli sprite.
  108. ; Cioe` la coordinata X varia da 0 a 320 e la Y da 0 a 256 (senza overscan).
  109. ; Poiche` in questo esempio non usiamo l'overscan, la tabella delle coordinate
  110. ; Y e` una tabella di byte. La tabella delle coordinate X, invece e` fatta
  111. ; di word perche` deve contenere anche valori maggiori di 256.
  112. ; Questa routine, pero` non posiziona direttamente lo sprite. Essa si limita
  113. ; semplicemente a farlo fare alla routine universale, comunicandogli le
  114. ; coordinate tramite i registri d0 e d1
  115.  
  116. LeggiTabelle:
  117.     ADDQ.L    #1,TABYPOINT     ; Fai puntare al byte successivo
  118.     MOVE.L    TABYPOINT(PC),A0 ; indirizzo contenuto in long TABXPOINT
  119.                  ; copiato in a0
  120.     CMP.L    #FINETABY-1,A0  ; Siamo all'ultimo byte della TAB?
  121.     BNE.S    NOBSTARTY    ; non ancora? allora continua
  122.     MOVE.L    #TABY-1,TABYPOINT ; Riparti a puntare dal primo byte
  123. NOBSTARTY:
  124.     moveq    #0,d0        ; Pulisci d0
  125.     MOVE.b    (A0),d0        ; copia il byte della tabella, cioe` la
  126.                 ; coordinata Y in d0 in modo da farla
  127.                 ; trovare alla routine universale
  128.  
  129.     ADDQ.L    #2,TABXPOINT     ; Fai puntare alla word successiva
  130.     MOVE.L    TABXPOINT(PC),A0 ; indirizzo contenuto in long TABXPOINT
  131.                  ; copiato in a0
  132.     CMP.L    #FINETABX-2,A0  ; Siamo all'ultima word della TAB?
  133.     BNE.S    NOBSTARTX    ; non ancora? allora continua
  134.     MOVE.L    #TABX-2,TABXPOINT ; Riparti a puntare dalla prima word-2
  135. NOBSTARTX:
  136.     moveq    #0,d1        ; azzeriamo d1
  137.     MOVE.w    (A0),d1        ; poniamo il valore della tabella, cioe`
  138.                 ; la coordinata X in d1
  139.  
  140.     lea    MIOSPRITE,a1    ; indirizzo dello sprite in A1
  141.     moveq    #13,d2        ; altezza dello sprite in d2
  142.     rts
  143.  
  144.  
  145. TABYPOINT:
  146.     dc.l    TABY-1        ; NOTA: i valori della tabella qua sono bytes,
  147.                 ; dunque lavoriamo con un ADDQ.L #1,TABYPOINT
  148.                 ; e non #2 come per quando sono word o con #4
  149.                 ; come quando sono longword.
  150. TABXPOINT:
  151.     dc.l    TABX-2        ; NOTA: i valori della tabella qua sono word,
  152.  
  153. ; Tabella con coordinate Y dello sprite precalcolate.
  154. ; Da notare che la posizione Y per far entrare lo sprite nella finestra video
  155. ; deve essere compresa tra $0 e $ff, infatti l'offset di $2c viene aggiunto
  156. ; dalla routine. Se non si usano schermi overscan, ossia non piu' lunghi di
  157. ; 255 linee, si puo' usare una tabella di valori dc.b (da $00 a $FF)
  158.  
  159.  
  160. ; Come rifarsi la tabella:
  161.  
  162. ; BEG> 0
  163. ; END> 360
  164. ; AMOUNT> 200
  165. ; AMPLITUDE> $f0/2
  166. ; YOFFSET> $f0/2
  167. ; SIZE (B/W/L)> b
  168. ; MULTIPLIER> 1
  169.  
  170.  
  171. TABY:
  172.     incbin    "ycoordinatok.tab"    ; 200 valori .B
  173. FINETABY:
  174.  
  175. ; Tabella con coordinate X dello sprite precalcolate. Questa tabella contiene
  176. ; i valori REALI delle coordinate dello schermo, non i valori "dimezzati" per
  177. ; lo scorrimento a scatti di due pixel come abbiamo visto fino ad ora.
  178. ; Nella tabella infatti ci sono byte non piu' grandi di 304 e non piu'
  179. ; piccoli di zero.
  180.  
  181. TABX:
  182.     incbin    "xcoordinatok.tab"    ; 150 valori .W
  183. FINETABX:
  184.  
  185.  
  186.  
  187.  
  188. ; Routine universale di posizionamento degli sprite.
  189. ; Questa routine modifica la posizione dello sprite il cui indirizzo e`
  190. ; contenuto nel registro a1 e la cui altezza e` contenuta nel registro d2,
  191. ; e posiziona lo sprite alle coordinate Y e X contenute rispettivamente nei
  192. ; registri d0 e d1.
  193. ; Prima di chiamare questa routine e` necessario mettere l'indirizzo dello
  194. ; sprite nel registro a1, la sua altezza nel registro d2, la coordinata Y nel
  195. ; registro d0, la X nel registro d1
  196.  
  197. ; Questa procedura e` chiamata "passaggio di parametri".
  198. ; Notate che questa routine modifica i registri d0 e d1.
  199.  
  200. ;
  201. ;    Parametri in entrata di UniMuoviSprite:
  202. ;
  203. ;    a1 = Indirizzo dello sprite
  204. ;    d0 = posizione verticale Y dello sprite sullo schermo (0-255)
  205. ;    d1 = posizione orizzontale X dello sprite sullo schermo (0-320)
  206. ;    d2 = altezza dello sprite
  207. ;
  208.  
  209. UniMuoviSprite:
  210. ; posizionamento verticale
  211.     ADD.W    #$2c,d0        ; aggiungi l'offset dell'inizio dello schermo
  212.  
  213. ; a1 contiene l'indirizzo dello sprite
  214.  
  215.     MOVE.b    d0,(a1)        ; copia il byte in VSTART
  216.     btst.l    #8,d0
  217.     beq.s    NonVSTARTSET
  218.     bset.b    #2,3(a1)    ; Setta il bit 8 di VSTART (numero > $FF)
  219.     bra.s    ToVSTOP
  220. NonVSTARTSET:
  221.     bclr.b    #2,3(a1)    ; Azzera il bit 8 di VSTART (numero < $FF)
  222. ToVSTOP:
  223.     ADD.w    D2,D0        ; Aggiungi l'altezza dello sprite per
  224.                 ; determinare la posizione finale (VSTOP)
  225.     move.b    d0,2(a1)    ; Muovi il valore giusto in VSTOP
  226.     btst.l    #8,d0
  227.     beq.s    NonVSTOPSET
  228.     bset.b    #1,3(a1)    ; Setta il bit 8 di VSTOP (numero > $FF)
  229.     bra.w    VstopFIN
  230. NonVSTOPSET:
  231.     bclr.b    #1,3(a1)    ; Azzera il bit 8 di VSTOP (numero < $FF)
  232. VstopFIN:
  233.  
  234. ; posizionamento orizzontale
  235.  
  236.     add.w    #128,D1        ; 128 - per centrare lo sprite.
  237.     btst    #0,D1        ; bit basso della coordinata X azzerato?
  238.     beq.s    BitBassoZERO
  239.     bset    #0,3(a1)    ; Settiamo il bit basso di HSTART
  240.     bra.s    PlaceCoords
  241.  
  242. BitBassoZERO:
  243.     bclr    #0,3(a1)    ; Azzeriamo il bit basso di HSTART
  244. PlaceCoords:
  245.     lsr.w    #1,D1        ; SHIFTIAMO, ossia spostiamo di 1 bit a destra
  246.                 ; il valore di HSTART, per "trasformarlo" nel
  247.                 ; valore fa porre nel byte HSTART, senza cioe'
  248.                 ; il bit basso.
  249.     move.b    D1,1(a1)    ; Poniamo il valore XX nel byte HSTART
  250.     rts
  251.  
  252.  
  253.     SECTION    GRAPHIC,DATA_C
  254.  
  255. COPPERLIST:
  256. SpritePointers:
  257.     dc.w    $120,0,$122,0,$124,0,$126,0,$128,0 ; SPRITE
  258.     dc.w    $12a,0,$12c,0,$12e,0,$130,0,$132,0
  259.     dc.w    $134,0,$136,0,$138,0,$13a,0,$13c,0
  260.     dc.w    $13e,0
  261.  
  262.     dc.w    $8E,$2c81    ; DiwStrt
  263.     dc.w    $90,$2cc1    ; DiwStop
  264.     dc.w    $92,$38        ; DdfStart
  265.     dc.w    $94,$d0        ; DdfStop
  266.     dc.w    $102,0        ; BplCon1
  267.     dc.w    $104,0        ; BplCon2
  268.     dc.w    $108,0        ; Bpl1Mod
  269.     dc.w    $10a,0        ; Bpl2Mod
  270.  
  271.             ; 5432109876543210
  272.     dc.w    $100,%0001001000000000    ; bit 12 acceso!! 1 bitplane lowres
  273.  
  274. BPLPOINTERS:
  275.     dc.w $e0,0,$e2,0    ;primo     bitplane
  276.  
  277.     dc.w    $180,$000    ; color0    ; sfondo nero
  278.     dc.w    $182,$123    ; color1    ; colore 1 del bitplane, che
  279.                         ; in questo caso e' vuoto,
  280.                         ; per cui non compare.
  281.  
  282.     dc.w    $1A2,$F00    ; color17, ossia COLOR1 dello sprite0 - ROSSO
  283.     dc.w    $1A4,$0F0    ; color18, ossia COLOR2 dello sprite0 - VERDE
  284.     dc.w    $1A6,$FF0    ; color19, ossia COLOR3 dello sprite0 - GIALLO
  285.  
  286.     dc.w    $FFFF,$FFFE    ; Fine della copperlist
  287.  
  288.  
  289. ; ************ Ecco lo sprite: OVVIAMENTE deve essere in CHIP RAM! ************
  290.  
  291. MIOSPRITE:        ; lunghezza 13 linee
  292.     dc.b $50    ; Posizione verticale di inizio sprite (da $2c a $f2)
  293.     dc.b $90    ; Posizione orizzontale di inizio sprite (da $40 a $d8)
  294.     dc.b $5d    ; $50+13=$5d    ; posizione verticale di fine sprite
  295.     dc.b $00
  296.  dc.w    %0000000000000000,%0000110000110000 ; Formato binario per modifiche
  297.  dc.w    %0000000000000000,%0000011001100000
  298.  dc.w    %0000000000000000,%0000001001000000
  299.  dc.w    %0000000110000000,%0011000110001100 ;BINARIO 00=COLORE 0 (TRASPARENTE)
  300.  dc.w    %0000011111100000,%0110011111100110 ;BINARIO 10=COLORE 1 (ROSSO)
  301.  dc.w    %0000011111100000,%1100100110010011 ;BINARIO 01=COLORE 2 (VERDE)
  302.  dc.w    %0000110110110000,%1111100110011111 ;BINARIO 11=COLORE 3 (GIALLO)
  303.  dc.w    %0000011111100000,%0000011111100000
  304.  dc.w    %0000011111100000,%0001111001111000
  305.  dc.w    %0000001111000000,%0011101111011100
  306.  dc.w    %0000000110000000,%0011000110001100
  307.  dc.w    %0000000000000000,%1111000000001111
  308.  dc.w    %0000000000000000,%1111000000001111
  309.  dc.w    0,0    ; 2 word azzerate definiscono la fine dello sprite.
  310.  
  311.  
  312.     SECTION    PLANEVUOTO,BSS_C    ; Il bitplane azzerato che usiamo,
  313.                     ; perche' per vedere gli sprite
  314.                     ; e' necessario che ci siano bitplanes
  315.                     ; abilitati
  316. BITPLANE:
  317.     ds.b    40*256        ; bitplane azzerato lowres
  318.  
  319.     end
  320.  
  321. In questa lezione presentiamo una routine universale per spostare gli sprite,
  322. chiamata "UniMuoviSprite".
  323. Questa routine si occupa di tutti gli aspetti del posizionamento degli sprite,
  324. gestisce correttamente tutti i bit della posizione e aggiunge anche gli offset
  325. in modo tale che nelle tabelle possono essere memorizzate le coordinate reali
  326. degli sprite.
  327. Questa routine funziona con un qualsiasi sprite. Infatti l'indirizzo dello
  328. sprite non e` fisso, ma viene letto nel registro a1.
  329. Questo vuol dire che:
  330.  
  331.   VSTART si trova all'indirizzo contenuto in a1
  332.  
  333.   HSTART si trova nel byte seguente, cioe` nell'indirizzo contenuto in a1 +1
  334.  
  335.   VSTOP si trova 2 byte dopo, cioe` nell'indirizzo contenuto in a1 +2
  336.  
  337.  il quarto byte si trova 3 bytes dopo, cioe` nell'indirizzo contenuto in a1 +3.
  338.  
  339. UniMuoviSprite accede a questi byte mediante l'indirizzamento indiretto
  340. a registro con spiazzamento:
  341.  
  342.  per accedere a VSTART si usa (a1)
  343.  per accedere a HSTART si usa 1(a1)
  344.  per accedere a VSTOP si usa 2(a1)
  345.  per accedere al quarto byte di controllo si usa 3(a1)
  346.  
  347. Anche l'altezza dello sprite non e` fissa, ma e` contenuta nel registro d2.
  348. In questo modo la routine puo` essere usata per muovere sprites di diversa
  349. altezza. Inoltre questa routine non legge direttamente le coordinate
  350. dalla tabella, ma li prende dai registri d0 e d1.
  351.  
  352. Chi mette i dati in questi registri? Se ne occupa un'altra routine
  353. "LeggiTabelle" che preleva le coordinate dalle tabelle, le mette nei registri
  354. d0 e d1, e esegue la routine "UniMuoviSprite". In pratica abbiamo diviso
  355. i compiti tra le 2 routine, come se fossero 2 impiegati. La routine
  356. "Leggitabelle" svolge il suo compito, poi dice:"Ehi routine UniMUoviSprite,
  357. eccoti lo sprite da mouvere, ti spedisco l'indirizzo nel registro a1.
  358. Ti spedisco in d2 l'altezza dello sprite.
  359. Eccoti inoltre le coordinate, te le spedisco attraverso i registri d0 e d1.
  360. Sai tu cosa farne!".
  361. La routine "UniMuoviSprite" riceve l'indirizzo dello sprite e le coordinate e
  362. le mette nei giusti byte dello sprite.
  363. La "spedizione" delle coordinate attraverso i registri si chiama "passaggio di
  364. parametri".
  365. La divisione dei compiti e` una cosa molto comoda. Supponiamo infatti di voler
  366. muovere uno sprite utilizzando una tabella per le Y, mentre per le X una
  367. routine di incremento e decremento continuo ADDQ/AUBQ separata, in modo da
  368. realizzare uno sprite che si muove sempre da sinistra a destra, ma che oscilla
  369. in alto e in basso.
  370. Poiche` la routine universale che abbimo appena visto prende le coordinate dai
  371. registri, senza interessarsi se prima questi dati provenivano da una tabella,
  372. possiamo usarla di nuovo cosi` com'e` in questo listato, senza doverla
  373. modificare per niente.
  374. Inoltre, poiche` prende l'indirizzo dello sprite da un registro, e la sua
  375. altezza da un altro, puo` essere usata per qualsiasi sprite.
  376. D'ora in poi, per ogni altro esempio sugli sprite, useremo quindi sempre la
  377. routine "UniMuoviSprite", senza doverla modificare ogni volta.
  378.  
  379.